rabin 1 년 전
부모
커밋
3729244328

+ 97 - 3
api/Admin.php

@@ -5,9 +5,103 @@ class Admin extends Auth
 {
     public function info()
     {
-        $this->user['username'] = '1';
-        $this->user['roles'] = ["Admin"];
-        $this->user['permissions'] = ["read:system", "write:system", "delete:system"];
+        $this->user['system']['show'] = true;
+        $this->user['system']['id'] = $this->user['select']['system_id'];
+        $this->user['system']['name'] = '当前系统';
+        $this->user['system']['list'] = $this->system();
         return $this->user;
     }
+
+    # 获取当前的系统列表
+    public function system()
+    {
+        $where = array();
+        if ($this->user['auth']['system']) {
+            $where['id'] = array('in', $this->user['auth']['system']);
+        }
+        $result = array();
+        $system = Dever::db('system')->select($where);
+        $i = 0;
+        foreach ($system as $k => $v) {
+            $child = Dever::db($v['relation_table'])->select([])->fetchAll();
+            if ($child) {
+                $data = array();
+                foreach ($child as $k1 => $v1) {
+                    $v1['select'] = false;
+                    if ($v['id'] == $this->user['select']['system_id'] && $v1['id'] == $this->user['select']['relation_id']) {
+                        $this->user['system']['name'] = $v1['name'];
+                        $v1['select'] = true;
+                    }
+                    $key = $v['id'] . '-' . $v1['id'];
+                    if ($this->user['system_relation']) {
+                        if (strstr($this->user['system_relation'], $key)) {
+                            $data[] = $v1;
+                        }
+                    } else {
+                        $data[] = $v1;
+                    }
+                }
+                if ($data) {
+                    $result[$i] = $v;
+                    $result[$i]['child'] = $data;
+                    $i++;
+                }
+            }
+        }
+        if ($i <= 1) {
+            $this->user['system']['show'] = false;
+        }
+        return $result;
+    }
+
+    # 根据角色获取子系统
+    public function getSystem($value = false)
+    {
+        if (!$value) {
+            $result['system_relation']['option'] = array();
+            return $result;
+        }
+        $result = array();
+        $role = Dever::db('role')->select(array('id' => array('in', $value)))->fetchAll();
+        if ($role) {
+            $info = $system = array();
+            foreach ($role as $k => $v) {
+                if ($v['system']) {
+                    $child = Dever::db('system')->select(array('id' => array('in', $v['system'])))->fetchAll();
+                    if ($child) {
+                        foreach ($child as $k1 => $v1) {
+                            if (isset($info[$v1['id']])) {
+                                continue;
+                            }
+                            $info[$v1['id']] = true;
+                            $v1['value'] = 's-' . $v1['id'];
+                            $v1['label'] = $v1['name'];
+                            $v1['children'] = array();
+                            $data = Dever::db($v1['relation_table'])->select([], array('col' => 'concat('.$v1['id'].', "-", id) as value, name as label'))->fetchAll();
+                            if ($data) {
+                                $v1['children'] = array_merge($v1['children'], $data);
+                            }
+                            $system[] = $v1;
+                        }
+                    }
+                }
+            }
+            $result['system_relation']['option'] = $system;
+        }
+        
+        return $result;
+    }
+
+    # 切换系统
+    public function setSystem()
+    {
+        $system_id = Dever::input('system_id');
+        $this->checkSystem($this->user['select']['system_id']);
+        $relation_id = Dever::input('relation_id');
+        if ($this->user['system_relation'] && !strstr($this->user['system_relation'], $relation_id)) {
+            Dever::error('无系统权限');
+        }
+        $result = Dever::load('common')->token($this->user['id'], $this->user['mobile'], $system_id, $relation_id);
+        return $result;
+    }
 }

+ 18 - 0
api/Icon.php

@@ -0,0 +1,18 @@
+<?php namespace Manage\Api;
+use Dever;
+use Manage\Lib\Auth;
+class Icon extends Auth
+{
+    public function list()
+    {
+        $set['num'] = Dever::input('pgnum', '', '', 16);
+        $key = Dever::input('title');
+        $where = array();
+        if ($key) {
+            $where['key'] = array('like', $key);
+        }
+        $data['list'] = Dever::db('icon')->select($where, $set);
+        $data['total'] = Dever::page('total');
+        return $data;
+    }
+}

+ 29 - 9
api/Login.php

@@ -1,6 +1,5 @@
 <?php namespace Manage\Api;
 use Dever;
-use Dever\Helper\Secure;
 use Dever\Helper\Str;
 use Dever\Helper\Code;
 class Login
@@ -8,28 +7,49 @@ class Login
     public function act()
     {
         //$this->checkCode();
+        $system = Dever::input('system', 'is_string', '系统', 'platform');
+        $system = Dever::db('system')->find(array('key' => $system));
+        if (!$system) {
+            Dever::error('登录失败,当前系统不存在');
+        }
+        $relation_id = Dever::input('relation_id', 'is_numeric', '关联表', 1);
+        $info = Dever::db($system['relation_table'])->find($relation_id);
+        if (!$info) {
+            Dever::error('登录失败,当前系统设置错误');
+        }
+        if ($system['id'] == 1 && $relation_id == 1) {
+            # 如果是平台,暂时不做分库
+            $db = Dever::db($system['relation_user_table']);
+        } else {
+            # 其他系统做分库
+            $db = Dever::db($system['relation_user_table'], '', 'default', array($system['partition'] => $info['id']));
+        }
         $where['mobile'] = Dever::input('mobile', Dever::rule('mobile'), '手机号');
         $password = Dever::input('password', 'is_string', '密码');
-        $admin = Dever::db('admin')->find($where);
+        $admin = $db->find($where);
         if (!$admin) {
-            $total = Dever::db('admin')->count();
-            if ($total <= 0) {
+            $total = $db->find(1);
+            if (!$total) {
                 $insert['name'] = Str::hide($where['mobile']);
                 $insert['mobile'] = $where['mobile'];
+                $insert['role'] = 1;
                 $insert += Dever::load('common')->createPwd($password);
-                $id = Dever::db('admin')->insert($insert);
-                $admin = Dever::db('admin')->find($id);
+                $id = $db->insert($insert);
+                $admin = $db->find($id);
             } else {
                 Dever::error('登录失败');
             }
         }
         if (!$admin) {
-            Dever::error('登录失败');
+            Dever::error('登录失败,管理员信息无效');
+        }
+        if ($admin['status'] == 2) {
+            Dever::error('登录失败,管理员已被封禁');
         }
         if (Dever::load('common')->hash($password, $admin['salt']) != $admin['password']) {
-            Dever::error('登录失败');
+            Dever::error('登录失败,账号密码无效');
         }
-        return array('token' => Secure::login($admin['id']));
+        return Dever::load('common')->token($admin['id'], $admin['mobile'], $system['id'], $relation_id);
     }
     private function checkCode()
     {

+ 23 - 20
api/Menu.php

@@ -3,15 +3,17 @@ use Dever;
 use Manage\Lib\Auth;
 class Menu extends Auth
 {
-    private $list = 'list,table,card';
     public function info()
     {
-        $top = Dever::db('menu')->select(array('parent_key' => '/'));
+        $this->top = false;
+        $top = Dever::db('menu')->select(array('parent_id' => '0', 'system_id' => $this->user['select']['system_id']));
         $result = $menu = array();
         foreach ($top as $v) {
             $menu = $this->getMenu($v);
         }
-        $result[] = $menu;
+        if ($menu) {
+            $result[] = $menu;
+        }
         $result[] = array
         (
             'path' => '/:pathMatch(.*)*',
@@ -24,18 +26,18 @@ class Menu extends Auth
         );
         return array('list' => $result);
     }
-    private function getMenu($v)
+    private function getMenu($v, $parent = '')
     {
         $info = array
         (
-            'path' => $v['key'],
-            'name' => ucfirst($v['key']),
+            'path' => $parent ? '/' . $parent . '/' . $v['key'] : $v['key'],
+            'name' => $v['key'],
             'meta' => array
             (
                 'title' => $v['name'],
                 'icon' => $v['icon'],
                 //'noClosable' => true,
-                //'breadcrumbHidden' => true,
+                'breadcrumbHidden' => true,
                 'dynamicNewTab' => true,
             )
         );
@@ -45,25 +47,26 @@ class Menu extends Auth
         if (isset($v['active']) && $v['active']) {
             $info['meta']['activeMenu'] = $v['active'];
         }
-        if ($v['parent_key'] == '/') {
-            $info['path'] = '/';
+        if ($v['parent_id'] <= 0) {
+            if ($this->top) {
+                $info['path'] = '/' . $v['key'];
+            } else {
+                $this->top = true;
+                $info['path'] = '/';
+            }
             $info['component'] = 'Layout';
         }
-        $child = Dever::db('menu')->select(array('parent_key' => $v['key']))->fetchAll();
+        $where = array('parent_id' => $v['id'], 'system_id' => $this->user['select']['system_id']);
+        $child = Dever::db('menu')->select($where)->fetchAll();
         if ($child) {
             foreach ($child as $v1) {
-                $info['children'][] = $this->getMenu($v1);
-                if (isset($v1['link']) && strstr($this->list, $v1['link'])) {
-                    $v1['active'] = '/' . $v1['key'];
-                    $v1['name'] .= '更新';
-                    $v1['link'] = 'update';
-                    $v1['key'] .= '/update';
-                    $v1['show'] = 2;
-                    $info['children'][] = $this->getMenu($v1);
+                if ($v1['func'] == 1 && $this->checkMenu($v1['id'])) {
+                    continue;
                 }
+                $info['children'][] = $this->getMenu($v1, $v['key']);
             }
-        } elseif ($v['link']) {
-            $info['component'] = '@/views/page/' . $v['link'];
+        } elseif ($v['path']) {
+            $info['component'] = '@/views/page/' . $v['path'];
         }
         return $info;
     }

+ 179 - 38
api/Page/Data.php

@@ -4,44 +4,132 @@ use Manage\Lib\Page;
 # 数据获取
 class Data extends Page
 {
-    public function __construct()
+    private $recycler = false;
+    private $selection = false;
+    private $expand = false;
+    public function __construct($load = '')
     {
-        parent::__construct('list');
+        parent::__construct('list', $load);
     }
     public function list()
     {
-        $where = $data['head'] = array();
-        $data['field'] = $this->setting('field', $data['head']);
-        $data['search'] = $this->search($where);
+        if (!$this->getFunc('list', '列表', 1)) {
+            Dever::error('无访问权限');
+        }
+        $data['title'] = '';
         $data['button'] = $this->button();
-        $data['body_button'] = $this->button('data_button');
-        $data['body'] = $this->data($where);
+        $data['bodyButton'] = $this->button('data_button');
+        $data['recycler'] = $this->recycler;
+        $data = array_merge($data, $this->out());
         $data['total'] = Dever::page('total');
         $data['height'] = $this->config['height'] ?? '100%';
-        $data['filter'] = $this->config['filter'] ?? 'name';
+        $data['type'] = $this->config['type'] ?? 'table';
         $data['desc'] = $this->config['desc'] ?? '';
+        $data['layout'] = $this->config['layout'] ?? array();
+        $data['exportButton'] = $this->export();
+        $data['show'] = array
+        (
+            'selection' => $this->selection,
+            'expand' => $this->expand,
+            'index' => $this->config['index'] ?? false,
+        );
+        $this->column($data);
+        return $data;
+    }
+    public function out()
+    {
+        $where = $this->config['where'] ?? array();
+        $data['field'] = $data['head'] = array();
+        $data['search'] = $this->search($where);
+        if (isset($this->config['data'])) {
+            $result = Dever::call($this->config['data'], $where);
+            $data = array_merge($data, $result);
+        } else {
+            $data['field'] = $this->setting('field', $data['head'], true, 'show');
+            $data['body'] = $this->data($where);
+        }
+        $method = Dever::input('method');
+        if ($method && strstr($method, '.')) {
+            $result = Dever::call($method, $data);
+            unset($data);
+            $data['field'] = $result['head'];
+            $data['body'] = $result['body'];
+        }
+        $data['stat'] = array();
+        if (isset($this->config['stat'])) {
+            $data['stat'] = Dever::call($this->config['stat'], $where);
+        }
         return $data;
     }
 
     private function data($where)
     {
         $set['num'] = Dever::input('pgnum', '', '', 10);
+        $order_col = Dever::input('order_col');
+        if ($order_col) {
+            $order_value = Dever::input('order_value');
+            if ($order_value) {
+                $set['order'] = $order_col . ' ' . $order_value . ', id desc';
+            }
+        }
+        if (isset($this->config['tree'])) {
+            return $this->db->tree($where, $this->config['tree'], array($this, 'handleData'));
+        }
         $data = $this->db->select($where, $set);
+        $result = array();
         if ($data) {
             foreach ($data as $k => $v) {
-                foreach ($v as $key => $value) {
-                    if (isset($this->config['field'][$key]) && $show = Dever::isset($this->config['field'][$key], 'show')) {
-                        $data[$k][$key] = $this->getShow($show, $v);
-                    } elseif ($value && isset($this->db->config['struct'][$key]['value']) && $this->db->config['struct'][$key]['value']) {
-                        $data[$k][$key] = $this->db->value($key, $value);
-                    } elseif ($key == 'cdate') {
-                        $data[$k][$key] = date('Y-m-d H:i', $value);
+                $result[$k] = $this->handleData($v);
+            }
+        }
+        return $result;
+    }
+
+    public function handleData($v)
+    {
+        $result['id'] = $v['id'];
+        $result['cdate'] = $v['cdate'];
+        foreach ($this->field as $value) {
+            $key = $value['key'];
+            if (isset($v[$key])) {
+                $result[$key] = $this->getValue($key, $v[$key], $v, $value);
+            } elseif (strpos($key, '/')) {
+                $other = $this->getOther($key, $value['where'], $v);
+                if ($other) {
+                    $otherName = array();
+                    foreach ($other as $k1 => $v1) {
+                        if (isset($v1['name'])) {
+                            $otherName[] = $v1['name'];
+                        }
+                    }
+                    if ($otherName) {
+                        $result[$key] = implode('、', $otherName);
+                    } else {
+                        $result[$key] = $other;
                     }
                 }
             }
+        }
+        if (isset($this->config['expand']) && $this->config['expand']) {
+            $result['expand'] = Dever::call($this->config['expand'], $result);
+            $this->expand = true;
+        }
+        return $result;
+    }
 
+    private function export()
+    {
+        $result = false;
+        if (isset($this->config['export'])) {
+            $result = array();
+            foreach ($this->config['export'] as $k => $v) {
+                $func = $this->getFunc($k, $v, 300);
+                if ($func) {
+                    $result[$k] = $v;
+                }
+            }
         }
-        return $data;
+        return $result;
     }
 
     private function search(&$where)
@@ -49,27 +137,27 @@ class Data extends Page
         $search = Dever::input('search');
         $list_search = $result = array();
         $this->setting('search', $list_search, false, 'text');
-        if ($list_search && $search) {
+        if ($list_search) {
             foreach ($list_search as $v) {
                 if ($v['type'] != 'hidden') {
                     $result[] = $v;
                 }
-                if ($value = Dever::isset($search, $v['key'])) {
-                    if ($v['type'] == 'group') {
-                        $where[$v['key']] = array('group', $value);
-                    } elseif ($v['type'] == 'selects') {
-                        $where[$v['key']] = array('group', $value);
-                    } elseif ($v['type'] == 'like') {
-                        $where[$v['key']] = array('like', $value);
-                    } elseif ($v['type'] == 'in') {
-                        $where[$v['key']] = array('in', $value);
-                    } else {
-                        $where[$v['key']] = $value;
+                if ($search) {
+                    if ($value = Dever::isset($search, $v['key'])) {
+                        if ($v['type'] == 'group') {
+                            $where[$v['key']] = array('group', $value);
+                        } elseif ($v['type'] == 'selects') {
+                            $where[$v['key']] = array('group', $value);
+                        } elseif ($v['type'] == 'like') {
+                            $where[$v['key']] = array('like', $value);
+                        } elseif ($v['type'] == 'in') {
+                            $where[$v['key']] = array('in', $value);
+                        } else {
+                            $where[$v['key']] = $value;
+                        }
                     }
                 }
             }
-        } else {
-            $result = $list_search;
         }
         return $result;
     }
@@ -78,12 +166,23 @@ class Data extends Page
     {
         $result = array();
         if (empty($this->config[$key])) {
-            if ($key == 'list_button') {
-                $this->config[$key] = array('新增' => 'fastadd', '删除' => 'del');
+            $num = 0;
+            if (isset($this->db->config['manage']['update']['field'])) {
+                $num = count($this->db->config['manage']['update']['field']);
+            } elseif (isset($this->db->config['struct']) && $this->db->config['struct']) {
+                $num = count($this->db->config['struct']);
+            }
+            $fast = 'fast';
+            if ($num > 8) {
+                $fast = '';
+            }
+            if ($key == 'button') {
+                $this->config[$key] = array('新增' => $fast . 'add');
             } else {
-                $this->config[$key] = array('编辑' => 'fastedit', '删除' => 'del');
+                $this->config[$key] = array('编辑' => $fast . 'edit', '删除' => 'recycle');
             }
         }
+        $sort = 1;
         foreach ($this->config[$key] as $k => $v) {
             $p = '';
             $i = '';
@@ -105,21 +204,59 @@ class Data extends Page
             } elseif (strstr($v, 'view')) {
                 $icon = 'View';
                 $button = '';
-            } elseif ($v == 'del') {
+            } elseif ($v == 'delete') {
+                if ($key == 'button') {
+                    if (isset($this->config['layout'])) {
+                        continue;
+                    }
+                    $this->selection = true;
+                }
+                $icon = 'Delete';
+                $button = 'danger';
+            } elseif ($v == 'recycle') {
+                if ($key == 'button') {
+                    if (isset($this->config['layout'])) {
+                        continue;
+                    }
+                    $this->selection = true;
+                }
                 $icon = 'Delete';
                 $button = 'danger';
             } elseif ($v == 'oper') {
+                if ($key == 'button') {
+                    if (isset($this->config['layout'])) {
+                        continue;
+                    }
+                    $this->selection = true;
+                }
+                $icon = 'Notification';
+                $button = 'warning';
+            } elseif ($v == 'api') {
+                if ($key == 'button') {
+                    if (isset($this->config['layout'])) {
+                        continue;
+                    }
+                    $this->selection = true;
+                }
                 $icon = 'Notification';
                 $button = 'warning';
             } elseif ($v == 'link') {
                 $icon = 'Link';
                 $button = 'success';
+            } elseif ($v == 'route') {
+                $icon = 'Link';
+                $button = 'success';
             } elseif ($v == 'recover') {
-                $icon = 'HelpFilled';
-                $button = 'info';
-            } elseif ($v == 'recycler') {
-                $icon = 'HelpFilled';
+                $icon = 'CirclePlus';
                 $button = 'info';
+            } else {
+                continue;
+            }
+            # 权限验证
+            $sort++;
+            $func = $this->getFunc($v, $k, $sort, $p);
+            if (!$func) {
+                continue;
             }
             if ($i) {
                 $icon = $i;
@@ -131,7 +268,11 @@ class Data extends Page
                 'param' => $p,
                 'icon' => $icon,
                 'button' => $button,
+                'func' => $func,
             );
+            if (!$this->recycler && $v == 'recycle') {
+                $this->recycler = true;
+            }
         }
         return $result;
     }

+ 10 - 8
api/Page/Oper.php

@@ -11,6 +11,7 @@ class Oper extends Page
         if (!$this->id) {
             Dever::error('无效数据');
         }
+        $this->checkFunc();
     }
 
     # 更改某个字段的值
@@ -37,8 +38,8 @@ class Oper extends Page
     }
 
     # 删除 删除到回收站
-    public function del_commit(){}
-    public function del()
+    public function recycle_commit(){}
+    public function recycle()
     {
         $where['id'] = array('in', $this->id);
         $data = $this->db->select($where)->fetchAll();
@@ -65,17 +66,18 @@ class Oper extends Page
     public function recover()
     {
         $where['id'] = array('in', $this->id);
-        $data = Dever::db('manage/recycler')->select($where);
+        $data = $this->db->select($where);
         if ($data) {
             foreach ($data as $k => $v) {
-                $state = Dever::db('manage/recycler')->delete($v['id']);
+                $v['content'] = Dever::json_decode($v['content']);
+                $v['table'] = ltrim($v['table'], '/');
+                $state = Dever::db($v['table'])->insert($v['content']);
                 if (!$state) {
-                    Dever::error('删除失败,请重试');
+                    Dever::error('恢复失败,请重试');
                 }
-                $v['content'] = Dever::json_decode($v['content']);
-                $state = $this->db->insert($v['content']);
+                $state = $this->db->delete($v['id']);
                 if (!$state) {
-                    Dever::error('删除失败,请重试');
+                    Dever::error('恢复失败,请重试');
                 }
             }
         }

+ 161 - 27
api/Page/Update.php

@@ -4,42 +4,123 @@ use Manage\Lib\Page;
 # 更新页
 class Update extends Page
 {
-    public function __construct()
+    public function __construct($load = '', $id = false)
     {
-        parent::__construct('update');
+        parent::__construct('update', $load, $id);
     }
     public function get()
     {
+        $func = $this->checkFunc();
+        $remote = $show = array();
         $data['update'] = $data['field'] = array();
         $this->setting('field', $data['update'], true, 'text');
         foreach ($data['update'] as $k => $v) {
+            if ($v['type'] == 'tree') {
+                $v['value'] = array();
+            }
+            if (isset($v['remote'])) {
+                # 需要设置remote
+                $remote[$v['key']] = array($k, $v['remote']);
+            }
+            if (isset($v['show']) && is_string($v['show'])) {
+                $show[$v['key']] = array($k, $v['show']);
+            }
             $data['field'][$v['key']] = $v['value'];
         }
-        if ($this->id) {
-            $data['info'] = $this->db->find($this->id);
-            if ($data['info']) {
-                foreach ($data['info'] as $k => $v) {
-                    if (isset($data['field'][$k])) {
-                        if (is_array($data['field'][$k])) {
-                            $v = explode(',', $v);
-                        }
-                        if (isset($this->config['field'][$k]) && isset($this->config['field'][$k]['value'])) {
-                            $v = $this->config['field'][$k]['value'];
+        $this->column($data);
+        $data['info_id'] = false;
+        if (!$this->info && $data['column'] && $data['column']['where'] == 'id') {
+            $this->info = $this->db->find($data['column']['active']);
+            if ($this->info) {
+                $data['info_id'] = $this->info['id'];
+                if (!$func) {
+                    $func = $this->getFunc('edit', '编辑', 1);
+                    if (!$func) {
+                        Dever::error('无操作权限');
+                    }
+                }
+            }
+        } elseif (!$func) {
+            $func = $this->getFunc('update', '更新', 1);
+            if (!$func) {
+                Dever::error('无操作权限');
+            }
+        }
+        if ($this->info) {
+            $data['info'] = $this->info;
+            foreach ($data['info'] as $k => $v) {
+                if (isset($data['field'][$k])) {
+                    if (is_array($data['field'][$k])) {
+                        $v = explode(',', $v);
+                    }
+                    if (isset($this->config['field'][$k]) && isset($this->config['field'][$k]['value'])) {
+                        $v = $this->config['field'][$k]['value'];
+                    }
+                    $data['field'][$k] = $v;
+                    if (isset($remote[$k])) {
+                        $data['update'][$remote[$k][0]]['remote'] = Dever::url($remote[$k][1]);
+                        $result = Dever::call($remote[$k][1], $v, 'api');
+                        if ($result) {
+                            $this->setUpdate($data['update'], $result);
                         }
-                        $data['field'][$k] = $v;
+                    }
+                    if (isset($show[$k])) {
+                        $data['update'][$show[$k][0]]['show'] = $this->getShow($show[$k][1], $data['info']);
                     }
                 }
             }
+        } else {
+            if ($remote) {
+                foreach ($remote as $k => $v) {
+                    $data['update'][$v[0]]['remote'] = Dever::url($v[1]);
+                }
+            }
+            if ($show) {
+                foreach ($show as $k => $v) {
+                    $data['update'][$v[0]]['show'] = true;
+                }
+            }
         }
         $data['desc'] = $this->config['desc'] ?? '';
+        $data['drag'] = $this->config['drag'] ?? false;
         $this->layout($data);
         $this->tab($data, 'step');
         if (!$data['step']) {
             $this->tab($data);
         }
+        $this->control($data);
         return $data;
     }
 
+    private function setUpdate(&$update, $result)
+    {
+        foreach ($update as $k => $v) {
+            if (isset($result[$v['key']])) {
+                $update[$k] = array_merge($update[$k], $result[$v['key']]);
+            }
+        }
+    }
+
+    private function control(&$data)
+    {
+        $data['control'] = array();
+        if (isset($this->config['control']) && $data['control'] = $this->config['control']) {
+            foreach ($data['control'] as $k => $v) {
+                foreach ($data['update'] as $k1 => $v1) {
+                    if ($v1['key'] == $k) {
+                        $show = true;
+                        foreach ($v as $k2 => $v2) {
+                            if ($data['field'][$k2] != $v2) {
+                                $show = false;
+                            }
+                        }
+                        $data['update'][$k1]['show'] = $show;
+                    }
+                } 
+            }
+        }
+    }
+
     private function tab(&$data, $type = 'tab')
     {
         $field = Dever::input('field');
@@ -111,10 +192,11 @@ class Update extends Page
     public function do_commit(){}
     public function do()
     {
+        $this->checkFunc();
         $update = array();
-        $this->setting('update', $update, true, 'text');
+        $this->setting('field', $update, true, 'text');
         if ($update) {
-            $data = array();
+            $data = $other = array();
             $input = Dever::input();
             $id = false;
             if (isset($input['id']) && $input['id'] > 0) {
@@ -122,27 +204,36 @@ class Update extends Page
             }
             foreach ($update as $k => $v) {
                 if (isset($input[$v['key']])) {
-                    if (isset($v['rule'])) {
+                    if (isset($v['rules'])) {
                         $this->checkRules($v, $input[$v['key']]);
                     }
-                    $this->doData($data, $v['key'], $input[$v['key']]);
+                    if (strpos($v['key'], '/')) {
+                        $other[$v['key']] = array($v['where'], $v['content']['field'], $v['content']['drag'], $input[$v['key']]);
+                    } else {
+                        $this->doData($data, $v['key'], $input[$v['key']]);
+                    }
                 } elseif ($id) {
                     $data[$v['key']] = '';
                 }
+                if (isset($data[$v['key']]) && !$data[$v['key']] && isset($v['empty']) && !$v['empty']) {
+                    unset($data[$v['key']]);
+                }
             }
             if (!$data) {
                 Dever::error('无效数据');
             }
-            $this->check($id, $data);
+            $this->exists($id, $data);
             $this->start($id, $data);
             if ($id) {
                 $info = $this->db->find($id);
-                if (!$info) {
-                    Dever::error('无效数据');
-                }
-                $state = $this->db->update($info['id'], $data);
-                if ($state) {
-                    $id = $info['id'];
+                if ($info) {
+                    $state = $this->db->update($info['id'], $data);
+                    if ($state) {
+                        $id = $info['id'];
+                    }
+                } else {
+                    $data['id'] = $id;
+                    $id = $this->db->insert($data);
                 }
             } else {
                 $id = $this->db->insert($data);
@@ -151,6 +242,7 @@ class Update extends Page
                 Dever::error('操作失败');
             }
             $this->end($id, $data);
+            $this->other($id, $data, $other);
             return '操作成功';
         }
     }
@@ -176,7 +268,7 @@ class Update extends Page
         $data[$key] = $value;
     }
 
-    private function check($id, $data)
+    private function exists($id, $data)
     {
         if (isset($this->config['check']) && $this->config['check']) {
             $check = explode(',', $this->config['check']);
@@ -211,14 +303,56 @@ class Update extends Page
     private function start($id, &$data)
     {
         if (isset($this->config['start']) && $this->config['start']) {
-            echo $this->config['start'];die;
+            $data['id'] = $id;
+            $data = Dever::call($this->config['start'], $data);
         }
     }
 
     private function end($id, $data)
     {
         if (isset($this->config['end']) && $this->config['end']) {
-            echo $this->config['end'];die;
+            $data['id'] = $id;
+            Dever::call($this->config['end'], $data);
+        }
+    }
+
+    private function other($rid, $data, $other)
+    {
+        if ($other) {
+            foreach ($other as $k => $v) {
+                $common = $v[0];
+                $update = $v[1];
+                $drag = $v[2];
+                $input = $v[3];
+                $value = array();
+                foreach ($input as $k1 => $v1) {
+                    if (isset($v1['id'])) {
+                        $value['id'] = $v1['id'];
+                    }
+                    foreach ($common as $k2 => $v2) {
+                        if ($v2 == 'id') {
+                            $value[$k2] = $rid;
+                        } elseif (isset($data[$v2])) {
+                            $value[$k2] = $data[$v2];
+                        }
+                    }
+                    foreach ($update as $k2 => $v2) {
+                        if (isset($v1[$k2])) {
+                            $value[$k2] = $v1[$k2];
+                        }
+                    }
+                    if ($drag) {
+                        $value[$drag] = $k1+1;
+                    }
+                    if (isset($value['id']) && $value['id'] > 0) {
+                        $id = $value['id'];
+                        unset($value['id']);
+                        Dever::db($k)->update($id, $value);
+                    } else {
+                        Dever::db($k)->insert($value);
+                    }
+                }
+            }
         }
     }
 }

+ 17 - 0
api/Page/View.php

@@ -0,0 +1,17 @@
+<?php namespace Manage\Api\Page;
+use Dever;
+use Manage\Lib\Page;
+# 详情页
+class View extends Page
+{
+    public function __construct($load = '', $id = false)
+    {
+        parent::__construct('view', $load, $id);
+    }
+    public function get()
+    {
+        $this->checkFunc();
+        $data = Dever::call($this->config, $this);
+        return $data;
+    }
+}

+ 105 - 10
lib/Auth.php

@@ -1,7 +1,5 @@
 <?php namespace Manage\Lib;
 use Dever;
-use Dever\Helper\Secure;
-use Dever\Helper\Env;
 class Auth
 {
     protected $login = true;
@@ -10,18 +8,115 @@ class Auth
     public $data = array();
     public function __construct()
     {
-        $auth = Env::header('authorization');
-        if (!$auth) {
+        $info = Dever::load('common')->auth();
+        if (!$info && $this->login) {
             $info['uid'] = 1;
             //Dever::error('请先登录');
-        } else {
-            $auth = ltrim($auth, 'Bearer ');
-            $info = Secure::checkLogin($auth, 86400*7);
-            if (!$info && $this->login) {
-                Dever::error('请先登录');
-            }
         }
         $this->uid = $info['uid'];
         $this->user = Dever::db('admin')->find($this->uid);
+        if (!$this->user) {
+            Dever::error('请先登录');
+        }
+        $this->user['auth'] = array('system' => '', 'menu' => '', 'func' => '');
+        if ($this->user['role']) {
+            $role = Dever::db('role')->select(array('id' => array('in', $this->user['role'])))->fetchAll();
+            foreach ($role as $k => $v) {
+                $this->user['auth']['system'] .= $v['system'] . ',';
+                $this->user['auth']['menu'] .= $v['menu'] . ',';
+                $this->user['auth']['func'] .= $v['auth'] . ',';
+            }
+        }
+        if ($this->user['auth']['system']) {
+            $this->user['auth']['system'] = rtrim($this->user['auth']['system'], ',');
+        }
+        if ($this->user['auth']['menu']) {
+            $this->user['auth']['menu'] = rtrim($this->user['auth']['menu'], ',');
+        }
+        if ($this->user['auth']['func']) {
+            $this->user['auth']['func'] = ',' . $this->user['auth']['func'];
+        }
+        $this->user['select'] = $info['extend'] ?? false;
+        if (!$this->user['select']) {
+            $this->user['select'] = array('system_id' => 1, 'relation_id' => 1);
+        }
+        $this->checkSystem($this->user['select']['system_id']);
+    }
+
+    # 设置功能权限
+    public function getFunc($key, $name, $sort = 1, $param = '')
+    {
+        if (!$key) {
+            $key = md5(base64_encode($name));
+        }
+        if ($param) {
+            if (is_array($param)) {
+                $param = Dever::json_encode($name);
+            }
+            $key = $key . '_' . md5($param);
+        }
+        $data['menu_id'] = $this->menu['id'];
+        $data['key'] = $key;
+        $info = Dever::db('menu_func')->find($data);
+        $name = $this->menu['name'] . '-' . $name;
+        if (!$info) {
+            $data['name'] = $name;
+            $data['sort'] = $sort;
+            $id = Dever::db('menu_func')->insert($data);
+            Dever::db('menu')->update($this->menu['id'], array('func' => 1));
+        } else {
+            if ($info['name'] != $name) {
+                $data['name'] = $name;
+                $data['sort'] = $sort;
+                Dever::db('menu_func')->update($info['id'], $data);
+                Dever::db('menu')->update($this->menu['id'], array('func' => 1));
+            }
+            $id = $info['id'];
+        }
+        if ($this->user['id'] == 1) {
+            return $id;
+        }
+        if ($this->user['auth']['func'] && strpos($this->user['auth']['func'], ',' . $id . ',')) {
+            return $id;
+        }
+        return false;
+    }
+
+    # 检测系统权限
+    protected function checkSystem($system_id)
+    {
+        if ($this->user['auth']['system'] && !Dever::check($this->user['auth']['system'], $system_id)) {
+            Dever::error('无系统权限');
+        }
+    }
+
+    # 检测菜单权限
+    protected function checkMenu($menu, $result = true)
+    {
+        if ($this->user['auth']['menu'] && !Dever::check($this->user['auth']['menu'], $menu)) {
+            if ($result) {
+                return true;
+            }
+            Dever::error('无访问权限');
+        }
+        if ($result) {
+            return false;
+        }
+    }
+
+    # 检测功能权限
+    protected function checkFunc()
+    {
+        $id = Dever::input('func');
+        if (!$id) {
+            return false;
+        }
+        if ($this->user['id'] == 1) {
+            return $id;
+        }
+        if ($this->user['auth']['func'] && strpos($this->user['auth']['func'], ',' . $id . ',')) {
+            return $id;
+        }
+        Dever::error('无操作权限');
     }
 }

+ 408 - 0
lib/Common.php

@@ -1,8 +1,61 @@
 <?php namespace Manage\Lib;
 use Dever;
 use Dever\Helper\Str;
+use Dever\Helper\Env;
+use Dever\Helper\Secure;
 class Common
 {
+    public function auth()
+    {
+        $auth = Env::header('authorization');
+        if ($auth) {
+            $auth = ltrim($auth, 'Bearer ');
+            Dever::session('auth', $auth);
+            $info = Secure::checkLogin($auth);
+            return $info;
+        }
+        return false;
+    }
+
+    # 获取当前使用的系统
+    public function system($key = '')
+    {
+        $info = $this->auth();
+        if (!$info) {
+            $auth = Dever::session('auth');
+            if (!$auth) {
+                return false;
+            }
+            $info = Secure::checkLogin($auth);
+        }
+        if ($info && isset($info['extend']) && isset($info['extend']['relation_id'])) {
+            # 这里后续增加从数据库中获取
+            $value = $info['extend']['system_id'] . '_' . $info['extend']['relation_id'];
+            if ($key) {
+                return array($key => $value);
+            }
+            return $value;
+        }
+        return false;
+    }
+
+    # 生成token
+    public function token($uid, $mobile, $system_id, $relation_id)
+    {
+        $extand['system_id'] = $system_id;
+        $extand['relation_id'] = $relation_id;
+        /* 暂时不做到库中
+        $select['mobile'] = $mobile;
+        $info = Dever::db('mobile_system')->find($select);
+        $select += $extand;
+        if (!$info) {
+            Dever::db('mobile_system')->insert($select);
+        } else {
+            Dever::db('mobile_system')->update($info['id'], $select);
+        }*/
+        return array('token' => Secure::login($uid, $extand));
+    }
+
     public function createPwd($password)
     {
         $data['salt'] = Str::salt(8);
@@ -14,4 +67,359 @@ class Common
     {
         return hash('sha256', $password . $salt);
     }
+
+    # 仅为测试用
+    public function out($data)
+    {
+        $result = array();
+        $result['head'] = array('id', '姓名', '时间');
+        $result['body'] = array();
+        foreach ($data['body'] as $k => $v) {
+            $result['body'][$k] = array($v['id'], $v['name'], $v['cdate']);
+        }
+        return $result;
+    }
+
+    # 仅为测试用,展示表格更多内容
+    public function show($data)
+    {
+        # 返回类型:string字符串,table表格,list列表
+        $result['type'] = 'string';
+        $result['content'] = 'ddddd';
+
+        $result['type'] = 'table';
+        $result['head'] = array('id' => 'id', 'name' => '姓名');
+        $result['body'] = array
+        (
+            array('id' => '1', 'name' => 'test'),
+            array('id' => '2', 'name' => 'test2'),
+        );
+
+        $result['type'] = 'list';
+        $result['content'] = array
+        (
+            array('日志类型', 'test'),
+            array('姓名', 'test1'),
+        );
+        return $result;
+    }
+
+    # 仅为测试用,展示详情
+    public function view($page)
+    {
+        # 这里获取基本信息
+        //print_r($page->info);die;
+        $info[] = array
+        (
+            # 类型,desc描述 table表格,表格有head和body即可
+            'type' => 'desc',
+            'name' => '基本信息',
+            # 每行展示数量
+            'column' => 4,
+            # 是否有边框
+            'border' => true,
+            # 排列方向:horizontal横向 vertical纵向
+            'direction' => 'vertical',
+            # 右侧按钮
+            'button' => array
+            (
+                array
+                (
+                    'name' => '编辑',
+                    # fastedit、fastadd、oper、api四个按钮类型,参数与list里的data_button一致,多了一个load,可以单独设置路由
+                    'type' => 'fastedit',
+                    'load' => 'platform/role',
+                    # 增加权限,第三个参数是排序,建议大一些
+                    //'func' => $page->getFunc('view_fastedit', '详情页-编辑角色', 1000),
+                    # 这里是按钮用到的参数数据
+                    'row' => array
+                    (
+                        'id' => 1,
+                    ),
+                ),
+            ),
+            # 具体内容
+            'content' => array
+            (
+                array
+                (
+                    'name' => '标题',
+                    # 类型,text普通文本,tag标签,link链接,image图片 progress进度条 stat统计 timeline时间线 table表格
+                    'type' => 'text',
+                    'content' => '内容',
+                    # 样式primary success warning danger info exception
+                    'style' => 'primary',
+                ),
+                array
+                (
+                    'name' => '标题',
+                    'type' => 'tag',
+                    'content' => '内容',
+                    'style' => 'warning',
+                ),
+                array
+                (
+                    'name' => '标题',
+                    'type' => 'link',
+                    'content' => '内容',
+                ),
+                array
+                (
+                    'name' => '图片',
+                    'type' => 'image',
+                    'content' => 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
+                    # 'fill', 'contain', 'cover', 'none', 'scale-down'
+                    'fit' => 'fill',
+                ),
+                array
+                (
+                    'name' => '进度条',
+                    'type' => 'progress',
+                    'content' => '10',
+                    'style' => 'exception',
+                    'width' => '20',
+                    'inside' => true,
+                    # line dashboard 仪表盘 circle 圆形
+                    'show' => 'line',
+                    # 开启条纹
+                    'striped' => true,
+                    # 开启动画
+                    'indeterminate' => true,
+                ),
+                array
+                (
+                    'name' => '统计',
+                    'type' => 'stat',
+                    'content' => array
+                    (
+                        array
+                        (
+                            # 一共24
+                            'span' => '6',
+                            'name' => '测试',
+                            'value' => '1000',
+                        ),
+                        array
+                        (
+                            'span' => '6',
+                            'name' => '测试1',
+                            'value' => '1000',
+                        ),
+                        array
+                        (
+                            'span' => '6',
+                            'name' => '测试2',
+                            'value' => '1000',
+                        ),
+                        array
+                        (
+                            'span' => '6',
+                            'name' => '测试2',
+                            'value' => '1000',
+                        ),
+                    ),
+                ),
+
+                array
+                (
+                    'name' => '时间线',
+                    'type' => 'timeline',
+                    'content' => array
+                    (
+                        array
+                        (
+                            'time' => '2020-10-11',
+                            'name' => '测试',
+                            'color' => '#0bbd87',
+                            'size' => 'large',
+                            'type' => 'primary',
+                            'hollow' => true,
+                        ),
+                        array
+                        (
+                            'time' => '2020-10-11',
+                            'name' => '测试',
+                        ),
+                        array
+                        (
+                            'time' => '2020-10-11',
+                            'name' => '测试',
+                        ),
+                        array
+                        (
+                            'time' => '2020-10-11',
+                            'name' => '测试',
+                        ),
+                    ),
+                ),
+
+                array
+                (
+                    'name' => '表格',
+                    'type' => 'table',
+                    'border' => true,
+                    'height' => '200',
+                    'head' => array
+                    (
+                        array
+                        (
+                            'key' => 'name',
+                            'name' => '姓名',
+                            'fixed' => 'fixed',
+                        ),
+                        array
+                        (
+                            'key' => 'desc',
+                            'name' => '描述',
+                            'fixed' => 'fixed',
+                        ),
+                    ),
+                    'button' => array
+                    (
+                        array
+                        (
+                            'name' => '编辑',
+                            'type' => 'fastedit',
+                            'load' => 'platform/role',
+                        ),
+                    ),
+                    'body' => array
+                    (
+                        array
+                        (
+                            'id' => 1,
+                            'name' => 'test',
+                            'desc' => 'dfdf',
+                        ),
+                    ),
+                ),
+            ),
+        );
+
+        $info[] = array
+        (
+            'type' => 'table',
+            'name' => '表格信息',
+            'border' => true,
+            'height' => '200',
+            'head' => array
+            (
+                array
+                (
+                    'key' => 'name',
+                    'name' => '姓名',
+                    'fixed' => 'fixed',
+                ),
+                array
+                (
+                    'key' => 'desc',
+                    'name' => '描述',
+                    'fixed' => 'fixed',
+                ),
+            ),
+            'button' => array
+            (
+                array
+                (
+                    'name' => '编辑',
+                    'type' => 'fastedit',
+                    'load' => 'platform/role',
+                    # 增加权限,第三个参数是排序,建议大一些
+                    'func' => $page->getFunc('view_fastedit', '详情页-编辑角色', 1000),
+                ),
+            ),
+            'body' => array
+            (
+                array
+                (
+                    'id' => 1,
+                    'name' => 'test',
+                    'desc' => 'dfdf',
+                ),
+            ),
+        );
+        $tab = array
+        (
+            'active' => 'table1',
+            'content' => array
+            (
+                'table1' => array
+                (
+                    # 这里跟desc一样
+                    'name' => '标题',
+                    'type' => 'text',
+                    'content' => '内容',
+                    'style' => 'primary',
+                ),
+
+                'tab2' => array
+                (
+                    'name' => '表格',
+                    'type' => 'table',
+                    'border' => true,
+                    'height' => '200',
+                    'head' => array
+                    (
+                        array
+                        (
+                            'key' => 'name',
+                            'name' => '姓名',
+                            'fixed' => 'fixed',
+                        ),
+                        array
+                        (
+                            'key' => 'desc',
+                            'name' => '描述',
+                            'fixed' => 'fixed',
+                        ),
+                    ),
+                    'button' => array
+                    (
+                        array
+                        (
+                            'name' => '编辑',
+                            'type' => 'fastedit',
+                            'load' => 'platform/role',
+                        ),
+                    ),
+                    'body' => array
+                    (
+                        array
+                        (
+                            'id' => 1,
+                            'name' => 'test',
+                            'desc' => 'dfdf',
+                        ),
+                    ),
+                ),
+            )
+        );
+        return array('info' => $info, 'tab' => $tab);
+    }
+
+    public function stat($where)
+    {
+        return array
+        (
+            array
+            (
+                # 一共24
+                'span' => '8',
+                'name' => '测试',
+                'value' => '1000',
+            ),
+            array
+            (
+                'span' => '8',
+                'name' => '测试1',
+                'value' => '1000',
+            ),
+            array
+            (
+                'span' => '8',
+                'name' => '测试2',
+                'value' => '1000',
+            ),
+        );
+    }
 }

+ 18 - 0
lib/Config.php

@@ -0,0 +1,18 @@
+<?php namespace Manage\Lib;
+use Dever;
+use Dever\Project;
+class Config extends Auth
+{
+    public function getTree()
+    {
+        $data = Dever::db('config')->select([])->fetchAll();
+        $result = array();
+        $result[] = array
+        (
+            'id' => 'root',
+            'name' => '全部配置',
+            'children' => $data,
+        );
+        return $result;
+    }
+}

+ 35 - 0
lib/Group.php

@@ -0,0 +1,35 @@
+<?php namespace Manage\Lib;
+use Dever;
+use Dever\Helper\Str;
+class Group extends Auth
+{
+    public function getTree()
+    {
+        $data = Dever::db('group')->select([])->fetchAll();
+        $result = array();
+        $result[] = array
+        (
+            'id' => 'root',
+            'name' => '全部集团',
+            'children' => $data,
+        );
+        return $result;
+    }
+
+    public function update($data)
+    {
+        if ($data['mobile']) {
+            $database = '"2_' . $data['id'] . '"';
+            $db = Dever::db('group_user', '', 'default', array('database' => $database));
+            $info = $db->find(1);
+            if (!$info) {
+                $password = '123456';
+                $insert['name'] = Str::hide($data['mobile']);
+                $insert['mobile'] = $data['mobile'];
+                $insert['role'] = 1;
+                $insert += Dever::load('common')->createPwd($password);
+                $db->insert($insert);
+            }
+        }
+    }
+}

+ 57 - 25
lib/Menu.php

@@ -10,44 +10,76 @@ class Menu
         foreach ($app as $k => $v) {
             $base = $v['path'] . 'table/manage/core.php';
             if (is_file($base)) {
-                $menu = include $base;
-                if ($menu) {
-                    $this->add($k, $menu);
+                $core = include $base;
+                if ($core) {
+                    $this->add($k, $core);
                 }
             }
         }
         return 'ok';
     }
-    private function add($app, $menu)
+    private function add($app, $core)
     {
-        foreach ($menu as $k => $v) {
-            $where = array();
-            $where['key'] = $app . '/' . $k;
-            $data = $where;
-            $data['name'] = $v['name'];
-            $data['icon'] = $v['icon'];
-            $data['sort'] = $v['sort'];
-            if (isset($v['badge'])) {
-                $data['badge'] = $v['badge'];
+        if (isset($core['system'])) {
+            foreach ($core['system'] as $k => $v) {
+                $where = array();
+                $where['key'] = $k;
+                $data = $where;
+                $data['name'] = $v['name'];
+                $data['sort'] = $v['sort'];
+                $data['partition'] = $v['partition'] ?? 'database';
+                $data['relation_table'] = $v['relation_table'];
+                $data['relation_field'] = $v['relation_field'];
+                $data['relation_user_table'] = $v['relation_user_table'];
+                Dever::db('system')->up($where, $data);
             }
-            if (isset($v['link'])) {
-                $data['link'] = $v['link'];
-            }
-            if (isset($v['parent'])) {
-                if (!strpos($v['parent'], '/')) {
-                    $v['parent'] = $app . '/' . $v['parent'];
+        }
+        if (isset($core['menu'])) {
+            foreach ($core['menu'] as $k => $v) {
+                $where = array();
+                if (isset($v['app'])) {
+                    $app = $v['app'];
                 }
-                $data['parent_key'] = $v['parent'];
-            }
-            if (isset($v['show'])) {
-                $data['show'] = $v['show'];
+                $where['app'] = $app;
+                $where['key'] = $k;
+                if (isset($v['parent'])) {
+                    $parent = Dever::db('menu')->find(array('key' => $v['parent']));
+                    if ($parent) {
+                        $where['parent_id'] = $parent['id'];
+                        $where['system_id'] = $parent['system_id'];
+                    }
+                }
+                if (isset($v['system'])) {
+                    $system = Dever::db('system')->find(array('key' => $v['system']));
+                    if ($system) {
+                        $where['system_id'] = $system['id'];
+                    }
+                }
+                $data = $where;
+                $data['name'] = $v['name'];
+                $data['icon'] = $v['icon'];
+                $data['sort'] = $v['sort'];
+                if (isset($v['show'])) {
+                    $data['show'] = $v['show'];
+                }
+                if (isset($v['badge'])) {
+                    $data['badge'] = $v['badge'];
+                }
+                if (isset($v['path'])) {
+                    $data['path'] = $v['path'];
+                } else {
+                    $data['path'] = 'main';
+                }
+                if (isset($v['link'])) {
+                    $data['link'] = $v['link'];
+                }
+                Dever::db('menu')->up($where, $data);
             }
-            Dever::db('menu')->up($where, $data);
         }
     }
     public function getAll()
     {
-        $data = Dever::db('menu')->select(array('parent_key' => '/'));
+        $data = Dever::db('menu')->select(array('parent_id' => '0'));
         return $data;
     }
 }

+ 268 - 80
lib/Page.php

@@ -4,30 +4,69 @@ use Dever;
 class Page extends Auth
 {
     protected $db;
+    protected $key;
     protected $id = false;
+    protected $menu = array();
     protected $config = array();
-    public function __construct($key = '')
+    protected $field = array();
+    public $info = array();
+    public function __construct($key = '', $load = '', $id = false)
     {
         parent::__construct();
-        $this->id = Dever::input('id');
-        list($app, $table) = explode('/', ltrim(Dever::input('load'), '/'));
-        $this->db = Dever::db($table, $app);
-        if (empty($this->db->config['struct'])) {
-            Dever::error('无效信息');
+        $this->key = $key;
+        if ($id == -1) {
+            $this->id = false;
+        } else {
+            $this->id = $id ? $id : Dever::input('id');
+        }
+        if (!$load) {
+            $load = Dever::input('load');
+        }
+        $load = explode('/', ltrim($load, '/'));
+        if (isset($load[2])) {
+            $app = $load[1];
+            $table = $load[2];
+        } else {
+            $app = $load[0];
+            $table = $load[1];
+        }
+        $parent = Dever::db('menu')->find(array('key' => $app));
+        if ($parent) {
+            $this->menu = Dever::db('menu')->find(array('parent_id' => $parent['id'], 'key' => $table));
+            if ($this->menu) {
+                $this->checkMenu($this->menu['id'], false);
+                $app = $this->menu['app'];
+            }  else {
+                Dever::error('菜单无效');
+            }
         }
-        $app = Dever::project($app);
-        $manage = $app['path'] . 'table/manage/'.$table.'.php';
+        $set = Dever::project($app);
+        $manage = $set['path'] . 'table/manage/'.$table.'.php';
         if (is_file($manage)) {
-            $this->db->config['manage'] = include $manage;
+            $manage = include $manage;
+            if ($source = Dever::isset($manage, 'source')) {
+                if (strpos($source, '/')) {
+                    $source = explode('/', $source);
+                    $app = $source[0];
+                    $table = $source[1];
+                } else {
+                    $table = $source;
+                }
+            }
             if ($key) {
-                $this->config = $this->db->config['manage'][$key] ?? array();
+                $this->config = $manage[$key] ?? array();
             }
         }
+        $this->db = Dever::db($table, $app);
+        $this->db->config['manage'] = $manage;
+        if ($this->id) {
+            $this->info = $this->db->find($this->id);
+        }
     }
 
-    protected function setting($key, &$data, $struct = true, $type = 'show', $disable = false)
+    public function setting($key, &$data, $struct = true, $type = 'show', $disable = false)
     {
-        if (empty($this->config[$key]) && $struct) {
+        if (empty($this->config[$key]) && $struct && isset($this->db->config['struct']) && $this->db->config['struct']) {
             $this->config[$key] = $this->db->config['struct'];
         }
         if (empty($this->config[$key])) {
@@ -38,19 +77,145 @@ class Page extends Auth
             $setting = explode(',', $setting);
         }
         $field = Dever::input('field');
-        $result = array();
-        foreach ($setting as $k => $v) {
-            if ($field) {
-                if (!Dever::check($field, $k)) {
-                    continue;
+        return $this->setData($setting, $data, $field, $type, $disable);
+    }
+
+    # 获取某个数据的具体展示值
+    public function getValue($key, $value, $data, $field = array())
+    {
+        if ($show = Dever::isset($field, 'show')) {
+            $value = $this->getShow($show, $data);
+        } elseif ($value && isset($this->db->config['struct'][$key]['value']) && $this->db->config['struct'][$key]['value']) {
+            $value = $this->db->value($key, $value);
+        } elseif ($key == 'cdate') {
+            if ($value) {
+                $value = date('Y-m-d H:i', $value);
+            } else {
+                $value = '-';
+            }
+        }
+        return $value;
+    }
+
+    # 获取关联数据
+    public function getOther($key, $set, $data, $method = 'fetchAll')
+    {
+        $where = array();
+        foreach ($set as $k => $v) {
+            if (isset($data[$v])) {
+                $where[$k] = $data[$v];
+            }
+        }
+        if ($where) {
+            return Dever::db($key)->select($where)->$method();
+        }
+        return array();
+    }
+
+    public function getShow($show, $data)
+    {
+        if (strpos($show, '{') !== false && strpos($show, '{"') === false) {
+            $func = function ($r) use ($data) {
+                if (isset($data[$r[1]])) {
+                    return $data[$r[1]];
+                }
+                return false;
+            };
+            $show = preg_replace_callback('/{(.*?)}/', $func, $show);
+        }
+        $eval = '$show = ' . $show . ';';
+        eval($eval);
+        return $show;
+    }
+
+    # 获取菜单标题
+    public function getTitle()
+    {
+        return $this->menu['name'];
+    }
+
+    # 获取左侧分栏
+    protected function column(&$data, $name = '左侧分栏')
+    {
+        $data['column'] = false;
+        if (isset($this->config['column'])) {
+            $data['column'] = $this->config['column'];
+            if (isset($this->config['column']['add'])) {
+                $data['column']['add'] = array('name' => $this->config['column']['add'], 'func' => $this->getFunc('column_add', $name . '-' . $this->config['column']['add'], 101));
+            }
+            if (isset($this->config['column']['edit'])) {
+                $data['column']['edit'] = array('name' => '编辑', 'func' => $this->getFunc('column_edit', $name . '-编辑', 102));
+            }
+            if (isset($this->config['column']['delete'])) {
+                $data['column']['delete'] = array('name' => '删除', 'func' => $this->getFunc('column_delete', $name . '-删除', 103));
+            }
+            $data['column']['data'] = Dever::call($this->config['column']['data']);
+            $data['height'] = '100%';
+        }
+    }
+
+    # 通用的规则验证 一般为更新数据时使用
+    protected function checkRules($set, $data)
+    {
+        if ($set['rules']) {
+            foreach ($set['rules'] as $k => $v) {
+                if (isset($v['required']) && $v['required'] && !$data && $data !== 0) {
+                    Dever::error($v['message']);
+                }
+                if ($data || $data === 0) {
+                    if (isset($v['pattern']) && $v['pattern'] && !preg_match('/' . $v['pattern'] . '/', $data)) {
+                        Dever::error($v['message']);
+                    }
+                    if (isset($v['type']) && $v['type']) {
+                        if ($v['type'] == 'number' && !is_numeric($data)) {
+                            Dever::error($v['message']);
+                        } elseif ($v['type'] == 'array' && !is_array($data)) {
+                            Dever::error($v['message']);
+                        } elseif ($v['type'] == 'integer' && !is_int($data)) {
+                            Dever::error($v['message']);
+                        } elseif ($v['type'] == 'float' && !is_float($data)) {
+                            Dever::error($v['message']);
+                        } elseif ($v['type'] == 'string' && !is_string($data)) {
+                            Dever::error($v['message']);
+                        } elseif ($v['type'] == 'boolean' && !is_bool($data)) {
+                            Dever::error($v['message']);
+                        } elseif ($v['type'] == 'url' && !filter_var($data, FILTER_VALIDATE_URL)) {
+                            Dever::error($v['message']);
+                        } elseif ($v['type'] == 'email' && !filter_var($data, FILTER_VALIDATE_EMAIL)) {
+                            Dever::error($v['message']);
+                        } elseif ($v['type'] == 'enum' && isset($v['enum']) && !in_array($data, $v['enum'])) {
+                            Dever::error($v['message']);
+                        }
+                    }
+                    if (isset($v['len']) && $v['len'] && strlen($data) > $v['len']) {
+                        Dever::error($v['message']);
+                    }
+                    if (isset($v['min']) && $v['min'] && strlen($data) < $v['min']) {
+                        Dever::error($v['message']);
+                    }
+                    if (isset($v['max']) && $v['max'] && strlen($data) > $v['max']) {
+                        Dever::error($v['message']);
+                    }
                 }
             }
+        }
+    }
+
+    private function setData($setting, &$data, $field, $type, $disable)
+    {
+        $result = array();
+        foreach ($setting as $k => $v) {
             if (!is_array($v)) {
-                if (is_string($k) && isset($this->db->config['struct'][$k])) {
-                    $v = array('name' => $this->db->config['struct'][$k]['name'], 'type' => $v);
-                } else {
+                if (is_numeric($k)) {
                     $k = $v;
-                    $v = array();
+                    $v = $type;
+                }
+                if ($k == 'id') {
+                    $v = array('name' => 'ID', 'type' => $v);
+                } elseif ($k == 'cdate') {
+                    $v = array('name' => '创建时间', 'type' => $v);
+                } elseif(isset($this->db->config['struct'][$k])) {
+                    $v = array('name' => $this->db->config['struct'][$k]['name'], 'type' => $v);
                 }
             } else {
                 if (isset($v['only'])) {
@@ -61,35 +226,96 @@ class Page extends Auth
                     }
                 }
             }
-            $result[] = $this->data($data, $k, $v, $type, $disable);
+            if ($field) {
+                if (is_array($field)) {
+                    if (isset($field['field']) && !Dever::check($field['field'], $k)) {
+                        continue;
+                    }
+                    if (isset($field[$k])) {
+                        $v['default'] = $field[$k];
+                        $v['type'] = 'hidden'; 
+                    }
+                } elseif (!Dever::check($field, $k)) {
+                    continue;
+                }
+            }
+            $info = $this->setField($data, $k, $v, $field, $type, $disable);
+            if ($info) {
+                $result[] = $info;
+            }
         }
         return $result;
     }
 
-    private function data(&$data, $key, $value = array(), $type = 'show', $disable = false)
+    private function setField(&$data, $key, $value = array(), $field, $type = 'show', $disable = false)
     {
         $value['key'] = $key;
         $this->setName($value);
-        $this->setType($value, $type);
-        $this->setDisable($value, $disable);
-        if ($type != 'show') {
-            # 一般为更新页面需要的参数
+        # 对每个字段进行权限设置
+        if (isset($value['func']) && $value['func']) {
+            $func = $this->getFunc('field_' . $value['key'], '字段-' . $value['name'], 200);
+            if (!$func) {
+                return false;
+            }
+        }
+        if (strpos($key, '/') && $this->key == 'update') {
+            $this->setType($value, 'array');
+            $this->setShow($value);
+            $value['value'] = $this->getOther($key, $value['where'], $this->info);
+            $update = new \Manage\Api\Page\Update($key, -1);
+            $value['content'] = $update->get();
+            $data[] = $value;
+            return $value['name'];
+        } else {
+            $this->setType($value, $type);
+            $this->setDisable($value, $disable);
+            if ($this->key == 'update') {
+                # 一般为更新页面需要的参数
+                $this->setShow($value);
+                $this->setRules($value);
+            }
+            if ($type == 'show') {
+                $in = array('switch', 'select', 'input');
+                if (in_array($value['type'], $in)) {
+                    $value['func'] = $this->getFunc('list_edit_' . $value['key'], '列表更新-' . $value['name'], 104);
+                    if (!$value['func']) {
+                        $value['type'] = 'show';
+                        if (isset($value['show'])) {
+                            unset($value['show']);
+                        }
+                    }
+                }
+                if (isset($value['child'])) {
+                    $child = array();
+                    $this->setData($value['child'], $child, $field, $type, $disable);
+                    $value['child'] = $child;
+                } else {
+                    $this->field[$key] = $value;
+                }
+            }
             $this->setForm($value);
-            $this->setRules($value);
+            $data[] = $value;
+            return $value['name'];
+        }
+    }
+
+    private function setShow(&$value)
+    {
+        if ($value['type'] == 'hidden') {
+            $value['show'] = false;
+        } elseif (empty($value['show'])) {
+            $value['show'] = true;
         }
-        $data[] = $value;
-        return $value['name'];
     }
 
     private function setName(&$value)
     {
-        if ($value['key'] == 'id') {
-            $value['name'] = 'id';
-        } elseif ($value['key'] == 'cdate') {
-            $value['name'] = '创建时间';
-        } elseif (empty($value['name'])) {
+        if (empty($value['name']) && isset($this->db->config['struct'][$value['key']])) {
             $value['name'] = $this->db->config['struct'][$value['key']]['name'];
         }
+        if (empty($value['placeholder'])) {
+            $value['placeholder'] = $value['name'];
+        }
     }
 
     private function setType(&$value, $type)
@@ -113,6 +339,13 @@ class Page extends Auth
     private function setForm(&$value)
     {
         $value['value'] = Dever::input('search')[$value['key']] ?? '';
+        if (!$value['value']) {
+            if (isset($value['default'])) {
+                $value['value'] = $value['default'];
+            } elseif ($this->key == 'update' && isset($this->db->config['struct'][$value['key']]['default'])) {
+                $value['value'] = $this->db->config['struct'][$value['key']]['default'];
+            }
+        }
         if ($option = $this->db->value($value['key'])) {
             if ($value['type'] == 'checkbox') {
                 $value['value'] = $value['value'] ? explode(',', $value['value']) : array();
@@ -143,49 +376,4 @@ class Page extends Auth
             }
         }
     }
-
-    # 通用的规则验证 一般为更新数据时使用
-    protected function checkRules($set, $data)
-    {
-        if ($set['rules']) {
-            foreach ($set['rules'] as $k => $v) {
-                if (isset($v['required']) && $v['required'] && !$data && $data !== 0) {
-                    Dever::error($v['message']);
-                }
-                if (isset($v['pattern']) && $v['pattern'] && $data && !preg_match('/' . $v['pattern'] . '/', $data)) {
-                    Dever::error($v['message']);
-                }
-                if (isset($v['type']) && $v['type']) {
-                    if ($v['type'] == 'number' && !is_numeric($data)) {
-                        Dever::error($v['message']);
-                    } elseif ($v['type'] == 'array' && !is_array($data)) {
-                        Dever::error($v['message']);
-                    } elseif ($v['type'] == 'integer' && !is_int($data)) {
-                        Dever::error($v['message']);
-                    } elseif ($v['type'] == 'float' && !is_float($data)) {
-                        Dever::error($v['message']);
-                    } elseif ($v['type'] == 'string' && !is_string($data)) {
-                        Dever::error($v['message']);
-                    } elseif ($v['type'] == 'boolean' && !is_bool($data)) {
-                        Dever::error($v['message']);
-                    } elseif ($v['type'] == 'url' && !filter_var($data, FILTER_VALIDATE_URL)) {
-                        Dever::error($v['message']);
-                    } elseif ($v['type'] == 'email' && !filter_var($data, FILTER_VALIDATE_EMAIL)) {
-                        Dever::error($v['message']);
-                    } elseif ($v['type'] == 'enum' && isset($v['enum']) && !in_array($data, $v['enum'])) {
-                        Dever::error($v['message']);
-                    }
-                }
-                if (isset($v['len']) && $v['len'] && strlen($data) > $v['len']) {
-                    Dever::error($v['message']);
-                }
-                if (isset($v['min']) && $v['min'] && strlen($data) < $v['min']) {
-                    Dever::error($v['message']);
-                }
-                if (isset($v['max']) && $v['max'] && strlen($data) > $v['max']) {
-                    Dever::error($v['message']);
-                }
-            }
-        }
-    }
 }

+ 29 - 0
lib/Recycler.php

@@ -0,0 +1,29 @@
+<?php namespace Manage\Lib;
+use Dever;
+class Recycler extends Auth
+{
+    # 获取后台展示需要的数据
+    public function getData($where)
+    {
+        if (empty($where['table'])) {
+            Dever::error('参数错误');
+        }
+        $data['head'] = $data['body'] = array();
+        $page = new Page('list', $where['table']);
+        $data['title'] = $page->getTitle() . '【回收站】';
+        $data['field'] = $page->setting('field', $data['head']);
+
+        $set['num'] = Dever::input('pgnum', '', '', 10);
+        $recycler = Dever::db('recycler')->select(array('table' => $where['table']), $set);
+        foreach ($recycler as $k => $v) {
+            $content = Dever::json_decode($v['content']);
+            foreach ($content as $key => $value) {
+                $content[$key] = $page->getValue($key, $value, $content);
+            }
+            $content['id'] = $v['id'];
+            $data['body'][] = $content;
+        }
+
+        return $data;
+    }
+}

+ 77 - 0
lib/Role.php

@@ -0,0 +1,77 @@
+<?php namespace Manage\Lib;
+use Dever;
+class Role extends Auth
+{
+    public function update($data)
+    {
+        if ($data['auth']) {
+            $auth = explode(',', $data['auth']);
+            $data['auth'] = array();
+            $system = $menu = $func = array();
+            foreach ($auth as $k => $v) {
+                if (!strstr($v, '-')) {
+                    if (strstr($v, 'v')) {
+                        $menu[] = trim($v, 'v');
+                    } else {
+                        $func[] = $v;
+                    }
+                    $data['auth'][] = $v;
+                }
+            }
+            if ($func) {
+                $funcData = Dever::db('menu_func')->select(array('id' => array('in', $func)), array('group' => 'menu_id'));
+                foreach ($funcData as $k => $v) {
+                    $menu[] = $v['menu_id'];
+                }
+                $menuData = Dever::db('menu')->select(array('id' => array('in', $menu)), array('group' => 'system_id'));
+                foreach ($menuData as $k => $v) {
+                    $system[] = $v['system_id'];
+                }
+            }
+            $data['auth'] = implode(',', $data['auth']);
+            $data['menu'] = implode(',', $menu);
+            $data['system'] = implode(',', $system);
+        }
+        return $data;
+    }
+
+    public function getAuthData()
+    {
+        $result = array();
+        $system = Dever::db('system')->select([]);
+        foreach ($system as $k => $v) {
+            $result[$k]['value'] = 's-' . $v['id'];
+            $result[$k]['label'] = $v['name'];
+            $result[$k]['children'] = Dever::db('menu')->tree(array('system_id' => $v['id']), array('parent_id', '0', 'id'), array($this, 'getAuthInfo'), array('col' => 'id,name as label,parent_id,`key`,func'));
+        }
+        return $result;
+    }
+    public function getAuthInfo($info)
+    {
+        if ($info['func'] == 1) {
+            $info['value'] = 'm-' . $info['id'];
+            $info['children'] = Dever::db('menu_func')->select(array('menu_id' => $info['id']), array('col' => 'id as value,name as label'))->fetchAll();
+            if (!$info['children']) {
+                return array();
+            }
+        } else {
+            $info['value'] = 'v' . $info['id'];
+        }
+        return $info;
+    }
+    # 展示系统
+    public function showSystem($data)
+    {
+        return Dever::db('system')->show(array('id' => array('in', $data)));
+    }
+    # 展示菜单
+    public function showMenu($data)
+    {
+        return Dever::db('menu')->show(array('id' => array('in', $data)));
+    }
+    # 展示权限
+    public function showFunc($data)
+    {
+        return Dever::db('menu_func')->show(array('id' => array('in', $data)));
+    }
+}

+ 18 - 0
lib/System.php

@@ -0,0 +1,18 @@
+<?php namespace Manage\Lib;
+use Dever;
+use Dever\Project;
+class System extends Auth
+{
+    public function getTree()
+    {
+        $data = Dever::db('system')->select([])->fetchAll();
+        $result = array();
+        $result[] = array
+        (
+            'id' => 'root',
+            'name' => '全部系统',
+            'children' => $data,
+        );
+        return $result;
+    }
+}

+ 17 - 1
table/admin.php

@@ -1,7 +1,7 @@
 <?php
 return array
 (
-    'name' => '管理员',
+    'name' => '平台管理员',
     'struct' => array
     (
         'name' => array
@@ -36,11 +36,27 @@ return array
             'value'    => array(1 => 'a', 2 => 'b'),//直接设置可选项
             */
         ),
+        'system_relation' => array
+        (
+            'name'      => '关联子系统',
+            'type'      => 'varchar(2000)',
+        ),
         'avatar' => array
         (
             'name'      => '头像',
             'type'      => 'varchar(300)',
         ),
+        'status' => array
+        (
+            'name'      => '状态',
+            'type'      => 'tinyint(1)',
+            'default'   => 1,
+            'value'     => array
+            (
+                1 => '正常',
+                2 => '封禁',
+            ),
+        ),
     ),
     'index' => array
     (

+ 23 - 0
table/config.php

@@ -0,0 +1,23 @@
+<?php
+return array
+(
+    'name' => '基础配置',
+    'struct' => array
+    (
+        'name' => array
+        (
+            'name'      => '配置名称',
+            'type'      => 'varchar(32)',
+        ),
+    ),
+
+    'default' => array
+    (
+        'field' => 'id,name',
+        'value' => array
+        (
+            '1,"默认配置"',
+        ),
+        'num' => 1,
+    ),
+);

+ 45 - 0
table/group.php

@@ -0,0 +1,45 @@
+<?php
+return array
+(
+    'name' => '集团',
+    'order' => 'sort asc',
+    'struct' => array
+    (
+        'name' => array
+        (
+            'name'      => '集团名称',
+            'type'      => 'varchar(200)',
+        ),
+        'mobile' => array
+        (
+            'name'      => '手机号',
+            'type'      => 'varchar(11)',
+        ),
+        'sort' => array
+        (
+            'name'      => '排序',
+            'type'      => 'int(11)',
+            'default'   => '1',
+        ),
+        'status' => array
+        (
+            'name'      => '状态',
+            'type'      => 'tinyint(1)',
+            'default'   => 1,
+            'value'     => array
+            (
+                1 => '启用',
+                2 => '关闭',
+            ),
+        ),
+    ),
+    'default' => array
+    (
+        'field' => 'name,sort,cdate',
+        'value' => array
+        (
+            '"默认集团",-100,' . DEVER_TIME,
+        ),
+        'num' => 1,
+    ),
+);

+ 43 - 0
table/group_org.php

@@ -0,0 +1,43 @@
+<?php
+return array
+(
+    'name' => '集团组织',
+    'partition' => array
+    (
+        'database' => 'Dever::call("manage/common.system")',
+    ),
+    'order' => 'sort asc',
+    'struct' => array
+    (
+        'name' => array
+        (
+            'name'      => '组织名称',
+            'type'      => 'varchar(200)',
+        ),
+        'sort' => array
+        (
+            'name'      => '排序',
+            'type'      => 'int(11)',
+            'default'   => '1',
+        ),
+        'status' => array
+        (
+            'name'      => '状态',
+            'type'      => 'tinyint(1)',
+            'default'   => 1,
+            'value'     => array
+            (
+                1 => '启用',
+                2 => '关闭',
+            ),
+        ),
+    ),
+    'default' => array
+    (
+        'field' => 'name,cdate',
+        'value' => array
+        (
+            '"默认组织",' . DEVER_TIME,
+        ),
+    ),
+);

+ 37 - 0
table/group_org_job.php

@@ -0,0 +1,37 @@
+<?php
+return array
+(
+    'name' => '组织职位',
+    'partition' => array
+    (
+        'database' => 'Dever::call("manage/common.system")',
+    ),
+    'order' => 'sort asc',
+    'struct' => array
+    (
+        'org_id'      => array
+        (
+            'name'      => '组织',
+            'type'      => 'int(11)',
+        ),
+        'name' => array
+        (
+            'name'      => '职位名称',
+            'type'      => 'varchar(100)',
+        ),
+        'sort' => array
+        (
+            'name'      => '排序',
+            'type'      => 'int(11)',
+            'default'   => '1',
+        ),
+    ),
+    'default' => array
+    (
+        'field' => 'name,org_id,cdate',
+        'value' => array
+        (
+            '"默认职位",1,' . DEVER_TIME,
+        ),
+    ),
+);

+ 42 - 0
table/group_role.php

@@ -0,0 +1,42 @@
+<?php
+return array
+(
+    'name' => '集团角色',
+    'partition' => array
+    (
+        'database' => 'Dever::call("manage/common.system")',
+    ),
+    'struct' => array
+    (
+        'name' => array
+        (
+            'name'      => '名称',
+            'type'      => 'varchar(32)',
+        ),
+        'system' => array
+        (
+            'name'      => '系统',
+            'type'      => 'varchar(1000)',
+        ),
+        'menu' => array
+        (
+            'name'      => '菜单',
+            'type'      => 'varchar(2000)',
+        ),
+        'auth' => array
+        (
+            'name'      => '权限',
+            'type'      => 'text',
+            'value'    => 'Dever::load("role.getAuthData")',
+        ),
+    ),
+    'default' => array
+    (
+        'field' => 'name,cdate',
+        'value' => array
+        (
+            '"默认角色",' . DEVER_TIME,
+        ),
+        'num' => 1,
+    ),
+);

+ 64 - 0
table/group_user.php

@@ -0,0 +1,64 @@
+<?php
+return array
+(
+    'name' => '集团账户',
+    # 定义数据分离
+    'partition' => array
+    (
+        'database' => 'Dever::call("manage/common.system")',
+    ),
+    'struct' => array
+    (
+        'name' => array
+        (
+            'name'      => '姓名',
+            'type'      => 'varchar(32)',
+        ),
+        'mobile' => array
+        (
+            'name'      => '手机号',
+            'type'      => 'varchar(11)',
+        ),
+        'password' => array
+        (
+            'name'      => '密码',
+            'type'      => 'varchar(64)',
+        ),
+        'salt' => array
+        (
+            'name'      => '密码salt',
+            'type'      => 'varchar(32)',
+        ),
+        'role' => array
+        (
+            'name'      => '角色',
+            'type'      => 'varchar(100)',
+            'value'    => 'group_role',
+        ),
+        'system_relation' => array
+        (
+            'name'      => '关联子系统',
+            'type'      => 'varchar(2000)',
+        ),
+        'avatar' => array
+        (
+            'name'      => '头像',
+            'type'      => 'varchar(300)',
+        ),
+        'status' => array
+        (
+            'name'      => '状态',
+            'type'      => 'tinyint(1)',
+            'default'   => 1,
+            'value'     => array
+            (
+                1 => '正常',
+                2 => '封禁',
+            ),
+        ),
+    ),
+    'index' => array
+    (
+        'mobile' => 'mobile.unique',
+    ),
+);

+ 2290 - 0
table/icon.php

@@ -0,0 +1,2290 @@
+<?php
+return array
+(
+    'name' => 'icon',
+    'struct' => array
+    (
+        'key' => array
+        (
+            'name'      => 'icon',
+            'type'      => 'varchar(100)',
+        ),
+    ),
+
+    'default' => array
+    (
+        'field' => '`key`',
+        'value' => array
+        (
+            '"24-hours-fill"',
+            '"24-hours-line"',
+            '"4k-fill"',
+            '"4k-line"',
+            '"a-b"',
+            '"account-box-fill"',
+            '"account-box-line"',
+            '"account-circle-fill"',
+            '"account-circle-line"',
+            '"account-pin-box-fill"',
+            '"account-pin-box-line"',
+            '"account-pin-circle-fill"',
+            '"account-pin-circle-line"',
+            '"add-box-fill"',
+            '"add-box-line"',
+            '"add-circle-fill"',
+            '"add-circle-line"',
+            '"add-fill"',
+            '"add-line"',
+            '"admin-fill"',
+            '"admin-line"',
+            '"airplay-fill"',
+            '"airplay-line"',
+            '"alarm-fill"',
+            '"alarm-line"',
+            '"alarm-warning-fill"',
+            '"alarm-warning-line"',
+            '"album-fill"',
+            '"album-line"',
+            '"alert-fill"',
+            '"alert-line"',
+            '"aliens-fill"',
+            '"aliens-line"',
+            '"align-bottom"',
+            '"align-center"',
+            '"align-justify"',
+            '"align-left"',
+            '"align-right"',
+            '"align-top"',
+            '"align-vertically"',
+            '"alipay-fill"',
+            '"alipay-line"',
+            '"amazon-fill"',
+            '"amazon-line"',
+            '"anchor-fill"',
+            '"anchor-line"',
+            '"ancient-gate-fill"',
+            '"ancient-gate-line"',
+            '"ancient-pavilion-fill"',
+            '"ancient-pavilion-line"',
+            '"android-fill"',
+            '"android-line"',
+            '"angularjs-fill"',
+            '"angularjs-line"',
+            '"anticlockwise-2-fill"',
+            '"anticlockwise-2-line"',
+            '"anticlockwise-fill"',
+            '"anticlockwise-line"',
+            '"app-store-fill"',
+            '"app-store-line"',
+            '"apple-fill"',
+            '"apple-line"',
+            '"apps-2-fill"',
+            '"apps-2-line"',
+            '"apps-fill"',
+            '"apps-line"',
+            '"archive-drawer-fill"',
+            '"archive-drawer-line"',
+            '"archive-fill"',
+            '"archive-line"',
+            '"arrow-down-circle-fill"',
+            '"arrow-down-circle-line"',
+            '"arrow-down-fill"',
+            '"arrow-down-line"',
+            '"arrow-down-s-fill"',
+            '"arrow-down-s-line"',
+            '"arrow-drop-down-fill"',
+            '"arrow-drop-down-line"',
+            '"arrow-drop-left-fill"',
+            '"arrow-drop-left-line"',
+            '"arrow-drop-right-fill"',
+            '"arrow-drop-right-line"',
+            '"arrow-drop-up-fill"',
+            '"arrow-drop-up-line"',
+            '"arrow-go-back-fill"',
+            '"arrow-go-back-line"',
+            '"arrow-go-forward-fill"',
+            '"arrow-go-forward-line"',
+            '"arrow-left-circle-fill"',
+            '"arrow-left-circle-line"',
+            '"arrow-left-down-fill"',
+            '"arrow-left-down-line"',
+            '"arrow-left-fill"',
+            '"arrow-left-line"',
+            '"arrow-left-right-fill"',
+            '"arrow-left-right-line"',
+            '"arrow-left-s-fill"',
+            '"arrow-left-s-line"',
+            '"arrow-left-up-fill"',
+            '"arrow-left-up-line"',
+            '"arrow-right-circle-fill"',
+            '"arrow-right-circle-line"',
+            '"arrow-right-down-fill"',
+            '"arrow-right-down-line"',
+            '"arrow-right-fill"',
+            '"arrow-right-line"',
+            '"arrow-right-s-fill"',
+            '"arrow-right-s-line"',
+            '"arrow-right-up-fill"',
+            '"arrow-right-up-line"',
+            '"arrow-up-circle-fill"',
+            '"arrow-up-circle-line"',
+            '"arrow-up-down-fill"',
+            '"arrow-up-down-line"',
+            '"arrow-up-fill"',
+            '"arrow-up-line"',
+            '"arrow-up-s-fill"',
+            '"arrow-up-s-line"',
+            '"artboard-2-fill"',
+            '"artboard-2-line"',
+            '"artboard-fill"',
+            '"artboard-line"',
+            '"article-fill"',
+            '"article-line"',
+            '"aspect-ratio-fill"',
+            '"aspect-ratio-line"',
+            '"asterisk"',
+            '"at-fill"',
+            '"at-line"',
+            '"attachment-2"',
+            '"attachment-fill"',
+            '"attachment-line"',
+            '"auction-fill"',
+            '"auction-line"',
+            '"award-fill"',
+            '"award-line"',
+            '"baidu-fill"',
+            '"baidu-line"',
+            '"ball-pen-fill"',
+            '"ball-pen-line"',
+            '"bank-card-2-fill"',
+            '"bank-card-2-line"',
+            '"bank-card-fill"',
+            '"bank-card-line"',
+            '"bank-fill"',
+            '"bank-line"',
+            '"bar-chart-2-fill"',
+            '"bar-chart-2-line"',
+            '"bar-chart-box-fill"',
+            '"bar-chart-box-line"',
+            '"bar-chart-fill"',
+            '"bar-chart-grouped-fill"',
+            '"bar-chart-grouped-line"',
+            '"bar-chart-horizontal-fill"',
+            '"bar-chart-horizontal-line"',
+            '"bar-chart-line"',
+            '"barcode-box-fill"',
+            '"barcode-box-line"',
+            '"barcode-fill"',
+            '"barcode-line"',
+            '"barricade-fill"',
+            '"barricade-line"',
+            '"base-station-fill"',
+            '"base-station-line"',
+            '"basketball-fill"',
+            '"basketball-line"',
+            '"battery-2-charge-fill"',
+            '"battery-2-charge-line"',
+            '"battery-2-fill"',
+            '"battery-2-line"',
+            '"battery-charge-fill"',
+            '"battery-charge-line"',
+            '"battery-fill"',
+            '"battery-line"',
+            '"battery-low-fill"',
+            '"battery-low-line"',
+            '"battery-saver-fill"',
+            '"battery-saver-line"',
+            '"battery-share-fill"',
+            '"battery-share-line"',
+            '"bear-smile-fill"',
+            '"bear-smile-line"',
+            '"behance-fill"',
+            '"behance-line"',
+            '"bell-fill"',
+            '"bell-line"',
+            '"bike-fill"',
+            '"bike-line"',
+            '"bilibili-fill"',
+            '"bilibili-line"',
+            '"bill-fill"',
+            '"bill-line"',
+            '"billiards-fill"',
+            '"billiards-line"',
+            '"bit-coin-fill"',
+            '"bit-coin-line"',
+            '"blaze-fill"',
+            '"blaze-line"',
+            '"bluetooth-connect-fill"',
+            '"bluetooth-connect-line"',
+            '"bluetooth-fill"',
+            '"bluetooth-line"',
+            '"blur-off-fill"',
+            '"blur-off-line"',
+            '"body-scan-fill"',
+            '"body-scan-line"',
+            '"bold"',
+            '"book-2-fill"',
+            '"book-2-line"',
+            '"book-3-fill"',
+            '"book-3-line"',
+            '"book-fill"',
+            '"book-line"',
+            '"book-mark-fill"',
+            '"book-mark-line"',
+            '"book-open-fill"',
+            '"book-open-line"',
+            '"book-read-fill"',
+            '"book-read-line"',
+            '"booklet-fill"',
+            '"booklet-line"',
+            '"bookmark-2-fill"',
+            '"bookmark-2-line"',
+            '"bookmark-3-fill"',
+            '"bookmark-3-line"',
+            '"bookmark-fill"',
+            '"bookmark-line"',
+            '"boxing-fill"',
+            '"boxing-line"',
+            '"braces-fill"',
+            '"braces-line"',
+            '"brackets-fill"',
+            '"brackets-line"',
+            '"briefcase-2-fill"',
+            '"briefcase-2-line"',
+            '"briefcase-3-fill"',
+            '"briefcase-3-line"',
+            '"briefcase-4-fill"',
+            '"briefcase-4-line"',
+            '"briefcase-5-fill"',
+            '"briefcase-5-line"',
+            '"briefcase-fill"',
+            '"briefcase-line"',
+            '"bring-forward"',
+            '"bring-to-front"',
+            '"broadcast-fill"',
+            '"broadcast-line"',
+            '"brush-2-fill"',
+            '"brush-2-line"',
+            '"brush-3-fill"',
+            '"brush-3-line"',
+            '"brush-4-fill"',
+            '"brush-4-line"',
+            '"brush-fill"',
+            '"brush-line"',
+            '"bubble-chart-fill"',
+            '"bubble-chart-line"',
+            '"bug-2-fill"',
+            '"bug-2-line"',
+            '"bug-fill"',
+            '"bug-line"',
+            '"building-2-fill"',
+            '"building-2-line"',
+            '"building-3-fill"',
+            '"building-3-line"',
+            '"building-4-fill"',
+            '"building-4-line"',
+            '"building-fill"',
+            '"building-line"',
+            '"bus-2-fill"',
+            '"bus-2-line"',
+            '"bus-fill"',
+            '"bus-line"',
+            '"bus-wifi-fill"',
+            '"bus-wifi-line"',
+            '"cactus-fill"',
+            '"cactus-line"',
+            '"cake-2-fill"',
+            '"cake-2-line"',
+            '"cake-3-fill"',
+            '"cake-3-line"',
+            '"cake-fill"',
+            '"cake-line"',
+            '"calculator-fill"',
+            '"calculator-line"',
+            '"calendar-2-fill"',
+            '"calendar-2-line"',
+            '"calendar-check-fill"',
+            '"calendar-check-line"',
+            '"calendar-event-fill"',
+            '"calendar-event-line"',
+            '"calendar-fill"',
+            '"calendar-line"',
+            '"calendar-todo-fill"',
+            '"calendar-todo-line"',
+            '"camera-2-fill"',
+            '"camera-2-line"',
+            '"camera-3-fill"',
+            '"camera-3-line"',
+            '"camera-fill"',
+            '"camera-lens-fill"',
+            '"camera-lens-line"',
+            '"camera-line"',
+            '"camera-off-fill"',
+            '"camera-off-line"',
+            '"camera-switch-fill"',
+            '"camera-switch-line"',
+            '"capsule-fill"',
+            '"capsule-line"',
+            '"car-fill"',
+            '"car-line"',
+            '"car-washing-fill"',
+            '"car-washing-line"',
+            '"caravan-fill"',
+            '"caravan-line"',
+            '"cast-fill"',
+            '"cast-line"',
+            '"cellphone-fill"',
+            '"cellphone-line"',
+            '"celsius-fill"',
+            '"celsius-line"',
+            '"centos-fill"',
+            '"centos-line"',
+            '"character-recognition-fill"',
+            '"character-recognition-line"',
+            '"charging-pile-2-fill"',
+            '"charging-pile-2-line"',
+            '"charging-pile-fill"',
+            '"charging-pile-line"',
+            '"chat-1-fill"',
+            '"chat-1-line"',
+            '"chat-2-fill"',
+            '"chat-2-line"',
+            '"chat-3-fill"',
+            '"chat-3-line"',
+            '"chat-4-fill"',
+            '"chat-4-line"',
+            '"chat-check-fill"',
+            '"chat-check-line"',
+            '"chat-delete-fill"',
+            '"chat-delete-line"',
+            '"chat-download-fill"',
+            '"chat-download-line"',
+            '"chat-follow-up-fill"',
+            '"chat-follow-up-line"',
+            '"chat-forward-fill"',
+            '"chat-forward-line"',
+            '"chat-heart-fill"',
+            '"chat-heart-line"',
+            '"chat-history-fill"',
+            '"chat-history-line"',
+            '"chat-new-fill"',
+            '"chat-new-line"',
+            '"chat-off-fill"',
+            '"chat-off-line"',
+            '"chat-poll-fill"',
+            '"chat-poll-line"',
+            '"chat-private-fill"',
+            '"chat-private-line"',
+            '"chat-quote-fill"',
+            '"chat-quote-line"',
+            '"chat-settings-fill"',
+            '"chat-settings-line"',
+            '"chat-smile-2-fill"',
+            '"chat-smile-2-line"',
+            '"chat-smile-3-fill"',
+            '"chat-smile-3-line"',
+            '"chat-smile-fill"',
+            '"chat-smile-line"',
+            '"chat-upload-fill"',
+            '"chat-upload-line"',
+            '"chat-voice-fill"',
+            '"chat-voice-line"',
+            '"check-double-fill"',
+            '"check-double-line"',
+            '"check-fill"',
+            '"check-line"',
+            '"checkbox-blank-circle-fill"',
+            '"checkbox-blank-circle-line"',
+            '"checkbox-blank-fill"',
+            '"checkbox-blank-line"',
+            '"checkbox-circle-fill"',
+            '"checkbox-circle-line"',
+            '"checkbox-fill"',
+            '"checkbox-indeterminate-fill"',
+            '"checkbox-indeterminate-line"',
+            '"checkbox-line"',
+            '"checkbox-multiple-blank-fill"',
+            '"checkbox-multiple-blank-line"',
+            '"checkbox-multiple-fill"',
+            '"checkbox-multiple-line"',
+            '"china-railway-fill"',
+            '"china-railway-line"',
+            '"chrome-fill"',
+            '"chrome-line"',
+            '"clapperboard-fill"',
+            '"clapperboard-line"',
+            '"clipboard-fill"',
+            '"clipboard-line"',
+            '"clockwise-2-fill"',
+            '"clockwise-2-line"',
+            '"clockwise-fill"',
+            '"clockwise-line"',
+            '"close-circle-fill"',
+            '"close-circle-line"',
+            '"close-fill"',
+            '"close-line"',
+            '"closed-captioning-fill"',
+            '"closed-captioning-line"',
+            '"cloud-fill"',
+            '"cloud-line"',
+            '"cloud-off-fill"',
+            '"cloud-off-line"',
+            '"cloud-windy-fill"',
+            '"cloud-windy-line"',
+            '"cloudy-2-fill"',
+            '"cloudy-2-line"',
+            '"cloudy-fill"',
+            '"cloudy-line"',
+            '"code-box-fill"',
+            '"code-box-line"',
+            '"code-fill"',
+            '"code-line"',
+            '"code-s-fill"',
+            '"code-s-line"',
+            '"code-s-slash-fill"',
+            '"code-s-slash-line"',
+            '"code-view"',
+            '"codepen-fill"',
+            '"codepen-line"',
+            '"coin-fill"',
+            '"coin-line"',
+            '"coins-fill"',
+            '"coins-line"',
+            '"collage-fill"',
+            '"collage-line"',
+            '"command-fill"',
+            '"command-line"',
+            '"community-fill"',
+            '"community-line"',
+            '"compass-2-fill"',
+            '"compass-2-line"',
+            '"compass-3-fill"',
+            '"compass-3-line"',
+            '"compass-4-fill"',
+            '"compass-4-line"',
+            '"compass-discover-fill"',
+            '"compass-discover-line"',
+            '"compass-fill"',
+            '"compass-line"',
+            '"compasses-2-fill"',
+            '"compasses-2-line"',
+            '"compasses-fill"',
+            '"compasses-line"',
+            '"computer-fill"',
+            '"computer-line"',
+            '"contacts-book-2-fill"',
+            '"contacts-book-2-line"',
+            '"contacts-book-fill"',
+            '"contacts-book-line"',
+            '"contacts-book-upload-fill"',
+            '"contacts-book-upload-line"',
+            '"contacts-fill"',
+            '"contacts-line"',
+            '"contrast-2-fill"',
+            '"contrast-2-line"',
+            '"contrast-drop-2-fill"',
+            '"contrast-drop-2-line"',
+            '"contrast-drop-fill"',
+            '"contrast-drop-line"',
+            '"contrast-fill"',
+            '"contrast-line"',
+            '"copper-coin-fill"',
+            '"copper-coin-line"',
+            '"copper-diamond-fill"',
+            '"copper-diamond-line"',
+            '"copyleft-fill"',
+            '"copyleft-line"',
+            '"copyright-fill"',
+            '"copyright-line"',
+            '"coreos-fill"',
+            '"coreos-line"',
+            '"coupon-2-fill"',
+            '"coupon-2-line"',
+            '"coupon-3-fill"',
+            '"coupon-3-line"',
+            '"coupon-4-fill"',
+            '"coupon-4-line"',
+            '"coupon-5-fill"',
+            '"coupon-5-line"',
+            '"coupon-fill"',
+            '"coupon-line"',
+            '"cpu-fill"',
+            '"cpu-line"',
+            '"creative-commons-by-fill"',
+            '"creative-commons-by-line"',
+            '"creative-commons-fill"',
+            '"creative-commons-line"',
+            '"creative-commons-nc-fill"',
+            '"creative-commons-nc-line"',
+            '"creative-commons-nd-fill"',
+            '"creative-commons-nd-line"',
+            '"creative-commons-sa-fill"',
+            '"creative-commons-sa-line"',
+            '"creative-commons-zero-fill"',
+            '"creative-commons-zero-line"',
+            '"criminal-fill"',
+            '"criminal-line"',
+            '"crop-2-fill"',
+            '"crop-2-line"',
+            '"crop-fill"',
+            '"crop-line"',
+            '"css3-fill"',
+            '"css3-line"',
+            '"cup-fill"',
+            '"cup-line"',
+            '"currency-fill"',
+            '"currency-line"',
+            '"cursor-fill"',
+            '"cursor-line"',
+            '"customer-service-2-fill"',
+            '"customer-service-2-line"',
+            '"customer-service-fill"',
+            '"customer-service-line"',
+            '"dashboard-2-fill"',
+            '"dashboard-2-line"',
+            '"dashboard-3-fill"',
+            '"dashboard-3-line"',
+            '"dashboard-fill"',
+            '"dashboard-line"',
+            '"database-2-fill"',
+            '"database-2-line"',
+            '"database-fill"',
+            '"database-line"',
+            '"delete-back-2-fill"',
+            '"delete-back-2-line"',
+            '"delete-back-fill"',
+            '"delete-back-line"',
+            '"delete-bin-2-fill"',
+            '"delete-bin-2-line"',
+            '"delete-bin-3-fill"',
+            '"delete-bin-3-line"',
+            '"delete-bin-4-fill"',
+            '"delete-bin-4-line"',
+            '"delete-bin-5-fill"',
+            '"delete-bin-5-line"',
+            '"delete-bin-6-fill"',
+            '"delete-bin-6-line"',
+            '"delete-bin-7-fill"',
+            '"delete-bin-7-line"',
+            '"delete-bin-fill"',
+            '"delete-bin-line"',
+            '"delete-column"',
+            '"delete-row"',
+            '"device-fill"',
+            '"device-line"',
+            '"device-recover-fill"',
+            '"device-recover-line"',
+            '"dingding-fill"',
+            '"dingding-line"',
+            '"direction-fill"',
+            '"direction-line"',
+            '"disc-fill"',
+            '"disc-line"',
+            '"discord-fill"',
+            '"discord-line"',
+            '"discuss-fill"',
+            '"discuss-line"',
+            '"dislike-fill"',
+            '"dislike-line"',
+            '"disqus-fill"',
+            '"disqus-line"',
+            '"divide-fill"',
+            '"divide-line"',
+            '"donut-chart-fill"',
+            '"donut-chart-line"',
+            '"door-closed-fill"',
+            '"door-closed-line"',
+            '"door-fill"',
+            '"door-line"',
+            '"door-lock-box-fill"',
+            '"door-lock-box-line"',
+            '"door-lock-fill"',
+            '"door-lock-line"',
+            '"door-open-fill"',
+            '"door-open-line"',
+            '"dossier-fill"',
+            '"dossier-line"',
+            '"douban-fill"',
+            '"douban-line"',
+            '"double-quotes-l"',
+            '"double-quotes-r"',
+            '"download-2-fill"',
+            '"download-2-line"',
+            '"download-cloud-2-fill"',
+            '"download-cloud-2-line"',
+            '"download-cloud-fill"',
+            '"download-cloud-line"',
+            '"download-fill"',
+            '"download-line"',
+            '"draft-fill"',
+            '"draft-line"',
+            '"drag-drop-fill"',
+            '"drag-drop-line"',
+            '"drag-move-2-fill"',
+            '"drag-move-2-line"',
+            '"drag-move-fill"',
+            '"drag-move-line"',
+            '"dribbble-fill"',
+            '"dribbble-line"',
+            '"drive-fill"',
+            '"drive-line"',
+            '"drizzle-fill"',
+            '"drizzle-line"',
+            '"drop-fill"',
+            '"drop-line"',
+            '"dropbox-fill"',
+            '"dropbox-line"',
+            '"dual-sim-1-fill"',
+            '"dual-sim-1-line"',
+            '"dual-sim-2-fill"',
+            '"dual-sim-2-line"',
+            '"dv-fill"',
+            '"dv-line"',
+            '"dvd-fill"',
+            '"dvd-line"',
+            '"e-bike-2-fill"',
+            '"e-bike-2-line"',
+            '"e-bike-fill"',
+            '"e-bike-line"',
+            '"earth-fill"',
+            '"earth-line"',
+            '"earthquake-fill"',
+            '"earthquake-line"',
+            '"edge-fill"',
+            '"edge-line"',
+            '"edit-2-fill"',
+            '"edit-2-line"',
+            '"edit-box-fill"',
+            '"edit-box-line"',
+            '"edit-circle-fill"',
+            '"edit-circle-line"',
+            '"edit-fill"',
+            '"edit-line"',
+            '"eject-fill"',
+            '"eject-line"',
+            '"emotion-2-fill"',
+            '"emotion-2-line"',
+            '"emotion-fill"',
+            '"emotion-happy-fill"',
+            '"emotion-happy-line"',
+            '"emotion-laugh-fill"',
+            '"emotion-laugh-line"',
+            '"emotion-line"',
+            '"emotion-normal-fill"',
+            '"emotion-normal-line"',
+            '"emotion-sad-fill"',
+            '"emotion-sad-line"',
+            '"emotion-unhappy-fill"',
+            '"emotion-unhappy-line"',
+            '"empathize-fill"',
+            '"empathize-line"',
+            '"emphasis-cn"',
+            '"emphasis"',
+            '"english-input"',
+            '"equalizer-fill"',
+            '"equalizer-line"',
+            '"eraser-fill"',
+            '"eraser-line"',
+            '"error-warning-fill"',
+            '"error-warning-line"',
+            '"evernote-fill"',
+            '"evernote-line"',
+            '"exchange-box-fill"',
+            '"exchange-box-line"',
+            '"exchange-cny-fill"',
+            '"exchange-cny-line"',
+            '"exchange-dollar-fill"',
+            '"exchange-dollar-line"',
+            '"exchange-fill"',
+            '"exchange-funds-fill"',
+            '"exchange-funds-line"',
+            '"exchange-line"',
+            '"external-link-fill"',
+            '"external-link-line"',
+            '"eye-2-fill"',
+            '"eye-2-line"',
+            '"eye-close-fill"',
+            '"eye-close-line"',
+            '"eye-fill"',
+            '"eye-line"',
+            '"eye-off-fill"',
+            '"eye-off-line"',
+            '"facebook-box-fill"',
+            '"facebook-box-line"',
+            '"facebook-circle-fill"',
+            '"facebook-circle-line"',
+            '"facebook-fill"',
+            '"facebook-line"',
+            '"fahrenheit-fill"',
+            '"fahrenheit-line"',
+            '"feedback-fill"',
+            '"feedback-line"',
+            '"file-2-fill"',
+            '"file-2-line"',
+            '"file-3-fill"',
+            '"file-3-line"',
+            '"file-4-fill"',
+            '"file-4-line"',
+            '"file-add-fill"',
+            '"file-add-line"',
+            '"file-chart-2-fill"',
+            '"file-chart-2-line"',
+            '"file-chart-fill"',
+            '"file-chart-line"',
+            '"file-cloud-fill"',
+            '"file-cloud-line"',
+            '"file-code-fill"',
+            '"file-code-line"',
+            '"file-copy-2-fill"',
+            '"file-copy-2-line"',
+            '"file-copy-fill"',
+            '"file-copy-line"',
+            '"file-damage-fill"',
+            '"file-damage-line"',
+            '"file-download-fill"',
+            '"file-download-line"',
+            '"file-edit-fill"',
+            '"file-edit-line"',
+            '"file-excel-2-fill"',
+            '"file-excel-2-line"',
+            '"file-excel-fill"',
+            '"file-excel-line"',
+            '"file-fill"',
+            '"file-forbid-fill"',
+            '"file-forbid-line"',
+            '"file-gif-fill"',
+            '"file-gif-line"',
+            '"file-history-fill"',
+            '"file-history-line"',
+            '"file-hwp-fill"',
+            '"file-hwp-line"',
+            '"file-info-fill"',
+            '"file-info-line"',
+            '"file-line"',
+            '"file-list-2-fill"',
+            '"file-list-2-line"',
+            '"file-list-3-fill"',
+            '"file-list-3-line"',
+            '"file-list-fill"',
+            '"file-list-line"',
+            '"file-lock-fill"',
+            '"file-lock-line"',
+            '"file-mark-fill"',
+            '"file-mark-line"',
+            '"file-music-fill"',
+            '"file-music-line"',
+            '"file-paper-2-fill"',
+            '"file-paper-2-line"',
+            '"file-paper-fill"',
+            '"file-paper-line"',
+            '"file-pdf-fill"',
+            '"file-pdf-line"',
+            '"file-ppt-2-fill"',
+            '"file-ppt-2-line"',
+            '"file-ppt-fill"',
+            '"file-ppt-line"',
+            '"file-reduce-fill"',
+            '"file-reduce-line"',
+            '"file-search-fill"',
+            '"file-search-line"',
+            '"file-settings-fill"',
+            '"file-settings-line"',
+            '"file-shield-2-fill"',
+            '"file-shield-2-line"',
+            '"file-shield-fill"',
+            '"file-shield-line"',
+            '"file-shred-fill"',
+            '"file-shred-line"',
+            '"file-text-fill"',
+            '"file-text-line"',
+            '"file-transfer-fill"',
+            '"file-transfer-line"',
+            '"file-unknow-fill"',
+            '"file-unknow-line"',
+            '"file-upload-fill"',
+            '"file-upload-line"',
+            '"file-user-fill"',
+            '"file-user-line"',
+            '"file-warning-fill"',
+            '"file-warning-line"',
+            '"file-word-2-fill"',
+            '"file-word-2-line"',
+            '"file-word-fill"',
+            '"file-word-line"',
+            '"file-zip-fill"',
+            '"file-zip-line"',
+            '"film-fill"',
+            '"film-line"',
+            '"filter-2-fill"',
+            '"filter-2-line"',
+            '"filter-3-fill"',
+            '"filter-3-line"',
+            '"filter-fill"',
+            '"filter-line"',
+            '"filter-off-fill"',
+            '"filter-off-line"',
+            '"find-replace-fill"',
+            '"find-replace-line"',
+            '"finder-fill"',
+            '"finder-line"',
+            '"fingerprint-2-fill"',
+            '"fingerprint-2-line"',
+            '"fingerprint-fill"',
+            '"fingerprint-line"',
+            '"fire-fill"',
+            '"fire-line"',
+            '"firefox-fill"',
+            '"firefox-line"',
+            '"first-aid-kit-fill"',
+            '"first-aid-kit-line"',
+            '"flag-2-fill"',
+            '"flag-2-line"',
+            '"flag-fill"',
+            '"flag-line"',
+            '"flashlight-fill"',
+            '"flashlight-line"',
+            '"flask-fill"',
+            '"flask-line"',
+            '"flight-land-fill"',
+            '"flight-land-line"',
+            '"flight-takeoff-fill"',
+            '"flight-takeoff-line"',
+            '"flood-fill"',
+            '"flood-line"',
+            '"flow-chart"',
+            '"flutter-fill"',
+            '"flutter-line"',
+            '"focus-2-fill"',
+            '"focus-2-line"',
+            '"focus-3-fill"',
+            '"focus-3-line"',
+            '"focus-fill"',
+            '"focus-line"',
+            '"foggy-fill"',
+            '"foggy-line"',
+            '"folder-2-fill"',
+            '"folder-2-line"',
+            '"folder-3-fill"',
+            '"folder-3-line"',
+            '"folder-4-fill"',
+            '"folder-4-line"',
+            '"folder-5-fill"',
+            '"folder-5-line"',
+            '"folder-add-fill"',
+            '"folder-add-line"',
+            '"folder-chart-2-fill"',
+            '"folder-chart-2-line"',
+            '"folder-chart-fill"',
+            '"folder-chart-line"',
+            '"folder-download-fill"',
+            '"folder-download-line"',
+            '"folder-fill"',
+            '"folder-forbid-fill"',
+            '"folder-forbid-line"',
+            '"folder-history-fill"',
+            '"folder-history-line"',
+            '"folder-info-fill"',
+            '"folder-info-line"',
+            '"folder-keyhole-fill"',
+            '"folder-keyhole-line"',
+            '"folder-line"',
+            '"folder-lock-fill"',
+            '"folder-lock-line"',
+            '"folder-music-fill"',
+            '"folder-music-line"',
+            '"folder-open-fill"',
+            '"folder-open-line"',
+            '"folder-received-fill"',
+            '"folder-received-line"',
+            '"folder-reduce-fill"',
+            '"folder-reduce-line"',
+            '"folder-settings-fill"',
+            '"folder-settings-line"',
+            '"folder-shared-fill"',
+            '"folder-shared-line"',
+            '"folder-shield-2-fill"',
+            '"folder-shield-2-line"',
+            '"folder-shield-fill"',
+            '"folder-shield-line"',
+            '"folder-transfer-fill"',
+            '"folder-transfer-line"',
+            '"folder-unknow-fill"',
+            '"folder-unknow-line"',
+            '"folder-upload-fill"',
+            '"folder-upload-line"',
+            '"folder-user-fill"',
+            '"folder-user-line"',
+            '"folder-warning-fill"',
+            '"folder-warning-line"',
+            '"folder-zip-fill"',
+            '"folder-zip-line"',
+            '"folders-fill"',
+            '"folders-line"',
+            '"font-color"',
+            '"font-size-2"',
+            '"font-size"',
+            '"football-fill"',
+            '"football-line"',
+            '"footprint-fill"',
+            '"footprint-line"',
+            '"forbid-2-fill"',
+            '"forbid-2-line"',
+            '"forbid-fill"',
+            '"forbid-line"',
+            '"format-clear"',
+            '"fridge-fill"',
+            '"fridge-line"',
+            '"fullscreen-exit-fill"',
+            '"fullscreen-exit-line"',
+            '"fullscreen-fill"',
+            '"fullscreen-line"',
+            '"function-fill"',
+            '"function-line"',
+            '"functions"',
+            '"funds-box-fill"',
+            '"funds-box-line"',
+            '"funds-fill"',
+            '"funds-line"',
+            '"gallery-fill"',
+            '"gallery-line"',
+            '"gallery-upload-fill"',
+            '"gallery-upload-line"',
+            '"game-fill"',
+            '"game-line"',
+            '"gamepad-fill"',
+            '"gamepad-line"',
+            '"gas-station-fill"',
+            '"gas-station-line"',
+            '"gatsby-fill"',
+            '"gatsby-line"',
+            '"genderless-fill"',
+            '"genderless-line"',
+            '"ghost-2-fill"',
+            '"ghost-2-line"',
+            '"ghost-fill"',
+            '"ghost-line"',
+            '"ghost-smile-fill"',
+            '"ghost-smile-line"',
+            '"gift-2-fill"',
+            '"gift-2-line"',
+            '"gift-fill"',
+            '"gift-line"',
+            '"git-branch-fill"',
+            '"git-branch-line"',
+            '"git-commit-fill"',
+            '"git-commit-line"',
+            '"git-merge-fill"',
+            '"git-merge-line"',
+            '"git-pull-request-fill"',
+            '"git-pull-request-line"',
+            '"git-repository-commits-fill"',
+            '"git-repository-commits-line"',
+            '"git-repository-fill"',
+            '"git-repository-line"',
+            '"git-repository-private-fill"',
+            '"git-repository-private-line"',
+            '"github-fill"',
+            '"github-line"',
+            '"gitlab-fill"',
+            '"gitlab-line"',
+            '"global-fill"',
+            '"global-line"',
+            '"globe-fill"',
+            '"globe-line"',
+            '"goblet-fill"',
+            '"goblet-line"',
+            '"google-fill"',
+            '"google-line"',
+            '"google-play-fill"',
+            '"google-play-line"',
+            '"government-fill"',
+            '"government-line"',
+            '"gps-fill"',
+            '"gps-line"',
+            '"gradienter-fill"',
+            '"gradienter-line"',
+            '"grid-fill"',
+            '"grid-line"',
+            '"group-2-fill"',
+            '"group-2-line"',
+            '"group-fill"',
+            '"group-line"',
+            '"guide-fill"',
+            '"guide-line"',
+            '"h-1"',
+            '"h-2"',
+            '"h-3"',
+            '"h-4"',
+            '"h-5"',
+            '"h-6"',
+            '"hail-fill"',
+            '"hail-line"',
+            '"hammer-fill"',
+            '"hammer-line"',
+            '"hand-coin-fill"',
+            '"hand-coin-line"',
+            '"hand-heart-fill"',
+            '"hand-heart-line"',
+            '"hand-sanitizer-fill"',
+            '"hand-sanitizer-line"',
+            '"handbag-fill"',
+            '"handbag-line"',
+            '"hard-drive-2-fill"',
+            '"hard-drive-2-line"',
+            '"hard-drive-fill"',
+            '"hard-drive-line"',
+            '"hashtag"',
+            '"haze-2-fill"',
+            '"haze-2-line"',
+            '"haze-fill"',
+            '"haze-line"',
+            '"hd-fill"',
+            '"hd-line"',
+            '"heading"',
+            '"headphone-fill"',
+            '"headphone-line"',
+            '"health-book-fill"',
+            '"health-book-line"',
+            '"heart-2-fill"',
+            '"heart-2-line"',
+            '"heart-3-fill"',
+            '"heart-3-line"',
+            '"heart-add-fill"',
+            '"heart-add-line"',
+            '"heart-fill"',
+            '"heart-line"',
+            '"heart-pulse-fill"',
+            '"heart-pulse-line"',
+            '"hearts-fill"',
+            '"hearts-line"',
+            '"heavy-showers-fill"',
+            '"heavy-showers-line"',
+            '"history-fill"',
+            '"history-line"',
+            '"home-2-fill"',
+            '"home-2-line"',
+            '"home-3-fill"',
+            '"home-3-line"',
+            '"home-4-fill"',
+            '"home-4-line"',
+            '"home-5-fill"',
+            '"home-5-line"',
+            '"home-6-fill"',
+            '"home-6-line"',
+            '"home-7-fill"',
+            '"home-7-line"',
+            '"home-8-fill"',
+            '"home-8-line"',
+            '"home-fill"',
+            '"home-gear-fill"',
+            '"home-gear-line"',
+            '"home-heart-fill"',
+            '"home-heart-line"',
+            '"home-line"',
+            '"home-smile-2-fill"',
+            '"home-smile-2-line"',
+            '"home-smile-fill"',
+            '"home-smile-line"',
+            '"home-wifi-fill"',
+            '"home-wifi-line"',
+            '"honor-of-kings-fill"',
+            '"honor-of-kings-line"',
+            '"honour-fill"',
+            '"honour-line"',
+            '"hospital-fill"',
+            '"hospital-line"',
+            '"hotel-bed-fill"',
+            '"hotel-bed-line"',
+            '"hotel-fill"',
+            '"hotel-line"',
+            '"hotspot-fill"',
+            '"hotspot-line"',
+            '"hq-fill"',
+            '"hq-line"',
+            '"html5-fill"',
+            '"html5-line"',
+            '"ie-fill"',
+            '"ie-line"',
+            '"image-2-fill"',
+            '"image-2-line"',
+            '"image-add-fill"',
+            '"image-add-line"',
+            '"image-edit-fill"',
+            '"image-edit-line"',
+            '"image-fill"',
+            '"image-line"',
+            '"inbox-archive-fill"',
+            '"inbox-archive-line"',
+            '"inbox-fill"',
+            '"inbox-line"',
+            '"inbox-unarchive-fill"',
+            '"inbox-unarchive-line"',
+            '"increase-decrease-fill"',
+            '"increase-decrease-line"',
+            '"indent-decrease"',
+            '"indent-increase"',
+            '"indeterminate-circle-fill"',
+            '"indeterminate-circle-line"',
+            '"information-fill"',
+            '"information-line"',
+            '"infrared-thermometer-fill"',
+            '"infrared-thermometer-line"',
+            '"ink-bottle-fill"',
+            '"ink-bottle-line"',
+            '"input-cursor-move"',
+            '"input-method-fill"',
+            '"input-method-line"',
+            '"insert-column-left"',
+            '"insert-column-right"',
+            '"insert-row-bottom"',
+            '"insert-row-top"',
+            '"instagram-fill"',
+            '"instagram-line"',
+            '"install-fill"',
+            '"install-line"',
+            '"invision-fill"',
+            '"invision-line"',
+            '"italic"',
+            '"kakao-talk-fill"',
+            '"kakao-talk-line"',
+            '"key-2-fill"',
+            '"key-2-line"',
+            '"key-fill"',
+            '"key-line"',
+            '"keyboard-box-fill"',
+            '"keyboard-box-line"',
+            '"keyboard-fill"',
+            '"keyboard-line"',
+            '"keynote-fill"',
+            '"keynote-line"',
+            '"knife-blood-fill"',
+            '"knife-blood-line"',
+            '"knife-fill"',
+            '"knife-line"',
+            '"landscape-fill"',
+            '"landscape-line"',
+            '"layout-2-fill"',
+            '"layout-2-line"',
+            '"layout-3-fill"',
+            '"layout-3-line"',
+            '"layout-4-fill"',
+            '"layout-4-line"',
+            '"layout-5-fill"',
+            '"layout-5-line"',
+            '"layout-6-fill"',
+            '"layout-6-line"',
+            '"layout-bottom-2-fill"',
+            '"layout-bottom-2-line"',
+            '"layout-bottom-fill"',
+            '"layout-bottom-line"',
+            '"layout-column-fill"',
+            '"layout-column-line"',
+            '"layout-fill"',
+            '"layout-grid-fill"',
+            '"layout-grid-line"',
+            '"layout-left-2-fill"',
+            '"layout-left-2-line"',
+            '"layout-left-fill"',
+            '"layout-left-line"',
+            '"layout-line"',
+            '"layout-masonry-fill"',
+            '"layout-masonry-line"',
+            '"layout-right-2-fill"',
+            '"layout-right-2-line"',
+            '"layout-right-fill"',
+            '"layout-right-line"',
+            '"layout-row-fill"',
+            '"layout-row-line"',
+            '"layout-top-2-fill"',
+            '"layout-top-2-line"',
+            '"layout-top-fill"',
+            '"layout-top-line"',
+            '"leaf-fill"',
+            '"leaf-line"',
+            '"lifebuoy-fill"',
+            '"lifebuoy-line"',
+            '"lightbulb-fill"',
+            '"lightbulb-flash-fill"',
+            '"lightbulb-flash-line"',
+            '"lightbulb-line"',
+            '"line-chart-fill"',
+            '"line-chart-line"',
+            '"line-fill"',
+            '"line-height"',
+            '"line-line"',
+            '"link-m"',
+            '"link-unlink-m"',
+            '"link-unlink"',
+            '"link"',
+            '"linkedin-box-fill"',
+            '"linkedin-box-line"',
+            '"linkedin-fill"',
+            '"linkedin-line"',
+            '"links-fill"',
+            '"links-line"',
+            '"list-check-2"',
+            '"list-check"',
+            '"list-ordered"',
+            '"list-settings-fill"',
+            '"list-settings-line"',
+            '"list-unordered"',
+            '"live-fill"',
+            '"live-line"',
+            '"loader-2-fill"',
+            '"loader-2-line"',
+            '"loader-3-fill"',
+            '"loader-3-line"',
+            '"loader-4-fill"',
+            '"loader-4-line"',
+            '"loader-5-fill"',
+            '"loader-5-line"',
+            '"loader-fill"',
+            '"loader-line"',
+            '"lock-2-fill"',
+            '"lock-2-line"',
+            '"lock-fill"',
+            '"lock-line"',
+            '"lock-password-fill"',
+            '"lock-password-line"',
+            '"lock-unlock-fill"',
+            '"lock-unlock-line"',
+            '"login-box-fill"',
+            '"login-box-line"',
+            '"login-circle-fill"',
+            '"login-circle-line"',
+            '"logout-box-fill"',
+            '"logout-box-line"',
+            '"logout-box-r-fill"',
+            '"logout-box-r-line"',
+            '"logout-circle-fill"',
+            '"logout-circle-line"',
+            '"logout-circle-r-fill"',
+            '"logout-circle-r-line"',
+            '"luggage-cart-fill"',
+            '"luggage-cart-line"',
+            '"luggage-deposit-fill"',
+            '"luggage-deposit-line"',
+            '"lungs-fill"',
+            '"lungs-line"',
+            '"mac-fill"',
+            '"mac-line"',
+            '"macbook-fill"',
+            '"macbook-line"',
+            '"magic-fill"',
+            '"magic-line"',
+            '"mail-add-fill"',
+            '"mail-add-line"',
+            '"mail-check-fill"',
+            '"mail-check-line"',
+            '"mail-close-fill"',
+            '"mail-close-line"',
+            '"mail-download-fill"',
+            '"mail-download-line"',
+            '"mail-fill"',
+            '"mail-forbid-fill"',
+            '"mail-forbid-line"',
+            '"mail-line"',
+            '"mail-lock-fill"',
+            '"mail-lock-line"',
+            '"mail-open-fill"',
+            '"mail-open-line"',
+            '"mail-send-fill"',
+            '"mail-send-line"',
+            '"mail-settings-fill"',
+            '"mail-settings-line"',
+            '"mail-star-fill"',
+            '"mail-star-line"',
+            '"mail-unread-fill"',
+            '"mail-unread-line"',
+            '"mail-volume-fill"',
+            '"mail-volume-line"',
+            '"map-2-fill"',
+            '"map-2-line"',
+            '"map-fill"',
+            '"map-line"',
+            '"map-pin-2-fill"',
+            '"map-pin-2-line"',
+            '"map-pin-3-fill"',
+            '"map-pin-3-line"',
+            '"map-pin-4-fill"',
+            '"map-pin-4-line"',
+            '"map-pin-5-fill"',
+            '"map-pin-5-line"',
+            '"map-pin-add-fill"',
+            '"map-pin-add-line"',
+            '"map-pin-fill"',
+            '"map-pin-line"',
+            '"map-pin-range-fill"',
+            '"map-pin-range-line"',
+            '"map-pin-time-fill"',
+            '"map-pin-time-line"',
+            '"map-pin-user-fill"',
+            '"map-pin-user-line"',
+            '"mark-pen-fill"',
+            '"mark-pen-line"',
+            '"markdown-fill"',
+            '"markdown-line"',
+            '"markup-fill"',
+            '"markup-line"',
+            '"mastercard-fill"',
+            '"mastercard-line"',
+            '"mastodon-fill"',
+            '"mastodon-line"',
+            '"medal-2-fill"',
+            '"medal-2-line"',
+            '"medal-fill"',
+            '"medal-line"',
+            '"medicine-bottle-fill"',
+            '"medicine-bottle-line"',
+            '"medium-fill"',
+            '"medium-line"',
+            '"men-fill"',
+            '"men-line"',
+            '"mental-health-fill"',
+            '"mental-health-line"',
+            '"menu-2-fill"',
+            '"menu-2-line"',
+            '"menu-3-fill"',
+            '"menu-3-line"',
+            '"menu-4-fill"',
+            '"menu-4-line"',
+            '"menu-5-fill"',
+            '"menu-5-line"',
+            '"menu-add-fill"',
+            '"menu-add-line"',
+            '"menu-fill"',
+            '"menu-fold-fill"',
+            '"menu-fold-line"',
+            '"menu-line"',
+            '"menu-unfold-fill"',
+            '"menu-unfold-line"',
+            '"merge-cells-horizontal"',
+            '"merge-cells-vertical"',
+            '"message-2-fill"',
+            '"message-2-line"',
+            '"message-3-fill"',
+            '"message-3-line"',
+            '"message-fill"',
+            '"message-line"',
+            '"messenger-fill"',
+            '"messenger-line"',
+            '"meteor-fill"',
+            '"meteor-line"',
+            '"mic-2-fill"',
+            '"mic-2-line"',
+            '"mic-fill"',
+            '"mic-line"',
+            '"mic-off-fill"',
+            '"mic-off-line"',
+            '"mickey-fill"',
+            '"mickey-line"',
+            '"microscope-fill"',
+            '"microscope-line"',
+            '"microsoft-fill"',
+            '"microsoft-line"',
+            '"mind-map"',
+            '"mini-program-fill"',
+            '"mini-program-line"',
+            '"mist-fill"',
+            '"mist-line"',
+            '"money-cny-box-fill"',
+            '"money-cny-box-line"',
+            '"money-cny-circle-fill"',
+            '"money-cny-circle-line"',
+            '"money-dollar-box-fill"',
+            '"money-dollar-box-line"',
+            '"money-dollar-circle-fill"',
+            '"money-dollar-circle-line"',
+            '"money-euro-box-fill"',
+            '"money-euro-box-line"',
+            '"money-euro-circle-fill"',
+            '"money-euro-circle-line"',
+            '"money-pound-box-fill"',
+            '"money-pound-box-line"',
+            '"money-pound-circle-fill"',
+            '"money-pound-circle-line"',
+            '"moon-clear-fill"',
+            '"moon-clear-line"',
+            '"moon-cloudy-fill"',
+            '"moon-cloudy-line"',
+            '"moon-fill"',
+            '"moon-foggy-fill"',
+            '"moon-foggy-line"',
+            '"moon-line"',
+            '"more-2-fill"',
+            '"more-2-line"',
+            '"more-fill"',
+            '"more-line"',
+            '"motorbike-fill"',
+            '"motorbike-line"',
+            '"mouse-fill"',
+            '"mouse-line"',
+            '"movie-2-fill"',
+            '"movie-2-line"',
+            '"movie-fill"',
+            '"movie-line"',
+            '"music-2-fill"',
+            '"music-2-line"',
+            '"music-fill"',
+            '"music-line"',
+            '"mv-fill"',
+            '"mv-line"',
+            '"navigation-fill"',
+            '"navigation-line"',
+            '"netease-cloud-music-fill"',
+            '"netease-cloud-music-line"',
+            '"netflix-fill"',
+            '"netflix-line"',
+            '"newspaper-fill"',
+            '"newspaper-line"',
+            '"node-tree"',
+            '"notification-2-fill"',
+            '"notification-2-line"',
+            '"notification-3-fill"',
+            '"notification-3-line"',
+            '"notification-4-fill"',
+            '"notification-4-line"',
+            '"notification-badge-fill"',
+            '"notification-badge-line"',
+            '"notification-fill"',
+            '"notification-line"',
+            '"notification-off-fill"',
+            '"notification-off-line"',
+            '"npmjs-fill"',
+            '"npmjs-line"',
+            '"number-0"',
+            '"number-1"',
+            '"number-2"',
+            '"number-3"',
+            '"number-4"',
+            '"number-5"',
+            '"number-6"',
+            '"number-7"',
+            '"number-8"',
+            '"number-9"',
+            '"numbers-fill"',
+            '"numbers-line"',
+            '"nurse-fill"',
+            '"nurse-line"',
+            '"oil-fill"',
+            '"oil-line"',
+            '"omega"',
+            '"open-arm-fill"',
+            '"open-arm-line"',
+            '"open-source-fill"',
+            '"open-source-line"',
+            '"opera-fill"',
+            '"opera-line"',
+            '"order-play-fill"',
+            '"order-play-line"',
+            '"organization-chart"',
+            '"outlet-2-fill"',
+            '"outlet-2-line"',
+            '"outlet-fill"',
+            '"outlet-line"',
+            '"page-separator"',
+            '"pages-fill"',
+            '"pages-line"',
+            '"paint-brush-fill"',
+            '"paint-brush-line"',
+            '"paint-fill"',
+            '"paint-line"',
+            '"palette-fill"',
+            '"palette-line"',
+            '"pantone-fill"',
+            '"pantone-line"',
+            '"paragraph"',
+            '"parent-fill"',
+            '"parent-line"',
+            '"parentheses-fill"',
+            '"parentheses-line"',
+            '"parking-box-fill"',
+            '"parking-box-line"',
+            '"parking-fill"',
+            '"parking-line"',
+            '"passport-fill"',
+            '"passport-line"',
+            '"patreon-fill"',
+            '"patreon-line"',
+            '"pause-circle-fill"',
+            '"pause-circle-line"',
+            '"pause-fill"',
+            '"pause-line"',
+            '"pause-mini-fill"',
+            '"pause-mini-line"',
+            '"paypal-fill"',
+            '"paypal-line"',
+            '"pen-nib-fill"',
+            '"pen-nib-line"',
+            '"pencil-fill"',
+            '"pencil-line"',
+            '"pencil-ruler-2-fill"',
+            '"pencil-ruler-2-line"',
+            '"pencil-ruler-fill"',
+            '"pencil-ruler-line"',
+            '"percent-fill"',
+            '"percent-line"',
+            '"phone-camera-fill"',
+            '"phone-camera-line"',
+            '"phone-fill"',
+            '"phone-find-fill"',
+            '"phone-find-line"',
+            '"phone-line"',
+            '"phone-lock-fill"',
+            '"phone-lock-line"',
+            '"picture-in-picture-2-fill"',
+            '"picture-in-picture-2-line"',
+            '"picture-in-picture-exit-fill"',
+            '"picture-in-picture-exit-line"',
+            '"picture-in-picture-fill"',
+            '"picture-in-picture-line"',
+            '"pie-chart-2-fill"',
+            '"pie-chart-2-line"',
+            '"pie-chart-box-fill"',
+            '"pie-chart-box-line"',
+            '"pie-chart-fill"',
+            '"pie-chart-line"',
+            '"pin-distance-fill"',
+            '"pin-distance-line"',
+            '"ping-pong-fill"',
+            '"ping-pong-line"',
+            '"pinterest-fill"',
+            '"pinterest-line"',
+            '"pinyin-input"',
+            '"pixelfed-fill"',
+            '"pixelfed-line"',
+            '"plane-fill"',
+            '"plane-line"',
+            '"plant-fill"',
+            '"plant-line"',
+            '"play-circle-fill"',
+            '"play-circle-line"',
+            '"play-fill"',
+            '"play-line"',
+            '"play-list-2-fill"',
+            '"play-list-2-line"',
+            '"play-list-add-fill"',
+            '"play-list-add-line"',
+            '"play-list-fill"',
+            '"play-list-line"',
+            '"play-mini-fill"',
+            '"play-mini-line"',
+            '"playstation-fill"',
+            '"playstation-line"',
+            '"plug-2-fill"',
+            '"plug-2-line"',
+            '"plug-fill"',
+            '"plug-line"',
+            '"polaroid-2-fill"',
+            '"polaroid-2-line"',
+            '"polaroid-fill"',
+            '"polaroid-line"',
+            '"police-car-fill"',
+            '"police-car-line"',
+            '"price-tag-2-fill"',
+            '"price-tag-2-line"',
+            '"price-tag-3-fill"',
+            '"price-tag-3-line"',
+            '"price-tag-fill"',
+            '"price-tag-line"',
+            '"printer-cloud-fill"',
+            '"printer-cloud-line"',
+            '"printer-fill"',
+            '"printer-line"',
+            '"product-hunt-fill"',
+            '"product-hunt-line"',
+            '"profile-fill"',
+            '"profile-line"',
+            '"projector-2-fill"',
+            '"projector-2-line"',
+            '"projector-fill"',
+            '"projector-line"',
+            '"psychotherapy-fill"',
+            '"psychotherapy-line"',
+            '"pulse-fill"',
+            '"pulse-line"',
+            '"pushpin-2-fill"',
+            '"pushpin-2-line"',
+            '"pushpin-fill"',
+            '"pushpin-line"',
+            '"qq-fill"',
+            '"qq-line"',
+            '"qr-code-fill"',
+            '"qr-code-line"',
+            '"qr-scan-2-fill"',
+            '"qr-scan-2-line"',
+            '"qr-scan-fill"',
+            '"qr-scan-line"',
+            '"question-answer-fill"',
+            '"question-answer-line"',
+            '"question-fill"',
+            '"question-line"',
+            '"question-mark"',
+            '"questionnaire-fill"',
+            '"questionnaire-line"',
+            '"quill-pen-fill"',
+            '"quill-pen-line"',
+            '"radar-fill"',
+            '"radar-line"',
+            '"radio-2-fill"',
+            '"radio-2-line"',
+            '"radio-button-fill"',
+            '"radio-button-line"',
+            '"radio-fill"',
+            '"radio-line"',
+            '"rainbow-fill"',
+            '"rainbow-line"',
+            '"rainy-fill"',
+            '"rainy-line"',
+            '"reactjs-fill"',
+            '"reactjs-line"',
+            '"record-circle-fill"',
+            '"record-circle-line"',
+            '"record-mail-fill"',
+            '"record-mail-line"',
+            '"recycle-fill"',
+            '"recycle-line"',
+            '"red-packet-fill"',
+            '"red-packet-line"',
+            '"reddit-fill"',
+            '"reddit-line"',
+            '"refresh-fill"',
+            '"refresh-line"',
+            '"refund-2-fill"',
+            '"refund-2-line"',
+            '"refund-fill"',
+            '"refund-line"',
+            '"registered-fill"',
+            '"registered-line"',
+            '"remixicon-fill"',
+            '"remixicon-line"',
+            '"remote-control-2-fill"',
+            '"remote-control-2-line"',
+            '"remote-control-fill"',
+            '"remote-control-line"',
+            '"repeat-2-fill"',
+            '"repeat-2-line"',
+            '"repeat-fill"',
+            '"repeat-line"',
+            '"repeat-one-fill"',
+            '"repeat-one-line"',
+            '"reply-all-fill"',
+            '"reply-all-line"',
+            '"reply-fill"',
+            '"reply-line"',
+            '"reserved-fill"',
+            '"reserved-line"',
+            '"rest-time-fill"',
+            '"rest-time-line"',
+            '"restart-fill"',
+            '"restart-line"',
+            '"restaurant-2-fill"',
+            '"restaurant-2-line"',
+            '"restaurant-fill"',
+            '"restaurant-line"',
+            '"rewind-fill"',
+            '"rewind-line"',
+            '"rewind-mini-fill"',
+            '"rewind-mini-line"',
+            '"rhythm-fill"',
+            '"rhythm-line"',
+            '"riding-fill"',
+            '"riding-line"',
+            '"road-map-fill"',
+            '"road-map-line"',
+            '"roadster-fill"',
+            '"roadster-line"',
+            '"robot-fill"',
+            '"robot-line"',
+            '"rocket-2-fill"',
+            '"rocket-2-line"',
+            '"rocket-fill"',
+            '"rocket-line"',
+            '"rotate-lock-fill"',
+            '"rotate-lock-line"',
+            '"rounded-corner"',
+            '"route-fill"',
+            '"route-line"',
+            '"router-fill"',
+            '"router-line"',
+            '"rss-fill"',
+            '"rss-line"',
+            '"ruler-2-fill"',
+            '"ruler-2-line"',
+            '"ruler-fill"',
+            '"ruler-line"',
+            '"run-fill"',
+            '"run-line"',
+            '"safari-fill"',
+            '"safari-line"',
+            '"safe-2-fill"',
+            '"safe-2-line"',
+            '"safe-fill"',
+            '"safe-line"',
+            '"sailboat-fill"',
+            '"sailboat-line"',
+            '"save-2-fill"',
+            '"save-2-line"',
+            '"save-3-fill"',
+            '"save-3-line"',
+            '"save-fill"',
+            '"save-line"',
+            '"scales-2-fill"',
+            '"scales-2-line"',
+            '"scales-3-fill"',
+            '"scales-3-line"',
+            '"scales-fill"',
+            '"scales-line"',
+            '"scan-2-fill"',
+            '"scan-2-line"',
+            '"scan-fill"',
+            '"scan-line"',
+            '"scissors-2-fill"',
+            '"scissors-2-line"',
+            '"scissors-cut-fill"',
+            '"scissors-cut-line"',
+            '"scissors-fill"',
+            '"scissors-line"',
+            '"screenshot-2-fill"',
+            '"screenshot-2-line"',
+            '"screenshot-fill"',
+            '"screenshot-line"',
+            '"sd-card-fill"',
+            '"sd-card-line"',
+            '"sd-card-mini-fill"',
+            '"sd-card-mini-line"',
+            '"search-2-fill"',
+            '"search-2-line"',
+            '"search-eye-fill"',
+            '"search-eye-line"',
+            '"search-fill"',
+            '"search-line"',
+            '"secure-payment-fill"',
+            '"secure-payment-line"',
+            '"seedling-fill"',
+            '"seedling-line"',
+            '"send-backward"',
+            '"send-plane-2-fill"',
+            '"send-plane-2-line"',
+            '"send-plane-fill"',
+            '"send-plane-line"',
+            '"send-to-back"',
+            '"sensor-fill"',
+            '"sensor-line"',
+            '"separator"',
+            '"server-fill"',
+            '"server-line"',
+            '"service-fill"',
+            '"service-line"',
+            '"settings-2-fill"',
+            '"settings-2-line"',
+            '"settings-3-fill"',
+            '"settings-3-line"',
+            '"settings-4-fill"',
+            '"settings-4-line"',
+            '"settings-5-fill"',
+            '"settings-5-line"',
+            '"settings-6-fill"',
+            '"settings-6-line"',
+            '"settings-fill"',
+            '"settings-line"',
+            '"shape-2-fill"',
+            '"shape-2-line"',
+            '"shape-fill"',
+            '"shape-line"',
+            '"share-box-fill"',
+            '"share-box-line"',
+            '"share-circle-fill"',
+            '"share-circle-line"',
+            '"share-fill"',
+            '"share-forward-2-fill"',
+            '"share-forward-2-line"',
+            '"share-forward-box-fill"',
+            '"share-forward-box-line"',
+            '"share-forward-fill"',
+            '"share-forward-line"',
+            '"share-line"',
+            '"shield-check-fill"',
+            '"shield-check-line"',
+            '"shield-cross-fill"',
+            '"shield-cross-line"',
+            '"shield-fill"',
+            '"shield-flash-fill"',
+            '"shield-flash-line"',
+            '"shield-keyhole-fill"',
+            '"shield-keyhole-line"',
+            '"shield-line"',
+            '"shield-star-fill"',
+            '"shield-star-line"',
+            '"shield-user-fill"',
+            '"shield-user-line"',
+            '"ship-2-fill"',
+            '"ship-2-line"',
+            '"ship-fill"',
+            '"ship-line"',
+            '"shirt-fill"',
+            '"shirt-line"',
+            '"shopping-bag-2-fill"',
+            '"shopping-bag-2-line"',
+            '"shopping-bag-3-fill"',
+            '"shopping-bag-3-line"',
+            '"shopping-bag-fill"',
+            '"shopping-bag-line"',
+            '"shopping-basket-2-fill"',
+            '"shopping-basket-2-line"',
+            '"shopping-basket-fill"',
+            '"shopping-basket-line"',
+            '"shopping-cart-2-fill"',
+            '"shopping-cart-2-line"',
+            '"shopping-cart-fill"',
+            '"shopping-cart-line"',
+            '"showers-fill"',
+            '"showers-line"',
+            '"shuffle-fill"',
+            '"shuffle-line"',
+            '"shut-down-fill"',
+            '"shut-down-line"',
+            '"side-bar-fill"',
+            '"side-bar-line"',
+            '"signal-tower-fill"',
+            '"signal-tower-line"',
+            '"signal-wifi-1-fill"',
+            '"signal-wifi-1-line"',
+            '"signal-wifi-2-fill"',
+            '"signal-wifi-2-line"',
+            '"signal-wifi-3-fill"',
+            '"signal-wifi-3-line"',
+            '"signal-wifi-error-fill"',
+            '"signal-wifi-error-line"',
+            '"signal-wifi-fill"',
+            '"signal-wifi-line"',
+            '"signal-wifi-off-fill"',
+            '"signal-wifi-off-line"',
+            '"sim-card-2-fill"',
+            '"sim-card-2-line"',
+            '"sim-card-fill"',
+            '"sim-card-line"',
+            '"single-quotes-l"',
+            '"single-quotes-r"',
+            '"sip-fill"',
+            '"sip-line"',
+            '"skip-back-fill"',
+            '"skip-back-line"',
+            '"skip-back-mini-fill"',
+            '"skip-back-mini-line"',
+            '"skip-forward-fill"',
+            '"skip-forward-line"',
+            '"skip-forward-mini-fill"',
+            '"skip-forward-mini-line"',
+            '"skull-2-fill"',
+            '"skull-2-line"',
+            '"skull-fill"',
+            '"skull-line"',
+            '"skype-fill"',
+            '"skype-line"',
+            '"slack-fill"',
+            '"slack-line"',
+            '"slice-fill"',
+            '"slice-line"',
+            '"slideshow-2-fill"',
+            '"slideshow-2-line"',
+            '"slideshow-3-fill"',
+            '"slideshow-3-line"',
+            '"slideshow-4-fill"',
+            '"slideshow-4-line"',
+            '"slideshow-fill"',
+            '"slideshow-line"',
+            '"smartphone-fill"',
+            '"smartphone-line"',
+            '"snapchat-fill"',
+            '"snapchat-line"',
+            '"snowy-fill"',
+            '"snowy-line"',
+            '"sort-asc"',
+            '"sort-desc"',
+            '"sound-module-fill"',
+            '"sound-module-line"',
+            '"soundcloud-fill"',
+            '"soundcloud-line"',
+            '"space-ship-fill"',
+            '"space-ship-line"',
+            '"space"',
+            '"spam-2-fill"',
+            '"spam-2-line"',
+            '"spam-3-fill"',
+            '"spam-3-line"',
+            '"spam-fill"',
+            '"spam-line"',
+            '"speaker-2-fill"',
+            '"speaker-2-line"',
+            '"speaker-3-fill"',
+            '"speaker-3-line"',
+            '"speaker-fill"',
+            '"speaker-line"',
+            '"spectrum-fill"',
+            '"spectrum-line"',
+            '"speed-fill"',
+            '"speed-line"',
+            '"speed-mini-fill"',
+            '"speed-mini-line"',
+            '"split-cells-horizontal"',
+            '"split-cells-vertical"',
+            '"spotify-fill"',
+            '"spotify-line"',
+            '"spy-fill"',
+            '"spy-line"',
+            '"stack-fill"',
+            '"stack-line"',
+            '"stack-overflow-fill"',
+            '"stack-overflow-line"',
+            '"stackshare-fill"',
+            '"stackshare-line"',
+            '"star-fill"',
+            '"star-half-fill"',
+            '"star-half-line"',
+            '"star-half-s-fill"',
+            '"star-half-s-line"',
+            '"star-line"',
+            '"star-s-fill"',
+            '"star-s-line"',
+            '"star-smile-fill"',
+            '"star-smile-line"',
+            '"steam-fill"',
+            '"steam-line"',
+            '"steering-2-fill"',
+            '"steering-2-line"',
+            '"steering-fill"',
+            '"steering-line"',
+            '"stethoscope-fill"',
+            '"stethoscope-line"',
+            '"sticky-note-2-fill"',
+            '"sticky-note-2-line"',
+            '"sticky-note-fill"',
+            '"sticky-note-line"',
+            '"stock-fill"',
+            '"stock-line"',
+            '"stop-circle-fill"',
+            '"stop-circle-line"',
+            '"stop-fill"',
+            '"stop-line"',
+            '"stop-mini-fill"',
+            '"stop-mini-line"',
+            '"store-2-fill"',
+            '"store-2-line"',
+            '"store-3-fill"',
+            '"store-3-line"',
+            '"store-fill"',
+            '"store-line"',
+            '"strikethrough-2"',
+            '"strikethrough"',
+            '"subscript-2"',
+            '"subscript"',
+            '"subtract-fill"',
+            '"subtract-line"',
+            '"subway-fill"',
+            '"subway-line"',
+            '"subway-wifi-fill"',
+            '"subway-wifi-line"',
+            '"suitcase-2-fill"',
+            '"suitcase-2-line"',
+            '"suitcase-3-fill"',
+            '"suitcase-3-line"',
+            '"suitcase-fill"',
+            '"suitcase-line"',
+            '"sun-cloudy-fill"',
+            '"sun-cloudy-line"',
+            '"sun-fill"',
+            '"sun-foggy-fill"',
+            '"sun-foggy-line"',
+            '"sun-line"',
+            '"superscript-2"',
+            '"superscript"',
+            '"surgical-mask-fill"',
+            '"surgical-mask-line"',
+            '"surround-sound-fill"',
+            '"surround-sound-line"',
+            '"survey-fill"',
+            '"survey-line"',
+            '"swap-box-fill"',
+            '"swap-box-line"',
+            '"swap-fill"',
+            '"swap-line"',
+            '"switch-fill"',
+            '"switch-line"',
+            '"sword-fill"',
+            '"sword-line"',
+            '"syringe-fill"',
+            '"syringe-line"',
+            '"t-box-fill"',
+            '"t-box-line"',
+            '"t-shirt-2-fill"',
+            '"t-shirt-2-line"',
+            '"t-shirt-air-fill"',
+            '"t-shirt-air-line"',
+            '"t-shirt-fill"',
+            '"t-shirt-line"',
+            '"table-2"',
+            '"table-alt-fill"',
+            '"table-alt-line"',
+            '"table-fill"',
+            '"table-line"',
+            '"tablet-fill"',
+            '"tablet-line"',
+            '"takeaway-fill"',
+            '"takeaway-line"',
+            '"taobao-fill"',
+            '"taobao-line"',
+            '"tape-fill"',
+            '"tape-line"',
+            '"task-fill"',
+            '"task-line"',
+            '"taxi-fill"',
+            '"taxi-line"',
+            '"taxi-wifi-fill"',
+            '"taxi-wifi-line"',
+            '"team-fill"',
+            '"team-line"',
+            '"telegram-fill"',
+            '"telegram-line"',
+            '"temp-cold-fill"',
+            '"temp-cold-line"',
+            '"temp-hot-fill"',
+            '"temp-hot-line"',
+            '"terminal-box-fill"',
+            '"terminal-box-line"',
+            '"terminal-fill"',
+            '"terminal-line"',
+            '"terminal-window-fill"',
+            '"terminal-window-line"',
+            '"test-tube-fill"',
+            '"test-tube-line"',
+            '"text-direction-l"',
+            '"text-direction-r"',
+            '"text-spacing"',
+            '"text-wrap"',
+            '"text"',
+            '"thermometer-fill"',
+            '"thermometer-line"',
+            '"thumb-down-fill"',
+            '"thumb-down-line"',
+            '"thumb-up-fill"',
+            '"thumb-up-line"',
+            '"thunderstorms-fill"',
+            '"thunderstorms-line"',
+            '"ticket-2-fill"',
+            '"ticket-2-line"',
+            '"ticket-fill"',
+            '"ticket-line"',
+            '"time-fill"',
+            '"time-line"',
+            '"timer-2-fill"',
+            '"timer-2-line"',
+            '"timer-fill"',
+            '"timer-flash-fill"',
+            '"timer-flash-line"',
+            '"timer-line"',
+            '"todo-fill"',
+            '"todo-line"',
+            '"toggle-fill"',
+            '"toggle-line"',
+            '"tools-fill"',
+            '"tools-line"',
+            '"tornado-fill"',
+            '"tornado-line"',
+            '"trademark-fill"',
+            '"trademark-line"',
+            '"traffic-light-fill"',
+            '"traffic-light-line"',
+            '"train-fill"',
+            '"train-line"',
+            '"train-wifi-fill"',
+            '"train-wifi-line"',
+            '"translate-2"',
+            '"translate"',
+            '"travesti-fill"',
+            '"travesti-line"',
+            '"treasure-map-fill"',
+            '"treasure-map-line"',
+            '"trello-fill"',
+            '"trello-line"',
+            '"trophy-fill"',
+            '"trophy-line"',
+            '"truck-fill"',
+            '"truck-line"',
+            '"tumblr-fill"',
+            '"tumblr-line"',
+            '"tv-2-fill"',
+            '"tv-2-line"',
+            '"tv-fill"',
+            '"tv-line"',
+            '"twitch-fill"',
+            '"twitch-line"',
+            '"twitter-fill"',
+            '"twitter-line"',
+            '"typhoon-fill"',
+            '"typhoon-line"',
+            '"u-disk-fill"',
+            '"u-disk-line"',
+            '"ubuntu-fill"',
+            '"ubuntu-line"',
+            '"umbrella-fill"',
+            '"umbrella-line"',
+            '"underline"',
+            '"uninstall-fill"',
+            '"uninstall-line"',
+            '"unsplash-fill"',
+            '"unsplash-line"',
+            '"upload-2-fill"',
+            '"upload-2-line"',
+            '"upload-cloud-2-fill"',
+            '"upload-cloud-2-line"',
+            '"upload-cloud-fill"',
+            '"upload-cloud-line"',
+            '"upload-fill"',
+            '"upload-line"',
+            '"usb-fill"',
+            '"usb-line"',
+            '"user-2-fill"',
+            '"user-2-line"',
+            '"user-3-fill"',
+            '"user-3-line"',
+            '"user-4-fill"',
+            '"user-4-line"',
+            '"user-5-fill"',
+            '"user-5-line"',
+            '"user-6-fill"',
+            '"user-6-line"',
+            '"user-add-fill"',
+            '"user-add-line"',
+            '"user-fill"',
+            '"user-follow-fill"',
+            '"user-follow-line"',
+            '"user-heart-fill"',
+            '"user-heart-line"',
+            '"user-line"',
+            '"user-location-fill"',
+            '"user-location-line"',
+            '"user-received-2-fill"',
+            '"user-received-2-line"',
+            '"user-received-fill"',
+            '"user-received-line"',
+            '"user-search-fill"',
+            '"user-search-line"',
+            '"user-settings-fill"',
+            '"user-settings-line"',
+            '"user-shared-2-fill"',
+            '"user-shared-2-line"',
+            '"user-shared-fill"',
+            '"user-shared-line"',
+            '"user-smile-fill"',
+            '"user-smile-line"',
+            '"user-star-fill"',
+            '"user-star-line"',
+            '"user-unfollow-fill"',
+            '"user-unfollow-line"',
+            '"user-voice-fill"',
+            '"user-voice-line"',
+            '"video-add-fill"',
+            '"video-add-line"',
+            '"video-chat-fill"',
+            '"video-chat-line"',
+            '"video-download-fill"',
+            '"video-download-line"',
+            '"video-fill"',
+            '"video-line"',
+            '"video-upload-fill"',
+            '"video-upload-line"',
+            '"vidicon-2-fill"',
+            '"vidicon-2-line"',
+            '"vidicon-fill"',
+            '"vidicon-line"',
+            '"vimeo-fill"',
+            '"vimeo-line"',
+            '"vip-crown-2-fill"',
+            '"vip-crown-2-line"',
+            '"vip-crown-fill"',
+            '"vip-crown-line"',
+            '"vip-diamond-fill"',
+            '"vip-diamond-line"',
+            '"vip-fill"',
+            '"vip-line"',
+            '"virus-fill"',
+            '"virus-line"',
+            '"visa-fill"',
+            '"visa-line"',
+            '"voice-recognition-fill"',
+            '"voice-recognition-line"',
+            '"voiceprint-fill"',
+            '"voiceprint-line"',
+            '"volume-down-fill"',
+            '"volume-down-line"',
+            '"volume-mute-fill"',
+            '"volume-mute-line"',
+            '"volume-off-vibrate-fill"',
+            '"volume-off-vibrate-line"',
+            '"volume-up-fill"',
+            '"volume-up-line"',
+            '"volume-vibrate-fill"',
+            '"volume-vibrate-line"',
+            '"vuejs-fill"',
+            '"vuejs-line"',
+            '"walk-fill"',
+            '"walk-line"',
+            '"wallet-2-fill"',
+            '"wallet-2-line"',
+            '"wallet-3-fill"',
+            '"wallet-3-line"',
+            '"wallet-fill"',
+            '"wallet-line"',
+            '"water-flash-fill"',
+            '"water-flash-line"',
+            '"webcam-fill"',
+            '"webcam-line"',
+            '"wechat-2-fill"',
+            '"wechat-2-line"',
+            '"wechat-fill"',
+            '"wechat-line"',
+            '"wechat-pay-fill"',
+            '"wechat-pay-line"',
+            '"weibo-fill"',
+            '"weibo-line"',
+            '"whatsapp-fill"',
+            '"whatsapp-line"',
+            '"wheelchair-fill"',
+            '"wheelchair-line"',
+            '"wifi-fill"',
+            '"wifi-line"',
+            '"wifi-off-fill"',
+            '"wifi-off-line"',
+            '"window-2-fill"',
+            '"window-2-line"',
+            '"window-fill"',
+            '"window-line"',
+            '"windows-fill"',
+            '"windows-line"',
+            '"windy-fill"',
+            '"windy-line"',
+            '"wireless-charging-fill"',
+            '"wireless-charging-line"',
+            '"women-fill"',
+            '"women-line"',
+            '"wubi-input"',
+            '"xbox-fill"',
+            '"xbox-line"',
+            '"xing-fill"',
+            '"xing-line"',
+            '"youtube-fill"',
+            '"youtube-line"',
+            '"zcool-fill"',
+            '"zcool-line"',
+            '"zhihu-fill"',
+            '"zhihu-line"',
+            '"zoom-in-fill"',
+            '"zoom-in-line"',
+            '"zoom-out-fill"',
+            '"zoom-out-line"',
+            '"zzz-fill"',
+            '"zzz-line"',
+        ),
+    ),
+);

+ 171 - 24
table/manage/admin.php

@@ -1,42 +1,156 @@
 <?php
 return array
 (
+    # 数据来源,如果当前菜单不是表名,这里可以定义从哪个表获取数据
+    //'source' => 'manage/admin',
     # 列表页配置
     'list' => array
     (
-        # 列表页描述
-        'desc' => 'test',
+        //'where' => array('group_id' => $group),
+        # 列表页类型 table表格、article文章、pic图片、goods商品,默认是表格,除table外,其余类型需要增加layout项,用以控制展示位置,并且批量操作功能将失效,如批量删除、批量操作等,后续增加更多类型
+        'type' => 'table',
+        # 是否显示序号
+        /*
+        'index' => array
+        (
+            'name' => '序号',
+            # 固定表头,field中也支持
+            'fixed' => true,
+        ),
+        */
         # 展示的字段
-        'field'      => 'id,name,mobile,role,cdate',
-        # 列表的高度,auto和100%或者具体数值,默认是auto
-        'height' => 'auto',
-        # 快速过滤字段,默认为name
-        'filter' => 'name',
-        'role' => array
+        'field'      => array
         (
-            'show' => 'Dever::db("role", "manage")->find({role})',
+            'id',
+            'name',
+            # 实现多级表头,两个字段合并到一起展示,因vue3问题,仅支持三级表头哦
+            /*
+            'test2' => array
+            (
+                'name' => '基本资料',
+                'type' => 'mul',
+                'child' => array
+                (
+                    'avatar' => 'image',
+                    'mobile' => array
+                    (
+                        'type' => 'show',
+                        # 加入排序
+                        'sort' => true,
+                    ),
+                ),
+            ),*/
+
+            'avatar' => 'image',
+            'mobile' => array
+            (
+                'sort' => true,
+            ),
+            'role',
+            /*
+            # 自定义展示内容
+            'role' => array
+            (
+                //'show' => 'Dever::db("role", "manage")->find("{id}")["name"]',
+                # 气泡卡片展示
+                'type' => 'popover',
+                # title
+                'title' => '查看更多',
+                # 位置:top/top-start/top-end/bottom/bottom-start/bottom-end/left/left-start/left-end/right/right-start/right-end
+                'location' => 'right',
+                'show' => 'Dever::load("common")->show("{role}")',
+            ),*/
+            'status' => array
+            (
+                'type' => 'switch',
+                'show'  => '{status}',
+                'active_value' => 1,
+                'inactive_value' => 2,
+            ),
+            'cdate',
         ),
+        # 扩展展示内容
+        //'expand' => 'manage/common.show',
+
+        /*
+        'type' => 'article',
+        'layout' => array
+        (
+            array
+            (
+                'type' => 'avatar',
+                'value' => array
+                (
+                    'image' => 'avatar',
+                )
+            ),
+            array
+            (
+                'type' => 'content',
+                'value' => array
+                (
+                    'title' => 'name',
+                    'description' => 'role'
+                )
+            ),
+            array
+            (
+                'type' => 'content',
+                'value' => array
+                (
+                    'item' => array('时间', 'cdate'),
+                )
+            ),
+        ),
+        */
+
+        /*
+        'type' => 'goods',
+        'layout' => array
+        (
+            'tag' => 'mobile',
+            'image' => 'avatar',
+            'title' => 'name',
+            'description' => 'role',
+            //'icon' => 'icon',
+        ),*/
+
+        /*
+        'type' => 'pic',
+        'layout' => array
+        (
+            'id' => 'id',
+            'image' => 'avatar',
+        ),*/
+        # 列表页描述
+        //'desc' => 'test',
+        # 列表的高度,auto和100%或者具体数值,默认是auto
+        'height' => 'auto',
+        
         # 列表页按钮,默认是快速新增和删除
         'button' => array
         (
             '新增' => 'add',
-            '快速新增' => 'fastadd',
-            '删除' => 'del',
-            '更改角色' => array('oper', 'role'),
-            '链接跳转' => array('link', 'https://www.baidu.com/'),
-            '路由跳转' => array('route', 'manage/menu?test=1'),
-            '回收站' => 'recycler',
+            //'新增' => 'fastadd',
+            '删除' => 'recycle',//删除到回收站
+            //'彻底删除' => 'delete',
+            //'更改角色' => array('oper', 'role'),
+            //'链接跳转' => array('link', 'https://www.baidu.com/'),
+            //'路由跳转' => array('route', 'manage/menu?test=1'),
         ),
         # 列表页每条数据的按钮,默认是快速编辑和删除
         'data_button' => array
         (
             '编辑' => 'edit',
+            //'编辑' => 'fastedit',
             # 只处理某个字段,多个用逗号隔开
             //'编辑' => array('fastedit', 'name'),
             //'编辑' => array('fastedit'),
-            '删除' => 'del',
-            '操作' => array('oper', 'role'),
-            '详情' => 'view',
+            '删除' => 'recycle',//删除到回收站
+            //'彻底删除' => 'delete',
+            //'操作' => array('oper', 'role'),
+            //'接口操作' => array('api', 'api'),
+            //'详情' => array('view', 'platform/admin?type=view&id=id'),
             //'链接跳转' => array('link', 'https://www.baidu.com/'),
             # 第三个参数可以自定义图标:https://element-plus.org/zh-CN/component/icon.html#icon-collection
             //'路由跳转' => array('route', 'manage/menu?test=1', 'ChatLineSquare'),
@@ -49,7 +163,8 @@ return array
         # 列表页导出
         'export' => array
         (
-
+            'out' => '导出',
+            'manage/common.out' => '自定义导出',
         ),
         # 搜索字段 fulltext 模糊查询
         'search'    => array
@@ -58,6 +173,8 @@ return array
             'mobile',
             'role' => 'group',
         ),
+        # 统计
+        //'stat' => 'manage/common.stat',
     ),
     
     # 更新页配置
@@ -171,12 +288,14 @@ return array
             max:多选限制选择数目,最大选择数目
 
             tree:树形选择器
+            tree2:大量数据下的树形选择器
             area:地区选择器
             select:选择器
+            select_tree:选择器,多选的树形模式
             set:
             clearable:是否可清空选择,true/false
             multiple:开启多选,true/false
-            filterable:开启搜索,true/false
+            remote:开启远程搜索,这里定义远程搜索的url
 
             rate:评分
             set:
@@ -267,6 +386,8 @@ return array
                 'value' => '',
                 # 对更新的值进行处理
                 'handle' => 'manage/common.createPwd',
+                # 空值不允许入库
+                'empty'  => false,
                 'rules'     => array
                 (
                     array
@@ -286,7 +407,19 @@ return array
                     ),
                 ),
             ),
-            'role' => 'checkbox',
+            'role' => array
+            (
+                'type' => 'checkbox',
+                # 是否开启控制功能,需要配置control
+                //'control' => true,
+                # 开启远程获取数据功能,这里设置接口即可,访问到api下
+                'remote' => 'manage/admin.getSystem',
+            ),
+            'system_relation' => array
+            (
+                'type' => 'tree',
+                //'value'    => 'Dever::load("role.getSystemData")',
+            ),
             # 定义另外一个表或者方法里的字段,带有"."就是方法,调用manage/role里的upload配置,这里也可以自行配置
             //'manage/role' => 'upload',
             'avatar' => array
@@ -295,17 +428,31 @@ return array
                 # 获取上传组件的配置
                 'upload' => 'pic',
                 # 显示的样式 可选值:'text' | 'picture' | 'picture-card'
-                'show' => 'picture-card',
+                'style' => 'picture-card',
                 # 是否支持多选
                 'multiple' => true,
             ),
         ),
 
+        # 是否开启控制功能
+        /*
+        'control' => array
+        (
+            'avatar' => array
+            (
+                'role' => 1,
+            ),
+        ),
+        */
+
         # update提交之前的操作,需要验证哪些字段唯一,多个用逗号隔开
         'check' => 'mobile',
-        # update提交之前的操作,多个用逗号隔开
+        # update提交之前的操作
         'start' => '',
-        # update提交之后的操作,多个用逗号隔开
+        # update提交之后的操作
         'end' => '',
     ),
+
+    # 详情页配置
+    'view' => 'common.view',
 );

+ 32 - 0
table/manage/config.php

@@ -0,0 +1,32 @@
+<?php
+return array
+(
+    'list' => array
+    (
+        'field'      => array
+        (
+            'name',
+        ),
+        'data_button' => array
+        (
+            '编辑' => 'fastedit',
+        ),
+    ),
+    'update' => array
+    (
+        # 展示左侧分栏
+        'column' => array
+        (
+            'load' => 'manage/config',
+            'add' => '新增',
+            'key' => 'id',
+            'data' => 'config.getTree',
+            'active' => 1,
+            'where' => 'id',
+        ),
+        'field'    => array
+        (
+            'name',
+        ),
+    ),
+);

+ 141 - 40
table/manage/core.php

@@ -3,49 +3,150 @@
 # 图标 https://vue-admin-beautiful.com/admin-plus/#/vab/icon/remixIcon
 return array
 (
-    # 定义父级菜单
-    'set' => array
+    # 系统定义 默认将建立platform和group系统
+    /*
+    'system' => array
     (
-        # 菜单名称
-        'name' => '配置',
-        # 菜单图标
-        'icon' => 'settings-line',
-        # 菜单排序 正序
-        'sort' => '100',
-    ),
-    # 定义子级菜单 key为表名,如果不是表名则为自定义菜单,link填写不同
-    'admin'      => array
-    (
-        # 上级菜单
-        'parent'    => 'set',
-        # 菜单名称
-        'name'      => '用户管理',
-        # 菜单图标
-        'icon'      => 'user-settings-line',
-        # 菜单排序 正序
-        'sort'      => '1',
-        # 菜单链接 可选项:table[可选项:table、list、photo]、update、stat
-        'link'      => 'table',
-        # 标签 这里需要设置获取标签的方法
-        'badge'     => 'test.badge',
-    ),
+        'main' => array
+        (
+            'name' => '测试系统',
+            'sort' => '-100',
+            # 这个是系统的数据隔离类型,database是分库隔离,table是分表隔离,field是分区隔离,where是字段隔离
+            'partition' => 'database',
+            # 关联表名
+            'relation_table' => 'manage/platform',
+            # 关联字段名
+            'relation_field' => 'platform_id',
+            # 关联用户表表名
+            'relation_user_table' => 'manage/admin',
+        ),
+    ),*/
 
-    'menu'      => array
+    # 菜单定义
+    'menu' => array
     (
-        'parent'    => 'set',
-        'name'      => '菜单管理',
-        'icon'      => 'menu-line',
-        'sort'      => '2',
-        'link'      => 'table',
-    ),
+        # 定义父级菜单
+        'set' => array
+        (
+            # 菜单名称
+            'name' => '配置',
+            # 菜单图标
+            'icon' => 'settings-line',
+            # 菜单排序 正序
+            'sort' => '100',
+            # 所属系统 系统key,一般只需主菜单填写system
+            'system' => 'platform',
+        ),
+        # 定义二级菜单
+        'platform' => array
+        (
+            'parent' => 'set',
+            'name' => '平台管理',
+            'icon' => 'book-open-line',
+            'sort' => '200',
+        ),
+        # 定义三级菜单 一般和表名一致,如果不是表名则为自定义菜单
+        'admin' => array
+        (
+            # 所属项目 不填写则获取当前deverapp
+            'app'       => 'manage',
+            # 上级菜单
+            'parent'    => 'platform',
+            # 菜单名称
+            'name'      => '账户管理',
+            # 菜单图标
+            'icon'      => 'user-settings-line',
+            # 菜单排序 正序
+            'sort'      => '1',
+            # 菜单路径 可选项:main列表页,update更新页,stat统计页,layout自定义页,不填写默认为main
+            'path'      => 'main',
+            # 标签 这里需要设置获取标签的方法
+            'badge'     => 'test.badge',
+        ),
 
-    'recycler'      => array
-    (
-        'parent'    => 'set',
-        'name'      => '回收站',
-        'icon'      => '',
-        'sort'      => '3',
-        'link'      => 'table',
-        'show'      => 2,
+        'role' => array
+        (
+            'parent'    => 'platform',
+            'name'      => '角色管理',
+            'icon'      => 'archive-line',
+            'sort'      => '2',
+        ),
+
+        'recycler' => array
+        (
+            'parent'    => 'platform',
+            'name'      => '回收站',
+            'icon'      => '',
+            'sort'      => '100',
+            # 不显示在菜单中
+            'show'      => 2,
+        ),
+
+        'menu' => array
+        (
+            'parent'    => 'platform',
+            'name'      => '菜单管理',
+            'icon'      => 'menu-line',
+            'sort'      => '3',
+        ),
+
+        'group_manage' => array
+        (
+            'parent'    => 'platform',
+            'name'      => '集团管理',
+            'icon'      => 'group-2-line',
+            'sort'      => '4',
+        ),
+
+        'config' => array
+        (
+            'parent'    => 'platform',
+            'name'      => '配置管理',
+            'icon'      => 'album-line',
+            'sort'      => '5',
+            'path'      => 'update',
+            # 后续完善配置功能
+            'show'      => 2,
+        ),
+
+        'set_group' => array
+        (
+            'name' => '配置',
+            'icon' => 'settings-line',
+            'sort' => '100',
+            'system' => 'group',
+        ),
+
+        'group' => array
+        (
+            'parent'    => 'set_group',
+            'name'      => '集团管理',
+            'icon'      => 'group-2-line',
+            'sort'      => '100',
+        ),
+
+        'group_user' => array
+        (
+            'parent'    => 'group',
+            'name'      => '账户管理',
+            'icon'      => 'user-settings-line',
+            'sort'      => '1',
+        ),
+
+        'group_role' => array
+        (
+            'parent'    => 'group',
+            'name'      => '角色管理',
+            'icon'      => 'archive-line',
+            'sort'      => '2',
+        ),
+
+        'group_org' => array
+        (
+            'parent'    => 'group',
+            'name'      => '组织管理',
+            'icon'      => 'voiceprint-fill',
+            'sort'      => '5',
+        ),
     ),
 );

+ 62 - 0
table/manage/group_manage.php

@@ -0,0 +1,62 @@
+<?php
+return array
+(
+    'source' => 'manage/group',
+    'list' => array
+    (
+        'field'      => array
+        (
+            'name',
+            'sort' => 'input',
+            'status' => array
+            (
+                'type' => 'switch',
+                'show'  => '{status}',
+                'active_value' => 1,
+                'inactive_value' => 2,
+            ),
+        ),
+        'data_button' => array
+        (
+            '编辑' => 'fastedit',
+            //'删除' => 'recycle',
+            //'管理账户列表' => array('route', array('path' => 'set_group/group_user', 'param' => array('set' => array('system_id' => 2, 'relation_id' => 'id')))),
+            //'管理账户列表' => array('route', 'set_group/group_user?set[system_id]=2&set[relation_id]=id'),
+        ),
+    ),
+    'update' => array
+    (
+        'field'    => array
+        (
+            'name',
+            'mobile' => array
+            (
+                'show'      => '"{mobile}" ? false : true',
+                'type'      => 'text',
+                'desc'      => '请输入管理员手机号,默认密码123456',
+                'placeholder' => '管理员手机号',
+                'rules'     => array
+                (
+                    array
+                    (
+                        'required' => true,
+                        'trigger' => 'blur',
+                        'message' => '请输入手机号',
+                    ),
+                    array
+                    (
+                        'len' => 11,
+                        'pattern' => Dever::rule('mobile', ''),
+                        'trigger' => 'blur',
+                        'message' => '手机号错误',
+                        'type' => 'string',
+                    ),
+                ),
+            ),
+            'sort',
+            'status' => 'radio',
+        ),
+
+        'end' => 'group.update',
+    ),
+);

+ 49 - 0
table/manage/group_org.php

@@ -0,0 +1,49 @@
+<?php
+return array
+(
+    'list' => array
+    (
+        'field'      => array
+        (
+            'name',
+            'sort' => 'input',
+            'manage/group_org_job'=> array
+            (
+                'name'      => '职位列表',
+                'where'      => array('org_id' => 'id'),
+            ),
+            'status' => array
+            (
+                'type' => 'switch',
+                'show'  => '{status}',
+                'active_value' => 1,
+                'inactive_value' => 2,
+            ),
+        ),
+
+        'button' => array
+        (
+            '新增' => array('fastadd'),
+        ),
+
+        'data_button' => array
+        (
+            '编辑' => array('fastedit', 'name,sort,status,manage/group_org_job'),
+        ),
+
+    ),
+    'update' => array
+    (
+        'field'    => array
+        (
+            'name',
+            'sort',
+            'status' => 'radio',
+            'manage/group_org_job'=> array
+            (
+                'name'      => '职位设置',
+                'where'      => array('org_id' => 'id'),
+            ),
+        ),
+    ),
+);

+ 13 - 0
table/manage/group_org_job.php

@@ -0,0 +1,13 @@
+<?php
+return array
+(
+    'update' => array
+    (
+        'field'    => array
+        (
+            'id' => 'hidden',
+            'name',
+        ),
+        'drag' => 'sort',
+    ),
+);

+ 2 - 0
table/manage/group_role.php

@@ -0,0 +1,2 @@
+<?php
+return include('role.php');

+ 2 - 0
table/manage/group_user.php

@@ -0,0 +1,2 @@
+<?php
+return include('admin.php');

+ 100 - 0
table/manage/menu.php

@@ -0,0 +1,100 @@
+<?php
+$system = Dever::input('search')['system_id'] ?? 1;
+return array
+(
+    'list' => array
+    (
+        # 展示左侧分栏
+        'column' => array
+        (
+            # 分栏数据来源
+            'load' => 'manage/system',
+            # 分栏新增按钮
+            //'add' => '新增',
+            # 分栏编辑按钮,这里直接用图标
+            //'edit' => true,
+            # 分栏删除按钮,这里直接用图标
+            //'delete' => true,
+            'edit' => true,
+            # 关键字段,一般为id或者key
+            'key' => 'id',
+            # 获取数据
+            'data' => 'system.getTree',
+            # 默认展开
+            'active' => 1,
+            # 对应的where条件的key
+            'where' => 'system_id',
+        ),
+        # 默认where条件
+        'where' => array('system_id' => $system),
+        # 展示的字段
+        'field'      => array
+        (
+            'name',
+            'key',
+            /*
+            'system_id' => array
+            (
+                'show' => 'Dever::db("system", "manage")->find(array("key" => "{system_id}"))["name"] ?? ""',
+            ),*/
+            //'path',
+            'icon' => 'icon',
+            'sort' => 'input',
+            'show' => array
+            (
+                # 行中修改 仅支持switch、select、input,太复杂的咱就别在行中修改了吧
+                'type' => 'switch',
+                'show'  => '{show}',
+                'active_value' => 1,
+                'inactive_value' => 2,
+            ),
+        ),
+        # 树形表格 仅type=table时支持,这里设置获取根数据的条件即可
+        'tree' => array('parent_id', '0', 'id'),
+
+        'search'    => array
+        (
+            'system_id' => 'hidden',
+        ),
+
+        'button' => array
+        (
+            '新增主菜单' => array('fastadd', array('parent_id' => '0', 'system_id' => $system, 'path' => '')),
+        ),
+
+        'data_button' => array
+        (
+            '编辑' => array('fastedit', 'name,key,icon,path,link,sort,show'),
+            '新增子菜单' => array('fastadd', array('parent_id' => 'id', 'system_id' => $system)),
+            //'删除' => 'recycle',
+        ),
+
+    ),
+    'update' => array
+    (
+        'field'    => array
+        (
+            'name',
+            'key',
+            'parent_id',
+            'system_id',
+            'path' => array
+            (
+                'type' => 'select',
+                'control' => true,
+            ),
+            'link',
+            'icon' => 'icon',
+            'sort',
+            'show' => 'radio',
+        ),
+        'check' => 'key',
+        'control' => array
+        (
+            'link' => array
+            (
+                'path' => 'link',
+            ),
+        ),
+    ),
+);

+ 7 - 1
table/manage/recycler.php

@@ -3,14 +3,20 @@ return array
 (
     'list' => array
     (
-        'field'      => 'id,table,table_id,content,cdate',
+        # 设置数据来源
+        'data'      => 'recycler.getData', 
         'search'    => array
         (
             'table' => 'hidden',
         ),
         'button' => array
+        (
+            '批量恢复' => 'recover',
+        ),
+        'data_button' => array
         (
             '恢复' => 'recover',
+            '彻底删除' => 'delete',
         ),
     ),
 );

+ 46 - 0
table/manage/role.php

@@ -0,0 +1,46 @@
+<?php
+return array
+(
+    'list' => array
+    (
+        'field'      => array
+        (
+            'id',
+            'name',
+            'system' => array
+            (
+                'show' => 'Dever::load("role")->showSystem("{system}")',
+            ),
+            'menu' => array
+            (
+                'show' => 'Dever::load("role")->showMenu("{menu}")',
+            ),
+            /*
+            'auth' => array
+            (
+                'show' => 'Dever::load("role")->showFunc("{auth}")',
+            ),*/
+            'cdate',
+        ),
+        'button' => array
+        (
+            '新增' => 'add',
+        ),
+        'data_button' => array
+        (
+            '编辑' => 'edit',
+        ),
+    ),
+    'update' => array
+    (
+        'field'    => array
+        (
+            'name',
+            'auth' => array
+            (
+                'type' => 'tree',
+            ),
+        ),
+        'start' => 'role.update',
+    ),
+);

+ 20 - 0
table/manage/system.php

@@ -0,0 +1,20 @@
+<?php
+return array
+(
+    'list' => array
+    (
+        'field'      => array
+        (
+            'name',
+            'sort',
+        ),
+    ),
+    'update' => array
+    (
+        'field'    => array
+        (
+            'name',
+            'sort',
+        ),
+    ),
+);

+ 40 - 4
table/menu.php

@@ -15,15 +15,40 @@ return array
             'name'      => '标识',
             'type'      => 'varchar(60)',
         ),
-        'parent_key' => array
+        'app' => array
         (
-            'name'      => '上级菜单',
+            'name'      => '项目',
             'type'      => 'varchar(60)',
-            'default'   => '/',
+            'value'     => '\\Dever\\Project::read()',
         ),
-        'link' => array
+        'parent_id' => array
+        (
+            'name'      => '上级菜单',
+            'type'      => 'int(11)',
+            'default'   => '0',
+        ),
+        'system_id' => array
+        (
+            'name'      => '系统',
+            'type'      => 'varchar(80)',
+        ),
+        'path' => array
         (
             'name'      => '路径',
+            'type'      => 'varchar(200)',
+            'default'   => 'main',
+            'value'     => array
+            (
+                'main' => '列表页',
+                'update' => '更新页',
+                'stat' => '统计页',
+                'layout' => '自定义页',
+                'link' => '链接',
+            ),
+        ),
+        'link' => array
+        (
+            'name'      => '链接',
             'type'      => 'varchar(2000)',
         ),
         'icon' => array
@@ -46,6 +71,17 @@ return array
             'name'      => '是否展示',
             'type'      => 'tinyint(1)',
             'default'   => 1,
+            'value'     => array
+            (
+                1 => '展示',
+                2 => '不展示',
+            ),
+        ),
+        'func' => array
+        (
+            'name'      => '是否有功能菜单',
+            'type'      => 'tinyint(1)',
+            'default'   => 2,
         ),
     ),
 );

+ 33 - 0
table/menu_func.php

@@ -0,0 +1,33 @@
+<?php
+return array
+(
+    'name' => '功能',
+    'order' => 'sort asc',
+    'struct' => array
+    (
+        'name' => array
+        (
+            'name'      => '名称',
+            'type'      => 'varchar(32)',
+        ),
+        'key' => array
+        (
+            'name'      => '标识',
+            'type'      => 'varchar(80)',
+        ),
+        'menu_id' => array
+        (
+            'name'      => '菜单id',
+            'type'      => 'int(11)',
+        ),
+        'sort' => array
+        (
+            'name'      => '排序',
+            'type'      => 'int(11)',
+        ),
+    ),
+    'index' => array
+    (
+        'search' => 'menu_id,`key`',
+    ),
+);

+ 23 - 0
table/mobile_system.php

@@ -0,0 +1,23 @@
+<?php
+return array
+(
+    'name' => '当前用户选择的系统',
+    'struct' => array
+    (
+        'mobile' => array
+        (
+            'name'      => '手机号',
+            'type'      => 'varchar(11)',
+        ),
+        'system_id' => array
+        (
+            'name'      => '系统id',
+            'type'      => 'int(11)',
+        ),
+        'relation_id' => array
+        (
+            'name'      => '系统关联表id',
+            'type'      => 'int(11)',
+        ),
+    ),
+);

+ 30 - 0
table/platform.php

@@ -0,0 +1,30 @@
+<?php
+return array
+(
+    # 暂时是单一平台,后续优化成多平台
+    'name' => '平台',
+    'order' => 'sort asc',
+    'struct' => array
+    (
+        'name' => array
+        (
+            'name'      => '平台名称',
+            'type'      => 'varchar(200)',
+        ),
+        'sort' => array
+        (
+            'name'      => '排序',
+            'type'      => 'int(11)',
+            'default'   => '1',
+        ),
+    ),
+    'default' => array
+    (
+        'field' => 'id,name,sort,cdate',
+        'value' => array
+        (
+            '1,"默认平台",-100,' . DEVER_TIME,
+        ),
+        'num' => 1,
+    ),
+);

+ 26 - 1
table/role.php

@@ -1,7 +1,7 @@
 <?php
 return array
 (
-    'name' => '角色',
+    'name' => '平台角色',
     'struct' => array
     (
         'name' => array
@@ -9,5 +9,30 @@ return array
             'name'      => '名称',
             'type'      => 'varchar(32)',
         ),
+        'system' => array
+        (
+            'name'      => '系统',
+            'type'      => 'varchar(1000)',
+        ),
+        'menu' => array
+        (
+            'name'      => '菜单',
+            'type'      => 'varchar(2000)',
+        ),
+        'auth' => array
+        (
+            'name'      => '权限',
+            'type'      => 'text',
+            'value'    => 'Dever::load("role.getAuthData")',
+        ),
+    ),
+    'default' => array
+    (
+        'field' => 'name,system,cdate',
+        'value' => array
+        (
+            '"默认角色",1,' . DEVER_TIME,
+        ),
+        'num' => 1,
     ),
 );

+ 63 - 0
table/system.php

@@ -0,0 +1,63 @@
+<?php
+return array
+(
+    'name' => '系统',
+    'order' => 'sort asc',
+    'struct' => array
+    (
+        'name' => array
+        (
+            'name'      => '系统名称',
+            'type'      => 'varchar(32)',
+        ),
+        'key' => array
+        (
+            'name'      => '系统标识',
+            'type'      => 'varchar(60)',
+        ),
+        'partition' => array
+        (
+            'name'      => '数据隔离类型',
+            'type'      => 'varchar(20)',
+            'default'   => 'database',
+            'value'     => array
+            (
+                'database' => '分库隔离',
+                'table' => '分表隔离',
+                'field' => '分区隔离',
+                'where' => '分条件隔离',
+            ),
+        ),
+        'relation_table' => array
+        (
+            'name'      => '关联表表名',
+            'type'      => 'varchar(200)',
+        ),
+        'relation_field' => array
+        (
+            'name'      => '关联表字段名',
+            'type'      => 'varchar(200)',
+        ),
+        'relation_user_table' => array
+        (
+            'name'      => '关联用户表表名',
+            'type'      => 'varchar(200)',
+        ),
+        'sort' => array
+        (
+            'name'      => '排序',
+            'type'      => 'int(11)',
+        ),
+    ),
+
+    'default' => array
+    (
+        'field' => 'id,name,`key`,`partition`,relation_table,relation_field,relation_user_table,sort',
+        'value' => array
+        (
+            '1,"平台","platform","database","manage/platform","platform_id","manage/admin",-1000',
+            '2,"集团","group","database","manage/group","group_id","manage/group_user",-900',
+        ),
+        'num' => 1,
+    ),
+);