liruzong 6 роки тому
батько
коміт
9edc950144
100 змінених файлів з 17672 додано та 0 видалено
  1. 8 0
      Thinkphp5整合excel导入导出/application/.htaccess
  2. 12 0
      Thinkphp5整合excel导入导出/application/command.php
  3. 12 0
      Thinkphp5整合excel导入导出/application/common.php
  4. 243 0
      Thinkphp5整合excel导入导出/application/config.php
  5. 53 0
      Thinkphp5整合excel导入导出/application/database.php
  6. 95 0
      Thinkphp5整合excel导入导出/application/index/controller/Index.php
  7. 57 0
      Thinkphp5整合excel导入导出/application/index/view/index/daoru.html
  8. 87 0
      Thinkphp5整合excel导入导出/application/index/view/index/index.html
  9. 21 0
      Thinkphp5整合excel导入导出/application/route.php
  10. 28 0
      Thinkphp5整合excel导入导出/application/tags.php
  11. 25 0
      Thinkphp5整合excel导入导出/build.php
  12. 2 0
      Thinkphp5整合excel导入导出/extend/.gitignore
  13. 39 0
      Thinkphp5整合excel导入导出/member.sql
  14. 8 0
      Thinkphp5整合excel导入导出/public/.htaccess
  15. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/0d73cf016450bf555d7d02e445ecd3ff.xlsx
  16. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/0db3d52e668da694e04ba68a7d740670.xls
  17. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/0fbfef46cda844d207fc0e5d65741019.xls
  18. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/186413a26ea78c1de168ac6eb8577ca7.xls
  19. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/194e4b3629f1a75a8a2f944309c56bcd.xls
  20. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/1cc2a4115ebd73d2407667367d467400.xlsx
  21. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/246a7c4f086d7d276f1cde98b401caa0.xls
  22. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/2bddc7fe48cf9f9203dbae5aa26a07e1.xlsx
  23. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/2f9e4df48af8b6d7a7328d35b20b53b3.xls
  24. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/31a5d89d5fbd1e7eb2b0d89557baaf27.xlsx
  25. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/395447dba0470c1345245d1074d24df9.xls
  26. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/3d41309b9f42de07c7d228aefc60587c.xls
  27. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/3f2ff1fd7a2ea331344616767a55baea.xls
  28. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/481017e2b9ddc2ebf463c0cbf8c99d30.xls
  29. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/4bb375685f7040007a5cffb1667e4182.xls
  30. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/59924c5b2b326120d4aab47a0fbdf8f0.xlsx
  31. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/5dbe8586fe3cc3c4bbe669fbde912b56.xls
  32. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/62f58857b57a147a676f29820b26f84f.xls
  33. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/6550ee0f31df10d6ea19ddab9ddff710.xls
  34. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/6bb7fe097bf77422645316780f6999dd.xls
  35. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/74d39af71e666ab04c8a2b3a8670e194.xlsx
  36. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/75beb07dcccb43787f449ce80ace50aa.xls
  37. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/97ebc2d29c52a80313c2de4078b4323b.xls
  38. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/a1a653de02eaa6efcde7a8a2ce55cb26.xls
  39. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/b304056b0dcafb0dacf86d94f7438b7e.xls
  40. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/bf4cea87af4d5b130b0a854845bd518d.xls
  41. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/c371218050c615c94f906b05f0ac90a5.xls
  42. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/c46ec03567405cc2ef797e2ec83fd54a.xls
  43. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/cea52c18692e41570f936aa8a122c099.xls
  44. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/cf04bfebbe473df0e209b3d8acf07ccb.xls
  45. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/d180eeaeb76233f049e0497b23b1dbdb.xls
  46. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/d503dc39bd711b288df2d328b0bf9bcd.xlsx
  47. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/e0a1d5c8aafcffda0adbd38102e1eda4.xlsx
  48. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/e2237bfc8aee22a42aba42537c5772a9.xls
  49. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/e29869061df9f4f39bbd2ff95ca0cfe6.xlsx
  50. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/e680902118dfae30cbf4a7df78553f11.xls
  51. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/edbec486ecff51e97894f2c7c7f7bfa2.xls
  52. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/ef1bdf8b96eaa8d6b4dcf3f1fce509a5.xlsx
  53. BIN
      Thinkphp5整合excel导入导出/public/excel/20171201/f1c62e4929a28ef5eb44200472ff2997.xls
  54. BIN
      Thinkphp5整合excel导入导出/public/favicon.ico
  55. 17 0
      Thinkphp5整合excel导入导出/public/index.php
  56. 2 0
      Thinkphp5整合excel导入导出/public/robots.txt
  57. 20 0
      Thinkphp5整合excel导入导出/public/router.php
  58. 2 0
      Thinkphp5整合excel导入导出/public/static/.gitignore
  59. 4 0
      Thinkphp5整合excel导入导出/thinkphp/.gitignore
  60. 1 0
      Thinkphp5整合excel导入导出/thinkphp/.htaccess
  61. 47 0
      Thinkphp5整合excel导入导出/thinkphp/.travis.yml
  62. 119 0
      Thinkphp5整合excel导入导出/thinkphp/CONTRIBUTING.md
  63. 32 0
      Thinkphp5整合excel导入导出/thinkphp/LICENSE.txt
  64. 114 0
      Thinkphp5整合excel导入导出/thinkphp/README.md
  65. 63 0
      Thinkphp5整合excel导入导出/thinkphp/base.php
  66. 12 0
      Thinkphp5整合excel导入导出/thinkphp/codecov.yml
  67. 35 0
      Thinkphp5整合excel导入导出/thinkphp/composer.json
  68. 20 0
      Thinkphp5整合excel导入导出/thinkphp/console.php
  69. 289 0
      Thinkphp5整合excel导入导出/thinkphp/convention.php
  70. 589 0
      Thinkphp5整合excel导入导出/thinkphp/helper.php
  71. 134 0
      Thinkphp5整合excel导入导出/thinkphp/lang/zh-cn.php
  72. 591 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/App.php
  73. 205 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Build.php
  74. 222 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Cache.php
  75. 391 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Collection.php
  76. 178 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Config.php
  77. 719 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Console.php
  78. 213 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Controller.php
  79. 224 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Cookie.php
  80. 156 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Db.php
  81. 212 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Debug.php
  82. 36 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Env.php
  83. 120 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Error.php
  84. 54 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Exception.php
  85. 431 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/File.php
  86. 136 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Hook.php
  87. 223 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Lang.php
  88. 563 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Loader.php
  89. 213 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Log.php
  90. 2268 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Model.php
  91. 401 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Paginator.php
  92. 1205 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Process.php
  93. 1648 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Request.php
  94. 334 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Response.php
  95. 1603 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Route.php
  96. 366 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Session.php
  97. 1147 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Template.php
  98. 329 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Url.php
  99. 1294 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/Validate.php
  100. 0 0
      Thinkphp5整合excel导入导出/thinkphp/library/think/View.php

+ 8 - 0
Thinkphp5整合excel导入导出/application/.htaccess

@@ -0,0 +1,8 @@
+<IfModule mod_rewrite.c>
+  Options +FollowSymlinks -Multiviews
+  RewriteEngine On
+
+  RewriteCond %{REQUEST_FILENAME} !-d
+  RewriteCond %{REQUEST_FILENAME} !-f
+  RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
+</IfModule>

+ 12 - 0
Thinkphp5整合excel导入导出/application/command.php

@@ -0,0 +1,12 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: yunwuxin <448901948@qq.com>
+// +----------------------------------------------------------------------
+
+return [];

+ 12 - 0
Thinkphp5整合excel导入导出/application/common.php

@@ -0,0 +1,12 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: 流年 <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+// 应用公共文件

+ 243 - 0
Thinkphp5整合excel导入导出/application/config.php

@@ -0,0 +1,243 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+return [
+    // +----------------------------------------------------------------------
+    // | 应用设置
+    // +----------------------------------------------------------------------
+
+    // 应用命名空间
+    'app_namespace'          => 'app',
+    // 应用调试模式
+    'app_debug'              => true,
+    // 应用Trace
+    'app_trace'              => false,
+    // 应用模式状态
+    'app_status'             => '',
+    // 是否支持多模块
+    'app_multi_module'       => true,
+    // 入口自动绑定模块
+    'auto_bind_module'       => false,
+    // 注册的根命名空间
+    'root_namespace'         => [],
+    // 扩展函数文件
+    'extra_file_list'        => [THINK_PATH . 'helper' . EXT],
+    // 默认输出类型
+    'default_return_type'    => 'html',
+    // 默认AJAX 数据返回格式,可选json xml ...
+    'default_ajax_return'    => 'json',
+    // 默认JSONP格式返回的处理方法
+    'default_jsonp_handler'  => 'jsonpReturn',
+    // 默认JSONP处理方法
+    'var_jsonp_handler'      => 'callback',
+    // 默认时区
+    'default_timezone'       => 'PRC',
+    // 是否开启多语言
+    'lang_switch_on'         => false,
+    // 默认全局过滤方法 用逗号分隔多个
+    'default_filter'         => '',
+    // 默认语言
+    'default_lang'           => 'zh-cn',
+    // 应用类库后缀
+    'class_suffix'           => false,
+    // 控制器类后缀
+    'controller_suffix'      => false,
+
+    // +----------------------------------------------------------------------
+    // | 模块设置
+    // +----------------------------------------------------------------------
+
+    // 默认模块名
+    'default_module'         => 'index',
+    // 禁止访问模块
+    'deny_module_list'       => ['common'],
+    // 默认控制器名
+    'default_controller'     => 'Index',
+    // 默认操作名
+    'default_action'         => 'index',
+    // 默认验证器
+    'default_validate'       => '',
+    // 默认的空控制器名
+    'empty_controller'       => 'Error',
+    // 操作方法后缀
+    'action_suffix'          => '',
+    // 自动搜索控制器
+    'controller_auto_search' => false,
+
+    // +----------------------------------------------------------------------
+    // | URL设置
+    // +----------------------------------------------------------------------
+
+    // PATHINFO变量名 用于兼容模式
+    'var_pathinfo'           => 's',
+    // 兼容PATH_INFO获取
+    'pathinfo_fetch'         => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
+    // pathinfo分隔符
+    'pathinfo_depr'          => '/',
+    // URL伪静态后缀
+    'url_html_suffix'        => 'html',
+    // URL普通方式参数 用于自动生成
+    'url_common_param'       => false,
+    // URL参数方式 0 按名称成对解析 1 按顺序解析
+    'url_param_type'         => 0,
+    // 是否开启路由
+    'url_route_on'           => true,
+    // 路由使用完整匹配
+    'route_complete_match'   => false,
+    // 路由配置文件(支持配置多个)
+    'route_config_file'      => ['route'],
+    // 是否强制使用路由
+    'url_route_must'         => false,
+    // 域名部署
+    'url_domain_deploy'      => false,
+    // 域名根,如thinkphp.cn
+    'url_domain_root'        => '',
+    // 是否自动转换URL中的控制器和操作名
+    'url_convert'            => true,
+    // 默认的访问控制器层
+    'url_controller_layer'   => 'controller',
+    // 表单请求类型伪装变量
+    'var_method'             => '_method',
+    // 表单ajax伪装变量
+    'var_ajax'               => '_ajax',
+    // 表单pjax伪装变量
+    'var_pjax'               => '_pjax',
+    // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
+    'request_cache'          => false,
+    // 请求缓存有效期
+    'request_cache_expire'   => null,
+    // 全局请求缓存排除规则
+    'request_cache_except'   => [],
+
+    // +----------------------------------------------------------------------
+    // | 模板设置
+    // +----------------------------------------------------------------------
+
+    'template'               => [
+        // 模板引擎类型 支持 php think 支持扩展
+        'type'         => 'Think',
+        // 模板路径
+        'view_path'    => '',
+        // 模板后缀
+        'view_suffix'  => 'html',
+        // 模板文件名分隔符
+        'view_depr'    => DS,
+        // 模板引擎普通标签开始标记
+        'tpl_begin'    => '{',
+        // 模板引擎普通标签结束标记
+        'tpl_end'      => '}',
+        // 标签库标签开始标记
+        'taglib_begin' => '{',
+        // 标签库标签结束标记
+        'taglib_end'   => '}',
+    ],
+
+    // 视图输出字符串内容替换
+    'view_replace_str'       => [],
+    // 默认跳转页面对应的模板文件
+    'dispatch_success_tmpl'  => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
+    'dispatch_error_tmpl'    => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
+
+    // +----------------------------------------------------------------------
+    // | 异常及错误设置
+    // +----------------------------------------------------------------------
+
+    // 异常页面的模板文件
+    'exception_tmpl'         => THINK_PATH . 'tpl' . DS . 'think_exception.tpl',
+
+    // 错误显示信息,非调试模式有效
+    'error_message'          => '页面错误!请稍后再试~',
+    // 显示错误信息
+    'show_error_msg'         => false,
+    // 异常处理handle类 留空使用 \think\exception\Handle
+    'exception_handle'       => '',
+
+    // +----------------------------------------------------------------------
+    // | 日志设置
+    // +----------------------------------------------------------------------
+
+    'log'                    => [
+        // 日志记录方式,内置 file socket 支持扩展
+        'type'  => 'File',
+        // 日志保存目录
+        'path'  => LOG_PATH,
+        // 日志记录级别
+        'level' => [],
+    ],
+
+    // +----------------------------------------------------------------------
+    // | Trace设置 开启 app_trace 后 有效
+    // +----------------------------------------------------------------------
+    'trace'                  => [
+        // 内置Html Console 支持扩展
+        'type' => 'Html',
+    ],
+
+    // +----------------------------------------------------------------------
+    // | 缓存设置
+    // +----------------------------------------------------------------------
+
+    'cache'                  => [
+        // 驱动方式
+        'type'   => 'File',
+        // 缓存保存目录
+        'path'   => CACHE_PATH,
+        // 缓存前缀
+        'prefix' => '',
+        // 缓存有效期 0表示永久缓存
+        'expire' => 0,
+    ],
+
+    // +----------------------------------------------------------------------
+    // | 会话设置
+    // +----------------------------------------------------------------------
+
+    'session'                => [
+        'id'             => '',
+        // SESSION_ID的提交变量,解决flash上传跨域
+        'var_session_id' => '',
+        // SESSION 前缀
+        'prefix'         => 'think',
+        // 驱动方式 支持redis memcache memcached
+        'type'           => '',
+        // 是否自动开启 SESSION
+        'auto_start'     => true,
+    ],
+
+    // +----------------------------------------------------------------------
+    // | Cookie设置
+    // +----------------------------------------------------------------------
+    'cookie'                 => [
+        // cookie 名称前缀
+        'prefix'    => '',
+        // cookie 保存时间
+        'expire'    => 0,
+        // cookie 保存路径
+        'path'      => '/',
+        // cookie 有效域名
+        'domain'    => '',
+        //  cookie 启用安全传输
+        'secure'    => false,
+        // httponly设置
+        'httponly'  => '',
+        // 是否使用 setcookie
+        'setcookie' => true,
+    ],
+
+    //分页配置
+    'paginate'               => [
+        'type'      => 'bootstrap',
+        'var_page'  => 'page',
+        'list_rows' => 15,
+    ],
+
+    
+];

+ 53 - 0
Thinkphp5整合excel导入导出/application/database.php

@@ -0,0 +1,53 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+return [
+    // 数据库类型
+    'type'            => 'mysql',
+    // 服务器地址
+    'hostname'        => '127.0.0.1',
+    // 数据库名
+    'database'        => 'demo',
+    // 用户名
+    'username'        => 'sucaishui',
+    // 密码
+    'password'        => '123456',
+    // 端口
+    'hostport'        => '3306',
+    // 连接dsn
+    'dsn'             => '',
+    // 数据库连接参数
+    'params'          => [],
+    // 数据库编码默认采用utf8
+    'charset'         => 'utf8',
+    // 数据库表前缀
+    'prefix'          => '',
+    // 数据库调试模式
+    'debug'           => true,
+    // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
+    'deploy'          => 0,
+    // 数据库读写是否分离 主从式有效
+    'rw_separate'     => false,
+    // 读写分离后 主服务器数量
+    'master_num'      => 1,
+    // 指定从服务器序号
+    'slave_no'        => '',
+    // 是否严格检查字段是否存在
+    'fields_strict'   => true,
+    // 数据集返回类型
+    'resultset_type'  => 'array',
+    // 自动写入时间戳字段
+    'auto_timestamp'  => false,
+    // 时间字段取出后的默认时间格式
+    'datetime_format' => 'Y-m-d H:i:s',
+    // 是否需要进行SQL性能分析
+    'sql_explain'     => false,
+];

+ 95 - 0
Thinkphp5整合excel导入导出/application/index/controller/Index.php

@@ -0,0 +1,95 @@
+<?php
+namespace app\index\controller;
+use think\Db;
+use think\Controller;
+use think\Loader;
+
+class Index extends Controller
+{
+
+     public function __construct()
+    {
+        parent::__construct();
+    }
+
+
+    public function index()
+    {
+        
+        return $this->fetch();
+            
+    }
+
+    public function impExcel(){
+        vendor("PHPExcel.PHPExcel");
+        Loader::import('PHPExcel.PHPExcel.IOFactory.PHPExcel_IOFactory');
+        Loader::import('PHPExcel.PHPExcel.Reader.Excel5');
+        $objPHPExcel = new \PHPExcel();
+        //获取表单上传文件  
+        $file = request()->file('excel');  
+        $info = $file->validate(['size'=>2097152,'ext'=>'xlsx,xls,csv'])->move(ROOT_PATH . 'public' . DS . 'excel');
+        if($info){  
+            $exclePath = $info->getSaveName();  //获取文件名
+            $name=strrchr($exclePath,'.');
+            $file_name = ROOT_PATH . 'public' . DS . 'excel' . DS . $exclePath;   //上传文件的地址
+            if($name=='.xlsx'){
+                $objReader =\PHPExcel_IOFactory::createReader('Excel2007');
+            }elseif($name=='.xls'){
+                $objReader =\PHPExcel_IOFactory::createReader('Excel5');
+
+            }elseif($name=='.csv'){
+                $objReader =\PHPExcel_IOFactory::createReader('csv');
+            }
+            $obj_PHPExcel =$objReader->load($file_name, $encode = 'utf-8');  //加载文件内容,编码utf-8
+            $excel_array=$obj_PHPExcel->getsheet(0)->toArray();   //转换为数组格式  
+            array_shift($excel_array);  //删除第一个数组(标题);
+            $data = [];  
+            $i=0;  
+            foreach($excel_array as $k=>$v) {  
+                $data[$k]['id'] = $v[0];  
+                $data[$k]['name'] = $v[1];  
+                $data[$k]['image'] = $v[2];  
+                $i++;  
+            }  
+           $success=Db::name('member')->insertAll($data); //批量插入数据
+           $error=$i-$success;  
+            echo "总{$i}条,成功{$success}条,失败{$error}条。";
+        }else{  
+            // 上传失败获取错误信息  
+            echo $file->getError();  
+        }
+    }  
+
+    public function expExcel()  
+    {  
+        vendor("PHPExcel.PHPExcel");  
+        $list=db('member')->field('*')->select();  
+        $objPHPExcel = new \PHPExcel();
+        $objWriter = new \PHPExcel_Writer_Excel5($objPHPExcel);
+        //设置sheet名称
+        $sheets=$objPHPExcel->getActiveSheet()->setTitle('demo');
+        //设置sheet列头信息
+        $objPHPExcel->setActiveSheetIndex()->setCellValue('A1', 'id')->setCellValue('B1', 'name')->setCellValue('C1', 'image');
+        $i=2;
+        foreach($list as $v){
+            //设置单元格的值
+            $sheets=$objPHPExcel->getActiveSheet()->setCellValue('A'.$i,$v['id']);
+            $sheets=$objPHPExcel->getActiveSheet()->setCellValue('B'.$i,$v['name']);
+            $sheets=$objPHPExcel->getActiveSheet()->setCellValue('C'.$i,$v['image']);
+            $i++;
+        }
+        //整体设置字体和字体大小
+        $objPHPExcel->getDefaultStyle()->getFont()->setName( 'Arial');
+        $objPHPExcel->getDefaultStyle()->getFont()->setSize(10);
+        // $objPHPExcel->getActiveSheet()->getColumnDimension('B')->setAutoSize(true); //单元格宽度自适应
+        $objPHPExcel->getActiveSheet()->getColumnDimension('A')->setWidth(20); //设置列宽度
+        $objPHPExcel->getActiveSheet()->getColumnDimension('B')->setWidth(20); //设置列宽度
+        $objPHPExcel->getActiveSheet()->getColumnDimension('C')->setWidth(20); //设置列宽度
+        $objPHPExcel->getActiveSheet()->getStyle('B3')->getFont()->setBold(true); //设置单元格字体加粗
+        // 输出Excel表格到浏览器下载
+        header('Content-Type: application/vnd.ms-excel');
+        header('Content-Disposition: attachment;filename="demo.xls"'); //excel表格名称
+        $objWriter->save('php://output'); 
+    }  
+
+}

+ 57 - 0
Thinkphp5整合excel导入导出/application/index/view/index/daoru.html

@@ -0,0 +1,57 @@
+<!DOCTYPE html>  
+<html>                  
+<head>  
+  <meta charset="utf-8">  
+  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">  
+  <title></title>  
+  <link href="/static/index/css/dandelion.css" rel="stylesheet">
+    <link href="/static/index/css/admin.css" rel="stylesheet" type="text/css"/>
+
+
+
+    <link href="/static/index/css/lib/bootstrap/bootstrap.min.css" rel="stylesheet" type="text/css"/>
+    <link href="/static/index/css/lib/H-ui/H-ui.min.css" rel="stylesheet" type="text/css"/>
+    <link href="/static/index/css/lib/H-ui/iconfont.css" rel="stylesheet" type="text/css"/>
+
+
+    <script type="text/javascript" src="/static/index/js/jquery-3.2.1.min.js"></script>
+    <script type="text/javascript" src="/static/index/js/access.js"></script>
+    <script type="text/javascript" src="/static/index/js/admin.js"></script>
+    <script type="text/javascript" src="/static/index/js/lib/bootstrap/bootstrap.min.js"></script>
+    <script type="text/javascript" src="/static/index/js/layer/layer.js"></script>
+    <script src="/static/index/zui/lib/jquery/jquery.js"></script>
+    <script src="/static/index/zui/js/zui.min.js"></script>
+<script type="text/javascript" src="http://libs.baidu.com/jquery/1.8.3/jquery.min.js"></script>  
+</head>  
+<body>  
+  
+<div class="layui-fluid" >  
+<form method="post" action="{:url('index/impExcel')}" class="form-signin" enctype="multipart/form-data" >
+	<div class="submit-button-form">  
+    	<input name="excel" type="file" class="img_upload_file" style="display: none">  
+    	<button type="button" class="btn btn-success img_upload_btn"  >选择文件 </button><br><br>
+    	<button class="btn btn-success" style="text-align: center">导入</button>  
+    </div>
+
+</form>
+<br>
+<br>
+
+
+<form method="post" action="{:url('index/expExcel')}" class="form-signin" enctype="multipart/form-data" >  
+    
+    <div class="submit-button-form">
+
+    	<button class="btn btn-success">导出</button>  
+               
+    </div>
+</form>
+</div>  
+
+</body>  
+</html>
+<script type="text/javascript">
+	$(".img_upload_btn").click(function() {
+        $(".img_upload_file").click();
+    });
+</script>  

+ 87 - 0
Thinkphp5整合excel导入导出/application/index/view/index/index.html

@@ -0,0 +1,87 @@
+<!DOCTYPE html>  
+<html>                  
+<head>  
+  <meta charset="utf-8">  
+  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">  
+  <title></title>  
+  
+
+    <link href="/static/index/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
+    
+<script type="text/javascript" src="http://libs.baidu.com/jquery/1.8.3/jquery.min.js"></script>  
+</head>  
+<body>  
+  
+<div class="layui-fluid" >  
+<form method="post" action="index.php/index/index/impExcel" class="form-signin" enctype="multipart/form-data" onsubmit="return check()">
+	<div style="text-align: center;">  
+    	<input name="excel" type="file" class="img_upload_file" id="f_file" style="display: none">  
+    	<button type="button" class="btn btn-success img_upload_btn"  >选择文件 </button><br><br>
+    	<button class="btn btn-success" style="text-align: center">导入</button>  
+    </div>
+
+</form>
+<br>
+<br>
+
+
+<form method="post" action="index.php/index/index/expExcel" class="form-signin" enctype="multipart/form-data" >
+    
+    <div style="text-align: center;">
+
+    	<button class="btn btn-success">导出</button>  
+               
+    </div>
+</form>
+</div>  
+
+</body>  
+</html>
+<script type="text/javascript">
+	$(".img_upload_btn").click(function() {
+        $(".img_upload_file").click();
+    });
+$(".img_upload_file").change(function() {
+    /* Act on the event */
+
+    var path = $(".img_upload_file").val(),
+            extStart = path.lastIndexOf('.'),
+            ext = path.substring(extStart,path.length).toUpperCase();
+        //判断图片格式
+    console.log(ext);
+          if(ext !== '.XLSX' && ext !== '.XLS' && ext !== '.CSV' ){
+              alert('请上传正确格式的文件');
+              
+              return false;
+          }
+          
+          var avatar =$(".img_upload_file");
+
+          var size = avatar[0].files[0].size / 1024;
+          // console.log(size)
+
+         if(size > 2048){
+            alert('文件大小不能超过2M');
+
+            return false;
+         }
+});
+
+function check(){
+    var str = document.getElementById("f_file").value;
+        if(str.length==0)
+        {
+            alert("请选择上传");
+            return false;
+        }else 
+        {
+            return true;
+        }
+        
+
+}
+
+
+          
+    
+</script>  

+ 21 - 0
Thinkphp5整合excel导入导出/application/route.php

@@ -0,0 +1,21 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+return [
+    '__pattern__' => [
+        'name' => '\w+',
+    ],
+    '[hello]'     => [
+        ':id'   => ['index/hello', ['method' => 'get'], ['id' => '\d+']],
+        ':name' => ['index/hello', ['method' => 'post']],
+    ],
+
+];

+ 28 - 0
Thinkphp5整合excel导入导出/application/tags.php

@@ -0,0 +1,28 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+// 应用行为扩展定义文件
+return [
+    // 应用初始化
+    'app_init'     => [],
+    // 应用开始
+    'app_begin'    => [],
+    // 模块初始化
+    'module_init'  => [],
+    // 操作开始执行
+    'action_begin' => [],
+    // 视图内容过滤
+    'view_filter'  => [],
+    // 日志写入
+    'log_write'    => [],
+    // 应用结束
+    'app_end'      => [],
+];

+ 25 - 0
Thinkphp5整合excel导入导出/build.php

@@ -0,0 +1,25 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+return [
+    // 生成应用公共文件
+    '__file__' => ['common.php', 'config.php', 'database.php'],
+
+    // 定义demo模块的自动生成 (按照实际定义的文件名生成)
+    'demo'     => [
+        '__file__'   => ['common.php'],
+        '__dir__'    => ['behavior', 'controller', 'model', 'view'],
+        'controller' => ['Index', 'Test', 'UserType'],
+        'model'      => ['User', 'UserType'],
+        'view'       => ['index/index'],
+    ],
+    // 其他更多的模块定义
+];

+ 2 - 0
Thinkphp5整合excel导入导出/extend/.gitignore

@@ -0,0 +1,2 @@
+*
+!.gitignore

+ 39 - 0
Thinkphp5整合excel导入导出/member.sql

@@ -0,0 +1,39 @@
+-- phpMyAdmin SQL Dump
+-- version phpStudy 2014
+-- http://www.phpmyadmin.net
+--
+-- 主机: localhost
+-- 生�日期: 2017 �11 �30 �17:33
+-- �务器版本: 5.5.53
+-- PHP 版本: 5.6.27
+
+SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
+SET time_zone = "+00:00";
+
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+
+--
+-- 数�库: `silence`
+--
+
+-- --------------------------------------------------------
+
+--
+-- 表的结构 `member`
+--
+
+CREATE TABLE IF NOT EXISTS `member` (
+  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
+  `name` varchar(50) NOT NULL COMMENT '�称',
+  `image` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `admin_id` (`id`)
+) ENGINE=MyISAM  DEFAULT CHARSET=utf8mb4 COMMENT='管�员表' AUTO_INCREMENT=22 ;
+
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

+ 8 - 0
Thinkphp5整合excel导入导出/public/.htaccess

@@ -0,0 +1,8 @@
+<IfModule mod_rewrite.c>
+  Options +FollowSymlinks -Multiviews
+  RewriteEngine On
+
+  RewriteCond %{REQUEST_FILENAME} !-d
+  RewriteCond %{REQUEST_FILENAME} !-f
+  RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
+</IfModule>

BIN
Thinkphp5整合excel导入导出/public/excel/20171201/0d73cf016450bf555d7d02e445ecd3ff.xlsx


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/0db3d52e668da694e04ba68a7d740670.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/0fbfef46cda844d207fc0e5d65741019.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/186413a26ea78c1de168ac6eb8577ca7.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/194e4b3629f1a75a8a2f944309c56bcd.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/1cc2a4115ebd73d2407667367d467400.xlsx


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/246a7c4f086d7d276f1cde98b401caa0.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/2bddc7fe48cf9f9203dbae5aa26a07e1.xlsx


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/2f9e4df48af8b6d7a7328d35b20b53b3.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/31a5d89d5fbd1e7eb2b0d89557baaf27.xlsx


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/395447dba0470c1345245d1074d24df9.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/3d41309b9f42de07c7d228aefc60587c.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/3f2ff1fd7a2ea331344616767a55baea.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/481017e2b9ddc2ebf463c0cbf8c99d30.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/4bb375685f7040007a5cffb1667e4182.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/59924c5b2b326120d4aab47a0fbdf8f0.xlsx


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/5dbe8586fe3cc3c4bbe669fbde912b56.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/62f58857b57a147a676f29820b26f84f.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/6550ee0f31df10d6ea19ddab9ddff710.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/6bb7fe097bf77422645316780f6999dd.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/74d39af71e666ab04c8a2b3a8670e194.xlsx


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/75beb07dcccb43787f449ce80ace50aa.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/97ebc2d29c52a80313c2de4078b4323b.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/a1a653de02eaa6efcde7a8a2ce55cb26.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/b304056b0dcafb0dacf86d94f7438b7e.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/bf4cea87af4d5b130b0a854845bd518d.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/c371218050c615c94f906b05f0ac90a5.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/c46ec03567405cc2ef797e2ec83fd54a.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/cea52c18692e41570f936aa8a122c099.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/cf04bfebbe473df0e209b3d8acf07ccb.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/d180eeaeb76233f049e0497b23b1dbdb.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/d503dc39bd711b288df2d328b0bf9bcd.xlsx


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/e0a1d5c8aafcffda0adbd38102e1eda4.xlsx


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/e2237bfc8aee22a42aba42537c5772a9.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/e29869061df9f4f39bbd2ff95ca0cfe6.xlsx


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/e680902118dfae30cbf4a7df78553f11.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/edbec486ecff51e97894f2c7c7f7bfa2.xls


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/ef1bdf8b96eaa8d6b4dcf3f1fce509a5.xlsx


BIN
Thinkphp5整合excel导入导出/public/excel/20171201/f1c62e4929a28ef5eb44200472ff2997.xls


BIN
Thinkphp5整合excel导入导出/public/favicon.ico


+ 17 - 0
Thinkphp5整合excel导入导出/public/index.php

@@ -0,0 +1,17 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+// [ 应用入口文件 ]
+
+// 定义应用目录
+define('APP_PATH', __DIR__ . '/../application/');
+// 加载框架引导文件
+require __DIR__ . '/../thinkphp/start.php';

+ 2 - 0
Thinkphp5整合excel导入导出/public/robots.txt

@@ -0,0 +1,2 @@
+User-agent: *
+Disallow:

+ 20 - 0
Thinkphp5整合excel导入导出/public/router.php

@@ -0,0 +1,20 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+// $Id$
+
+if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) {
+    return false;
+} else {
+    if (!isset($_SERVER['PATH_INFO'])) {
+        $_SERVER['PATH_INFO'] = $_SERVER['REQUEST_URI'];
+    }
+    require __DIR__ . "/index.php";
+}

+ 2 - 0
Thinkphp5整合excel导入导出/public/static/.gitignore

@@ -0,0 +1,2 @@
+*
+!.gitignore

+ 4 - 0
Thinkphp5整合excel导入导出/thinkphp/.gitignore

@@ -0,0 +1,4 @@
+/composer.lock
+/vendor
+.idea
+.DS_Store

+ 1 - 0
Thinkphp5整合excel导入导出/thinkphp/.htaccess

@@ -0,0 +1 @@
+deny from all

+ 47 - 0
Thinkphp5整合excel导入导出/thinkphp/.travis.yml

@@ -0,0 +1,47 @@
+sudo: false
+
+language: php
+
+services:
+  - memcached
+  - mongodb
+  - mysql
+  - postgresql
+  - redis-server
+
+matrix:
+  fast_finish: true
+  include:
+    - php: 5.4
+    - php: 5.5
+    - php: 5.6
+    - php: 7.0
+    - php: hhvm
+  allow_failures:
+    - php: hhvm
+
+cache:
+  directories:
+    - $HOME/.composer/cache
+
+before_install:
+  - composer self-update
+  - mysql -e "create database IF NOT EXISTS test;" -uroot
+  - psql -c 'DROP DATABASE IF EXISTS test;' -U postgres
+  - psql -c 'create database test;' -U postgres
+
+install:
+  - ./tests/script/install.sh
+
+script:
+  ## LINT
+  - find . -path ./vendor -prune -o -type f -name \*.php -exec php -l {} \;
+  ## PHP Copy/Paste Detector
+  - vendor/bin/phpcpd --verbose --exclude vendor ./ || true
+  ## PHPLOC
+  - vendor/bin/phploc --exclude vendor ./
+  ## PHPUNIT
+  - vendor/bin/phpunit --coverage-clover=coverage.xml --configuration=phpunit.xml
+
+after_success:
+  - bash <(curl -s https://codecov.io/bash)

+ 119 - 0
Thinkphp5整合excel导入导出/thinkphp/CONTRIBUTING.md

@@ -0,0 +1,119 @@
+如何贡献我的源代码
+===
+
+此文档介绍了 ThinkPHP 团队的组成以及运转机制,您提交的代码将给 ThinkPHP 项目带来什么好处,以及如何才能加入我们的行列。
+
+## 通过 Github 贡献代码
+
+ThinkPHP 目前使用 Git 来控制程序版本,如果你想为 ThinkPHP 贡献源代码,请先大致了解 Git 的使用方法。我们目前把项目托管在 GitHub 上,任何 GitHub 用户都可以向我们贡献代码。
+
+参与的方式很简单,`fork`一份 ThinkPHP 的代码到你的仓库中,修改后提交,并向我们发起`pull request`申请,我们会及时对代码进行审查并处理你的申请并。审查通过后,你的代码将被`merge`进我们的仓库中,这样你就会自动出现在贡献者名单里了,非常方便。
+
+我们希望你贡献的代码符合:
+
+* ThinkPHP 的编码规范
+* 适当的注释,能让其他人读懂
+* 遵循 Apache2 开源协议
+
+**如果想要了解更多细节或有任何疑问,请继续阅读下面的内容**
+
+### 注意事项
+
+* 本项目代码格式化标准选用 [**PSR-2**](http://www.kancloud.cn/thinkphp/php-fig-psr/3141);
+* 类名和类文件名遵循 [**PSR-4**](http://www.kancloud.cn/thinkphp/php-fig-psr/3144);
+* 对于 Issues 的处理,请使用诸如 `fix #xxx(Issue ID)` 的 commit title 直接关闭 issue。
+* 系统会自动在 PHP 5.4 5.5 5.6 7.0 和 HHVM 上测试修改,其中 HHVM 下的测试容许报错,请确保你的修改符合 PHP 5.4 ~ 5.6 和 PHP 7.0 的语法规范;
+* 管理员不会合并造成 CI faild 的修改,若出现 CI faild 请检查自己的源代码或修改相应的[单元测试文件](tests);
+
+## GitHub Issue
+
+GitHub 提供了 Issue 功能,该功能可以用于:
+
+* 提出 bug
+* 提出功能改进
+* 反馈使用体验
+
+该功能不应该用于:
+
+ * 提出修改意见(涉及代码署名和修订追溯问题)
+ * 不友善的言论
+
+## 快速修改
+
+**GitHub 提供了快速编辑文件的功能**
+
+1. 登录 GitHub 帐号;
+2. 浏览项目文件,找到要进行修改的文件;
+3. 点击右上角铅笔图标进行修改;
+4. 填写 `Commit changes` 相关内容(Title 必填);
+5. 提交修改,等待 CI 验证和管理员合并。
+
+**若您需要一次提交大量修改,请继续阅读下面的内容**
+
+## 完整流程
+
+1. `fork`本项目;
+2. 克隆(`clone`)你 `fork` 的项目到本地;
+3. 新建分支(`branch`)并检出(`checkout`)新分支;
+4. 添加本项目到你的本地 git 仓库作为上游(`upstream`);
+5. 进行修改,若你的修改包含方法或函数的增减,请记得修改[单元测试文件](tests);
+6. 变基(衍合 `rebase`)你的分支到上游 master 分支;
+7. `push` 你的本地仓库到 GitHub;
+8. 提交 `pull request`;
+9. 等待 CI 验证(若不通过则重复 5~7,GitHub 会自动更新你的 `pull request`);
+10. 等待管理员处理,并及时 `rebase` 你的分支到上游 master 分支(若上游 master 分支有修改)。
+
+*若有必要,可以 `git push -f` 强行推送 rebase 后的分支到自己的 `fork`*
+
+*绝对不可以使用 `git push -f` 强行推送修改到上游*
+
+### 注意事项
+
+* 若对上述流程有任何不清楚的地方,请查阅 GIT 教程,如 [这个](http://backlogtool.com/git-guide/cn/);
+* 对于代码**不同方面**的修改,请在自己 `fork` 的项目中**创建不同的分支**(原因参见`完整流程`第9条备注部分);
+* 变基及交互式变基操作参见 [Git 交互式变基](http://pakchoi.me/2015/03/17/git-interactive-rebase/)
+
+## 推荐资源
+
+### 开发环境
+
+* XAMPP for Windows 5.5.x
+* WampServer (for Windows)
+* upupw Apache PHP5.4 ( for Windows)
+
+或自行安装
+
+- Apache / Nginx
+- PHP 5.4 ~ 5.6
+- MySQL / MariaDB
+
+*Windows 用户推荐添加 PHP bin 目录到 PATH,方便使用 composer*
+
+*Linux 用户自行配置环境, Mac 用户推荐使用内置 Apache 配合 Homebrew 安装 PHP 和 MariaDB*
+
+### 编辑器
+
+Sublime Text 3 + phpfmt 插件
+
+phpfmt 插件参数
+
+```json
+{
+	"autocomplete": true,
+	"enable_auto_align": true,
+	"format_on_save": true,
+	"indent_with_space": true,
+	"psr1_naming": false,
+	"psr2": true,
+	"version": 4
+}
+```
+
+或其他 编辑器 / IDE 配合 PSR2 自动格式化工具
+
+### Git GUI
+
+* SourceTree
+* GitHub Desktop
+
+或其他 Git 图形界面客户端

+ 32 - 0
Thinkphp5整合excel导入导出/thinkphp/LICENSE.txt

@@ -0,0 +1,32 @@
+
+ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
+版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
+All rights reserved。
+ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
+
+Apache Licence是著名的非盈利开源组织Apache采用的协议。
+该协议和BSD类似,鼓励代码共享和尊重原作者的著作权,
+允许代码修改,再作为开源或商业软件发布。需要满足
+的条件: 
+1. 需要给代码的用户一份Apache Licence ;
+2. 如果你修改了代码,需要在被修改的文件中说明;
+3. 在延伸的代码中(修改和有源代码衍生的代码中)需要
+带有原来代码中的协议,商标,专利声明和其他原来作者规
+定需要包含的说明;
+4. 如果再发布的产品中包含一个Notice文件,则在Notice文
+件中需要带有本协议内容。你可以在Notice中增加自己的
+许可,但不可以表现为对Apache Licence构成更改。 
+具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.

+ 114 - 0
Thinkphp5整合excel导入导出/thinkphp/README.md

@@ -0,0 +1,114 @@
+ThinkPHP 5.0
+===============
+
+[![StyleCI](https://styleci.io/repos/48530411/shield?style=flat&branch=master)](https://styleci.io/repos/48530411)
+[![Build Status](https://travis-ci.org/top-think/framework.svg?branch=master)](https://travis-ci.org/top-think/framework)
+[![codecov.io](http://codecov.io/github/top-think/framework/coverage.svg?branch=master)](http://codecov.io/github/github/top-think/framework?branch=master)
+[![Total Downloads](https://poser.pugx.org/topthink/framework/downloads)](https://packagist.org/packages/topthink/framework)
+[![Latest Stable Version](https://poser.pugx.org/topthink/framework/v/stable)](https://packagist.org/packages/topthink/framework)
+[![Latest Unstable Version](https://poser.pugx.org/topthink/framework/v/unstable)](https://packagist.org/packages/topthink/framework)
+[![License](https://poser.pugx.org/topthink/framework/license)](https://packagist.org/packages/topthink/framework)
+
+ThinkPHP5在保持快速开发和大道至简的核心理念不变的同时,PHP版本要求提升到5.4,优化核心,减少依赖,基于全新的架构思想和命名空间实现,是ThinkPHP突破原有框架思路的颠覆之作,其主要特性包括:
+
+ + 基于命名空间和众多PHP新特性
+ + 核心功能组件化
+ + 强化路由功能
+ + 更灵活的控制器
+ + 重构的模型和数据库类
+ + 配置文件可分离
+ + 重写的自动验证和完成
+ + 简化扩展机制
+ + API支持完善
+ + 改进的Log类
+ + 命令行访问支持
+ + REST支持
+ + 引导文件支持
+ + 方便的自动生成定义
+ + 真正惰性加载
+ + 分布式环境支持
+ + 支持Composer
+ + 支持MongoDb
+
+> ThinkPHP5的运行环境要求PHP5.4以上。
+
+详细开发文档参考 [ThinkPHP5完全开发手册](http://www.kancloud.cn/manual/thinkphp5) 以及[ThinkPHP5入门系列教程](http://www.kancloud.cn/special/thinkphp5_quickstart)
+
+## 目录结构
+
+初始的目录结构如下:
+
+~~~
+www  WEB部署目录(或者子目录)
+├─application           应用目录
+│  ├─common             公共模块目录(可以更改)
+│  ├─module_name        模块目录
+│  │  ├─config.php      模块配置文件
+│  │  ├─common.php      模块函数文件
+│  │  ├─controller      控制器目录
+│  │  ├─model           模型目录
+│  │  ├─view            视图目录
+│  │  └─ ...            更多类库目录
+│  │
+│  ├─command.php        命令行工具配置文件
+│  ├─common.php         公共函数文件
+│  ├─config.php         公共配置文件
+│  ├─route.php          路由配置文件
+│  ├─tags.php           应用行为扩展定义文件
+│  └─database.php       数据库配置文件
+│
+├─public                WEB目录(对外访问目录)
+│  ├─index.php          入口文件
+│  ├─router.php         快速测试文件
+│  └─.htaccess          用于apache的重写
+│
+├─thinkphp              框架系统目录
+│  ├─lang               语言文件目录
+│  ├─library            框架类库目录
+│  │  ├─think           Think类库包目录
+│  │  └─traits          系统Trait目录
+│  │
+│  ├─tpl                系统模板目录
+│  ├─base.php           基础定义文件
+│  ├─console.php        控制台入口文件
+│  ├─convention.php     框架惯例配置文件
+│  ├─helper.php         助手函数文件
+│  ├─phpunit.xml        phpunit配置文件
+│  └─start.php          框架入口文件
+│
+├─extend                扩展类库目录
+├─runtime               应用的运行时目录(可写,可定制)
+├─vendor                第三方类库目录(Composer依赖库)
+├─build.php             自动生成定义文件(参考)
+├─composer.json         composer 定义文件
+├─LICENSE.txt           授权说明文件
+├─README.md             README 文件
+├─think                 命令行入口文件
+~~~
+
+> router.php用于php自带webserver支持,可用于快速测试
+> 切换到public目录后,启动命令:php -S localhost:8888  router.php
+> 上面的目录结构和名称是可以改变的,这取决于你的入口文件和配置参数。
+
+## 命名规范
+
+ThinkPHP5的命名规范遵循PSR-2规范以及PSR-4自动加载规范。
+
+## 参与开发
+注册并登录 Github 帐号, fork 本项目并进行改动。
+
+更多细节参阅 [CONTRIBUTING.md](CONTRIBUTING.md)
+
+## 版权信息
+
+ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
+
+本项目包含的第三方源码和二进制文件之版权信息另行标注。
+
+版权所有Copyright © 2006-2017 by ThinkPHP (http://thinkphp.cn)
+
+All rights reserved。
+
+ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
+
+更多细节参阅 [LICENSE.txt](LICENSE.txt)

+ 63 - 0
Thinkphp5整合excel导入导出/thinkphp/base.php

@@ -0,0 +1,63 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+define('THINK_VERSION', '5.0.12');
+define('THINK_START_TIME', microtime(true));
+define('THINK_START_MEM', memory_get_usage());
+define('EXT', '.php');
+define('DS', DIRECTORY_SEPARATOR);
+defined('THINK_PATH') or define('THINK_PATH', __DIR__ . DS);
+define('LIB_PATH', THINK_PATH . 'library' . DS);
+define('CORE_PATH', LIB_PATH . 'think' . DS);
+define('TRAIT_PATH', LIB_PATH . 'traits' . DS);
+defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']) . DS);
+defined('ROOT_PATH') or define('ROOT_PATH', dirname(realpath(APP_PATH)) . DS);
+defined('EXTEND_PATH') or define('EXTEND_PATH', ROOT_PATH . 'extend' . DS);
+defined('VENDOR_PATH') or define('VENDOR_PATH', ROOT_PATH . 'vendor' . DS);
+defined('RUNTIME_PATH') or define('RUNTIME_PATH', ROOT_PATH . 'runtime' . DS);
+defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH . 'log' . DS);
+defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH . 'cache' . DS);
+defined('TEMP_PATH') or define('TEMP_PATH', RUNTIME_PATH . 'temp' . DS);
+defined('CONF_PATH') or define('CONF_PATH', APP_PATH); // 配置文件目录
+defined('CONF_EXT') or define('CONF_EXT', EXT); // 配置文件后缀
+defined('ENV_PREFIX') or define('ENV_PREFIX', 'PHP_'); // 环境变量的配置前缀
+
+// 环境常量
+define('IS_CLI', PHP_SAPI == 'cli' ? true : false);
+define('IS_WIN', strpos(PHP_OS, 'WIN') !== false);
+
+// 载入Loader类
+require CORE_PATH . 'Loader.php';
+
+// 加载环境变量配置文件
+if (is_file(ROOT_PATH . '.env')) {
+    $env = parse_ini_file(ROOT_PATH . '.env', true);
+    foreach ($env as $key => $val) {
+        $name = ENV_PREFIX . strtoupper($key);
+        if (is_array($val)) {
+            foreach ($val as $k => $v) {
+                $item = $name . '_' . strtoupper($k);
+                putenv("$item=$v");
+            }
+        } else {
+            putenv("$name=$val");
+        }
+    }
+}
+
+// 注册自动加载
+\think\Loader::register();
+
+// 注册错误和异常处理机制
+\think\Error::register();
+
+// 加载惯例配置文件
+\think\Config::set(include THINK_PATH . 'convention' . EXT);

+ 12 - 0
Thinkphp5整合excel导入导出/thinkphp/codecov.yml

@@ -0,0 +1,12 @@
+comment:
+  layout: header, changes, diff
+coverage:
+  ignore:
+  - base.php
+  - helper.php
+  - convention.php
+  - lang/zh-cn.php
+  - start.php
+  - console.php
+  status:
+    patch: false

+ 35 - 0
Thinkphp5整合excel导入导出/thinkphp/composer.json

@@ -0,0 +1,35 @@
+{
+    "name": "topthink/framework",
+    "description": "the new thinkphp framework",
+    "type": "think-framework",
+    "keywords": [
+        "framework",
+        "thinkphp",
+        "ORM"
+    ],
+    "homepage": "http://thinkphp.cn/",
+    "license": "Apache-2.0",
+    "authors": [
+        {
+            "name": "liu21st",
+            "email": "liu21st@gmail.com"
+        }
+    ],
+    "require": {
+        "php": ">=5.4.0",
+        "topthink/think-installer": "~1.0"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "4.8.*",
+        "johnkary/phpunit-speedtrap": "^1.0",
+        "mikey179/vfsStream": "~1.6",
+        "phploc/phploc": "2.*",
+        "sebastian/phpcpd": "2.*",
+        "phpdocumentor/reflection-docblock": "^2.0"
+    },
+    "autoload": {
+        "psr-4": {
+            "think\\": "library/think"
+        }
+    }
+}

+ 20 - 0
Thinkphp5整合excel导入导出/thinkphp/console.php

@@ -0,0 +1,20 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006-2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: yunwuxin <448901948@qq.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+// ThinkPHP 引导文件
+// 加载基础文件
+require __DIR__ . '/base.php';
+
+// 执行应用
+App::initCommon();
+Console::init();

+ 289 - 0
Thinkphp5整合excel导入导出/thinkphp/convention.php

@@ -0,0 +1,289 @@
+<?php
+
+return [
+    // +----------------------------------------------------------------------
+    // | 应用设置
+    // +----------------------------------------------------------------------
+    // 默认Host地址
+    'app_host'               => '',
+    // 应用调试模式
+    'app_debug'              => false,
+    // 应用Trace
+    'app_trace'              => false,
+    // 应用模式状态
+    'app_status'             => '',
+    // 是否支持多模块
+    'app_multi_module'       => true,
+    // 入口自动绑定模块
+    'auto_bind_module'       => false,
+    // 注册的根命名空间
+    'root_namespace'         => [],
+    // 扩展函数文件
+    'extra_file_list'        => [THINK_PATH . 'helper' . EXT],
+    // 默认输出类型
+    'default_return_type'    => 'html',
+    // 默认AJAX 数据返回格式,可选json xml ...
+    'default_ajax_return'    => 'json',
+    // 默认JSONP格式返回的处理方法
+    'default_jsonp_handler'  => 'jsonpReturn',
+    // 默认JSONP处理方法
+    'var_jsonp_handler'      => 'callback',
+    // 默认时区
+    'default_timezone'       => 'PRC',
+    // 是否开启多语言
+    'lang_switch_on'         => false,
+    // 默认全局过滤方法 用逗号分隔多个
+    'default_filter'         => '',
+    // 默认语言
+    'default_lang'           => 'zh-cn',
+    // 应用类库后缀
+    'class_suffix'           => false,
+    // 控制器类后缀
+    'controller_suffix'      => false,
+
+    // +----------------------------------------------------------------------
+    // | 模块设置
+    // +----------------------------------------------------------------------
+
+    // 默认模块名
+    'default_module'         => 'index',
+    // 禁止访问模块
+    'deny_module_list'       => ['common'],
+    // 默认控制器名
+    'default_controller'     => 'Index',
+    // 默认操作名
+    'default_action'         => 'index',
+    // 默认验证器
+    'default_validate'       => '',
+    // 默认的空控制器名
+    'empty_controller'       => 'Error',
+    // 操作方法前缀
+    'use_action_prefix'      => false,
+    // 操作方法后缀
+    'action_suffix'          => '',
+    // 自动搜索控制器
+    'controller_auto_search' => false,
+
+    // +----------------------------------------------------------------------
+    // | URL设置
+    // +----------------------------------------------------------------------
+
+    // PATHINFO变量名 用于兼容模式
+    'var_pathinfo'           => 's',
+    // 兼容PATH_INFO获取
+    'pathinfo_fetch'         => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
+    // pathinfo分隔符
+    'pathinfo_depr'          => '/',
+    // HTTPS代理标识
+    'https_agent_name'       => '',
+    // URL伪静态后缀
+    'url_html_suffix'        => 'html',
+    // URL普通方式参数 用于自动生成
+    'url_common_param'       => false,
+    // URL参数方式 0 按名称成对解析 1 按顺序解析
+    'url_param_type'         => 0,
+    // 是否开启路由
+    'url_route_on'           => true,
+    // 路由配置文件(支持配置多个)
+    'route_config_file'      => ['route'],
+    // 路由使用完整匹配
+    'route_complete_match'   => false,
+    // 是否强制使用路由
+    'url_route_must'         => false,
+    // 域名部署
+    'url_domain_deploy'      => false,
+    // 域名根,如thinkphp.cn
+    'url_domain_root'        => '',
+    // 是否自动转换URL中的控制器和操作名
+    'url_convert'            => true,
+    // 默认的访问控制器层
+    'url_controller_layer'   => 'controller',
+    // 表单请求类型伪装变量
+    'var_method'             => '_method',
+    // 表单ajax伪装变量
+    'var_ajax'               => '_ajax',
+    // 表单pjax伪装变量
+    'var_pjax'               => '_pjax',
+    // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
+    'request_cache'          => false,
+    // 请求缓存有效期
+    'request_cache_expire'   => null,
+    // 全局请求缓存排除规则
+    'request_cache_except'   => [],
+
+    // +----------------------------------------------------------------------
+    // | 模板设置
+    // +----------------------------------------------------------------------
+
+    'template'               => [
+        // 模板引擎类型 支持 php think 支持扩展
+        'type'         => 'Think',
+        // 视图基础目录,配置目录为所有模块的视图起始目录
+        'view_base'    => '',
+        // 当前模板的视图目录 留空为自动获取
+        'view_path'    => '',
+        // 模板后缀
+        'view_suffix'  => 'html',
+        // 模板文件名分隔符
+        'view_depr'    => DS,
+        // 模板引擎普通标签开始标记
+        'tpl_begin'    => '{',
+        // 模板引擎普通标签结束标记
+        'tpl_end'      => '}',
+        // 标签库标签开始标记
+        'taglib_begin' => '{',
+        // 标签库标签结束标记
+        'taglib_end'   => '}',
+    ],
+
+    // 视图输出字符串内容替换
+    'view_replace_str'       => [],
+    // 默认跳转页面对应的模板文件
+    'dispatch_success_tmpl'  => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
+    'dispatch_error_tmpl'    => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
+
+    // +----------------------------------------------------------------------
+    // | 异常及错误设置
+    // +----------------------------------------------------------------------
+
+    // 异常页面的模板文件
+    'exception_tmpl'         => THINK_PATH . 'tpl' . DS . 'think_exception.tpl',
+
+    // 错误显示信息,非调试模式有效
+    'error_message'          => '页面错误!请稍后再试~',
+    // 显示错误信息
+    'show_error_msg'         => false,
+    // 异常处理handle类 留空使用 \think\exception\Handle
+    'exception_handle'       => '',
+    // 是否记录trace信息到日志
+    'record_trace'           => false,
+
+    // +----------------------------------------------------------------------
+    // | 日志设置
+    // +----------------------------------------------------------------------
+
+    'log'                    => [
+        // 日志记录方式,内置 file socket 支持扩展
+        'type'  => 'File',
+        // 日志保存目录
+        'path'  => LOG_PATH,
+        // 日志记录级别
+        'level' => [],
+    ],
+
+    // +----------------------------------------------------------------------
+    // | Trace设置 开启 app_trace 后 有效
+    // +----------------------------------------------------------------------
+    'trace'                  => [
+        // 内置Html Console 支持扩展
+        'type' => 'Html',
+    ],
+
+    // +----------------------------------------------------------------------
+    // | 缓存设置
+    // +----------------------------------------------------------------------
+
+    'cache'                  => [
+        // 驱动方式
+        'type'   => 'File',
+        // 缓存保存目录
+        'path'   => CACHE_PATH,
+        // 缓存前缀
+        'prefix' => '',
+        // 缓存有效期 0表示永久缓存
+        'expire' => 0,
+    ],
+
+    // +----------------------------------------------------------------------
+    // | 会话设置
+    // +----------------------------------------------------------------------
+
+    'session'                => [
+        'id'             => '',
+        // SESSION_ID的提交变量,解决flash上传跨域
+        'var_session_id' => '',
+        // SESSION 前缀
+        'prefix'         => 'think',
+        // 驱动方式 支持redis memcache memcached
+        'type'           => '',
+        // 是否自动开启 SESSION
+        'auto_start'     => true,
+        'httponly'       => true,
+        'secure'         => false,
+    ],
+
+    // +----------------------------------------------------------------------
+    // | Cookie设置
+    // +----------------------------------------------------------------------
+    'cookie'                 => [
+        // cookie 名称前缀
+        'prefix'    => '',
+        // cookie 保存时间
+        'expire'    => 0,
+        // cookie 保存路径
+        'path'      => '/',
+        // cookie 有效域名
+        'domain'    => '',
+        //  cookie 启用安全传输
+        'secure'    => false,
+        // httponly设置
+        'httponly'  => '',
+        // 是否使用 setcookie
+        'setcookie' => true,
+    ],
+
+    // +----------------------------------------------------------------------
+    // | 数据库设置
+    // +----------------------------------------------------------------------
+
+    'database'               => [
+        // 数据库类型
+        'type'            => 'mysql',
+        // 数据库连接DSN配置
+        'dsn'             => '',
+        // 服务器地址
+        'hostname'        => '127.0.0.1',
+        // 数据库名
+        'database'        => '',
+        // 数据库用户名
+        'username'        => 'root',
+        // 数据库密码
+        'password'        => '',
+        // 数据库连接端口
+        'hostport'        => '',
+        // 数据库连接参数
+        'params'          => [],
+        // 数据库编码默认采用utf8
+        'charset'         => 'utf8',
+        // 数据库表前缀
+        'prefix'          => '',
+        // 数据库调试模式
+        'debug'           => false,
+        // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
+        'deploy'          => 0,
+        // 数据库读写是否分离 主从式有效
+        'rw_separate'     => false,
+        // 读写分离后 主服务器数量
+        'master_num'      => 1,
+        // 指定从服务器序号
+        'slave_no'        => '',
+        // 是否严格检查字段是否存在
+        'fields_strict'   => true,
+        // 数据集返回类型
+        'resultset_type'  => 'array',
+        // 自动写入时间戳字段
+        'auto_timestamp'  => false,
+        // 时间字段取出后的默认时间格式
+        'datetime_format' => 'Y-m-d H:i:s',
+        // 是否需要进行SQL性能分析
+        'sql_explain'     => false,
+    ],
+
+    //分页配置
+    'paginate'               => [
+        'type'      => 'bootstrap',
+        'var_page'  => 'page',
+        'list_rows' => 15,
+    ],
+
+];

+ 589 - 0
Thinkphp5整合excel导入导出/thinkphp/helper.php

@@ -0,0 +1,589 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+//------------------------
+// ThinkPHP 助手函数
+//-------------------------
+
+use think\Cache;
+use think\Config;
+use think\Cookie;
+use think\Db;
+use think\Debug;
+use think\exception\HttpException;
+use think\exception\HttpResponseException;
+use think\Lang;
+use think\Loader;
+use think\Log;
+use think\Model;
+use think\Request;
+use think\Response;
+use think\Session;
+use think\Url;
+use think\View;
+
+if (!function_exists('load_trait')) {
+    /**
+     * 快速导入Traits PHP5.5以上无需调用
+     * @param string    $class trait库
+     * @param string    $ext 类库后缀
+     * @return boolean
+     */
+    function load_trait($class, $ext = EXT)
+    {
+        return Loader::import($class, TRAIT_PATH, $ext);
+    }
+}
+
+if (!function_exists('exception')) {
+    /**
+     * 抛出异常处理
+     *
+     * @param string    $msg  异常消息
+     * @param integer   $code 异常代码 默认为0
+     * @param string    $exception 异常类
+     *
+     * @throws Exception
+     */
+    function exception($msg, $code = 0, $exception = '')
+    {
+        $e = $exception ?: '\think\Exception';
+        throw new $e($msg, $code);
+    }
+}
+
+if (!function_exists('debug')) {
+    /**
+     * 记录时间(微秒)和内存使用情况
+     * @param string            $start 开始标签
+     * @param string            $end 结束标签
+     * @param integer|string    $dec 小数位 如果是m 表示统计内存占用
+     * @return mixed
+     */
+    function debug($start, $end = '', $dec = 6)
+    {
+        if ('' == $end) {
+            Debug::remark($start);
+        } else {
+            return 'm' == $dec ? Debug::getRangeMem($start, $end) : Debug::getRangeTime($start, $end, $dec);
+        }
+    }
+}
+
+if (!function_exists('lang')) {
+    /**
+     * 获取语言变量值
+     * @param string    $name 语言变量名
+     * @param array     $vars 动态变量值
+     * @param string    $lang 语言
+     * @return mixed
+     */
+    function lang($name, $vars = [], $lang = '')
+    {
+        return Lang::get($name, $vars, $lang);
+    }
+}
+
+if (!function_exists('config')) {
+    /**
+     * 获取和设置配置参数
+     * @param string|array  $name 参数名
+     * @param mixed         $value 参数值
+     * @param string        $range 作用域
+     * @return mixed
+     */
+    function config($name = '', $value = null, $range = '')
+    {
+        if (is_null($value) && is_string($name)) {
+            return 0 === strpos($name, '?') ? Config::has(substr($name, 1), $range) : Config::get($name, $range);
+        } else {
+            return Config::set($name, $value, $range);
+        }
+    }
+}
+
+if (!function_exists('input')) {
+    /**
+     * 获取输入数据 支持默认值和过滤
+     * @param string    $key 获取的变量名
+     * @param mixed     $default 默认值
+     * @param string    $filter 过滤方法
+     * @return mixed
+     */
+    function input($key = '', $default = null, $filter = '')
+    {
+        if (0 === strpos($key, '?')) {
+            $key = substr($key, 1);
+            $has = true;
+        }
+        if ($pos = strpos($key, '.')) {
+            // 指定参数来源
+            list($method, $key) = explode('.', $key, 2);
+            if (!in_array($method, ['get', 'post', 'put', 'patch', 'delete', 'route', 'param', 'request', 'session', 'cookie', 'server', 'env', 'path', 'file'])) {
+                $key    = $method . '.' . $key;
+                $method = 'param';
+            }
+        } else {
+            // 默认为自动判断
+            $method = 'param';
+        }
+        if (isset($has)) {
+            return request()->has($key, $method, $default);
+        } else {
+            return request()->$method($key, $default, $filter);
+        }
+    }
+}
+
+if (!function_exists('widget')) {
+    /**
+     * 渲染输出Widget
+     * @param string    $name Widget名称
+     * @param array     $data 传入的参数
+     * @return mixed
+     */
+    function widget($name, $data = [])
+    {
+        return Loader::action($name, $data, 'widget');
+    }
+}
+
+if (!function_exists('model')) {
+    /**
+     * 实例化Model
+     * @param string    $name Model名称
+     * @param string    $layer 业务层名称
+     * @param bool      $appendSuffix 是否添加类名后缀
+     * @return \think\Model
+     */
+    function model($name = '', $layer = 'model', $appendSuffix = false)
+    {
+        return Loader::model($name, $layer, $appendSuffix);
+    }
+}
+
+if (!function_exists('validate')) {
+    /**
+     * 实例化验证器
+     * @param string    $name 验证器名称
+     * @param string    $layer 业务层名称
+     * @param bool      $appendSuffix 是否添加类名后缀
+     * @return \think\Validate
+     */
+    function validate($name = '', $layer = 'validate', $appendSuffix = false)
+    {
+        return Loader::validate($name, $layer, $appendSuffix);
+    }
+}
+
+if (!function_exists('db')) {
+    /**
+     * 实例化数据库类
+     * @param string        $name 操作的数据表名称(不含前缀)
+     * @param array|string  $config 数据库配置参数
+     * @param bool          $force 是否强制重新连接
+     * @return \think\db\Query
+     */
+    function db($name = '', $config = [], $force = false)
+    {
+        return Db::connect($config, $force)->name($name);
+    }
+}
+
+if (!function_exists('controller')) {
+    /**
+     * 实例化控制器 格式:[模块/]控制器
+     * @param string    $name 资源地址
+     * @param string    $layer 控制层名称
+     * @param bool      $appendSuffix 是否添加类名后缀
+     * @return \think\Controller
+     */
+    function controller($name, $layer = 'controller', $appendSuffix = false)
+    {
+        return Loader::controller($name, $layer, $appendSuffix);
+    }
+}
+
+if (!function_exists('action')) {
+    /**
+     * 调用模块的操作方法 参数格式 [模块/控制器/]操作
+     * @param string        $url 调用地址
+     * @param string|array  $vars 调用参数 支持字符串和数组
+     * @param string        $layer 要调用的控制层名称
+     * @param bool          $appendSuffix 是否添加类名后缀
+     * @return mixed
+     */
+    function action($url, $vars = [], $layer = 'controller', $appendSuffix = false)
+    {
+        return Loader::action($url, $vars, $layer, $appendSuffix);
+    }
+}
+
+if (!function_exists('import')) {
+    /**
+     * 导入所需的类库 同java的Import 本函数有缓存功能
+     * @param string    $class 类库命名空间字符串
+     * @param string    $baseUrl 起始路径
+     * @param string    $ext 导入的文件扩展名
+     * @return boolean
+     */
+    function import($class, $baseUrl = '', $ext = EXT)
+    {
+        return Loader::import($class, $baseUrl, $ext);
+    }
+}
+
+if (!function_exists('vendor')) {
+    /**
+     * 快速导入第三方框架类库 所有第三方框架的类库文件统一放到 系统的Vendor目录下面
+     * @param string    $class 类库
+     * @param string    $ext 类库后缀
+     * @return boolean
+     */
+    function vendor($class, $ext = EXT)
+    {
+        return Loader::import($class, VENDOR_PATH, $ext);
+    }
+}
+
+if (!function_exists('dump')) {
+    /**
+     * 浏览器友好的变量输出
+     * @param mixed     $var 变量
+     * @param boolean   $echo 是否输出 默认为true 如果为false 则返回输出字符串
+     * @param string    $label 标签 默认为空
+     * @return void|string
+     */
+    function dump($var, $echo = true, $label = null)
+    {
+        return Debug::dump($var, $echo, $label);
+    }
+}
+
+if (!function_exists('url')) {
+    /**
+     * Url生成
+     * @param string        $url 路由地址
+     * @param string|array  $vars 变量
+     * @param bool|string   $suffix 生成的URL后缀
+     * @param bool|string   $domain 域名
+     * @return string
+     */
+    function url($url = '', $vars = '', $suffix = true, $domain = false)
+    {
+        return Url::build($url, $vars, $suffix, $domain);
+    }
+}
+
+if (!function_exists('session')) {
+    /**
+     * Session管理
+     * @param string|array  $name session名称,如果为数组表示进行session设置
+     * @param mixed         $value session值
+     * @param string        $prefix 前缀
+     * @return mixed
+     */
+    function session($name, $value = '', $prefix = null)
+    {
+        if (is_array($name)) {
+            // 初始化
+            Session::init($name);
+        } elseif (is_null($name)) {
+            // 清除
+            Session::clear('' === $value ? null : $value);
+        } elseif ('' === $value) {
+            // 判断或获取
+            return 0 === strpos($name, '?') ? Session::has(substr($name, 1), $prefix) : Session::get($name, $prefix);
+        } elseif (is_null($value)) {
+            // 删除
+            return Session::delete($name, $prefix);
+        } else {
+            // 设置
+            return Session::set($name, $value, $prefix);
+        }
+    }
+}
+
+if (!function_exists('cookie')) {
+    /**
+     * Cookie管理
+     * @param string|array  $name cookie名称,如果为数组表示进行cookie设置
+     * @param mixed         $value cookie值
+     * @param mixed         $option 参数
+     * @return mixed
+     */
+    function cookie($name, $value = '', $option = null)
+    {
+        if (is_array($name)) {
+            // 初始化
+            Cookie::init($name);
+        } elseif (is_null($name)) {
+            // 清除
+            Cookie::clear($value);
+        } elseif ('' === $value) {
+            // 获取
+            return 0 === strpos($name, '?') ? Cookie::has(substr($name, 1), $option) : Cookie::get($name, $option);
+        } elseif (is_null($value)) {
+            // 删除
+            return Cookie::delete($name);
+        } else {
+            // 设置
+            return Cookie::set($name, $value, $option);
+        }
+    }
+}
+
+if (!function_exists('cache')) {
+    /**
+     * 缓存管理
+     * @param mixed     $name 缓存名称,如果为数组表示进行缓存设置
+     * @param mixed     $value 缓存值
+     * @param mixed     $options 缓存参数
+     * @param string    $tag 缓存标签
+     * @return mixed
+     */
+    function cache($name, $value = '', $options = null, $tag = null)
+    {
+        if (is_array($options)) {
+            // 缓存操作的同时初始化
+            $cache = Cache::connect($options);
+        } elseif (is_array($name)) {
+            // 缓存初始化
+            return Cache::connect($name);
+        } else {
+            $cache = Cache::init();
+        }
+
+        if (is_null($name)) {
+            return $cache->clear($value);
+        } elseif ('' === $value) {
+            // 获取缓存
+            return 0 === strpos($name, '?') ? $cache->has(substr($name, 1)) : $cache->get($name);
+        } elseif (is_null($value)) {
+            // 删除缓存
+            return $cache->rm($name);
+        } elseif (0 === strpos($name, '?') && '' !== $value) {
+            $expire = is_numeric($options) ? $options : null;
+            return $cache->remember(substr($name, 1), $value, $expire);
+        } else {
+            // 缓存数据
+            if (is_array($options)) {
+                $expire = isset($options['expire']) ? $options['expire'] : null; //修复查询缓存无法设置过期时间
+            } else {
+                $expire = is_numeric($options) ? $options : null; //默认快捷缓存设置过期时间
+            }
+            if (is_null($tag)) {
+                return $cache->set($name, $value, $expire);
+            } else {
+                return $cache->tag($tag)->set($name, $value, $expire);
+            }
+        }
+    }
+}
+
+if (!function_exists('trace')) {
+    /**
+     * 记录日志信息
+     * @param mixed     $log log信息 支持字符串和数组
+     * @param string    $level 日志级别
+     * @return void|array
+     */
+    function trace($log = '[think]', $level = 'log')
+    {
+        if ('[think]' === $log) {
+            return Log::getLog();
+        } else {
+            Log::record($log, $level);
+        }
+    }
+}
+
+if (!function_exists('request')) {
+    /**
+     * 获取当前Request对象实例
+     * @return Request
+     */
+    function request()
+    {
+        return Request::instance();
+    }
+}
+
+if (!function_exists('response')) {
+    /**
+     * 创建普通 Response 对象实例
+     * @param mixed      $data   输出数据
+     * @param int|string $code   状态码
+     * @param array      $header 头信息
+     * @param string     $type
+     * @return Response
+     */
+    function response($data = [], $code = 200, $header = [], $type = 'html')
+    {
+        return Response::create($data, $type, $code, $header);
+    }
+}
+
+if (!function_exists('view')) {
+    /**
+     * 渲染模板输出
+     * @param string    $template 模板文件
+     * @param array     $vars 模板变量
+     * @param array     $replace 模板替换
+     * @param integer   $code 状态码
+     * @return \think\response\View
+     */
+    function view($template = '', $vars = [], $replace = [], $code = 200)
+    {
+        return Response::create($template, 'view', $code)->replace($replace)->assign($vars);
+    }
+}
+
+if (!function_exists('json')) {
+    /**
+     * 获取\think\response\Json对象实例
+     * @param mixed   $data 返回的数据
+     * @param integer $code 状态码
+     * @param array   $header 头部
+     * @param array   $options 参数
+     * @return \think\response\Json
+     */
+    function json($data = [], $code = 200, $header = [], $options = [])
+    {
+        return Response::create($data, 'json', $code, $header, $options);
+    }
+}
+
+if (!function_exists('jsonp')) {
+    /**
+     * 获取\think\response\Jsonp对象实例
+     * @param mixed   $data    返回的数据
+     * @param integer $code    状态码
+     * @param array   $header 头部
+     * @param array   $options 参数
+     * @return \think\response\Jsonp
+     */
+    function jsonp($data = [], $code = 200, $header = [], $options = [])
+    {
+        return Response::create($data, 'jsonp', $code, $header, $options);
+    }
+}
+
+if (!function_exists('xml')) {
+    /**
+     * 获取\think\response\Xml对象实例
+     * @param mixed   $data    返回的数据
+     * @param integer $code    状态码
+     * @param array   $header  头部
+     * @param array   $options 参数
+     * @return \think\response\Xml
+     */
+    function xml($data = [], $code = 200, $header = [], $options = [])
+    {
+        return Response::create($data, 'xml', $code, $header, $options);
+    }
+}
+
+if (!function_exists('redirect')) {
+    /**
+     * 获取\think\response\Redirect对象实例
+     * @param mixed         $url 重定向地址 支持Url::build方法的地址
+     * @param array|integer $params 额外参数
+     * @param integer       $code 状态码
+     * @param array         $with 隐式传参
+     * @return \think\response\Redirect
+     */
+    function redirect($url = [], $params = [], $code = 302, $with = [])
+    {
+        if (is_integer($params)) {
+            $code   = $params;
+            $params = [];
+        }
+        return Response::create($url, 'redirect', $code)->params($params)->with($with);
+    }
+}
+
+if (!function_exists('abort')) {
+    /**
+     * 抛出HTTP异常
+     * @param integer|Response      $code 状态码 或者 Response对象实例
+     * @param string                $message 错误信息
+     * @param array                 $header 参数
+     */
+    function abort($code, $message = null, $header = [])
+    {
+        if ($code instanceof Response) {
+            throw new HttpResponseException($code);
+        } else {
+            throw new HttpException($code, $message, null, $header);
+        }
+    }
+}
+
+if (!function_exists('halt')) {
+    /**
+     * 调试变量并且中断输出
+     * @param mixed      $var 调试变量或者信息
+     */
+    function halt($var)
+    {
+        dump($var);
+        throw new HttpResponseException(new Response);
+    }
+}
+
+if (!function_exists('token')) {
+    /**
+     * 生成表单令牌
+     * @param string $name 令牌名称
+     * @param mixed  $type 令牌生成方法
+     * @return string
+     */
+    function token($name = '__token__', $type = 'md5')
+    {
+        $token = Request::instance()->token($name, $type);
+        return '<input type="hidden" name="' . $name . '" value="' . $token . '" />';
+    }
+}
+
+if (!function_exists('load_relation')) {
+    /**
+     * 延迟预载入关联查询
+     * @param mixed $resultSet 数据集
+     * @param mixed $relation 关联
+     * @return array
+     */
+    function load_relation($resultSet, $relation)
+    {
+        $item = current($resultSet);
+        if ($item instanceof Model) {
+            $item->eagerlyResultSet($resultSet, $relation);
+        }
+        return $resultSet;
+    }
+}
+
+if (!function_exists('collection')) {
+    /**
+     * 数组转换为数据集对象
+     * @param array $resultSet 数据集数组
+     * @return \think\model\Collection|\think\Collection
+     */
+    function collection($resultSet)
+    {
+        $item = current($resultSet);
+        if ($item instanceof Model) {
+            return \think\model\Collection::make($resultSet);
+        } else {
+            return \think\Collection::make($resultSet);
+        }
+    }
+}

+ 134 - 0
Thinkphp5整合excel导入导出/thinkphp/lang/zh-cn.php

@@ -0,0 +1,134 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+// 核心中文语言包
+return [
+    // 系统错误提示
+    'Undefined variable'                                        => '未定义变量',
+    'Undefined index'                                           => '未定义数组索引',
+    'Undefined offset'                                          => '未定义数组下标',
+    'Parse error'                                               => '语法解析错误',
+    'Type error'                                                => '类型错误',
+    'Fatal error'                                               => '致命错误',
+    'syntax error'                                              => '语法错误',
+
+    // 框架核心错误提示
+    'dispatch type not support'                                 => '不支持的调度类型',
+    'method param miss'                                         => '方法参数错误',
+    'method not exists'                                         => '方法不存在',
+    'module not exists'                                         => '模块不存在',
+    'controller not exists'                                     => '控制器不存在',
+    'class not exists'                                          => '类不存在',
+    'property not exists'                                       => '类的属性不存在',
+    'template not exists'                                       => '模板文件不存在',
+    'illegal controller name'                                   => '非法的控制器名称',
+    'illegal action name'                                       => '非法的操作名称',
+    'url suffix deny'                                           => '禁止的URL后缀访问',
+    'Route Not Found'                                           => '当前访问路由未定义',
+    'Undefined db type'                                         => '未定义数据库类型',
+    'variable type error'                                       => '变量类型错误',
+    'PSR-4 error'                                               => 'PSR-4 规范错误',
+    'not support total'                                         => '简洁模式下不能获取数据总数',
+    'not support last'                                          => '简洁模式下不能获取最后一页',
+    'error session handler'                                     => '错误的SESSION处理器类',
+    'not allow php tag'                                         => '模板不允许使用PHP语法',
+    'not support'                                               => '不支持',
+    'redisd master'                                             => 'Redisd 主服务器错误',
+    'redisd slave'                                              => 'Redisd 从服务器错误',
+    'must run at sae'                                           => '必须在SAE运行',
+    'memcache init error'                                       => '未开通Memcache服务,请在SAE管理平台初始化Memcache服务',
+    'KVDB init error'                                           => '没有初始化KVDB,请在SAE管理平台初始化KVDB服务',
+    'fields not exists'                                         => '数据表字段不存在',
+    'where express error'                                       => '查询表达式错误',
+    'no data to update'                                         => '没有任何数据需要更新',
+    'miss data to insert'                                       => '缺少需要写入的数据',
+    'miss complex primary data'                                 => '缺少复合主键数据',
+    'miss update condition'                                     => '缺少更新条件',
+    'model data Not Found'                                      => '模型数据不存在',
+    'table data not Found'                                      => '表数据不存在',
+    'delete without condition'                                  => '没有条件不会执行删除操作',
+    'miss relation data'                                        => '缺少关联表数据',
+    'tag attr must'                                             => '模板标签属性必须',
+    'tag error'                                                 => '模板标签错误',
+    'cache write error'                                         => '缓存写入失败',
+    'sae mc write error'                                        => 'SAE mc 写入错误',
+    'route name not exists'                                     => '路由标识不存在(或参数不够)',
+    'invalid request'                                           => '非法请求',
+    'bind attr has exists'                                      => '模型的属性已经存在',
+    'relation data not exists'                                  => '关联数据不存在',
+    'relation not support'                                      => '关联不支持',
+    'chunk not support order'                                   => 'Chunk不支持调用order方法',
+
+    // 上传错误信息
+    'unknown upload error'                                      => '未知上传错误!',
+    'file write error'                                          => '文件写入失败!',
+    'upload temp dir not found'                                 => '找不到临时文件夹!',
+    'no file to uploaded'                                       => '没有文件被上传!',
+    'only the portion of file is uploaded'                      => '文件只有部分被上传!',
+    'upload File size exceeds the maximum value'                => '上传文件大小超过了最大值!',
+    'upload write error'                                        => '文件上传保存错误!',
+    'has the same filename: {:filename}'                        => '存在同名文件:{:filename}',
+    'upload illegal files'                                      => '非法上传文件',
+    'illegal image files'                                       => '非法图片文件',
+    'extensions to upload is not allowed'                       => '上传文件后缀不允许',
+    'mimetype to upload is not allowed'                         => '上传文件MIME类型不允许!',
+    'filesize not match'                                        => '上传文件大小不符!',
+    'directory {:path} creation failed'                         => '目录 {:path} 创建失败!',
+
+    // Validate Error Message
+    ':attribute require'                                        => ':attribute不能为空',
+    ':attribute must be numeric'                                => ':attribute必须是数字',
+    ':attribute must be integer'                                => ':attribute必须是整数',
+    ':attribute must be float'                                  => ':attribute必须是浮点数',
+    ':attribute must be bool'                                   => ':attribute必须是布尔值',
+    ':attribute not a valid email address'                      => ':attribute格式不符',
+    ':attribute not a valid mobile'                             => ':attribute格式不符',
+    ':attribute must be a array'                                => ':attribute必须是数组',
+    ':attribute must be yes,on or 1'                            => ':attribute必须是yes、on或者1',
+    ':attribute not a valid datetime'                           => ':attribute不是一个有效的日期或时间格式',
+    ':attribute not a valid file'                               => ':attribute不是有效的上传文件',
+    ':attribute not a valid image'                              => ':attribute不是有效的图像文件',
+    ':attribute must be alpha'                                  => ':attribute只能是字母',
+    ':attribute must be alpha-numeric'                          => ':attribute只能是字母和数字',
+    ':attribute must be alpha-numeric, dash, underscore'        => ':attribute只能是字母、数字和下划线_及破折号-',
+    ':attribute not a valid domain or ip'                       => ':attribute不是有效的域名或者IP',
+    ':attribute must be chinese'                                => ':attribute只能是汉字',
+    ':attribute must be chinese or alpha'                       => ':attribute只能是汉字、字母',
+    ':attribute must be chinese,alpha-numeric'                  => ':attribute只能是汉字、字母和数字',
+    ':attribute must be chinese,alpha-numeric,underscore, dash' => ':attribute只能是汉字、字母、数字和下划线_及破折号-',
+    ':attribute not a valid url'                                => ':attribute不是有效的URL地址',
+    ':attribute not a valid ip'                                 => ':attribute不是有效的IP地址',
+    ':attribute must be dateFormat of :rule'                    => ':attribute必须使用日期格式 :rule',
+    ':attribute must be in :rule'                               => ':attribute必须在 :rule 范围内',
+    ':attribute be notin :rule'                                 => ':attribute不能在 :rule 范围内',
+    ':attribute must between :1 - :2'                           => ':attribute只能在 :1 - :2 之间',
+    ':attribute not between :1 - :2'                            => ':attribute不能在 :1 - :2 之间',
+    'size of :attribute must be :rule'                          => ':attribute长度不符合要求 :rule',
+    'max size of :attribute must be :rule'                      => ':attribute长度不能超过 :rule',
+    'min size of :attribute must be :rule'                      => ':attribute长度不能小于 :rule',
+    ':attribute cannot be less than :rule'                      => ':attribute日期不能小于 :rule',
+    ':attribute cannot exceed :rule'                            => ':attribute日期不能超过 :rule',
+    ':attribute not within :rule'                               => '不在有效期内 :rule',
+    'access IP is not allowed'                                  => '不允许的IP访问',
+    'access IP denied'                                          => '禁止的IP访问',
+    ':attribute out of accord with :2'                          => ':attribute和确认字段:2不一致',
+    ':attribute cannot be same with :2'                         => ':attribute和比较字段:2不能相同',
+    ':attribute must greater than or equal :rule'               => ':attribute必须大于等于 :rule',
+    ':attribute must greater than :rule'                        => ':attribute必须大于 :rule',
+    ':attribute must less than or equal :rule'                  => ':attribute必须小于等于 :rule',
+    ':attribute must less than :rule'                           => ':attribute必须小于 :rule',
+    ':attribute must equal :rule'                               => ':attribute必须等于 :rule',
+    ':attribute has exists'                                     => ':attribute已存在',
+    ':attribute not conform to the rules'                       => ':attribute不符合指定规则',
+    'invalid Request method'                                    => '无效的请求类型',
+    'invalid token'                                             => '令牌数据无效',
+    'not conform to the rules'                                  => '规则错误',
+];

+ 591 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/App.php

@@ -0,0 +1,591 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+use think\exception\ClassNotFoundException;
+use think\exception\HttpException;
+use think\exception\HttpResponseException;
+use think\exception\RouteNotFoundException;
+
+/**
+ * App 应用管理
+ * @author  liu21st <liu21st@gmail.com>
+ */
+class App
+{
+    /**
+     * @var bool 是否初始化过
+     */
+    protected static $init = false;
+
+    /**
+     * @var string 当前模块路径
+     */
+    public static $modulePath;
+
+    /**
+     * @var bool 应用调试模式
+     */
+    public static $debug = true;
+
+    /**
+     * @var string 应用类库命名空间
+     */
+    public static $namespace = 'app';
+
+    /**
+     * @var bool 应用类库后缀
+     */
+    public static $suffix = false;
+
+    /**
+     * @var bool 应用路由检测
+     */
+    protected static $routeCheck;
+
+    /**
+     * @var bool 严格路由检测
+     */
+    protected static $routeMust;
+
+    protected static $dispatch;
+    protected static $file = [];
+
+    /**
+     * 执行应用程序
+     * @access public
+     * @param Request $request Request对象
+     * @return Response
+     * @throws Exception
+     */
+    public static function run(Request $request = null)
+    {
+        is_null($request) && $request = Request::instance();
+
+        try {
+            $config = self::initCommon();
+            if (defined('BIND_MODULE')) {
+                // 模块/控制器绑定
+                BIND_MODULE && Route::bind(BIND_MODULE);
+            } elseif ($config['auto_bind_module']) {
+                // 入口自动绑定
+                $name = pathinfo($request->baseFile(), PATHINFO_FILENAME);
+                if ($name && 'index' != $name && is_dir(APP_PATH . $name)) {
+                    Route::bind($name);
+                }
+            }
+
+            $request->filter($config['default_filter']);
+
+            // 默认语言
+            Lang::range($config['default_lang']);
+            if ($config['lang_switch_on']) {
+                // 开启多语言机制 检测当前语言
+                Lang::detect();
+            }
+            $request->langset(Lang::range());
+
+            // 加载系统语言包
+            Lang::load([
+                THINK_PATH . 'lang' . DS . $request->langset() . EXT,
+                APP_PATH . 'lang' . DS . $request->langset() . EXT,
+            ]);
+
+            // 获取应用调度信息
+            $dispatch = self::$dispatch;
+            if (empty($dispatch)) {
+                // 进行URL路由检测
+                $dispatch = self::routeCheck($request, $config);
+            }
+            // 记录当前调度信息
+            $request->dispatch($dispatch);
+
+            // 记录路由和请求信息
+            if (self::$debug) {
+                Log::record('[ ROUTE ] ' . var_export($dispatch, true), 'info');
+                Log::record('[ HEADER ] ' . var_export($request->header(), true), 'info');
+                Log::record('[ PARAM ] ' . var_export($request->param(), true), 'info');
+            }
+
+            // 监听app_begin
+            Hook::listen('app_begin', $dispatch);
+            // 请求缓存检查
+            $request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);
+
+            $data = self::exec($dispatch, $config);
+        } catch (HttpResponseException $exception) {
+            $data = $exception->getResponse();
+        }
+
+        // 清空类的实例化
+        Loader::clearInstance();
+
+        // 输出数据到客户端
+        if ($data instanceof Response) {
+            $response = $data;
+        } elseif (!is_null($data)) {
+            // 默认自动识别响应输出类型
+            $isAjax   = $request->isAjax();
+            $type     = $isAjax ? Config::get('default_ajax_return') : Config::get('default_return_type');
+            $response = Response::create($data, $type);
+        } else {
+            $response = Response::create();
+        }
+
+        // 监听app_end
+        Hook::listen('app_end', $response);
+
+        return $response;
+    }
+
+    /**
+     * 设置当前请求的调度信息
+     * @access public
+     * @param array|string  $dispatch 调度信息
+     * @param string        $type 调度类型
+     * @return void
+     */
+    public static function dispatch($dispatch, $type = 'module')
+    {
+        self::$dispatch = ['type' => $type, $type => $dispatch];
+    }
+
+    /**
+     * 执行函数或者闭包方法 支持参数调用
+     * @access public
+     * @param string|array|\Closure $function 函数或者闭包
+     * @param array                 $vars     变量
+     * @return mixed
+     */
+    public static function invokeFunction($function, $vars = [])
+    {
+        $reflect = new \ReflectionFunction($function);
+        $args    = self::bindParams($reflect, $vars);
+        // 记录执行信息
+        self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info');
+        return $reflect->invokeArgs($args);
+    }
+
+    /**
+     * 调用反射执行类的方法 支持参数绑定
+     * @access public
+     * @param string|array $method 方法
+     * @param array        $vars   变量
+     * @return mixed
+     */
+    public static function invokeMethod($method, $vars = [])
+    {
+        if (is_array($method)) {
+            $class   = is_object($method[0]) ? $method[0] : self::invokeClass($method[0]);
+            $reflect = new \ReflectionMethod($class, $method[1]);
+        } else {
+            // 静态方法
+            $reflect = new \ReflectionMethod($method);
+        }
+        $args = self::bindParams($reflect, $vars);
+
+        self::$debug && Log::record('[ RUN ] ' . $reflect->class . '->' . $reflect->name . '[ ' . $reflect->getFileName() . ' ]', 'info');
+        return $reflect->invokeArgs(isset($class) ? $class : null, $args);
+    }
+
+    /**
+     * 调用反射执行类的实例化 支持依赖注入
+     * @access public
+     * @param string    $class 类名
+     * @param array     $vars  变量
+     * @return mixed
+     */
+    public static function invokeClass($class, $vars = [])
+    {
+        $reflect     = new \ReflectionClass($class);
+        $constructor = $reflect->getConstructor();
+        if ($constructor) {
+            $args = self::bindParams($constructor, $vars);
+        } else {
+            $args = [];
+        }
+        return $reflect->newInstanceArgs($args);
+    }
+
+    /**
+     * 绑定参数
+     * @access private
+     * @param \ReflectionMethod|\ReflectionFunction $reflect 反射类
+     * @param array                                 $vars    变量
+     * @return array
+     */
+    private static function bindParams($reflect, $vars = [])
+    {
+        if (empty($vars)) {
+            // 自动获取请求变量
+            if (Config::get('url_param_type')) {
+                $vars = Request::instance()->route();
+            } else {
+                $vars = Request::instance()->param();
+            }
+        }
+        $args = [];
+        if ($reflect->getNumberOfParameters() > 0) {
+            // 判断数组类型 数字数组时按顺序绑定参数
+            reset($vars);
+            $type   = key($vars) === 0 ? 1 : 0;
+            $params = $reflect->getParameters();
+            foreach ($params as $param) {
+                $args[] = self::getParamValue($param, $vars, $type);
+            }
+        }
+        return $args;
+    }
+
+    /**
+     * 获取参数值
+     * @access private
+     * @param \ReflectionParameter  $param
+     * @param array                 $vars    变量
+     * @param string                $type
+     * @return array
+     */
+    private static function getParamValue($param, &$vars, $type)
+    {
+        $name  = $param->getName();
+        $class = $param->getClass();
+        if ($class) {
+            $className = $class->getName();
+            $bind      = Request::instance()->$name;
+            if ($bind instanceof $className) {
+                $result = $bind;
+            } else {
+                if (method_exists($className, 'invoke')) {
+                    $method = new \ReflectionMethod($className, 'invoke');
+                    if ($method->isPublic() && $method->isStatic()) {
+                        return $className::invoke(Request::instance());
+                    }
+                }
+                $result = method_exists($className, 'instance') ? $className::instance() : new $className;
+            }
+        } elseif (1 == $type && !empty($vars)) {
+            $result = array_shift($vars);
+        } elseif (0 == $type && isset($vars[$name])) {
+            $result = $vars[$name];
+        } elseif ($param->isDefaultValueAvailable()) {
+            $result = $param->getDefaultValue();
+        } else {
+            throw new \InvalidArgumentException('method param miss:' . $name);
+        }
+        return $result;
+    }
+
+    protected static function exec($dispatch, $config)
+    {
+        switch ($dispatch['type']) {
+            case 'redirect':
+                // 执行重定向跳转
+                $data = Response::create($dispatch['url'], 'redirect')->code($dispatch['status']);
+                break;
+            case 'module':
+                // 模块/控制器/操作
+                $data = self::module($dispatch['module'], $config, isset($dispatch['convert']) ? $dispatch['convert'] : null);
+                break;
+            case 'controller':
+                // 执行控制器操作
+                $vars = array_merge(Request::instance()->param(), $dispatch['var']);
+                $data = Loader::action($dispatch['controller'], $vars, $config['url_controller_layer'], $config['controller_suffix']);
+                break;
+            case 'method':
+                // 执行回调方法
+                $vars = array_merge(Request::instance()->param(), $dispatch['var']);
+                $data = self::invokeMethod($dispatch['method'], $vars);
+                break;
+            case 'function':
+                // 执行闭包
+                $data = self::invokeFunction($dispatch['function']);
+                break;
+            case 'response':
+                $data = $dispatch['response'];
+                break;
+            default:
+                throw new \InvalidArgumentException('dispatch type not support');
+        }
+        return $data;
+    }
+
+    /**
+     * 执行模块
+     * @access public
+     * @param array $result 模块/控制器/操作
+     * @param array $config 配置参数
+     * @param bool  $convert 是否自动转换控制器和操作名
+     * @return mixed
+     */
+    public static function module($result, $config, $convert = null)
+    {
+        if (is_string($result)) {
+            $result = explode('/', $result);
+        }
+        $request = Request::instance();
+        if ($config['app_multi_module']) {
+            // 多模块部署
+            $module    = strip_tags(strtolower($result[0] ?: $config['default_module']));
+            $bind      = Route::getBind('module');
+            $available = false;
+            if ($bind) {
+                // 绑定模块
+                list($bindModule) = explode('/', $bind);
+                if (empty($result[0])) {
+                    $module    = $bindModule;
+                    $available = true;
+                } elseif ($module == $bindModule) {
+                    $available = true;
+                }
+            } elseif (!in_array($module, $config['deny_module_list']) && is_dir(APP_PATH . $module)) {
+                $available = true;
+            }
+
+            // 模块初始化
+            if ($module && $available) {
+                // 初始化模块
+                $request->module($module);
+                $config = self::init($module);
+                // 模块请求缓存检查
+                $request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);
+            } else {
+                throw new HttpException(404, 'module not exists:' . $module);
+            }
+        } else {
+            // 单一模块部署
+            $module = '';
+            $request->module($module);
+        }
+        // 当前模块路径
+        App::$modulePath = APP_PATH . ($module ? $module . DS : '');
+
+        // 是否自动转换控制器和操作名
+        $convert = is_bool($convert) ? $convert : $config['url_convert'];
+        // 获取控制器名
+        $controller = strip_tags($result[1] ?: $config['default_controller']);
+        $controller = $convert ? strtolower($controller) : $controller;
+
+        // 获取操作名
+        $actionName = strip_tags($result[2] ?: $config['default_action']);
+        $actionName = $convert ? strtolower($actionName) : $actionName;
+
+        // 设置当前请求的控制器、操作
+        $request->controller(Loader::parseName($controller, 1))->action($actionName);
+
+        // 监听module_init
+        Hook::listen('module_init', $request);
+
+        try {
+            $instance = Loader::controller($controller, $config['url_controller_layer'], $config['controller_suffix'], $config['empty_controller']);
+        } catch (ClassNotFoundException $e) {
+            throw new HttpException(404, 'controller not exists:' . $e->getClass());
+        }
+
+        // 获取当前操作名
+        $action = $actionName . $config['action_suffix'];
+
+        $vars = [];
+        if (is_callable([$instance, $action])) {
+            // 执行操作方法
+            $call = [$instance, $action];
+        } elseif (is_callable([$instance, '_empty'])) {
+            // 空操作
+            $call = [$instance, '_empty'];
+            $vars = [$actionName];
+        } else {
+            // 操作不存在
+            throw new HttpException(404, 'method not exists:' . get_class($instance) . '->' . $action . '()');
+        }
+
+        Hook::listen('action_begin', $call);
+
+        return self::invokeMethod($call, $vars);
+    }
+
+    /**
+     * 初始化应用
+     */
+    public static function initCommon()
+    {
+        if (empty(self::$init)) {
+            if (defined('APP_NAMESPACE')) {
+                self::$namespace = APP_NAMESPACE;
+            }
+            Loader::addNamespace(self::$namespace, APP_PATH);
+
+            // 初始化应用
+            $config       = self::init();
+            self::$suffix = $config['class_suffix'];
+
+            // 应用调试模式
+            self::$debug = Env::get('app_debug', Config::get('app_debug'));
+            if (!self::$debug) {
+                ini_set('display_errors', 'Off');
+            } elseif (!IS_CLI) {
+                //重新申请一块比较大的buffer
+                if (ob_get_level() > 0) {
+                    $output = ob_get_clean();
+                }
+                ob_start();
+                if (!empty($output)) {
+                    echo $output;
+                }
+            }
+
+            if (!empty($config['root_namespace'])) {
+                Loader::addNamespace($config['root_namespace']);
+            }
+
+            // 加载额外文件
+            if (!empty($config['extra_file_list'])) {
+                foreach ($config['extra_file_list'] as $file) {
+                    $file = strpos($file, '.') ? $file : APP_PATH . $file . EXT;
+                    if (is_file($file) && !isset(self::$file[$file])) {
+                        include $file;
+                        self::$file[$file] = true;
+                    }
+                }
+            }
+
+            // 设置系统时区
+            date_default_timezone_set($config['default_timezone']);
+
+            // 监听app_init
+            Hook::listen('app_init');
+
+            self::$init = true;
+        }
+        return Config::get();
+    }
+
+    /**
+     * 初始化应用或模块
+     * @access public
+     * @param string $module 模块名
+     * @return array
+     */
+    private static function init($module = '')
+    {
+        // 定位模块目录
+        $module = $module ? $module . DS : '';
+
+        // 加载初始化文件
+        if (is_file(APP_PATH . $module . 'init' . EXT)) {
+            include APP_PATH . $module . 'init' . EXT;
+        } elseif (is_file(RUNTIME_PATH . $module . 'init' . EXT)) {
+            include RUNTIME_PATH . $module . 'init' . EXT;
+        } else {
+            $path = APP_PATH . $module;
+            // 加载模块配置
+            $config = Config::load(CONF_PATH . $module . 'config' . CONF_EXT);
+            // 读取数据库配置文件
+            $filename = CONF_PATH . $module . 'database' . CONF_EXT;
+            Config::load($filename, 'database');
+            // 读取扩展配置文件
+            if (is_dir(CONF_PATH . $module . 'extra')) {
+                $dir   = CONF_PATH . $module . 'extra';
+                $files = scandir($dir);
+                foreach ($files as $file) {
+                    if ('.' . pathinfo($file, PATHINFO_EXTENSION) === CONF_EXT) {
+                        $filename = $dir . DS . $file;
+                        Config::load($filename, pathinfo($file, PATHINFO_FILENAME));
+                    }
+                }
+            }
+
+            // 加载应用状态配置
+            if ($config['app_status']) {
+                $config = Config::load(CONF_PATH . $module . $config['app_status'] . CONF_EXT);
+            }
+
+            // 加载行为扩展文件
+            if (is_file(CONF_PATH . $module . 'tags' . EXT)) {
+                Hook::import(include CONF_PATH . $module . 'tags' . EXT);
+            }
+
+            // 加载公共文件
+            if (is_file($path . 'common' . EXT)) {
+                include $path . 'common' . EXT;
+            }
+
+            // 加载当前模块语言包
+            if ($module) {
+                Lang::load($path . 'lang' . DS . Request::instance()->langset() . EXT);
+            }
+        }
+        return Config::get();
+    }
+
+    /**
+     * URL路由检测(根据PATH_INFO)
+     * @access public
+     * @param  \think\Request $request
+     * @param  array          $config
+     * @return array
+     * @throws \think\Exception
+     */
+    public static function routeCheck($request, array $config)
+    {
+        $path   = $request->path();
+        $depr   = $config['pathinfo_depr'];
+        $result = false;
+        // 路由检测
+        $check = !is_null(self::$routeCheck) ? self::$routeCheck : $config['url_route_on'];
+        if ($check) {
+            // 开启路由
+            if (is_file(RUNTIME_PATH . 'route.php')) {
+                // 读取路由缓存
+                $rules = include RUNTIME_PATH . 'route.php';
+                if (is_array($rules)) {
+                    Route::rules($rules);
+                }
+            } else {
+                $files = $config['route_config_file'];
+                foreach ($files as $file) {
+                    if (is_file(CONF_PATH . $file . CONF_EXT)) {
+                        // 导入路由配置
+                        $rules = include CONF_PATH . $file . CONF_EXT;
+                        if (is_array($rules)) {
+                            Route::import($rules);
+                        }
+                    }
+                }
+            }
+
+            // 路由检测(根据路由定义返回不同的URL调度)
+            $result = Route::check($request, $path, $depr, $config['url_domain_deploy']);
+            $must   = !is_null(self::$routeMust) ? self::$routeMust : $config['url_route_must'];
+            if ($must && false === $result) {
+                // 路由无效
+                throw new RouteNotFoundException();
+            }
+        }
+        if (false === $result) {
+            // 路由无效 解析模块/控制器/操作/参数... 支持控制器自动搜索
+            $result = Route::parseUrl($path, $depr, $config['controller_auto_search']);
+        }
+        return $result;
+    }
+
+    /**
+     * 设置应用的路由检测机制
+     * @access public
+     * @param  bool $route 是否需要检测路由
+     * @param  bool $must  是否强制检测路由
+     * @return void
+     */
+    public static function route($route, $must = false)
+    {
+        self::$routeCheck = $route;
+        self::$routeMust  = $must;
+    }
+}

+ 205 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Build.php

@@ -0,0 +1,205 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+class Build
+{
+    /**
+     * 根据传入的build资料创建目录和文件
+     * @access protected
+     * @param  array  $build build列表
+     * @param  string $namespace 应用类库命名空间
+     * @param  bool   $suffix 类库后缀
+     * @return void
+     */
+    public static function run(array $build = [], $namespace = 'app', $suffix = false)
+    {
+        // 锁定
+        $lockfile = APP_PATH . 'build.lock';
+        if (is_writable($lockfile)) {
+            return;
+        } elseif (!touch($lockfile)) {
+            throw new Exception('应用目录[' . APP_PATH . ']不可写,目录无法自动生成!<BR>请手动生成项目目录~', 10006);
+        }
+        foreach ($build as $module => $list) {
+            if ('__dir__' == $module) {
+                // 创建目录列表
+                self::buildDir($list);
+            } elseif ('__file__' == $module) {
+                // 创建文件列表
+                self::buildFile($list);
+            } else {
+                // 创建模块
+                self::module($module, $list, $namespace, $suffix);
+            }
+        }
+        // 解除锁定
+        unlink($lockfile);
+    }
+
+    /**
+     * 创建目录
+     * @access protected
+     * @param  array $list 目录列表
+     * @return void
+     */
+    protected static function buildDir($list)
+    {
+        foreach ($list as $dir) {
+            if (!is_dir(APP_PATH . $dir)) {
+                // 创建目录
+                mkdir(APP_PATH . $dir, 0755, true);
+            }
+        }
+    }
+
+    /**
+     * 创建文件
+     * @access protected
+     * @param  array $list 文件列表
+     * @return void
+     */
+    protected static function buildFile($list)
+    {
+        foreach ($list as $file) {
+            if (!is_dir(APP_PATH . dirname($file))) {
+                // 创建目录
+                mkdir(APP_PATH . dirname($file), 0755, true);
+            }
+            if (!is_file(APP_PATH . $file)) {
+                file_put_contents(APP_PATH . $file, 'php' == pathinfo($file, PATHINFO_EXTENSION) ? "<?php\n" : '');
+            }
+        }
+    }
+
+    /**
+     * 创建模块
+     * @access public
+     * @param  string $module 模块名
+     * @param  array  $list build列表
+     * @param  string $namespace 应用类库命名空间
+     * @param  bool   $suffix 类库后缀
+     * @return void
+     */
+    public static function module($module = '', $list = [], $namespace = 'app', $suffix = false)
+    {
+        $module = $module ? $module : '';
+        if (!is_dir(APP_PATH . $module)) {
+            // 创建模块目录
+            mkdir(APP_PATH . $module);
+        }
+        if (basename(RUNTIME_PATH) != $module) {
+            // 创建配置文件和公共文件
+            self::buildCommon($module);
+            // 创建模块的默认页面
+            self::buildHello($module, $namespace, $suffix);
+        }
+        if (empty($list)) {
+            // 创建默认的模块目录和文件
+            $list = [
+                '__file__' => ['config.php', 'common.php'],
+                '__dir__'  => ['controller', 'model', 'view'],
+            ];
+        }
+        // 创建子目录和文件
+        foreach ($list as $path => $file) {
+            $modulePath = APP_PATH . $module . DS;
+            if ('__dir__' == $path) {
+                // 生成子目录
+                foreach ($file as $dir) {
+                    self::checkDirBuild($modulePath . $dir);
+                }
+            } elseif ('__file__' == $path) {
+                // 生成(空白)文件
+                foreach ($file as $name) {
+                    if (!is_file($modulePath . $name)) {
+                        file_put_contents($modulePath . $name, 'php' == pathinfo($name, PATHINFO_EXTENSION) ? "<?php\n" : '');
+                    }
+                }
+            } else {
+                // 生成相关MVC文件
+                foreach ($file as $val) {
+                    $val      = trim($val);
+                    $filename = $modulePath . $path . DS . $val . ($suffix ? ucfirst($path) : '') . EXT;
+                    $space    = $namespace . '\\' . ($module ? $module . '\\' : '') . $path;
+                    $class    = $val . ($suffix ? ucfirst($path) : '');
+                    switch ($path) {
+                        case 'controller': // 控制器
+                            $content = "<?php\nnamespace {$space};\n\nclass {$class}\n{\n\n}";
+                            break;
+                        case 'model': // 模型
+                            $content = "<?php\nnamespace {$space};\n\nuse think\Model;\n\nclass {$class} extends Model\n{\n\n}";
+                            break;
+                        case 'view': // 视图
+                            $filename = $modulePath . $path . DS . $val . '.html';
+                            self::checkDirBuild(dirname($filename));
+                            $content = '';
+                            break;
+                        default:
+                            // 其他文件
+                            $content = "<?php\nnamespace {$space};\n\nclass {$class}\n{\n\n}";
+                    }
+
+                    if (!is_file($filename)) {
+                        file_put_contents($filename, $content);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 创建模块的欢迎页面
+     * @access public
+     * @param  string $module 模块名
+     * @param  string $namespace 应用类库命名空间
+     * @param  bool   $suffix 类库后缀
+     * @return void
+     */
+    protected static function buildHello($module, $namespace, $suffix = false)
+    {
+        $filename = APP_PATH . ($module ? $module . DS : '') . 'controller' . DS . 'Index' . ($suffix ? 'Controller' : '') . EXT;
+        if (!is_file($filename)) {
+            $content = file_get_contents(THINK_PATH . 'tpl' . DS . 'default_index.tpl');
+            $content = str_replace(['{$app}', '{$module}', '{layer}', '{$suffix}'], [$namespace, $module ? $module . '\\' : '', 'controller', $suffix ? 'Controller' : ''], $content);
+            self::checkDirBuild(dirname($filename));
+            file_put_contents($filename, $content);
+        }
+    }
+
+    /**
+     * 创建模块的公共文件
+     * @access public
+     * @param  string $module 模块名
+     * @return void
+     */
+    protected static function buildCommon($module)
+    {
+        $filename = CONF_PATH . ($module ? $module . DS : '') . 'config.php';
+
+        self::checkDirBuild(dirname($filename));
+        if (!is_file($filename)) {
+            file_put_contents($filename, "<?php\n//配置文件\nreturn [\n\n];");
+        }
+        $filename = APP_PATH . ($module ? $module . DS : '') . 'common.php';
+        if (!is_file($filename)) {
+            file_put_contents($filename, "<?php\n");
+        }
+    }
+
+    protected static function checkDirBuild($dirname)
+    {
+        if (!is_dir($dirname)) {
+            mkdir($dirname, 0755, true);
+        }
+    }
+}

+ 222 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Cache.php

@@ -0,0 +1,222 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+use think\cache\Driver;
+
+class Cache
+{
+    protected static $instance = [];
+    public static $readTimes   = 0;
+    public static $writeTimes  = 0;
+
+    /**
+     * 操作句柄
+     * @var object
+     * @access protected
+     */
+    protected static $handler;
+
+    /**
+     * 连接缓存
+     * @access public
+     * @param array         $options  配置数组
+     * @param bool|string   $name 缓存连接标识 true 强制重新连接
+     * @return Driver
+     */
+    public static function connect(array $options = [], $name = false)
+    {
+        $type = !empty($options['type']) ? $options['type'] : 'File';
+        if (false === $name) {
+            $name = md5(serialize($options));
+        }
+
+        if (true === $name || !isset(self::$instance[$name])) {
+            $class = false !== strpos($type, '\\') ? $type : '\\think\\cache\\driver\\' . ucwords($type);
+
+            // 记录初始化信息
+            App::$debug && Log::record('[ CACHE ] INIT ' . $type, 'info');
+            if (true === $name) {
+                return new $class($options);
+            } else {
+                self::$instance[$name] = new $class($options);
+            }
+        }
+        return self::$instance[$name];
+    }
+
+    /**
+     * 自动初始化缓存
+     * @access public
+     * @param array         $options  配置数组
+     * @return Driver
+     */
+    public static function init(array $options = [])
+    {
+        if (is_null(self::$handler)) {
+            // 自动初始化缓存
+            if (!empty($options)) {
+                $connect = self::connect($options);
+            } elseif ('complex' == Config::get('cache.type')) {
+                $connect = self::connect(Config::get('cache.default'));
+            } else {
+                $connect = self::connect(Config::get('cache'));
+            }
+            self::$handler = $connect;
+        }
+        return self::$handler;
+    }
+
+    /**
+     * 切换缓存类型 需要配置 cache.type 为 complex
+     * @access public
+     * @param string $name 缓存标识
+     * @return Driver
+     */
+    public static function store($name = '')
+    {
+        if ('' !== $name && 'complex' == Config::get('cache.type')) {
+            return self::connect(Config::get('cache.' . $name), strtolower($name));
+        }
+        return self::init();
+    }
+
+    /**
+     * 判断缓存是否存在
+     * @access public
+     * @param string $name 缓存变量名
+     * @return bool
+     */
+    public static function has($name)
+    {
+        self::$readTimes++;
+        return self::init()->has($name);
+    }
+
+    /**
+     * 读取缓存
+     * @access public
+     * @param string $name 缓存标识
+     * @param mixed  $default 默认值
+     * @return mixed
+     */
+    public static function get($name, $default = false)
+    {
+        self::$readTimes++;
+        return self::init()->get($name, $default);
+    }
+
+    /**
+     * 写入缓存
+     * @access public
+     * @param string        $name 缓存标识
+     * @param mixed         $value  存储数据
+     * @param int|null      $expire  有效时间 0为永久
+     * @return boolean
+     */
+    public static function set($name, $value, $expire = null)
+    {
+        self::$writeTimes++;
+        return self::init()->set($name, $value, $expire);
+    }
+
+    /**
+     * 自增缓存(针对数值缓存)
+     * @access public
+     * @param string    $name 缓存变量名
+     * @param int       $step 步长
+     * @return false|int
+     */
+    public static function inc($name, $step = 1)
+    {
+        self::$writeTimes++;
+        return self::init()->inc($name, $step);
+    }
+
+    /**
+     * 自减缓存(针对数值缓存)
+     * @access public
+     * @param string    $name 缓存变量名
+     * @param int       $step 步长
+     * @return false|int
+     */
+    public static function dec($name, $step = 1)
+    {
+        self::$writeTimes++;
+        return self::init()->dec($name, $step);
+    }
+
+    /**
+     * 删除缓存
+     * @access public
+     * @param string    $name 缓存标识
+     * @return boolean
+     */
+    public static function rm($name)
+    {
+        self::$writeTimes++;
+        return self::init()->rm($name);
+    }
+
+    /**
+     * 清除缓存
+     * @access public
+     * @param string $tag 标签名
+     * @return boolean
+     */
+    public static function clear($tag = null)
+    {
+        self::$writeTimes++;
+        return self::init()->clear($tag);
+    }
+
+    /**
+     * 读取缓存并删除
+     * @access public
+     * @param string $name 缓存变量名
+     * @return mixed
+     */
+    public static function pull($name)
+    {
+        self::$readTimes++;
+        self::$writeTimes++;
+        return self::init()->pull($name);
+    }
+
+    /**
+     * 如果不存在则写入缓存
+     * @access public
+     * @param string    $name 缓存变量名
+     * @param mixed     $value  存储数据
+     * @param int       $expire  有效时间 0为永久
+     * @return mixed
+     */
+    public static function remember($name, $value, $expire = null)
+    {
+        self::$readTimes++;
+        return self::init()->remember($name, $value, $expire);
+    }
+
+    /**
+     * 缓存标签
+     * @access public
+     * @param string        $name 标签名
+     * @param string|array  $keys 缓存标识
+     * @param bool          $overlay 是否覆盖
+     * @return Driver
+     */
+    public static function tag($name, $keys = null, $overlay = false)
+    {
+        return self::init()->tag($name, $keys, $overlay);
+    }
+
+}

+ 391 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Collection.php

@@ -0,0 +1,391 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: zhangyajun <448901948@qq.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+use ArrayAccess;
+use ArrayIterator;
+use Countable;
+use IteratorAggregate;
+use JsonSerializable;
+
+class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable
+{
+    protected $items = [];
+
+    public function __construct($items = [])
+    {
+        $this->items = $this->convertToArray($items);
+    }
+
+    public static function make($items = [])
+    {
+        return new static($items);
+    }
+
+    /**
+     * 是否为空
+     * @return bool
+     */
+    public function isEmpty()
+    {
+        return empty($this->items);
+    }
+
+    public function toArray()
+    {
+        return array_map(function ($value) {
+            return ($value instanceof Model || $value instanceof self) ? $value->toArray() : $value;
+        }, $this->items);
+    }
+
+    public function all()
+    {
+        return $this->items;
+    }
+
+    /**
+     * 合并数组
+     *
+     * @param  mixed $items
+     * @return static
+     */
+    public function merge($items)
+    {
+        return new static(array_merge($this->items, $this->convertToArray($items)));
+    }
+
+    /**
+     * 比较数组,返回差集
+     *
+     * @param  mixed $items
+     * @return static
+     */
+    public function diff($items)
+    {
+        return new static(array_diff($this->items, $this->convertToArray($items)));
+    }
+
+    /**
+     * 交换数组中的键和值
+     *
+     * @return static
+     */
+    public function flip()
+    {
+        return new static(array_flip($this->items));
+    }
+
+    /**
+     * 比较数组,返回交集
+     *
+     * @param  mixed $items
+     * @return static
+     */
+    public function intersect($items)
+    {
+        return new static(array_intersect($this->items, $this->convertToArray($items)));
+    }
+
+    /**
+     * 返回数组中所有的键名
+     *
+     * @return static
+     */
+    public function keys()
+    {
+        return new static(array_keys($this->items));
+    }
+
+    /**
+     * 删除数组的最后一个元素(出栈)
+     *
+     * @return mixed
+     */
+    public function pop()
+    {
+        return array_pop($this->items);
+    }
+
+    /**
+     * 通过使用用户自定义函数,以字符串返回数组
+     *
+     * @param  callable $callback
+     * @param  mixed    $initial
+     * @return mixed
+     */
+    public function reduce(callable $callback, $initial = null)
+    {
+        return array_reduce($this->items, $callback, $initial);
+    }
+
+    /**
+     * 以相反的顺序返回数组。
+     *
+     * @return static
+     */
+    public function reverse()
+    {
+        return new static(array_reverse($this->items));
+    }
+
+    /**
+     * 删除数组中首个元素,并返回被删除元素的值
+     *
+     * @return mixed
+     */
+    public function shift()
+    {
+        return array_shift($this->items);
+    }
+
+    /**
+     * 把一个数组分割为新的数组块.
+     *
+     * @param  int  $size
+     * @param  bool $preserveKeys
+     * @return static
+     */
+    public function chunk($size, $preserveKeys = false)
+    {
+        $chunks = [];
+
+        foreach (array_chunk($this->items, $size, $preserveKeys) as $chunk) {
+            $chunks[] = new static($chunk);
+        }
+
+        return new static($chunks);
+    }
+
+    /**
+     * 在数组开头插入一个元素
+     * @param mixed     $value
+     * @param miexed    $key
+     * @return void
+     */
+    public function unshift($value, $key = null)
+    {
+        if (is_null($key)) {
+            array_unshift($this->items, $value);
+        } else {
+            $this->items = [$key => $value] + $this->items;
+        }
+    }
+
+    /**
+     * 在数组结尾插入一个元素
+     * @param mixed  $value
+     * @param mixed  $key
+     * @return void
+     */
+    public function push($value, $key = null)
+    {
+        if (is_null($key)) {
+            $this->items[] = $value;
+        } else {
+            $this->items[$key] = $value;
+        }
+    }
+
+    /**
+     * 给每个元素执行个回调
+     *
+     * @param  callable $callback
+     * @return $this
+     */
+    public function each(callable $callback)
+    {
+        foreach ($this->items as $key => $item) {
+            $result = $callback($item, $key);
+            if (false === $result) {
+                break;
+            } elseif (!is_object($item)) {
+                $this->items[$key] = $result;
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * 用回调函数过滤数组中的元素
+     * @param callable|null $callback
+     * @return static
+     */
+    public function filter(callable $callback = null)
+    {
+        if ($callback) {
+            return new static(array_filter($this->items, $callback));
+        }
+
+        return new static(array_filter($this->items));
+    }
+
+    /**
+     * 返回数组中指定的一列
+     * @param      $column_key
+     * @param null $index_key
+     * @return array
+     */
+    public function column($column_key, $index_key = null)
+    {
+        if (function_exists('array_column')) {
+            return array_column($this->items, $column_key, $index_key);
+        }
+
+        $result = [];
+        foreach ($this->items as $row) {
+            $key    = $value    = null;
+            $keySet = $valueSet = false;
+            if (null !== $index_key && array_key_exists($index_key, $row)) {
+                $keySet = true;
+                $key    = (string) $row[$index_key];
+            }
+            if (null === $column_key) {
+                $valueSet = true;
+                $value    = $row;
+            } elseif (is_array($row) && array_key_exists($column_key, $row)) {
+                $valueSet = true;
+                $value    = $row[$column_key];
+            }
+            if ($valueSet) {
+                if ($keySet) {
+                    $result[$key] = $value;
+                } else {
+                    $result[] = $value;
+                }
+            }
+        }
+        return $result;
+    }
+
+    /**
+     * 对数组排序
+     *
+     * @param  callable|null $callback
+     * @return static
+     */
+    public function sort(callable $callback = null)
+    {
+        $items = $this->items;
+
+        $callback ? uasort($items, $callback) : uasort($items, function ($a, $b) {
+
+            if ($a == $b) {
+                return 0;
+            }
+
+            return ($a < $b) ? -1 : 1;
+        });
+
+        return new static($items);
+    }
+
+    /**
+     * 将数组打乱
+     *
+     * @return static
+     */
+    public function shuffle()
+    {
+        $items = $this->items;
+
+        shuffle($items);
+
+        return new static($items);
+    }
+
+    /**
+     * 截取数组
+     *
+     * @param  int  $offset
+     * @param  int  $length
+     * @param  bool $preserveKeys
+     * @return static
+     */
+    public function slice($offset, $length = null, $preserveKeys = false)
+    {
+        return new static(array_slice($this->items, $offset, $length, $preserveKeys));
+    }
+
+    // ArrayAccess
+    public function offsetExists($offset)
+    {
+        return array_key_exists($offset, $this->items);
+    }
+
+    public function offsetGet($offset)
+    {
+        return $this->items[$offset];
+    }
+
+    public function offsetSet($offset, $value)
+    {
+        if (is_null($offset)) {
+            $this->items[] = $value;
+        } else {
+            $this->items[$offset] = $value;
+        }
+    }
+
+    public function offsetUnset($offset)
+    {
+        unset($this->items[$offset]);
+    }
+
+    //Countable
+    public function count()
+    {
+        return count($this->items);
+    }
+
+    //IteratorAggregate
+    public function getIterator()
+    {
+        return new ArrayIterator($this->items);
+    }
+
+    //JsonSerializable
+    public function jsonSerialize()
+    {
+        return $this->toArray();
+    }
+
+    /**
+     * 转换当前数据集为JSON字符串
+     * @access public
+     * @param integer $options json参数
+     * @return string
+     */
+    public function toJson($options = JSON_UNESCAPED_UNICODE)
+    {
+        return json_encode($this->toArray(), $options);
+    }
+
+    public function __toString()
+    {
+        return $this->toJson();
+    }
+
+    /**
+     * 转换成数组
+     *
+     * @param  mixed $items
+     * @return array
+     */
+    protected function convertToArray($items)
+    {
+        if ($items instanceof self) {
+            return $items->all();
+        }
+        return (array) $items;
+    }
+}

+ 178 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Config.php

@@ -0,0 +1,178 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+class Config
+{
+    // 配置参数
+    private static $config = [];
+    // 参数作用域
+    private static $range = '_sys_';
+
+    // 设定配置参数的作用域
+    public static function range($range)
+    {
+        self::$range = $range;
+        if (!isset(self::$config[$range])) {
+            self::$config[$range] = [];
+        }
+    }
+
+    /**
+     * 解析配置文件或内容
+     * @param string    $config 配置文件路径或内容
+     * @param string    $type 配置解析类型
+     * @param string    $name 配置名(如设置即表示二级配置)
+     * @param string    $range  作用域
+     * @return mixed
+     */
+    public static function parse($config, $type = '', $name = '', $range = '')
+    {
+        $range = $range ?: self::$range;
+        if (empty($type)) {
+            $type = pathinfo($config, PATHINFO_EXTENSION);
+        }
+        $class = false !== strpos($type, '\\') ? $type : '\\think\\config\\driver\\' . ucwords($type);
+        return self::set((new $class())->parse($config), $name, $range);
+    }
+
+    /**
+     * 加载配置文件(PHP格式)
+     * @param string    $file 配置文件名
+     * @param string    $name 配置名(如设置即表示二级配置)
+     * @param string    $range  作用域
+     * @return mixed
+     */
+    public static function load($file, $name = '', $range = '')
+    {
+        $range = $range ?: self::$range;
+        if (!isset(self::$config[$range])) {
+            self::$config[$range] = [];
+        }
+        if (is_file($file)) {
+            $name = strtolower($name);
+            $type = pathinfo($file, PATHINFO_EXTENSION);
+            if ('php' == $type) {
+                return self::set(include $file, $name, $range);
+            } elseif ('yaml' == $type && function_exists('yaml_parse_file')) {
+                return self::set(yaml_parse_file($file), $name, $range);
+            } else {
+                return self::parse($file, $type, $name, $range);
+            }
+        } else {
+            return self::$config[$range];
+        }
+    }
+
+    /**
+     * 检测配置是否存在
+     * @param string    $name 配置参数名(支持二级配置 .号分割)
+     * @param string    $range  作用域
+     * @return bool
+     */
+    public static function has($name, $range = '')
+    {
+        $range = $range ?: self::$range;
+
+        if (!strpos($name, '.')) {
+            return isset(self::$config[$range][strtolower($name)]);
+        } else {
+            // 二维数组设置和获取支持
+            $name = explode('.', $name, 2);
+            return isset(self::$config[$range][strtolower($name[0])][$name[1]]);
+        }
+    }
+
+    /**
+     * 获取配置参数 为空则获取所有配置
+     * @param string    $name 配置参数名(支持二级配置 .号分割)
+     * @param string    $range  作用域
+     * @return mixed
+     */
+    public static function get($name = null, $range = '')
+    {
+        $range = $range ?: self::$range;
+        // 无参数时获取所有
+        if (empty($name) && isset(self::$config[$range])) {
+            return self::$config[$range];
+        }
+
+        if (!strpos($name, '.')) {
+            $name = strtolower($name);
+            return isset(self::$config[$range][$name]) ? self::$config[$range][$name] : null;
+        } else {
+            // 二维数组设置和获取支持
+            $name    = explode('.', $name, 2);
+            $name[0] = strtolower($name[0]);
+
+            if (!isset(self::$config[$range][$name[0]])) {
+                // 动态载入额外配置
+                $module = Request::instance()->module();
+                $file   = CONF_PATH . ($module ? $module . DS : '') . 'extra' . DS . $name[0] . CONF_EXT;
+
+                is_file($file) && self::load($file, $name[0]);
+            }
+
+            return isset(self::$config[$range][$name[0]][$name[1]]) ? self::$config[$range][$name[0]][$name[1]] : null;
+        }
+    }
+
+    /**
+     * 设置配置参数 name为数组则为批量设置
+     * @param string|array  $name 配置参数名(支持二级配置 .号分割)
+     * @param mixed         $value 配置值
+     * @param string        $range  作用域
+     * @return mixed
+     */
+    public static function set($name, $value = null, $range = '')
+    {
+        $range = $range ?: self::$range;
+        if (!isset(self::$config[$range])) {
+            self::$config[$range] = [];
+        }
+        if (is_string($name)) {
+            if (!strpos($name, '.')) {
+                self::$config[$range][strtolower($name)] = $value;
+            } else {
+                // 二维数组设置和获取支持
+                $name                                                 = explode('.', $name, 2);
+                self::$config[$range][strtolower($name[0])][$name[1]] = $value;
+            }
+            return;
+        } elseif (is_array($name)) {
+            // 批量设置
+            if (!empty($value)) {
+                self::$config[$range][$value] = isset(self::$config[$range][$value]) ?
+                array_merge(self::$config[$range][$value], $name) : $name;
+                return self::$config[$range][$value];
+            } else {
+                return self::$config[$range] = array_merge(self::$config[$range], array_change_key_case($name));
+            }
+        } else {
+            // 为空直接返回 已有配置
+            return self::$config[$range];
+        }
+    }
+
+    /**
+     * 重置配置参数
+     */
+    public static function reset($range = '')
+    {
+        $range = $range ?: self::$range;
+        if (true === $range) {
+            self::$config = [];
+        } else {
+            self::$config[$range] = [];
+        }
+    }
+}

+ 719 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Console.php

@@ -0,0 +1,719 @@
+<?php
+// +----------------------------------------------------------------------
+// | TopThink [ WE CAN DO IT JUST THINK IT ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2015 http://www.topthink.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Author: zhangyajun <448901948@qq.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+use think\console\Command;
+use think\console\command\Help as HelpCommand;
+use think\console\Input;
+use think\console\input\Argument as InputArgument;
+use think\console\input\Definition as InputDefinition;
+use think\console\input\Option as InputOption;
+use think\console\Output;
+use think\console\output\driver\Buffer;
+
+class Console
+{
+
+    private $name;
+    private $version;
+
+    /** @var Command[] */
+    private $commands = [];
+
+    private $wantHelps = false;
+
+    private $catchExceptions = true;
+    private $autoExit        = true;
+    private $definition;
+    private $defaultCommand;
+
+    private static $defaultCommands = [
+        "think\\console\\command\\Help",
+        "think\\console\\command\\Lists",
+        "think\\console\\command\\Build",
+        "think\\console\\command\\Clear",
+        "think\\console\\command\\make\\Controller",
+        "think\\console\\command\\make\\Model",
+        "think\\console\\command\\optimize\\Autoload",
+        "think\\console\\command\\optimize\\Config",
+        "think\\console\\command\\optimize\\Route",
+        "think\\console\\command\\optimize\\Schema",
+    ];
+
+    public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
+    {
+        $this->name    = $name;
+        $this->version = $version;
+
+        $this->defaultCommand = 'list';
+        $this->definition     = $this->getDefaultInputDefinition();
+
+        foreach ($this->getDefaultCommands() as $command) {
+            $this->add($command);
+        }
+    }
+
+    public static function init($run = true)
+    {
+        static $console;
+        if (!$console) {
+            // 实例化console
+            $console = new self('Think Console', '0.1');
+            // 读取指令集
+            if (is_file(CONF_PATH . 'command' . EXT)) {
+                $commands = include CONF_PATH . 'command' . EXT;
+                if (is_array($commands)) {
+                    foreach ($commands as $command) {
+                        if (class_exists($command) && is_subclass_of($command, "\\think\\console\\Command")) {
+                            // 注册指令
+                            $console->add(new $command());
+                        }
+                    }
+                }
+            }
+        }
+        if ($run) {
+            // 运行
+            return $console->run();
+        } else {
+            return $console;
+        }
+    }
+
+    /**
+     * @param        $command
+     * @param array  $parameters
+     * @param string $driver
+     * @return Output|Buffer
+     */
+    public static function call($command, array $parameters = [], $driver = 'buffer')
+    {
+        $console = self::init(false);
+
+        array_unshift($parameters, $command);
+
+        $input  = new Input($parameters);
+        $output = new Output($driver);
+
+        $console->setCatchExceptions(false);
+        $console->find($command)->run($input, $output);
+
+        return $output;
+    }
+
+    /**
+     * 执行当前的指令
+     * @return int
+     * @throws \Exception
+     * @api
+     */
+    public function run()
+    {
+        $input  = new Input();
+        $output = new Output();
+
+        $this->configureIO($input, $output);
+
+        try {
+            $exitCode = $this->doRun($input, $output);
+        } catch (\Exception $e) {
+            if (!$this->catchExceptions) {
+                throw $e;
+            }
+
+            $output->renderException($e);
+
+            $exitCode = $e->getCode();
+            if (is_numeric($exitCode)) {
+                $exitCode = (int) $exitCode;
+                if (0 === $exitCode) {
+                    $exitCode = 1;
+                }
+            } else {
+                $exitCode = 1;
+            }
+        }
+
+        if ($this->autoExit) {
+            if ($exitCode > 255) {
+                $exitCode = 255;
+            }
+
+            exit($exitCode);
+        }
+
+        return $exitCode;
+    }
+
+    /**
+     * 执行指令
+     * @param Input  $input
+     * @param Output $output
+     * @return int
+     */
+    public function doRun(Input $input, Output $output)
+    {
+        if (true === $input->hasParameterOption(['--version', '-V'])) {
+            $output->writeln($this->getLongVersion());
+
+            return 0;
+        }
+
+        $name = $this->getCommandName($input);
+
+        if (true === $input->hasParameterOption(['--help', '-h'])) {
+            if (!$name) {
+                $name  = 'help';
+                $input = new Input(['help']);
+            } else {
+                $this->wantHelps = true;
+            }
+        }
+
+        if (!$name) {
+            $name  = $this->defaultCommand;
+            $input = new Input([$this->defaultCommand]);
+        }
+
+        $command = $this->find($name);
+
+        $exitCode = $this->doRunCommand($command, $input, $output);
+
+        return $exitCode;
+    }
+
+    /**
+     * 设置输入参数定义
+     * @param InputDefinition $definition
+     */
+    public function setDefinition(InputDefinition $definition)
+    {
+        $this->definition = $definition;
+    }
+
+    /**
+     * 获取输入参数定义
+     * @return InputDefinition The InputDefinition instance
+     */
+    public function getDefinition()
+    {
+        return $this->definition;
+    }
+
+    /**
+     * Gets the help message.
+     * @return string A help message.
+     */
+    public function getHelp()
+    {
+        return $this->getLongVersion();
+    }
+
+    /**
+     * 是否捕获异常
+     * @param bool $boolean
+     * @api
+     */
+    public function setCatchExceptions($boolean)
+    {
+        $this->catchExceptions = (bool) $boolean;
+    }
+
+    /**
+     * 是否自动退出
+     * @param bool $boolean
+     * @api
+     */
+    public function setAutoExit($boolean)
+    {
+        $this->autoExit = (bool) $boolean;
+    }
+
+    /**
+     * 获取名称
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * 设置名称
+     * @param string $name
+     */
+    public function setName($name)
+    {
+        $this->name = $name;
+    }
+
+    /**
+     * 获取版本
+     * @return string
+     * @api
+     */
+    public function getVersion()
+    {
+        return $this->version;
+    }
+
+    /**
+     * 设置版本
+     * @param string $version
+     */
+    public function setVersion($version)
+    {
+        $this->version = $version;
+    }
+
+    /**
+     * 获取完整的版本号
+     * @return string
+     */
+    public function getLongVersion()
+    {
+        if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) {
+            return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
+        }
+
+        return '<info>Console Tool</info>';
+    }
+
+    /**
+     * 注册一个指令
+     * @param string $name
+     * @return Command
+     */
+    public function register($name)
+    {
+        return $this->add(new Command($name));
+    }
+
+    /**
+     * 添加指令
+     * @param Command[] $commands
+     */
+    public function addCommands(array $commands)
+    {
+        foreach ($commands as $command) {
+            $this->add($command);
+        }
+    }
+
+    /**
+     * 添加一个指令
+     * @param Command $command
+     * @return Command
+     */
+    public function add(Command $command)
+    {
+        $command->setConsole($this);
+
+        if (!$command->isEnabled()) {
+            $command->setConsole(null);
+            return;
+        }
+
+        if (null === $command->getDefinition()) {
+            throw new \LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
+        }
+
+        $this->commands[$command->getName()] = $command;
+
+        foreach ($command->getAliases() as $alias) {
+            $this->commands[$alias] = $command;
+        }
+
+        return $command;
+    }
+
+    /**
+     * 获取指令
+     * @param string $name 指令名称
+     * @return Command
+     * @throws \InvalidArgumentException
+     */
+    public function get($name)
+    {
+        if (!isset($this->commands[$name])) {
+            throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name));
+        }
+
+        $command = $this->commands[$name];
+
+        if ($this->wantHelps) {
+            $this->wantHelps = false;
+
+            /** @var HelpCommand $helpCommand */
+            $helpCommand = $this->get('help');
+            $helpCommand->setCommand($command);
+
+            return $helpCommand;
+        }
+
+        return $command;
+    }
+
+    /**
+     * 某个指令是否存在
+     * @param string $name 指令名称
+     * @return bool
+     */
+    public function has($name)
+    {
+        return isset($this->commands[$name]);
+    }
+
+    /**
+     * 获取所有的命名空间
+     * @return array
+     */
+    public function getNamespaces()
+    {
+        $namespaces = [];
+        foreach ($this->commands as $command) {
+            $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
+
+            foreach ($command->getAliases() as $alias) {
+                $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
+            }
+        }
+
+        return array_values(array_unique(array_filter($namespaces)));
+    }
+
+    /**
+     * 查找注册命名空间中的名称或缩写。
+     * @param string $namespace
+     * @return string
+     * @throws \InvalidArgumentException
+     */
+    public function findNamespace($namespace)
+    {
+        $allNamespaces = $this->getNamespaces();
+        $expr          = preg_replace_callback('{([^:]+|)}', function ($matches) {
+            return preg_quote($matches[1]) . '[^:]*';
+        }, $namespace);
+        $namespaces = preg_grep('{^' . $expr . '}', $allNamespaces);
+
+        if (empty($namespaces)) {
+            $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
+
+            if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
+                if (1 == count($alternatives)) {
+                    $message .= "\n\nDid you mean this?\n    ";
+                } else {
+                    $message .= "\n\nDid you mean one of these?\n    ";
+                }
+
+                $message .= implode("\n    ", $alternatives);
+            }
+
+            throw new \InvalidArgumentException($message);
+        }
+
+        $exact = in_array($namespace, $namespaces, true);
+        if (count($namespaces) > 1 && !$exact) {
+            throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))));
+        }
+
+        return $exact ? $namespace : reset($namespaces);
+    }
+
+    /**
+     * 查找指令
+     * @param string $name 名称或者别名
+     * @return Command
+     * @throws \InvalidArgumentException
+     */
+    public function find($name)
+    {
+        $allCommands = array_keys($this->commands);
+        $expr        = preg_replace_callback('{([^:]+|)}', function ($matches) {
+            return preg_quote($matches[1]) . '[^:]*';
+        }, $name);
+        $commands = preg_grep('{^' . $expr . '}', $allCommands);
+
+        if (empty($commands) || count(preg_grep('{^' . $expr . '$}', $commands)) < 1) {
+            if (false !== $pos = strrpos($name, ':')) {
+                $this->findNamespace(substr($name, 0, $pos));
+            }
+
+            $message = sprintf('Command "%s" is not defined.', $name);
+
+            if ($alternatives = $this->findAlternatives($name, $allCommands)) {
+                if (1 == count($alternatives)) {
+                    $message .= "\n\nDid you mean this?\n    ";
+                } else {
+                    $message .= "\n\nDid you mean one of these?\n    ";
+                }
+                $message .= implode("\n    ", $alternatives);
+            }
+
+            throw new \InvalidArgumentException($message);
+        }
+
+        if (count($commands) > 1) {
+            $commandList = $this->commands;
+            $commands    = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) {
+                $commandName = $commandList[$nameOrAlias]->getName();
+
+                return $commandName === $nameOrAlias || !in_array($commandName, $commands);
+            });
+        }
+
+        $exact = in_array($name, $commands, true);
+        if (count($commands) > 1 && !$exact) {
+            $suggestions = $this->getAbbreviationSuggestions(array_values($commands));
+
+            throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions));
+        }
+
+        return $this->get($exact ? $name : reset($commands));
+    }
+
+    /**
+     * 获取所有的指令
+     * @param string $namespace 命名空间
+     * @return Command[]
+     * @api
+     */
+    public function all($namespace = null)
+    {
+        if (null === $namespace) {
+            return $this->commands;
+        }
+
+        $commands = [];
+        foreach ($this->commands as $name => $command) {
+            if ($this->extractNamespace($name, substr_count($namespace, ':') + 1) === $namespace) {
+                $commands[$name] = $command;
+            }
+        }
+
+        return $commands;
+    }
+
+    /**
+     * 获取可能的指令名
+     * @param array $names
+     * @return array
+     */
+    public static function getAbbreviations($names)
+    {
+        $abbrevs = [];
+        foreach ($names as $name) {
+            for ($len = strlen($name); $len > 0; --$len) {
+                $abbrev             = substr($name, 0, $len);
+                $abbrevs[$abbrev][] = $name;
+            }
+        }
+
+        return $abbrevs;
+    }
+
+    /**
+     * 配置基于用户的参数和选项的输入和输出实例。
+     * @param Input  $input  输入实例
+     * @param Output $output 输出实例
+     */
+    protected function configureIO(Input $input, Output $output)
+    {
+        if (true === $input->hasParameterOption(['--ansi'])) {
+            $output->setDecorated(true);
+        } elseif (true === $input->hasParameterOption(['--no-ansi'])) {
+            $output->setDecorated(false);
+        }
+
+        if (true === $input->hasParameterOption(['--no-interaction', '-n'])) {
+            $input->setInteractive(false);
+        }
+
+        if (true === $input->hasParameterOption(['--quiet', '-q'])) {
+            $output->setVerbosity(Output::VERBOSITY_QUIET);
+        } else {
+            if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) {
+                $output->setVerbosity(Output::VERBOSITY_DEBUG);
+            } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) {
+                $output->setVerbosity(Output::VERBOSITY_VERY_VERBOSE);
+            } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
+                $output->setVerbosity(Output::VERBOSITY_VERBOSE);
+            }
+        }
+    }
+
+    /**
+     * 执行指令
+     * @param Command $command 指令实例
+     * @param Input   $input   输入实例
+     * @param Output  $output  输出实例
+     * @return int
+     * @throws \Exception
+     */
+    protected function doRunCommand(Command $command, Input $input, Output $output)
+    {
+        return $command->run($input, $output);
+    }
+
+    /**
+     * 获取指令的基础名称
+     * @param Input $input
+     * @return string
+     */
+    protected function getCommandName(Input $input)
+    {
+        return $input->getFirstArgument();
+    }
+
+    /**
+     * 获取默认输入定义
+     * @return InputDefinition
+     */
+    protected function getDefaultInputDefinition()
+    {
+        return new InputDefinition([
+            new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
+            new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
+            new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this console version'),
+            new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
+            new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
+            new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
+            new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
+            new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
+        ]);
+    }
+
+    /**
+     * 设置默认命令
+     * @return Command[] An array of default Command instances
+     */
+    protected function getDefaultCommands()
+    {
+        $defaultCommands = [];
+
+        foreach (self::$defaultCommands as $classname) {
+            if (class_exists($classname) && is_subclass_of($classname, "think\\console\\Command")) {
+                $defaultCommands[] = new $classname();
+            }
+        }
+
+        return $defaultCommands;
+    }
+
+    public static function addDefaultCommands(array $classnames)
+    {
+        self::$defaultCommands = array_merge(self::$defaultCommands, $classnames);
+    }
+
+    /**
+     * 获取可能的建议
+     * @param array $abbrevs
+     * @return string
+     */
+    private function getAbbreviationSuggestions($abbrevs)
+    {
+        return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
+    }
+
+    /**
+     * 返回命名空间部分
+     * @param string $name  指令
+     * @param string $limit 部分的命名空间的最大数量
+     * @return string
+     */
+    public function extractNamespace($name, $limit = null)
+    {
+        $parts = explode(':', $name);
+        array_pop($parts);
+
+        return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
+    }
+
+    /**
+     * 查找可替代的建议
+     * @param string             $name
+     * @param array|\Traversable $collection
+     * @return array
+     */
+    private function findAlternatives($name, $collection)
+    {
+        $threshold    = 1e3;
+        $alternatives = [];
+
+        $collectionParts = [];
+        foreach ($collection as $item) {
+            $collectionParts[$item] = explode(':', $item);
+        }
+
+        foreach (explode(':', $name) as $i => $subname) {
+            foreach ($collectionParts as $collectionName => $parts) {
+                $exists = isset($alternatives[$collectionName]);
+                if (!isset($parts[$i]) && $exists) {
+                    $alternatives[$collectionName] += $threshold;
+                    continue;
+                } elseif (!isset($parts[$i])) {
+                    continue;
+                }
+
+                $lev = levenshtein($subname, $parts[$i]);
+                if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
+                    $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
+                } elseif ($exists) {
+                    $alternatives[$collectionName] += $threshold;
+                }
+            }
+        }
+
+        foreach ($collection as $item) {
+            $lev = levenshtein($name, $item);
+            if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
+                $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
+            }
+        }
+
+        $alternatives = array_filter($alternatives, function ($lev) use ($threshold) {
+            return $lev < 2 * $threshold;
+        });
+        asort($alternatives);
+
+        return array_keys($alternatives);
+    }
+
+    /**
+     * 设置默认的指令
+     * @param string $commandName The Command name
+     */
+    public function setDefaultCommand($commandName)
+    {
+        $this->defaultCommand = $commandName;
+    }
+
+    /**
+     * 返回所有的命名空间
+     * @param string $name
+     * @return array
+     */
+    private function extractAllNamespaces($name)
+    {
+        $parts      = explode(':', $name, -1);
+        $namespaces = [];
+
+        foreach ($parts as $part) {
+            if (count($namespaces)) {
+                $namespaces[] = end($namespaces) . ':' . $part;
+            } else {
+                $namespaces[] = $part;
+            }
+        }
+
+        return $namespaces;
+    }
+
+}

+ 213 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Controller.php

@@ -0,0 +1,213 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+use think\exception\ValidateException;
+use traits\controller\Jump;
+
+Loader::import('controller/Jump', TRAIT_PATH, EXT);
+
+class Controller
+{
+    use Jump;
+
+    /**
+     * @var \think\View 视图类实例
+     */
+    protected $view;
+    /**
+     * @var \think\Request Request实例
+     */
+    protected $request;
+    // 验证失败是否抛出异常
+    protected $failException = false;
+    // 是否批量验证
+    protected $batchValidate = false;
+
+    /**
+     * 前置操作方法列表
+     * @var array $beforeActionList
+     * @access protected
+     */
+    protected $beforeActionList = [];
+
+    /**
+     * 构造方法
+     * @param Request $request Request对象
+     * @access public
+     */
+    public function __construct(Request $request = null)
+    {
+        if (is_null($request)) {
+            $request = Request::instance();
+        }
+        $this->view    = View::instance(Config::get('template'), Config::get('view_replace_str'));
+        $this->request = $request;
+
+        // 控制器初始化
+        $this->_initialize();
+
+        // 前置操作方法
+        if ($this->beforeActionList) {
+            foreach ($this->beforeActionList as $method => $options) {
+                is_numeric($method) ?
+                $this->beforeAction($options) :
+                $this->beforeAction($method, $options);
+            }
+        }
+    }
+
+    // 初始化
+    protected function _initialize()
+    {
+    }
+
+    /**
+     * 前置操作
+     * @access protected
+     * @param string $method  前置操作方法名
+     * @param array  $options 调用参数 ['only'=>[...]] 或者['except'=>[...]]
+     */
+    protected function beforeAction($method, $options = [])
+    {
+        if (isset($options['only'])) {
+            if (is_string($options['only'])) {
+                $options['only'] = explode(',', $options['only']);
+            }
+            if (!in_array($this->request->action(), $options['only'])) {
+                return;
+            }
+        } elseif (isset($options['except'])) {
+            if (is_string($options['except'])) {
+                $options['except'] = explode(',', $options['except']);
+            }
+            if (in_array($this->request->action(), $options['except'])) {
+                return;
+            }
+        }
+
+        call_user_func([$this, $method]);
+    }
+
+    /**
+     * 加载模板输出
+     * @access protected
+     * @param string $template 模板文件名
+     * @param array  $vars     模板输出变量
+     * @param array  $replace  模板替换
+     * @param array  $config   模板参数
+     * @return mixed
+     */
+    protected function fetch($template = '', $vars = [], $replace = [], $config = [])
+    {
+        return $this->view->fetch($template, $vars, $replace, $config);
+    }
+
+    /**
+     * 渲染内容输出
+     * @access protected
+     * @param string $content 模板内容
+     * @param array  $vars    模板输出变量
+     * @param array  $replace 替换内容
+     * @param array  $config  模板参数
+     * @return mixed
+     */
+    protected function display($content = '', $vars = [], $replace = [], $config = [])
+    {
+        return $this->view->display($content, $vars, $replace, $config);
+    }
+
+    /**
+     * 模板变量赋值
+     * @access protected
+     * @param mixed $name  要显示的模板变量
+     * @param mixed $value 变量的值
+     * @return void
+     */
+    protected function assign($name, $value = '')
+    {
+        $this->view->assign($name, $value);
+    }
+
+    /**
+     * 初始化模板引擎
+     * @access protected
+     * @param array|string $engine 引擎参数
+     * @return void
+     */
+    protected function engine($engine)
+    {
+        $this->view->engine($engine);
+    }
+
+    /**
+     * 设置验证失败后是否抛出异常
+     * @access protected
+     * @param bool $fail 是否抛出异常
+     * @return $this
+     */
+    protected function validateFailException($fail = true)
+    {
+        $this->failException = $fail;
+        return $this;
+    }
+
+    /**
+     * 验证数据
+     * @access protected
+     * @param array        $data     数据
+     * @param string|array $validate 验证器名或者验证规则数组
+     * @param array        $message  提示信息
+     * @param bool         $batch    是否批量验证
+     * @param mixed        $callback 回调方法(闭包)
+     * @return array|string|true
+     * @throws ValidateException
+     */
+    protected function validate($data, $validate, $message = [], $batch = false, $callback = null)
+    {
+        if (is_array($validate)) {
+            $v = Loader::validate();
+            $v->rule($validate);
+        } else {
+            if (strpos($validate, '.')) {
+                // 支持场景
+                list($validate, $scene) = explode('.', $validate);
+            }
+            $v = Loader::validate($validate);
+            if (!empty($scene)) {
+                $v->scene($scene);
+            }
+        }
+        // 是否批量验证
+        if ($batch || $this->batchValidate) {
+            $v->batch(true);
+        }
+
+        if (is_array($message)) {
+            $v->message($message);
+        }
+
+        if ($callback && is_callable($callback)) {
+            call_user_func_array($callback, [$v, &$data]);
+        }
+
+        if (!$v->check($data)) {
+            if ($this->failException) {
+                throw new ValidateException($v->getError());
+            } else {
+                return $v->getError();
+            }
+        } else {
+            return true;
+        }
+    }
+}

+ 224 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Cookie.php

@@ -0,0 +1,224 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+class Cookie
+{
+    protected static $config = [
+        // cookie 名称前缀
+        'prefix'    => '',
+        // cookie 保存时间
+        'expire'    => 0,
+        // cookie 保存路径
+        'path'      => '/',
+        // cookie 有效域名
+        'domain'    => '',
+        //  cookie 启用安全传输
+        'secure'    => false,
+        // httponly设置
+        'httponly'  => '',
+        // 是否使用 setcookie
+        'setcookie' => true,
+    ];
+
+    protected static $init;
+
+    /**
+     * Cookie初始化
+     * @param array $config
+     * @return void
+     */
+    public static function init(array $config = [])
+    {
+        if (empty($config)) {
+            $config = Config::get('cookie');
+        }
+        self::$config = array_merge(self::$config, array_change_key_case($config));
+        if (!empty(self::$config['httponly'])) {
+            ini_set('session.cookie_httponly', 1);
+        }
+        self::$init = true;
+    }
+
+    /**
+     * 设置或者获取cookie作用域(前缀)
+     * @param string $prefix
+     * @return string|void
+     */
+    public static function prefix($prefix = '')
+    {
+        if (empty($prefix)) {
+            return self::$config['prefix'];
+        }
+        self::$config['prefix'] = $prefix;
+    }
+
+    /**
+     * Cookie 设置、获取、删除
+     *
+     * @param string $name  cookie名称
+     * @param mixed  $value cookie值
+     * @param mixed  $option 可选参数 可能会是 null|integer|string
+     *
+     * @return mixed
+     * @internal param mixed $options cookie参数
+     */
+    public static function set($name, $value = '', $option = null)
+    {
+        !isset(self::$init) && self::init();
+        // 参数设置(会覆盖黙认设置)
+        if (!is_null($option)) {
+            if (is_numeric($option)) {
+                $option = ['expire' => $option];
+            } elseif (is_string($option)) {
+                parse_str($option, $option);
+            }
+            $config = array_merge(self::$config, array_change_key_case($option));
+        } else {
+            $config = self::$config;
+        }
+        $name = $config['prefix'] . $name;
+        // 设置cookie
+        if (is_array($value)) {
+            array_walk_recursive($value, 'self::jsonFormatProtect', 'encode');
+            $value = 'think:' . json_encode($value);
+        }
+        $expire = !empty($config['expire']) ? $_SERVER['REQUEST_TIME'] + intval($config['expire']) : 0;
+        if ($config['setcookie']) {
+            setcookie($name, $value, $expire, $config['path'], $config['domain'], $config['secure'], $config['httponly']);
+        }
+        $_COOKIE[$name] = $value;
+    }
+
+    /**
+     * 永久保存Cookie数据
+     * @param string $name  cookie名称
+     * @param mixed  $value cookie值
+     * @param mixed  $option 可选参数 可能会是 null|integer|string
+     * @return void
+     */
+    public static function forever($name, $value = '', $option = null)
+    {
+        if (is_null($option) || is_numeric($option)) {
+            $option = [];
+        }
+        $option['expire'] = 315360000;
+        self::set($name, $value, $option);
+    }
+
+    /**
+     * 判断Cookie数据
+     * @param string        $name cookie名称
+     * @param string|null   $prefix cookie前缀
+     * @return bool
+     */
+    public static function has($name, $prefix = null)
+    {
+        !isset(self::$init) && self::init();
+        $prefix = !is_null($prefix) ? $prefix : self::$config['prefix'];
+        $name   = $prefix . $name;
+        return isset($_COOKIE[$name]);
+    }
+
+    /**
+     * Cookie获取
+     * @param string        $name cookie名称
+     * @param string|null   $prefix cookie前缀
+     * @return mixed
+     */
+    public static function get($name = '', $prefix = null)
+    {
+        !isset(self::$init) && self::init();
+        $prefix = !is_null($prefix) ? $prefix : self::$config['prefix'];
+        $key    = $prefix . $name;
+
+        if ('' == $name) {
+            // 获取全部
+            if ($prefix) {
+                $value = [];
+                foreach ($_COOKIE as $k => $val) {
+                    if (0 === strpos($k, $prefix)) {
+                        $value[$k] = $val;
+                    }
+                }
+            } else {
+                $value = $_COOKIE;
+            }
+        } elseif (isset($_COOKIE[$key])) {
+            $value = $_COOKIE[$key];
+            if (0 === strpos($value, 'think:')) {
+                $value = substr($value, 6);
+                $value = json_decode($value, true);
+                array_walk_recursive($value, 'self::jsonFormatProtect', 'decode');
+            }
+        } else {
+            $value = null;
+        }
+        return $value;
+    }
+
+    /**
+     * Cookie删除
+     * @param string        $name cookie名称
+     * @param string|null   $prefix cookie前缀
+     * @return mixed
+     */
+    public static function delete($name, $prefix = null)
+    {
+        !isset(self::$init) && self::init();
+        $config = self::$config;
+        $prefix = !is_null($prefix) ? $prefix : $config['prefix'];
+        $name   = $prefix . $name;
+        if ($config['setcookie']) {
+            setcookie($name, '', $_SERVER['REQUEST_TIME'] - 3600, $config['path'], $config['domain'], $config['secure'], $config['httponly']);
+        }
+        // 删除指定cookie
+        unset($_COOKIE[$name]);
+    }
+
+    /**
+     * Cookie清空
+     * @param string|null $prefix cookie前缀
+     * @return mixed
+     */
+    public static function clear($prefix = null)
+    {
+        // 清除指定前缀的所有cookie
+        if (empty($_COOKIE)) {
+            return;
+        }
+        !isset(self::$init) && self::init();
+        // 要删除的cookie前缀,不指定则删除config设置的指定前缀
+        $config = self::$config;
+        $prefix = !is_null($prefix) ? $prefix : $config['prefix'];
+        if ($prefix) {
+            // 如果前缀为空字符串将不作处理直接返回
+            foreach ($_COOKIE as $key => $val) {
+                if (0 === strpos($key, $prefix)) {
+                    if ($config['setcookie']) {
+                        setcookie($key, '', $_SERVER['REQUEST_TIME'] - 3600, $config['path'], $config['domain'], $config['secure'], $config['httponly']);
+                    }
+                    unset($_COOKIE[$key]);
+                }
+            }
+        }
+        return;
+    }
+
+    private static function jsonFormatProtect(&$val, $key, $type = 'encode')
+    {
+        if (!empty($val) && true !== $val) {
+            $val = 'decode' == $type ? urldecode($val) : urlencode($val);
+        }
+    }
+
+}

+ 156 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Db.php

@@ -0,0 +1,156 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+use think\db\Connection;
+use think\db\Query;
+
+/**
+ * Class Db
+ * @package think
+ * @method Query table(string $table) static 指定数据表(含前缀)
+ * @method Query name(string $name) static 指定数据表(不含前缀)
+ * @method Query where(mixed $field, string $op = null, mixed $condition = null) static 查询条件
+ * @method Query join(mixed $join, mixed $condition = null, string $type = 'INNER') static JOIN查询
+ * @method Query union(mixed $union, boolean $all = false) static UNION查询
+ * @method Query limit(mixed $offset, integer $length = null) static 查询LIMIT
+ * @method Query order(mixed $field, string $order = null) static 查询ORDER
+ * @method Query cache(mixed $key = null , integer $expire = null) static 设置查询缓存
+ * @method mixed value(string $field) static 获取某个字段的值
+ * @method array column(string $field, string $key = '') static 获取某个列的值
+ * @method Query view(mixed $join, mixed $field = null, mixed $on = null, string $type = 'INNER') static 视图查询
+ * @method mixed find(mixed $data = null) static 查询单个记录
+ * @method mixed select(mixed $data = null) static 查询多个记录
+ * @method integer insert(array $data, boolean $replace = false, boolean $getLastInsID = false, string $sequence = null) static 插入一条记录
+ * @method integer insertGetId(array $data, boolean $replace = false, string $sequence = null) static 插入一条记录并返回自增ID
+ * @method integer insertAll(array $dataSet) static 插入多条记录
+ * @method integer update(array $data) static 更新记录
+ * @method integer delete(mixed $data = null) static 删除记录
+ * @method boolean chunk(integer $count, callable $callback, string $column = null) static 分块获取数据
+ * @method mixed query(string $sql, array $bind = [], boolean $master = false, bool $pdo = false) static SQL查询
+ * @method integer execute(string $sql, array $bind = [], boolean $fetch = false, boolean $getLastInsID = false, string $sequence = null) static SQL执行
+ * @method Paginator paginate(integer $listRows = 15, mixed $simple = null, array $config = []) static 分页查询
+ * @method mixed transaction(callable $callback) static 执行数据库事务
+ * @method void startTrans() static 启动事务
+ * @method void commit() static 用于非自动提交状态下面的查询提交
+ * @method void rollback() static 事务回滚
+ * @method boolean batchQuery(array $sqlArray) static 批处理执行SQL语句
+ * @method string quote(string $str) static SQL指令安全过滤
+ * @method string getLastInsID($sequence = null) static 获取最近插入的ID
+ */
+class Db
+{
+    //  数据库连接实例
+    private static $instance = [];
+    // 查询次数
+    public static $queryTimes = 0;
+    // 执行次数
+    public static $executeTimes = 0;
+
+    /**
+     * 数据库初始化 并取得数据库类实例
+     * @static
+     * @access public
+     * @param mixed         $config 连接配置
+     * @param bool|string   $name 连接标识 true 强制重新连接
+     * @return Connection
+     * @throws Exception
+     */
+    public static function connect($config = [], $name = false)
+    {
+        if (false === $name) {
+            $name = md5(serialize($config));
+        }
+        if (true === $name || !isset(self::$instance[$name])) {
+            // 解析连接参数 支持数组和字符串
+            $options = self::parseConfig($config);
+            if (empty($options['type'])) {
+                throw new \InvalidArgumentException('Undefined db type');
+            }
+            $class = false !== strpos($options['type'], '\\') ? $options['type'] : '\\think\\db\\connector\\' . ucwords($options['type']);
+            // 记录初始化信息
+            if (App::$debug) {
+                Log::record('[ DB ] INIT ' . $options['type'], 'info');
+            }
+            if (true === $name) {
+                $name = md5(serialize($config));
+            }
+            self::$instance[$name] = new $class($options);
+        }
+        return self::$instance[$name];
+    }
+    
+    public static function clear() {
+        self::$instance = null;
+    }
+
+    /**
+     * 数据库连接参数解析
+     * @static
+     * @access private
+     * @param mixed $config
+     * @return array
+     */
+    private static function parseConfig($config)
+    {
+        if (empty($config)) {
+            $config = Config::get('database');
+        } elseif (is_string($config) && false === strpos($config, '/')) {
+            // 支持读取配置参数
+            $config = Config::get($config);
+        }
+        if (is_string($config)) {
+            return self::parseDsn($config);
+        } else {
+            return $config;
+        }
+    }
+
+    /**
+     * DSN解析
+     * 格式: mysql://username:passwd@localhost:3306/DbName?param1=val1&param2=val2#utf8
+     * @static
+     * @access private
+     * @param string $dsnStr
+     * @return array
+     */
+    private static function parseDsn($dsnStr)
+    {
+        $info = parse_url($dsnStr);
+        if (!$info) {
+            return [];
+        }
+        $dsn = [
+            'type'     => $info['scheme'],
+            'username' => isset($info['user']) ? $info['user'] : '',
+            'password' => isset($info['pass']) ? $info['pass'] : '',
+            'hostname' => isset($info['host']) ? $info['host'] : '',
+            'hostport' => isset($info['port']) ? $info['port'] : '',
+            'database' => !empty($info['path']) ? ltrim($info['path'], '/') : '',
+            'charset'  => isset($info['fragment']) ? $info['fragment'] : 'utf8',
+        ];
+
+        if (isset($info['query'])) {
+            parse_str($info['query'], $dsn['params']);
+        } else {
+            $dsn['params'] = [];
+        }
+        return $dsn;
+    }
+
+    // 调用驱动类的方法
+    public static function __callStatic($method, $params)
+    {
+        // 自动初始化数据库
+        return call_user_func_array([self::connect(), $method], $params);
+    }
+}

+ 212 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Debug.php

@@ -0,0 +1,212 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+use think\exception\ClassNotFoundException;
+use think\response\Redirect;
+
+class Debug
+{
+    // 区间时间信息
+    protected static $info = [];
+    // 区间内存信息
+    protected static $mem = [];
+
+    /**
+     * 记录时间(微秒)和内存使用情况
+     * @param string    $name 标记位置
+     * @param mixed     $value 标记值 留空则取当前 time 表示仅记录时间 否则同时记录时间和内存
+     * @return mixed
+     */
+    public static function remark($name, $value = '')
+    {
+        // 记录时间和内存使用
+        self::$info[$name] = is_float($value) ? $value : microtime(true);
+        if ('time' != $value) {
+            self::$mem['mem'][$name]  = is_float($value) ? $value : memory_get_usage();
+            self::$mem['peak'][$name] = memory_get_peak_usage();
+        }
+    }
+
+    /**
+     * 统计某个区间的时间(微秒)使用情况 返回值以秒为单位
+     * @param string            $start 开始标签
+     * @param string            $end 结束标签
+     * @param integer|string    $dec 小数位
+     * @return integer
+     */
+    public static function getRangeTime($start, $end, $dec = 6)
+    {
+        if (!isset(self::$info[$end])) {
+            self::$info[$end] = microtime(true);
+        }
+        return number_format((self::$info[$end] - self::$info[$start]), $dec);
+    }
+
+    /**
+     * 统计从开始到统计时的时间(微秒)使用情况 返回值以秒为单位
+     * @param integer|string $dec 小数位
+     * @return integer
+     */
+    public static function getUseTime($dec = 6)
+    {
+        return number_format((microtime(true) - THINK_START_TIME), $dec);
+    }
+
+    /**
+     * 获取当前访问的吞吐率情况
+     * @return string
+     */
+    public static function getThroughputRate()
+    {
+        return number_format(1 / self::getUseTime(), 2) . 'req/s';
+    }
+
+    /**
+     * 记录区间的内存使用情况
+     * @param string            $start 开始标签
+     * @param string            $end 结束标签
+     * @param integer|string    $dec 小数位
+     * @return string
+     */
+    public static function getRangeMem($start, $end, $dec = 2)
+    {
+        if (!isset(self::$mem['mem'][$end])) {
+            self::$mem['mem'][$end] = memory_get_usage();
+        }
+        $size = self::$mem['mem'][$end] - self::$mem['mem'][$start];
+        $a    = ['B', 'KB', 'MB', 'GB', 'TB'];
+        $pos  = 0;
+        while ($size >= 1024) {
+            $size /= 1024;
+            $pos++;
+        }
+        return round($size, $dec) . " " . $a[$pos];
+    }
+
+    /**
+     * 统计从开始到统计时的内存使用情况
+     * @param integer|string $dec 小数位
+     * @return string
+     */
+    public static function getUseMem($dec = 2)
+    {
+        $size = memory_get_usage() - THINK_START_MEM;
+        $a    = ['B', 'KB', 'MB', 'GB', 'TB'];
+        $pos  = 0;
+        while ($size >= 1024) {
+            $size /= 1024;
+            $pos++;
+        }
+        return round($size, $dec) . " " . $a[$pos];
+    }
+
+    /**
+     * 统计区间的内存峰值情况
+     * @param string            $start 开始标签
+     * @param string            $end 结束标签
+     * @param integer|string    $dec 小数位
+     * @return mixed
+     */
+    public static function getMemPeak($start, $end, $dec = 2)
+    {
+        if (!isset(self::$mem['peak'][$end])) {
+            self::$mem['peak'][$end] = memory_get_peak_usage();
+        }
+        $size = self::$mem['peak'][$end] - self::$mem['peak'][$start];
+        $a    = ['B', 'KB', 'MB', 'GB', 'TB'];
+        $pos  = 0;
+        while ($size >= 1024) {
+            $size /= 1024;
+            $pos++;
+        }
+        return round($size, $dec) . " " . $a[$pos];
+    }
+
+    /**
+     * 获取文件加载信息
+     * @param bool  $detail 是否显示详细
+     * @return integer|array
+     */
+    public static function getFile($detail = false)
+    {
+        if ($detail) {
+            $files = get_included_files();
+            $info  = [];
+            foreach ($files as $key => $file) {
+                $info[] = $file . ' ( ' . number_format(filesize($file) / 1024, 2) . ' KB )';
+            }
+            return $info;
+        }
+        return count(get_included_files());
+    }
+
+    /**
+     * 浏览器友好的变量输出
+     * @param mixed         $var 变量
+     * @param boolean       $echo 是否输出 默认为true 如果为false 则返回输出字符串
+     * @param string        $label 标签 默认为空
+     * @param integer       $flags htmlspecialchars flags
+     * @return void|string
+     */
+    public static function dump($var, $echo = true, $label = null, $flags = ENT_SUBSTITUTE)
+    {
+        $label = (null === $label) ? '' : rtrim($label) . ':';
+        ob_start();
+        var_dump($var);
+        $output = ob_get_clean();
+        $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output);
+        if (IS_CLI) {
+            $output = PHP_EOL . $label . $output . PHP_EOL;
+        } else {
+            if (!extension_loaded('xdebug')) {
+                $output = htmlspecialchars($output, $flags);
+            }
+            $output = '<pre>' . $label . $output . '</pre>';
+        }
+        if ($echo) {
+            echo($output);
+            return;
+        } else {
+            return $output;
+        }
+    }
+
+    public static function inject(Response $response, &$content)
+    {
+        $config  = Config::get('trace');
+        $type    = isset($config['type']) ? $config['type'] : 'Html';
+        $request = Request::instance();
+        $class   = false !== strpos($type, '\\') ? $type : '\\think\\debug\\' . ucwords($type);
+        unset($config['type']);
+        if (class_exists($class)) {
+            $trace = new $class($config);
+        } else {
+            throw new ClassNotFoundException('class not exists:' . $class, $class);
+        }
+
+        if ($response instanceof Redirect) {
+            //TODO 记录
+        } else {
+            $output = $trace->output($response, Log::getLog());
+            if (is_string($output)) {
+                // trace调试信息注入
+                $pos = strripos($content, '</body>');
+                if (false !== $pos) {
+                    $content = substr($content, 0, $pos) . $output . substr($content, $pos);
+                } else {
+                    $content = $content . $output;
+                }
+            }
+        }
+    }
+}

+ 36 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Env.php

@@ -0,0 +1,36 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+class Env
+{
+    /**
+     * 获取环境变量值
+     * @param string    $name 环境变量名(支持二级 .号分割)
+     * @param string    $default  默认值
+     * @return mixed
+     */
+    public static function get($name, $default = null)
+    {
+        $result = getenv(ENV_PREFIX . strtoupper(str_replace('.', '_', $name)));
+        if (false !== $result) {
+            if ('false' === $result) {
+                $result = false;
+            } elseif ('true' === $result) {
+                $result = true;
+            }
+            return $result;
+        } else {
+            return $default;
+        }
+    }
+}

+ 120 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Error.php

@@ -0,0 +1,120 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://zjzit.cn>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+use think\console\Output as ConsoleOutput;
+use think\exception\ErrorException;
+use think\exception\Handle;
+use think\exception\ThrowableError;
+
+class Error
+{
+    /**
+     * 注册异常处理
+     * @return void
+     */
+    public static function register()
+    {
+        error_reporting(E_ALL);
+        set_error_handler([__CLASS__, 'appError']);
+        set_exception_handler([__CLASS__, 'appException']);
+        register_shutdown_function([__CLASS__, 'appShutdown']);
+    }
+
+    /**
+     * Exception Handler
+     * @param  \Exception|\Throwable $e
+     */
+    public static function appException($e)
+    {
+        if (!$e instanceof \Exception) {
+            $e = new ThrowableError($e);
+        }
+
+        self::getExceptionHandler()->report($e);
+        if (IS_CLI) {
+            self::getExceptionHandler()->renderForConsole(new ConsoleOutput, $e);
+        } else {
+            self::getExceptionHandler()->render($e)->send();
+        }
+    }
+
+    /**
+     * Error Handler
+     * @param  integer $errno   错误编号
+     * @param  integer $errstr  详细错误信息
+     * @param  string  $errfile 出错的文件
+     * @param  integer $errline 出错行号
+     * @param array    $errcontext
+     * @throws ErrorException
+     */
+    public static function appError($errno, $errstr, $errfile = '', $errline = 0, $errcontext = [])
+    {
+        $exception = new ErrorException($errno, $errstr, $errfile, $errline, $errcontext);
+        if (error_reporting() & $errno) {
+            // 将错误信息托管至 think\exception\ErrorException
+            throw $exception;
+        } else {
+            self::getExceptionHandler()->report($exception);
+        }
+    }
+
+    /**
+     * Shutdown Handler
+     */
+    public static function appShutdown()
+    {
+        if (!is_null($error = error_get_last()) && self::isFatal($error['type'])) {
+            // 将错误信息托管至think\ErrorException
+            $exception = new ErrorException($error['type'], $error['message'], $error['file'], $error['line']);
+
+            self::appException($exception);
+        }
+
+        // 写入日志
+        Log::save();
+    }
+
+    /**
+     * 确定错误类型是否致命
+     *
+     * @param  int $type
+     * @return bool
+     */
+    protected static function isFatal($type)
+    {
+        return in_array($type, [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE]);
+    }
+
+    /**
+     * Get an instance of the exception handler.
+     *
+     * @return Handle
+     */
+    public static function getExceptionHandler()
+    {
+        static $handle;
+        if (!$handle) {
+            // 异常处理handle
+            $class = Config::get('exception_handle');
+            if ($class && is_string($class) && class_exists($class) && is_subclass_of($class, "\\think\\exception\\Handle")) {
+                $handle = new $class;
+            } else {
+                $handle = new Handle;
+                if ($class instanceof \Closure) {
+                    $handle->setRender($class);
+                }
+            }
+        }
+        return $handle;
+    }
+}

+ 54 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Exception.php

@@ -0,0 +1,54 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://zjzit.cn>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+class Exception extends \Exception
+{
+
+    /**
+     * 保存异常页面显示的额外Debug数据
+     * @var array
+     */
+    protected $data = [];
+
+    /**
+     * 设置异常额外的Debug数据
+     * 数据将会显示为下面的格式
+     *
+     * Exception Data
+     * --------------------------------------------------
+     * Label 1
+     *   key1      value1
+     *   key2      value2
+     * Label 2
+     *   key1      value1
+     *   key2      value2
+     *
+     * @param string $label 数据分类,用于异常页面显示
+     * @param array  $data  需要显示的数据,必须为关联数组
+     */
+    final protected function setData($label, array $data)
+    {
+        $this->data[$label] = $data;
+    }
+
+    /**
+     * 获取异常额外Debug数据
+     * 主要用于输出到异常页面便于调试
+     * @return array 由setData设置的Debug数据
+     */
+    final public function getData()
+    {
+        return $this->data;
+    }
+    
+}

+ 431 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/File.php

@@ -0,0 +1,431 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+use SplFileObject;
+
+class File extends SplFileObject
+{
+    /**
+     * 错误信息
+     * @var string
+     */
+    private $error = '';
+    // 当前完整文件名
+    protected $filename;
+    // 上传文件名
+    protected $saveName;
+    // 文件上传命名规则
+    protected $rule = 'date';
+    // 文件上传验证规则
+    protected $validate = [];
+    // 单元测试
+    protected $isTest;
+    // 上传文件信息
+    protected $info;
+    // 文件hash信息
+    protected $hash = [];
+
+    public function __construct($filename, $mode = 'r')
+    {
+        parent::__construct($filename, $mode);
+        $this->filename = $this->getRealPath() ?: $this->getPathname();
+    }
+
+    /**
+     * 是否测试
+     * @param  bool   $test 是否测试
+     * @return $this
+     */
+    public function isTest($test = false)
+    {
+        $this->isTest = $test;
+        return $this;
+    }
+
+    /**
+     * 设置上传信息
+     * @param  array   $info 上传文件信息
+     * @return $this
+     */
+    public function setUploadInfo($info)
+    {
+        $this->info = $info;
+        return $this;
+    }
+
+    /**
+     * 获取上传文件的信息
+     * @param  string   $name
+     * @return array|string
+     */
+    public function getInfo($name = '')
+    {
+        return isset($this->info[$name]) ? $this->info[$name] : $this->info;
+    }
+
+    /**
+     * 获取上传文件的文件名
+     * @return string
+     */
+    public function getSaveName()
+    {
+        return $this->saveName;
+    }
+
+    /**
+     * 设置上传文件的保存文件名
+     * @param  string   $saveName
+     * @return $this
+     */
+    public function setSaveName($saveName)
+    {
+        $this->saveName = $saveName;
+        return $this;
+    }
+
+    /**
+     * 获取文件的哈希散列值
+     * @param string $type
+     * @return string
+     */
+    public function hash($type = 'sha1')
+    {
+        if (!isset($this->hash[$type])) {
+            $this->hash[$type] = hash_file($type, $this->filename);
+        }
+        return $this->hash[$type];
+    }
+
+    /**
+     * 检查目录是否可写
+     * @param  string   $path    目录
+     * @return boolean
+     */
+    protected function checkPath($path)
+    {
+        if (is_dir($path)) {
+            return true;
+        }
+
+        if (mkdir($path, 0755, true)) {
+            return true;
+        } else {
+            $this->error = ['directory {:path} creation failed', ['path' => $path]];
+            return false;
+        }
+    }
+
+    /**
+     * 获取文件类型信息
+     * @return string
+     */
+    public function getMime()
+    {
+        $finfo = finfo_open(FILEINFO_MIME_TYPE);
+        return finfo_file($finfo, $this->filename);
+    }
+
+    /**
+     * 设置文件的命名规则
+     * @param  string   $rule    文件命名规则
+     * @return $this
+     */
+    public function rule($rule)
+    {
+        $this->rule = $rule;
+        return $this;
+    }
+
+    /**
+     * 设置上传文件的验证规则
+     * @param  array   $rule    验证规则
+     * @return $this
+     */
+    public function validate($rule = [])
+    {
+        $this->validate = $rule;
+        return $this;
+    }
+
+    /**
+     * 检测是否合法的上传文件
+     * @return bool
+     */
+    public function isValid()
+    {
+        if ($this->isTest) {
+            return is_file($this->filename);
+        }
+        return is_uploaded_file($this->filename);
+    }
+
+    /**
+     * 检测上传文件
+     * @param  array   $rule    验证规则
+     * @return bool
+     */
+    public function check($rule = [])
+    {
+        $rule = $rule ?: $this->validate;
+
+        /* 检查文件大小 */
+        if (isset($rule['size']) && !$this->checkSize($rule['size'])) {
+            $this->error = 'filesize not match';
+            return false;
+        }
+
+        /* 检查文件Mime类型 */
+        if (isset($rule['type']) && !$this->checkMime($rule['type'])) {
+            $this->error = 'mimetype to upload is not allowed';
+            return false;
+        }
+
+        /* 检查文件后缀 */
+        if (isset($rule['ext']) && !$this->checkExt($rule['ext'])) {
+            $this->error = 'extensions to upload is not allowed';
+            return false;
+        }
+
+        /* 检查图像文件 */
+        if (!$this->checkImg()) {
+            $this->error = 'illegal image files';
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 检测上传文件后缀
+     * @param  array|string   $ext    允许后缀
+     * @return bool
+     */
+    public function checkExt($ext)
+    {
+        if (is_string($ext)) {
+            $ext = explode(',', $ext);
+        }
+
+        $extension = strtolower(pathinfo($this->getInfo('name'), PATHINFO_EXTENSION));
+
+        if (!in_array($extension, $ext)) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 检测图像文件
+     * @return bool
+     */
+    public function checkImg()
+    {
+        $extension = strtolower(pathinfo($this->getInfo('name'), PATHINFO_EXTENSION));
+
+        /* 对图像文件进行严格检测 */
+        if (in_array($extension, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'swf']) && !in_array($this->getImageType($this->filename), [1, 2, 3, 4, 6, 13])) {
+            return false;
+        }
+        return true;
+    }
+
+    // 判断图像类型
+    protected function getImageType($image)
+    {
+        if (function_exists('exif_imagetype')) {
+            return exif_imagetype($image);
+        } else {
+            try {
+                $info = getimagesize($image);
+                return $info ? $info[2] : false;
+            } catch (\Exception $e) {
+                return false;
+            }
+        }
+    }
+
+    /**
+     * 检测上传文件大小
+     * @param  integer   $size    最大大小
+     * @return bool
+     */
+    public function checkSize($size)
+    {
+        if ($this->getSize() > $size) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 检测上传文件类型
+     * @param  array|string   $mime    允许类型
+     * @return bool
+     */
+    public function checkMime($mime)
+    {
+        if (is_string($mime)) {
+            $mime = explode(',', $mime);
+        }
+
+        if (!in_array(strtolower($this->getMime()), $mime)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * 移动文件
+     * @param  string           $path    保存路径
+     * @param  string|bool      $savename    保存的文件名 默认自动生成
+     * @param  boolean          $replace 同名文件是否覆盖
+     * @return false|File       false-失败 否则返回File实例
+     */
+    public function move($path, $savename = true, $replace = true)
+    {
+        // 文件上传失败,捕获错误代码
+        if (!empty($this->info['error'])) {
+            $this->error($this->info['error']);
+            return false;
+        }
+
+        // 检测合法性
+        if (!$this->isValid()) {
+            $this->error = 'upload illegal files';
+            return false;
+        }
+
+        // 验证上传
+        if (!$this->check()) {
+            return false;
+        }
+
+        $path = rtrim($path, DS) . DS;
+        // 文件保存命名规则
+        $saveName = $this->buildSaveName($savename);
+        $filename = $path . $saveName;
+
+        // 检测目录
+        if (false === $this->checkPath(dirname($filename))) {
+            return false;
+        }
+
+        /* 不覆盖同名文件 */
+        if (!$replace && is_file($filename)) {
+            $this->error = ['has the same filename: {:filename}', ['filename' => $filename]];
+            return false;
+        }
+
+        /* 移动文件 */
+        if ($this->isTest) {
+            rename($this->filename, $filename);
+        } elseif (!move_uploaded_file($this->filename, $filename)) {
+            $this->error = 'upload write error';
+            return false;
+        }
+
+        // 返回 File对象实例
+        $file = new self($filename);
+        $file->setSaveName($saveName);
+        $file->setUploadInfo($this->info);
+
+        return $file;
+    }
+
+    /**
+     * 获取保存文件名
+     * @param  string|bool   $savename    保存的文件名 默认自动生成
+     * @return string
+     */
+    protected function buildSaveName($savename)
+    {
+        if (true === $savename) {
+            // 自动生成文件名
+            if ($this->rule instanceof \Closure) {
+                $savename = call_user_func_array($this->rule, [$this]);
+            } else {
+                switch ($this->rule) {
+                    case 'date':
+                        $savename = date('Ymd') . DS . md5(microtime(true));
+                        break;
+                    default:
+                        if (in_array($this->rule, hash_algos())) {
+                            $hash     = $this->hash($this->rule);
+                            $savename = substr($hash, 0, 2) . DS . substr($hash, 2);
+                        } elseif (is_callable($this->rule)) {
+                            $savename = call_user_func($this->rule);
+                        } else {
+                            $savename = date('Ymd') . DS . md5(microtime(true));
+                        }
+                }
+            }
+        } elseif ('' === $savename || false === $savename) {
+            $savename = $this->getInfo('name');
+        }
+
+        if (!strpos($savename, '.')) {
+            $savename .= '.' . pathinfo($this->getInfo('name'), PATHINFO_EXTENSION);
+        }
+
+        return $savename;
+    }
+
+    /**
+     * 获取错误代码信息
+     * @param int $errorNo  错误号
+     */
+    private function error($errorNo)
+    {
+        switch ($errorNo) {
+            case 1:
+            case 2:
+                $this->error = 'upload File size exceeds the maximum value';
+                break;
+            case 3:
+                $this->error = 'only the portion of file is uploaded';
+                break;
+            case 4:
+                $this->error = 'no file to uploaded';
+                break;
+            case 6:
+                $this->error = 'upload temp dir not found';
+                break;
+            case 7:
+                $this->error = 'file write error';
+                break;
+            default:
+                $this->error = 'unknown upload error';
+        }
+    }
+
+    /**
+     * 获取错误信息(支持多语言)
+     * @return string
+     */
+    public function getError()
+    {
+        if (is_array($this->error)) {
+            list($msg, $vars) = $this->error;
+        } else {
+            $msg  = $this->error;
+            $vars = [];
+        }
+
+        return Lang::has($msg) ? Lang::get($msg, $vars) : $msg;
+    }
+
+    public function __call($method, $args)
+    {
+        return $this->hash($method);
+    }
+}

+ 136 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Hook.php

@@ -0,0 +1,136 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+class Hook
+{
+
+    private static $tags = [];
+
+    /**
+     * 动态添加行为扩展到某个标签
+     * @param string    $tag 标签名称
+     * @param mixed     $behavior 行为名称
+     * @param bool      $first 是否放到开头执行
+     * @return void
+     */
+    public static function add($tag, $behavior, $first = false)
+    {
+        isset(self::$tags[$tag]) || self::$tags[$tag] = [];
+        if (is_array($behavior) && !is_callable($behavior)) {
+            if (!array_key_exists('_overlay', $behavior) || !$behavior['_overlay']) {
+                unset($behavior['_overlay']);
+                self::$tags[$tag] = array_merge(self::$tags[$tag], $behavior);
+            } else {
+                unset($behavior['_overlay']);
+                self::$tags[$tag] = $behavior;
+            }
+        } elseif ($first) {
+            array_unshift(self::$tags[$tag], $behavior);
+        } else {
+            self::$tags[$tag][] = $behavior;
+        }
+    }
+
+    /**
+     * 批量导入插件
+     * @param array        $tags 插件信息
+     * @param boolean     $recursive 是否递归合并
+     */
+    public static function import(array $tags, $recursive = true)
+    {
+        if ($recursive) {
+            foreach ($tags as $tag => $behavior) {
+                self::add($tag, $behavior);
+            }
+        } else {
+            self::$tags = $tags + self::$tags;
+        }
+    }
+
+    /**
+     * 获取插件信息
+     * @param string $tag 插件位置 留空获取全部
+     * @return array
+     */
+    public static function get($tag = '')
+    {
+        if (empty($tag)) {
+            //获取全部的插件信息
+            return self::$tags;
+        } else {
+            return array_key_exists($tag, self::$tags) ? self::$tags[$tag] : [];
+        }
+    }
+
+    /**
+     * 监听标签的行为
+     * @param string $tag    标签名称
+     * @param mixed  $params 传入参数
+     * @param mixed  $extra  额外参数
+     * @param bool   $once   只获取一个有效返回值
+     * @return mixed
+     */
+    public static function listen($tag, &$params = null, $extra = null, $once = false)
+    {
+        $results = [];
+        $tags    = static::get($tag);
+        foreach ($tags as $key => $name) {
+            $results[$key] = self::exec($name, $tag, $params, $extra);
+            if (false === $results[$key]) {
+                // 如果返回false 则中断行为执行
+                break;
+            } elseif (!is_null($results[$key]) && $once) {
+                break;
+            }
+        }
+        return $once ? end($results) : $results;
+    }
+
+    /**
+     * 执行某个行为
+     * @param mixed     $class 要执行的行为
+     * @param string    $tag 方法名(标签名)
+     * @param Mixed     $params 传人的参数
+     * @param mixed     $extra 额外参数
+     * @return mixed
+     */
+    public static function exec($class, $tag = '', &$params = null, $extra = null)
+    {
+        App::$debug && Debug::remark('behavior_start', 'time');
+        $method = Loader::parseName($tag, 1, false);
+        if ($class instanceof \Closure) {
+            $result = call_user_func_array($class, [ & $params, $extra]);
+            $class  = 'Closure';
+        } elseif (is_array($class)) {
+            list($class, $method) = $class;
+
+            $result = (new $class())->$method($params, $extra);
+            $class  = $class . '->' . $method;
+        } elseif (is_object($class)) {
+            $result = $class->$method($params, $extra);
+            $class  = get_class($class);
+        } elseif (strpos($class, '::')) {
+            $result = call_user_func_array($class, [ & $params, $extra]);
+        } else {
+            $obj    = new $class();
+            $method = ($tag && is_callable([$obj, $method])) ? $method : 'run';
+            $result = $obj->$method($params, $extra);
+        }
+        if (App::$debug) {
+            Debug::remark('behavior_end', 'time');
+            Log::record('[ BEHAVIOR ] Run ' . $class . ' @' . $tag . ' [ RunTime:' . Debug::getRangeTime('behavior_start', 'behavior_end') . 's ]', 'info');
+        }
+        return $result;
+    }
+
+}

+ 223 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Lang.php

@@ -0,0 +1,223 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+class Lang
+{
+    // 语言数据
+    private static $lang = [];
+    // 语言作用域
+    private static $range = 'zh-cn';
+    // 语言自动侦测的变量
+    protected static $langDetectVar = 'lang';
+    // 语言Cookie变量
+    protected static $langCookieVar = 'think_var';
+    // 语言Cookie的过期时间
+    protected static $langCookieExpire = 3600;
+    // 允许语言列表
+    protected static $allowLangList = [];
+    // Accept-Language转义为对应语言包名称 系统默认配置
+    protected static $acceptLanguage = [
+        'zh-hans-cn' => 'zh-cn',
+    ];
+
+    // 设定当前的语言
+    public static function range($range = '')
+    {
+        if ('' == $range) {
+            return self::$range;
+        } else {
+            self::$range = $range;
+        }
+        return self::$range;
+    }
+
+    /**
+     * 设置语言定义(不区分大小写)
+     * @param string|array  $name 语言变量
+     * @param string        $value 语言值
+     * @param string        $range 语言作用域
+     * @return mixed
+     */
+    public static function set($name, $value = null, $range = '')
+    {
+        $range = $range ?: self::$range;
+        // 批量定义
+        if (!isset(self::$lang[$range])) {
+            self::$lang[$range] = [];
+        }
+        if (is_array($name)) {
+            return self::$lang[$range] = array_change_key_case($name) + self::$lang[$range];
+        } else {
+            return self::$lang[$range][strtolower($name)] = $value;
+        }
+    }
+
+    /**
+     * 加载语言定义(不区分大小写)
+     * @param array|string $file 语言文件
+     * @param string $range 语言作用域
+     * @return mixed
+     */
+    public static function load($file, $range = '')
+    {
+        $range = $range ?: self::$range;
+        if (!isset(self::$lang[$range])) {
+            self::$lang[$range] = [];
+        }
+        // 批量定义
+        if (is_string($file)) {
+            $file = [$file];
+        }
+        $lang = [];
+        foreach ($file as $_file) {
+            if (is_file($_file)) {
+                // 记录加载信息
+                App::$debug && Log::record('[ LANG ] ' . $_file, 'info');
+                $_lang = include $_file;
+                if (is_array($_lang)) {
+                    $lang = array_change_key_case($_lang) + $lang;
+                }
+            }
+        }
+        if (!empty($lang)) {
+            self::$lang[$range] = $lang + self::$lang[$range];
+        }
+        return self::$lang[$range];
+    }
+
+    /**
+     * 获取语言定义(不区分大小写)
+     * @param string|null   $name 语言变量
+     * @param string        $range 语言作用域
+     * @return mixed
+     */
+    public static function has($name, $range = '')
+    {
+        $range = $range ?: self::$range;
+        return isset(self::$lang[$range][strtolower($name)]);
+    }
+
+    /**
+     * 获取语言定义(不区分大小写)
+     * @param string|null   $name 语言变量
+     * @param array         $vars 变量替换
+     * @param string        $range 语言作用域
+     * @return mixed
+     */
+    public static function get($name = null, $vars = [], $range = '')
+    {
+        $range = $range ?: self::$range;
+        // 空参数返回所有定义
+        if (empty($name)) {
+            return self::$lang[$range];
+        }
+        $key   = strtolower($name);
+        $value = isset(self::$lang[$range][$key]) ? self::$lang[$range][$key] : $name;
+
+        // 变量解析
+        if (!empty($vars) && is_array($vars)) {
+            /**
+             * Notes:
+             * 为了检测的方便,数字索引的判断仅仅是参数数组的第一个元素的key为数字0
+             * 数字索引采用的是系统的 sprintf 函数替换,用法请参考 sprintf 函数
+             */
+            if (key($vars) === 0) {
+                // 数字索引解析
+                array_unshift($vars, $value);
+                $value = call_user_func_array('sprintf', $vars);
+            } else {
+                // 关联索引解析
+                $replace = array_keys($vars);
+                foreach ($replace as &$v) {
+                    $v = "{:{$v}}";
+                }
+                $value = str_replace($replace, $vars, $value);
+            }
+
+        }
+        return $value;
+    }
+
+    /**
+     * 自动侦测设置获取语言选择
+     * @return string
+     */
+    public static function detect()
+    {
+        // 自动侦测设置获取语言选择
+        $langSet = '';
+
+        if (isset($_GET[self::$langDetectVar])) {
+            // url中设置了语言变量
+            $langSet = strtolower($_GET[self::$langDetectVar]);
+        } elseif (isset($_COOKIE[self::$langCookieVar])) {
+            // Cookie中设置了语言变量
+            $langSet = strtolower($_COOKIE[self::$langCookieVar]);
+        } elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
+            // 自动侦测浏览器语言
+            preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
+            $langSet     = strtolower($matches[1]);
+            $acceptLangs = Config::get('header_accept_lang');
+            if (isset($acceptLangs[$langSet])) {
+                $langSet = $acceptLangs[$langSet];
+            } elseif (isset(self::$acceptLanguage[$langSet])) {
+                $langSet = self::$acceptLanguage[$langSet];
+            }
+        }
+        if (empty(self::$allowLangList) || in_array($langSet, self::$allowLangList)) {
+            // 合法的语言
+            self::$range = $langSet ?: self::$range;
+        }
+        return self::$range;
+    }
+
+    /**
+     * 设置语言自动侦测的变量
+     * @param string $var 变量名称
+     * @return void
+     */
+    public static function setLangDetectVar($var)
+    {
+        self::$langDetectVar = $var;
+    }
+
+    /**
+     * 设置语言的cookie保存变量
+     * @param string $var 变量名称
+     * @return void
+     */
+    public static function setLangCookieVar($var)
+    {
+        self::$langCookieVar = $var;
+    }
+
+    /**
+     * 设置语言的cookie的过期时间
+     * @param string $expire 过期时间
+     * @return void
+     */
+    public static function setLangCookieExpire($expire)
+    {
+        self::$langCookieExpire = $expire;
+    }
+
+    /**
+     * 设置允许的语言列表
+     * @param array $list 语言列表
+     * @return void
+     */
+    public static function setAllowLangList($list)
+    {
+        self::$allowLangList = $list;
+    }
+}

+ 563 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Loader.php

@@ -0,0 +1,563 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+use think\exception\ClassNotFoundException;
+
+class Loader
+{
+    protected static $instance = [];
+    // 类名映射
+    protected static $map = [];
+
+    // 命名空间别名
+    protected static $namespaceAlias = [];
+
+    // PSR-4
+    private static $prefixLengthsPsr4 = [];
+    private static $prefixDirsPsr4    = [];
+    private static $fallbackDirsPsr4  = [];
+
+    // PSR-0
+    private static $prefixesPsr0     = [];
+    private static $fallbackDirsPsr0 = [];
+
+    // 自动加载的文件
+    private static $autoloadFiles = [];
+
+    // 自动加载
+    public static function autoload($class)
+    {
+        // 检测命名空间别名
+        if (!empty(self::$namespaceAlias)) {
+            $namespace = dirname($class);
+            if (isset(self::$namespaceAlias[$namespace])) {
+                $original = self::$namespaceAlias[$namespace] . '\\' . basename($class);
+                if (class_exists($original)) {
+                    return class_alias($original, $class, false);
+                }
+            }
+        }
+
+        if ($file = self::findFile($class)) {
+
+            // Win环境严格区分大小写
+            if (IS_WIN && pathinfo($file, PATHINFO_FILENAME) != pathinfo(realpath($file), PATHINFO_FILENAME)) {
+                return false;
+            }
+
+            __include_file($file);
+            return true;
+        }
+    }
+
+    /**
+     * 查找文件
+     * @param $class
+     * @return bool
+     */
+    private static function findFile($class)
+    {
+        if (!empty(self::$map[$class])) {
+            // 类库映射
+            return self::$map[$class];
+        }
+
+        // 查找 PSR-4
+        $logicalPathPsr4 = strtr($class, '\\', DS) . EXT;
+
+        $first = $class[0];
+        if (isset(self::$prefixLengthsPsr4[$first])) {
+            foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) {
+                if (0 === strpos($class, $prefix)) {
+                    foreach (self::$prefixDirsPsr4[$prefix] as $dir) {
+                        if (is_file($file = $dir . DS . substr($logicalPathPsr4, $length))) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // 查找 PSR-4 fallback dirs
+        foreach (self::$fallbackDirsPsr4 as $dir) {
+            if (is_file($file = $dir . DS . $logicalPathPsr4)) {
+                return $file;
+            }
+        }
+
+        // 查找 PSR-0
+        if (false !== $pos = strrpos($class, '\\')) {
+            // namespaced class name
+            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+            . strtr(substr($logicalPathPsr4, $pos + 1), '_', DS);
+        } else {
+            // PEAR-like class name
+            $logicalPathPsr0 = strtr($class, '_', DS) . EXT;
+        }
+
+        if (isset(self::$prefixesPsr0[$first])) {
+            foreach (self::$prefixesPsr0[$first] as $prefix => $dirs) {
+                if (0 === strpos($class, $prefix)) {
+                    foreach ($dirs as $dir) {
+                        if (is_file($file = $dir . DS . $logicalPathPsr0)) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // 查找 PSR-0 fallback dirs
+        foreach (self::$fallbackDirsPsr0 as $dir) {
+            if (is_file($file = $dir . DS . $logicalPathPsr0)) {
+                return $file;
+            }
+        }
+
+        return self::$map[$class] = false;
+    }
+
+    // 注册classmap
+    public static function addClassMap($class, $map = '')
+    {
+        if (is_array($class)) {
+            self::$map = array_merge(self::$map, $class);
+        } else {
+            self::$map[$class] = $map;
+        }
+    }
+
+    // 注册命名空间
+    public static function addNamespace($namespace, $path = '')
+    {
+        if (is_array($namespace)) {
+            foreach ($namespace as $prefix => $paths) {
+                self::addPsr4($prefix . '\\', rtrim($paths, DS), true);
+            }
+        } else {
+            self::addPsr4($namespace . '\\', rtrim($path, DS), true);
+        }
+    }
+
+    // 添加Ps0空间
+    private static function addPsr0($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            if ($prepend) {
+                self::$fallbackDirsPsr0 = array_merge(
+                    (array) $paths,
+                    self::$fallbackDirsPsr0
+                );
+            } else {
+                self::$fallbackDirsPsr0 = array_merge(
+                    self::$fallbackDirsPsr0,
+                    (array) $paths
+                );
+            }
+
+            return;
+        }
+
+        $first = $prefix[0];
+        if (!isset(self::$prefixesPsr0[$first][$prefix])) {
+            self::$prefixesPsr0[$first][$prefix] = (array) $paths;
+
+            return;
+        }
+        if ($prepend) {
+            self::$prefixesPsr0[$first][$prefix] = array_merge(
+                (array) $paths,
+                self::$prefixesPsr0[$first][$prefix]
+            );
+        } else {
+            self::$prefixesPsr0[$first][$prefix] = array_merge(
+                self::$prefixesPsr0[$first][$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    // 添加Psr4空间
+    private static function addPsr4($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            // Register directories for the root namespace.
+            if ($prepend) {
+                self::$fallbackDirsPsr4 = array_merge(
+                    (array) $paths,
+                    self::$fallbackDirsPsr4
+                );
+            } else {
+                self::$fallbackDirsPsr4 = array_merge(
+                    self::$fallbackDirsPsr4,
+                    (array) $paths
+                );
+            }
+        } elseif (!isset(self::$prefixDirsPsr4[$prefix])) {
+            // Register directories for a new namespace.
+            $length = strlen($prefix);
+            if ('\\' !== $prefix[$length - 1]) {
+                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+            }
+            self::$prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+            self::$prefixDirsPsr4[$prefix]                = (array) $paths;
+        } elseif ($prepend) {
+            // Prepend directories for an already registered namespace.
+            self::$prefixDirsPsr4[$prefix] = array_merge(
+                (array) $paths,
+                self::$prefixDirsPsr4[$prefix]
+            );
+        } else {
+            // Append directories for an already registered namespace.
+            self::$prefixDirsPsr4[$prefix] = array_merge(
+                self::$prefixDirsPsr4[$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    // 注册命名空间别名
+    public static function addNamespaceAlias($namespace, $original = '')
+    {
+        if (is_array($namespace)) {
+            self::$namespaceAlias = array_merge(self::$namespaceAlias, $namespace);
+        } else {
+            self::$namespaceAlias[$namespace] = $original;
+        }
+    }
+
+    // 注册自动加载机制
+    public static function register($autoload = '')
+    {
+        // 注册系统自动加载
+        spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);
+        // 注册命名空间定义
+        self::addNamespace([
+            'think'    => LIB_PATH . 'think' . DS,
+            'behavior' => LIB_PATH . 'behavior' . DS,
+            'traits'   => LIB_PATH . 'traits' . DS,
+        ]);
+        // 加载类库映射文件
+        if (is_file(RUNTIME_PATH . 'classmap' . EXT)) {
+            self::addClassMap(__include_file(RUNTIME_PATH . 'classmap' . EXT));
+        }
+
+        // Composer自动加载支持
+        if (is_dir(VENDOR_PATH . 'composer')) {
+            self::registerComposerLoader();
+        }
+
+        // 自动加载extend目录
+        self::$fallbackDirsPsr4[] = rtrim(EXTEND_PATH, DS);
+    }
+
+    // 注册composer自动加载
+    private static function registerComposerLoader()
+    {
+        if (is_file(VENDOR_PATH . 'composer/autoload_namespaces.php')) {
+            $map = require VENDOR_PATH . 'composer/autoload_namespaces.php';
+            foreach ($map as $namespace => $path) {
+                self::addPsr0($namespace, $path);
+            }
+        }
+
+        if (is_file(VENDOR_PATH . 'composer/autoload_psr4.php')) {
+            $map = require VENDOR_PATH . 'composer/autoload_psr4.php';
+            foreach ($map as $namespace => $path) {
+                self::addPsr4($namespace, $path);
+            }
+        }
+
+        if (is_file(VENDOR_PATH . 'composer/autoload_classmap.php')) {
+            $classMap = require VENDOR_PATH . 'composer/autoload_classmap.php';
+            if ($classMap) {
+                self::addClassMap($classMap);
+            }
+        }
+
+        if (is_file(VENDOR_PATH . 'composer/autoload_files.php')) {
+            $includeFiles = require VENDOR_PATH . 'composer/autoload_files.php';
+            foreach ($includeFiles as $fileIdentifier => $file) {
+                if (empty(self::$autoloadFiles[$fileIdentifier])) {
+                    __require_file($file);
+                    self::$autoloadFiles[$fileIdentifier] = true;
+                }
+            }
+        }
+    }
+
+    /**
+     * 导入所需的类库 同java的Import 本函数有缓存功能
+     * @param string $class   类库命名空间字符串
+     * @param string $baseUrl 起始路径
+     * @param string $ext     导入的文件扩展名
+     * @return boolean
+     */
+    public static function import($class, $baseUrl = '', $ext = EXT)
+    {
+        static $_file = [];
+        $key          = $class . $baseUrl;
+        $class        = str_replace(['.', '#'], [DS, '.'], $class);
+        if (isset($_file[$key])) {
+            return true;
+        }
+
+        if (empty($baseUrl)) {
+            list($name, $class) = explode(DS, $class, 2);
+
+            if (isset(self::$prefixDirsPsr4[$name . '\\'])) {
+                // 注册的命名空间
+                $baseUrl = self::$prefixDirsPsr4[$name . '\\'];
+            } elseif ('@' == $name) {
+                //加载当前模块应用类库
+                $baseUrl = App::$modulePath;
+            } elseif (is_dir(EXTEND_PATH . $name)) {
+                $baseUrl = EXTEND_PATH . $name . DS;
+            } else {
+                // 加载其它模块的类库
+                $baseUrl = APP_PATH . $name . DS;
+            }
+        } elseif (substr($baseUrl, -1) != DS) {
+            $baseUrl .= DS;
+        }
+        // 如果类存在 则导入类库文件
+        if (is_array($baseUrl)) {
+            foreach ($baseUrl as $path) {
+                $filename = $path . DS . $class . $ext;
+                if (is_file($filename)) {
+                    break;
+                }
+            }
+        } else {
+            $filename = $baseUrl . $class . $ext;
+        }
+
+        if (!empty($filename) && is_file($filename)) {
+            // 开启调试模式Win环境严格区分大小写
+            if (IS_WIN && pathinfo($filename, PATHINFO_FILENAME) != pathinfo(realpath($filename), PATHINFO_FILENAME)) {
+                return false;
+            }
+            __include_file($filename);
+            $_file[$key] = true;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 实例化(分层)模型
+     * @param string $name         Model名称
+     * @param string $layer        业务层名称
+     * @param bool   $appendSuffix 是否添加类名后缀
+     * @param string $common       公共模块名
+     * @return object
+     * @throws ClassNotFoundException
+     */
+    public static function model($name = '', $layer = 'model', $appendSuffix = false, $common = 'common')
+    {
+        $guid = $name . $layer;
+        if (isset(self::$instance[$guid])) {
+            return self::$instance[$guid];
+        }
+        list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix);
+        if (class_exists($class)) {
+            $model = new $class();
+        } else {
+            $class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class);
+            if (class_exists($class)) {
+                $model = new $class();
+            } else {
+                throw new ClassNotFoundException('class not exists:' . $class, $class);
+            }
+        }
+        self::$instance[$guid] = $model;
+        return $model;
+    }
+
+    /**
+     * 实例化(分层)控制器 格式:[模块名/]控制器名
+     * @param string $name         资源地址
+     * @param string $layer        控制层名称
+     * @param bool   $appendSuffix 是否添加类名后缀
+     * @param string $empty        空控制器名称
+     * @return object
+     * @throws ClassNotFoundException
+     */
+    public static function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '')
+    {
+        list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix);
+        if (class_exists($class)) {
+            return App::invokeClass($class);
+        } elseif ($empty && class_exists($emptyClass = self::parseClass($module, $layer, $empty, $appendSuffix))) {
+            return new $emptyClass(Request::instance());
+        } else {
+            throw new ClassNotFoundException('class not exists:' . $class, $class);
+        }
+    }
+
+    /**
+     * 实例化验证类 格式:[模块名/]验证器名
+     * @param string $name         资源地址
+     * @param string $layer        验证层名称
+     * @param bool   $appendSuffix 是否添加类名后缀
+     * @param string $common       公共模块名
+     * @return object|false
+     * @throws ClassNotFoundException
+     */
+    public static function validate($name = '', $layer = 'validate', $appendSuffix = false, $common = 'common')
+    {
+        $name = $name ?: Config::get('default_validate');
+        if (empty($name)) {
+            return new Validate;
+        }
+        $guid = $name . $layer;
+        if (isset(self::$instance[$guid])) {
+            return self::$instance[$guid];
+        }
+        list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix);
+        if (class_exists($class)) {
+            $validate = new $class;
+        } else {
+            $class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class);
+            if (class_exists($class)) {
+                $validate = new $class;
+            } else {
+                throw new ClassNotFoundException('class not exists:' . $class, $class);
+            }
+        }
+        self::$instance[$guid] = $validate;
+        return $validate;
+    }
+
+    /**
+     * 解析模块和类名
+     * @param string $name         资源地址
+     * @param string $layer        验证层名称
+     * @param bool   $appendSuffix 是否添加类名后缀
+     * @return array
+     */
+    protected static function getModuleAndClass($name, $layer, $appendSuffix)
+    {
+        if (false !== strpos($name, '\\')) {
+            $module = Request::instance()->module();
+            $class  = $name;
+        } else {
+            if (strpos($name, '/')) {
+                list($module, $name) = explode('/', $name, 2);
+            } else {
+                $module = Request::instance()->module();
+            }
+            $class = self::parseClass($module, $layer, $name, $appendSuffix);
+        }
+        return [$module, $class];
+    }
+
+    /**
+     * 数据库初始化 并取得数据库类实例
+     * @param mixed         $config 数据库配置
+     * @param bool|string   $name 连接标识 true 强制重新连接
+     * @return \think\db\Connection
+     */
+    public static function db($config = [], $name = false)
+    {
+        return Db::connect($config, $name);
+    }
+
+    /**
+     * 远程调用模块的操作方法 参数格式 [模块/控制器/]操作
+     * @param string       $url          调用地址
+     * @param string|array $vars         调用参数 支持字符串和数组
+     * @param string       $layer        要调用的控制层名称
+     * @param bool         $appendSuffix 是否添加类名后缀
+     * @return mixed
+     */
+    public static function action($url, $vars = [], $layer = 'controller', $appendSuffix = false)
+    {
+        $info   = pathinfo($url);
+        $action = $info['basename'];
+        $module = '.' != $info['dirname'] ? $info['dirname'] : Request::instance()->controller();
+        $class  = self::controller($module, $layer, $appendSuffix);
+        if ($class) {
+            if (is_scalar($vars)) {
+                if (strpos($vars, '=')) {
+                    parse_str($vars, $vars);
+                } else {
+                    $vars = [$vars];
+                }
+            }
+            return App::invokeMethod([$class, $action . Config::get('action_suffix')], $vars);
+        }
+    }
+
+    /**
+     * 字符串命名风格转换
+     * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
+     * @param string  $name 字符串
+     * @param integer $type 转换类型
+     * @param bool    $ucfirst 首字母是否大写(驼峰规则)
+     * @return string
+     */
+    public static function parseName($name, $type = 0, $ucfirst = true)
+    {
+        if ($type) {
+            $name = preg_replace_callback('/_([a-zA-Z])/', function ($match) {
+                return strtoupper($match[1]);
+            }, $name);
+            return $ucfirst ? ucfirst($name) : lcfirst($name);
+        } else {
+            return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
+        }
+    }
+
+    /**
+     * 解析应用类的类名
+     * @param string $module 模块名
+     * @param string $layer  层名 controller model ...
+     * @param string $name   类名
+     * @param bool   $appendSuffix
+     * @return string
+     */
+    public static function parseClass($module, $layer, $name, $appendSuffix = false)
+    {
+        $name  = str_replace(['/', '.'], '\\', $name);
+        $array = explode('\\', $name);
+        $class = self::parseName(array_pop($array), 1) . (App::$suffix || $appendSuffix ? ucfirst($layer) : '');
+        $path  = $array ? implode('\\', $array) . '\\' : '';
+        return App::$namespace . '\\' . ($module ? $module . '\\' : '') . $layer . '\\' . $path . $class;
+    }
+
+    /**
+     * 初始化类的实例
+     * @return void
+     */
+    public static function clearInstance()
+    {
+        self::$instance = [];
+    }
+}
+
+/**
+ * 作用范围隔离
+ *
+ * @param $file
+ * @return mixed
+ */
+function __include_file($file)
+{
+    return include $file;
+}
+
+function __require_file($file)
+{
+    return require $file;
+}

+ 213 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Log.php

@@ -0,0 +1,213 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+use think\exception\ClassNotFoundException;
+
+/**
+ * Class Log
+ * @package think
+ *
+ * @method void log($msg) static
+ * @method void error($msg) static
+ * @method void info($msg) static
+ * @method void sql($msg) static
+ * @method void notice($msg) static
+ * @method void alert($msg) static
+ */
+class Log
+{
+    const LOG    = 'log';
+    const ERROR  = 'error';
+    const INFO   = 'info';
+    const SQL    = 'sql';
+    const NOTICE = 'notice';
+    const ALERT  = 'alert';
+    const DEBUG  = 'debug';
+
+    // 日志信息
+    protected static $log = [];
+    // 配置参数
+    protected static $config = [];
+    // 日志类型
+    protected static $type = ['log', 'error', 'info', 'sql', 'notice', 'alert', 'debug'];
+    // 日志写入驱动
+    protected static $driver;
+
+    // 当前日志授权key
+    protected static $key;
+
+    /**
+     * 日志初始化
+     * @param array $config
+     */
+    public static function init($config = [])
+    {
+        $type         = isset($config['type']) ? $config['type'] : 'File';
+        $class        = false !== strpos($type, '\\') ? $type : '\\think\\log\\driver\\' . ucwords($type);
+        self::$config = $config;
+        unset($config['type']);
+        if (class_exists($class)) {
+            self::$driver = new $class($config);
+        } else {
+            throw new ClassNotFoundException('class not exists:' . $class, $class);
+        }
+        // 记录初始化信息
+        App::$debug && Log::record('[ LOG ] INIT ' . $type, 'info');
+    }
+
+    /**
+     * 获取日志信息
+     * @param string $type 信息类型
+     * @return array
+     */
+    public static function getLog($type = '')
+    {
+        return $type ? self::$log[$type] : self::$log;
+    }
+
+    /**
+     * 记录调试信息
+     * @param mixed  $msg  调试信息
+     * @param string $type 信息类型
+     * @return void
+     */
+    public static function record($msg, $type = 'log')
+    {
+        self::$log[$type][] = $msg;
+        if (IS_CLI) {
+            // 命令行下面日志写入改进
+            self::save();
+        }
+    }
+
+    /**
+     * 清空日志信息
+     * @return void
+     */
+    public static function clear()
+    {
+        self::$log = [];
+    }
+
+    /**
+     * 当前日志记录的授权key
+     * @param string $key 授权key
+     * @return void
+     */
+    public static function key($key)
+    {
+        self::$key = $key;
+    }
+
+    /**
+     * 检查日志写入权限
+     * @param array $config 当前日志配置参数
+     * @return bool
+     */
+    public static function check($config)
+    {
+        if (self::$key && !empty($config['allow_key']) && !in_array(self::$key, $config['allow_key'])) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 保存调试信息
+     * @return bool
+     */
+    public static function save()
+    {
+        if (!empty(self::$log)) {
+            if (is_null(self::$driver)) {
+                self::init(Config::get('log'));
+            }
+
+            if (!self::check(self::$config)) {
+                // 检测日志写入权限
+                return false;
+            }
+
+            if (empty(self::$config['level'])) {
+                // 获取全部日志
+                $log = self::$log;
+                if (!App::$debug && isset($log['debug'])) {
+                    unset($log['debug']);
+                }
+            } else {
+                // 记录允许级别
+                $log = [];
+                foreach (self::$config['level'] as $level) {
+                    if (isset(self::$log[$level])) {
+                        $log[$level] = self::$log[$level];
+                    }
+                }
+            }
+
+            $result = self::$driver->save($log);
+            if ($result) {
+                self::$log = [];
+            }
+            Hook::listen('log_write_done', $log);
+            return $result;
+        }
+        return true;
+    }
+
+    /**
+     * 实时写入日志信息 并支持行为
+     * @param mixed  $msg   调试信息
+     * @param string $type  信息类型
+     * @param bool   $force 是否强制写入
+     * @return bool
+     */
+    public static function write($msg, $type = 'log', $force = false)
+    {
+        $log = self::$log;
+        // 封装日志信息
+        if (true === $force || empty(self::$config['level'])) {
+            $log[$type][] = $msg;
+        } elseif (in_array($type, self::$config['level'])) {
+            $log[$type][] = $msg;
+        } else {
+            return false;
+        }
+
+        // 监听log_write
+        Hook::listen('log_write', $log);
+        if (is_null(self::$driver)) {
+            self::init(Config::get('log'));
+        }
+        // 写入日志
+        $result = self::$driver->save($log);
+        if ($result) {
+            self::$log = [];
+        }
+        return $result;
+    }
+
+    /**
+     * 静态调用
+     * @param $method
+     * @param $args
+     * @return mixed
+     */
+    public static function __callStatic($method, $args)
+    {
+        if (in_array($method, self::$type)) {
+            array_push($args, $method);
+            return call_user_func_array('\\think\\Log::record', $args);
+        }
+    }
+
+}

Різницю між файлами не показано, бо вона завелика
+ 2268 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Model.php


+ 401 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Paginator.php

@@ -0,0 +1,401 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: zhangyajun <448901948@qq.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+use ArrayAccess;
+use ArrayIterator;
+use Countable;
+use IteratorAggregate;
+use JsonSerializable;
+use Traversable;
+
+abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable
+{
+    /** @var bool 是否为简洁模式 */
+    protected $simple = false;
+
+    /** @var Collection 数据集 */
+    protected $items;
+
+    /** @var integer 当前页 */
+    protected $currentPage;
+
+    /** @var  integer 最后一页 */
+    protected $lastPage;
+
+    /** @var integer|null 数据总数 */
+    protected $total;
+
+    /** @var  integer 每页的数量 */
+    protected $listRows;
+
+    /** @var bool 是否有下一页 */
+    protected $hasMore;
+
+    /** @var array 一些配置 */
+    protected $options = [
+        'var_page' => 'page',
+        'path'     => '/',
+        'query'    => [],
+        'fragment' => '',
+    ];
+
+    /** @var mixed simple模式下的下个元素 */
+    protected $nextItem;
+
+    public function __construct($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = [])
+    {
+        $this->options = array_merge($this->options, $options);
+
+        $this->options['path'] = '/' != $this->options['path'] ? rtrim($this->options['path'], '/') : $this->options['path'];
+
+        $this->simple   = $simple;
+        $this->listRows = $listRows;
+
+        if (!$items instanceof Collection) {
+            $items = Collection::make($items);
+        }
+
+        if ($simple) {
+            $this->currentPage = $this->setCurrentPage($currentPage);
+            $this->hasMore     = count($items) > ($this->listRows);
+            if ($this->hasMore) {
+                $this->nextItem = $items->slice($this->listRows, 1);
+            }
+            $items = $items->slice(0, $this->listRows);
+        } else {
+            $this->total       = $total;
+            $this->lastPage    = (int) ceil($total / $listRows);
+            $this->currentPage = $this->setCurrentPage($currentPage);
+            $this->hasMore     = $this->currentPage < $this->lastPage;
+        }
+        $this->items = $items;
+    }
+
+    /**
+     * @param       $items
+     * @param       $listRows
+     * @param null  $currentPage
+     * @param bool  $simple
+     * @param null  $total
+     * @param array $options
+     * @return Paginator
+     */
+    public static function make($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = [])
+    {
+        return new static($items, $listRows, $currentPage, $total, $simple, $options);
+    }
+
+    protected function setCurrentPage($currentPage)
+    {
+        if (!$this->simple && $currentPage > $this->lastPage) {
+            return $this->lastPage > 0 ? $this->lastPage : 1;
+        }
+
+        return $currentPage;
+    }
+
+    /**
+     * 获取页码对应的链接
+     *
+     * @param $page
+     * @return string
+     */
+    protected function url($page)
+    {
+        if ($page <= 0) {
+            $page = 1;
+        }
+
+        if (strpos($this->options['path'], '[PAGE]') === false) {
+            $parameters = [$this->options['var_page'] => $page];
+            $path       = $this->options['path'];
+        } else {
+            $parameters = [];
+            $path       = str_replace('[PAGE]', $page, $this->options['path']);
+        }
+        if (count($this->options['query']) > 0) {
+            $parameters = array_merge($this->options['query'], $parameters);
+        }
+        $url = $path;
+        if (!empty($parameters)) {
+            $url .= '?' . urldecode(http_build_query($parameters, null, '&'));
+        }
+        return $url . $this->buildFragment();
+    }
+
+    /**
+     * 自动获取当前页码
+     * @param string $varPage
+     * @param int    $default
+     * @return int
+     */
+    public static function getCurrentPage($varPage = 'page', $default = 1)
+    {
+        $page = (int) Request::instance()->param($varPage);
+
+        if (filter_var($page, FILTER_VALIDATE_INT) !== false && $page >= 1) {
+            return $page;
+        }
+
+        return $default;
+    }
+
+    /**
+     * 自动获取当前的path
+     * @return string
+     */
+    public static function getCurrentPath()
+    {
+        return Request::instance()->baseUrl();
+    }
+
+    public function total()
+    {
+        if ($this->simple) {
+            throw new \DomainException('not support total');
+        }
+        return $this->total;
+    }
+
+    public function listRows()
+    {
+        return $this->listRows;
+    }
+
+    public function currentPage()
+    {
+        return $this->currentPage;
+    }
+
+    public function lastPage()
+    {
+        if ($this->simple) {
+            throw new \DomainException('not support last');
+        }
+        return $this->lastPage;
+    }
+
+    /**
+     * 数据是否足够分页
+     * @return boolean
+     */
+    public function hasPages()
+    {
+        return !(1 == $this->currentPage && !$this->hasMore);
+    }
+
+    /**
+     * 创建一组分页链接
+     *
+     * @param  int $start
+     * @param  int $end
+     * @return array
+     */
+    public function getUrlRange($start, $end)
+    {
+        $urls = [];
+
+        for ($page = $start; $page <= $end; $page++) {
+            $urls[$page] = $this->url($page);
+        }
+
+        return $urls;
+    }
+
+    /**
+     * 设置URL锚点
+     *
+     * @param  string|null $fragment
+     * @return $this
+     */
+    public function fragment($fragment)
+    {
+        $this->options['fragment'] = $fragment;
+        return $this;
+    }
+
+    /**
+     * 添加URL参数
+     *
+     * @param  array|string $key
+     * @param  string|null  $value
+     * @return $this
+     */
+    public function appends($key, $value = null)
+    {
+        if (!is_array($key)) {
+            $queries = [$key => $value];
+        } else {
+            $queries = $key;
+        }
+
+        foreach ($queries as $k => $v) {
+            if ($k !== $this->options['var_page']) {
+                $this->options['query'][$k] = $v;
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * 构造锚点字符串
+     *
+     * @return string
+     */
+    protected function buildFragment()
+    {
+        return $this->options['fragment'] ? '#' . $this->options['fragment'] : '';
+    }
+
+    /**
+     * 渲染分页html
+     * @return mixed
+     */
+    abstract public function render();
+
+    public function items()
+    {
+        return $this->items->all();
+    }
+
+    public function getCollection()
+    {
+        return $this->items;
+    }
+
+    public function isEmpty()
+    {
+        return $this->items->isEmpty();
+    }
+
+    /**
+     * 给每个元素执行个回调
+     *
+     * @param  callable $callback
+     * @return $this
+     */
+    public function each(callable $callback)
+    {
+        foreach ($this->items as $key => $item) {
+            $result = $callback($item, $key);
+            if (false === $result) {
+                break;
+            } elseif (!is_object($item)) {
+                $this->items[$key] = $result;
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Retrieve an external iterator
+     * @return Traversable An instance of an object implementing <b>Iterator</b> or
+     * <b>Traversable</b>
+     */
+    public function getIterator()
+    {
+        return new ArrayIterator($this->items->all());
+    }
+
+    /**
+     * Whether a offset exists
+     * @param mixed $offset
+     * @return bool
+     */
+    public function offsetExists($offset)
+    {
+        return $this->items->offsetExists($offset);
+    }
+
+    /**
+     * Offset to retrieve
+     * @param mixed $offset
+     * @return mixed
+     */
+    public function offsetGet($offset)
+    {
+        return $this->items->offsetGet($offset);
+    }
+
+    /**
+     * Offset to set
+     * @param mixed $offset
+     * @param mixed $value
+     */
+    public function offsetSet($offset, $value)
+    {
+        $this->items->offsetSet($offset, $value);
+    }
+
+    /**
+     * Offset to unset
+     * @param mixed $offset
+     * @return void
+     * @since 5.0.0
+     */
+    public function offsetUnset($offset)
+    {
+        $this->items->offsetUnset($offset);
+    }
+
+    /**
+     * Count elements of an object
+     */
+    public function count()
+    {
+        return $this->items->count();
+    }
+
+    public function __toString()
+    {
+        return (string) $this->render();
+    }
+
+    public function toArray()
+    {
+        if ($this->simple) {
+            return [
+                'per_page'     => $this->listRows,
+                'current_page' => $this->currentPage,
+                'has_more'     => $this->hasMore,
+                'next_item'    => $this->nextItem,
+                'data'         => $this->items->toArray(),
+            ];
+        } else {
+            return [
+                'total'        => $this->total,
+                'per_page'     => $this->listRows,
+                'current_page' => $this->currentPage,
+                'last_page'    => $this->lastPage,
+                'data'         => $this->items->toArray(),
+            ];
+        }
+
+    }
+
+    /**
+     * Specify data which should be serialized to JSON
+     */
+    public function jsonSerialize()
+    {
+        return $this->toArray();
+    }
+
+    public function __call($name, $arguments)
+    {
+        return call_user_func_array([$this->getCollection(), $name], $arguments);
+    }
+
+}

Різницю між файлами не показано, бо вона завелика
+ 1205 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Process.php


Різницю між файлами не показано, бо вона завелика
+ 1648 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Request.php


+ 334 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Response.php

@@ -0,0 +1,334 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+use think\response\Json as JsonResponse;
+use think\response\Jsonp as JsonpResponse;
+use think\response\Redirect as RedirectResponse;
+use think\response\View as ViewResponse;
+use think\response\Xml as XmlResponse;
+
+class Response
+{
+    // 原始数据
+    protected $data;
+
+    // 当前的contentType
+    protected $contentType = 'text/html';
+
+    // 字符集
+    protected $charset = 'utf-8';
+
+    //状态
+    protected $code = 200;
+
+    // 输出参数
+    protected $options = [];
+    // header参数
+    protected $header = [];
+
+    protected $content = null;
+
+    /**
+     * 构造函数
+     * @access   public
+     * @param mixed $data    输出数据
+     * @param int   $code
+     * @param array $header
+     * @param array $options 输出参数
+     */
+    public function __construct($data = '', $code = 200, array $header = [], $options = [])
+    {
+        $this->data($data);
+        if (!empty($options)) {
+            $this->options = array_merge($this->options, $options);
+        }
+        $this->contentType($this->contentType, $this->charset);
+        $this->header = array_merge($this->header, $header);
+        $this->code   = $code;
+    }
+
+    /**
+     * 创建Response对象
+     * @access public
+     * @param mixed  $data    输出数据
+     * @param string $type    输出类型
+     * @param int    $code
+     * @param array  $header
+     * @param array  $options 输出参数
+     * @return Response|JsonResponse|ViewResponse|XmlResponse|RedirectResponse|JsonpResponse
+     */
+    public static function create($data = '', $type = '', $code = 200, array $header = [], $options = [])
+    {
+        $type = empty($type) ? 'null' : strtolower($type);
+
+        $class = false !== strpos($type, '\\') ? $type : '\\think\\response\\' . ucfirst($type);
+        if (class_exists($class)) {
+            $response = new $class($data, $code, $header, $options);
+        } else {
+            $response = new static($data, $code, $header, $options);
+        }
+
+        return $response;
+    }
+
+    /**
+     * 发送数据到客户端
+     * @access public
+     * @return mixed
+     * @throws \InvalidArgumentException
+     */
+    public function send()
+    {
+        // 监听response_send
+        Hook::listen('response_send', $this);
+
+        // 处理输出数据
+        $data = $this->getContent();
+
+        // Trace调试注入
+        if (Env::get('app_trace', Config::get('app_trace'))) {
+            Debug::inject($this, $data);
+        }
+
+        if (200 == $this->code) {
+            $cache = Request::instance()->getCache();
+            if ($cache) {
+                $this->header['Cache-Control'] = 'max-age=' . $cache[1] . ',must-revalidate';
+                $this->header['Last-Modified'] = gmdate('D, d M Y H:i:s') . ' GMT';
+                $this->header['Expires']       = gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME'] + $cache[1]) . ' GMT';
+                Cache::tag($cache[2])->set($cache[0], [$data, $this->header], $cache[1]);
+            }
+        }
+
+        if (!headers_sent() && !empty($this->header)) {
+            // 发送状态码
+            http_response_code($this->code);
+            // 发送头部信息
+            foreach ($this->header as $name => $val) {
+                if (is_null($val)) {
+                    header($name);
+                } else {
+                    header($name . ':' . $val);
+                }
+            }
+        }
+
+        echo $data;
+
+        if (function_exists('fastcgi_finish_request')) {
+            // 提高页面响应
+            fastcgi_finish_request();
+        }
+
+        // 监听response_end
+        Hook::listen('response_end', $this);
+
+        // 清空当次请求有效的数据
+        if (!($this instanceof RedirectResponse)) {
+            Session::flush();
+        }
+    }
+
+    /**
+     * 处理数据
+     * @access protected
+     * @param mixed $data 要处理的数据
+     * @return mixed
+     */
+    protected function output($data)
+    {
+        return $data;
+    }
+
+    /**
+     * 输出的参数
+     * @access public
+     * @param mixed $options 输出参数
+     * @return $this
+     */
+    public function options($options = [])
+    {
+        $this->options = array_merge($this->options, $options);
+        return $this;
+    }
+
+    /**
+     * 输出数据设置
+     * @access public
+     * @param mixed $data 输出数据
+     * @return $this
+     */
+    public function data($data)
+    {
+        $this->data = $data;
+        return $this;
+    }
+
+    /**
+     * 设置响应头
+     * @access public
+     * @param string|array $name  参数名
+     * @param string       $value 参数值
+     * @return $this
+     */
+    public function header($name, $value = null)
+    {
+        if (is_array($name)) {
+            $this->header = array_merge($this->header, $name);
+        } else {
+            $this->header[$name] = $value;
+        }
+        return $this;
+    }
+
+    /**
+     * 设置页面输出内容
+     * @param $content
+     * @return $this
+     */
+    public function content($content)
+    {
+        if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([
+            $content,
+            '__toString',
+        ])
+        ) {
+            throw new \InvalidArgumentException(sprintf('variable type error: %s', gettype($content)));
+        }
+
+        $this->content = (string) $content;
+
+        return $this;
+    }
+
+    /**
+     * 发送HTTP状态
+     * @param integer $code 状态码
+     * @return $this
+     */
+    public function code($code)
+    {
+        $this->code = $code;
+        return $this;
+    }
+
+    /**
+     * LastModified
+     * @param string $time
+     * @return $this
+     */
+    public function lastModified($time)
+    {
+        $this->header['Last-Modified'] = $time;
+        return $this;
+    }
+
+    /**
+     * Expires
+     * @param string $time
+     * @return $this
+     */
+    public function expires($time)
+    {
+        $this->header['Expires'] = $time;
+        return $this;
+    }
+
+    /**
+     * ETag
+     * @param string $eTag
+     * @return $this
+     */
+    public function eTag($eTag)
+    {
+        $this->header['ETag'] = $eTag;
+        return $this;
+    }
+
+    /**
+     * 页面缓存控制
+     * @param string $cache 状态码
+     * @return $this
+     */
+    public function cacheControl($cache)
+    {
+        $this->header['Cache-control'] = $cache;
+        return $this;
+    }
+
+    /**
+     * 页面输出类型
+     * @param string $contentType 输出类型
+     * @param string $charset     输出编码
+     * @return $this
+     */
+    public function contentType($contentType, $charset = 'utf-8')
+    {
+        $this->header['Content-Type'] = $contentType . '; charset=' . $charset;
+        return $this;
+    }
+
+    /**
+     * 获取头部信息
+     * @param string $name 头部名称
+     * @return mixed
+     */
+    public function getHeader($name = '')
+    {
+        if (!empty($name)) {
+            return isset($this->header[$name]) ? $this->header[$name] : null;
+        } else {
+            return $this->header;
+        }
+    }
+
+    /**
+     * 获取原始数据
+     * @return mixed
+     */
+    public function getData()
+    {
+        return $this->data;
+    }
+
+    /**
+     * 获取输出数据
+     * @return mixed
+     */
+    public function getContent()
+    {
+        if (null == $this->content) {
+            $content = $this->output($this->data);
+
+            if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([
+                $content,
+                '__toString',
+            ])
+            ) {
+                throw new \InvalidArgumentException(sprintf('variable type error: %s', gettype($content)));
+            }
+
+            $this->content = (string) $content;
+        }
+        return $this->content;
+    }
+
+    /**
+     * 获取状态码
+     * @return integer
+     */
+    public function getCode()
+    {
+        return $this->code;
+    }
+}

Різницю між файлами не показано, бо вона завелика
+ 1603 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Route.php


+ 366 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Session.php

@@ -0,0 +1,366 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+use think\exception\ClassNotFoundException;
+
+class Session
+{
+    protected static $prefix = '';
+    protected static $init   = null;
+
+    /**
+     * 设置或者获取session作用域(前缀)
+     * @param string $prefix
+     * @return string|void
+     */
+    public static function prefix($prefix = '')
+    {
+        empty(self::$init) && self::boot();
+        if (empty($prefix) && null !== $prefix) {
+            return self::$prefix;
+        } else {
+            self::$prefix = $prefix;
+        }
+    }
+
+    /**
+     * session初始化
+     * @param array $config
+     * @return void
+     * @throws \think\Exception
+     */
+    public static function init(array $config = [])
+    {
+        if (empty($config)) {
+            $config = Config::get('session');
+        }
+        // 记录初始化信息
+        App::$debug && Log::record('[ SESSION ] INIT ' . var_export($config, true), 'info');
+        $isDoStart = false;
+        if (isset($config['use_trans_sid'])) {
+            ini_set('session.use_trans_sid', $config['use_trans_sid'] ? 1 : 0);
+        }
+
+        // 启动session
+        if (!empty($config['auto_start']) && PHP_SESSION_ACTIVE != session_status()) {
+            ini_set('session.auto_start', 0);
+            $isDoStart = true;
+        }
+
+        if (isset($config['prefix']) && ('' === self::$prefix || null === self::$prefix)) {
+            self::$prefix = $config['prefix'];
+        }
+        if (isset($config['var_session_id']) && isset($_REQUEST[$config['var_session_id']])) {
+            session_id($_REQUEST[$config['var_session_id']]);
+        } elseif (isset($config['id']) && !empty($config['id'])) {
+            session_id($config['id']);
+        }
+        if (isset($config['name'])) {
+            session_name($config['name']);
+        }
+        if (isset($config['path'])) {
+            session_save_path($config['path']);
+        }
+        if (isset($config['domain'])) {
+            ini_set('session.cookie_domain', $config['domain']);
+        }
+        if (isset($config['expire'])) {
+            ini_set('session.gc_maxlifetime', $config['expire']);
+            ini_set('session.cookie_lifetime', $config['expire']);
+        }
+        if (isset($config['secure'])) {
+            ini_set('session.cookie_secure', $config['secure']);
+        }
+        if (isset($config['httponly'])) {
+            ini_set('session.cookie_httponly', $config['httponly']);
+        }
+        if (isset($config['use_cookies'])) {
+            ini_set('session.use_cookies', $config['use_cookies'] ? 1 : 0);
+        }
+        if (isset($config['cache_limiter'])) {
+            session_cache_limiter($config['cache_limiter']);
+        }
+        if (isset($config['cache_expire'])) {
+            session_cache_expire($config['cache_expire']);
+        }
+        if (!empty($config['type'])) {
+            // 读取session驱动
+            $class = false !== strpos($config['type'], '\\') ? $config['type'] : '\\think\\session\\driver\\' . ucwords($config['type']);
+
+            // 检查驱动类
+            if (!class_exists($class) || !session_set_save_handler(new $class($config))) {
+                throw new ClassNotFoundException('error session handler:' . $class, $class);
+            }
+        }
+        if ($isDoStart) {
+            session_start();
+            self::$init = true;
+        } else {
+            self::$init = false;
+        }
+    }
+
+    /**
+     * session自动启动或者初始化
+     * @return void
+     */
+    public static function boot()
+    {
+        if (is_null(self::$init)) {
+            self::init();
+        } elseif (false === self::$init) {
+            if (PHP_SESSION_ACTIVE != session_status()) {
+                session_start();
+            }
+            self::$init = true;
+        }
+    }
+
+    /**
+     * session设置
+     * @param string        $name session名称
+     * @param mixed         $value session值
+     * @param string|null   $prefix 作用域(前缀)
+     * @return void
+     */
+    public static function set($name, $value = '', $prefix = null)
+    {
+        empty(self::$init) && self::boot();
+
+        $prefix = !is_null($prefix) ? $prefix : self::$prefix;
+        if (strpos($name, '.')) {
+            // 二维数组赋值
+            list($name1, $name2) = explode('.', $name);
+            if ($prefix) {
+                $_SESSION[$prefix][$name1][$name2] = $value;
+            } else {
+                $_SESSION[$name1][$name2] = $value;
+            }
+        } elseif ($prefix) {
+            $_SESSION[$prefix][$name] = $value;
+        } else {
+            $_SESSION[$name] = $value;
+        }
+    }
+
+    /**
+     * session获取
+     * @param string        $name session名称
+     * @param string|null   $prefix 作用域(前缀)
+     * @return mixed
+     */
+    public static function get($name = '', $prefix = null)
+    {
+        empty(self::$init) && self::boot();
+        $prefix = !is_null($prefix) ? $prefix : self::$prefix;
+        if ('' == $name) {
+            // 获取全部的session
+            $value = $prefix ? (!empty($_SESSION[$prefix]) ? $_SESSION[$prefix] : []) : $_SESSION;
+        } elseif ($prefix) {
+            // 获取session
+            if (strpos($name, '.')) {
+                list($name1, $name2) = explode('.', $name);
+                $value               = isset($_SESSION[$prefix][$name1][$name2]) ? $_SESSION[$prefix][$name1][$name2] : null;
+            } else {
+                $value = isset($_SESSION[$prefix][$name]) ? $_SESSION[$prefix][$name] : null;
+            }
+        } else {
+            if (strpos($name, '.')) {
+                list($name1, $name2) = explode('.', $name);
+                $value               = isset($_SESSION[$name1][$name2]) ? $_SESSION[$name1][$name2] : null;
+            } else {
+                $value = isset($_SESSION[$name]) ? $_SESSION[$name] : null;
+            }
+        }
+        return $value;
+    }
+
+    /**
+     * session获取并删除
+     * @param string        $name session名称
+     * @param string|null   $prefix 作用域(前缀)
+     * @return mixed
+     */
+    public static function pull($name, $prefix = null)
+    {
+        $result = self::get($name, $prefix);
+        if ($result) {
+            self::delete($name, $prefix);
+            return $result;
+        } else {
+            return;
+        }
+    }
+
+    /**
+     * session设置 下一次请求有效
+     * @param string        $name session名称
+     * @param mixed         $value session值
+     * @param string|null   $prefix 作用域(前缀)
+     * @return void
+     */
+    public static function flash($name, $value)
+    {
+        self::set($name, $value);
+        if (!self::has('__flash__.__time__')) {
+            self::set('__flash__.__time__', $_SERVER['REQUEST_TIME_FLOAT']);
+        }
+        self::push('__flash__', $name);
+    }
+
+    /**
+     * 清空当前请求的session数据
+     * @return void
+     */
+    public static function flush()
+    {
+        if (self::$init) {
+            $item = self::get('__flash__');
+
+            if (!empty($item)) {
+                $time = $item['__time__'];
+                if ($_SERVER['REQUEST_TIME_FLOAT'] > $time) {
+                    unset($item['__time__']);
+                    self::delete($item);
+                    self::set('__flash__', []);
+                }
+            }
+        }
+    }
+
+    /**
+     * 删除session数据
+     * @param string|array  $name session名称
+     * @param string|null   $prefix 作用域(前缀)
+     * @return void
+     */
+    public static function delete($name, $prefix = null)
+    {
+        empty(self::$init) && self::boot();
+        $prefix = !is_null($prefix) ? $prefix : self::$prefix;
+        if (is_array($name)) {
+            foreach ($name as $key) {
+                self::delete($key, $prefix);
+            }
+        } elseif (strpos($name, '.')) {
+            list($name1, $name2) = explode('.', $name);
+            if ($prefix) {
+                unset($_SESSION[$prefix][$name1][$name2]);
+            } else {
+                unset($_SESSION[$name1][$name2]);
+            }
+        } else {
+            if ($prefix) {
+                unset($_SESSION[$prefix][$name]);
+            } else {
+                unset($_SESSION[$name]);
+            }
+        }
+    }
+
+    /**
+     * 清空session数据
+     * @param string|null   $prefix 作用域(前缀)
+     * @return void
+     */
+    public static function clear($prefix = null)
+    {
+        empty(self::$init) && self::boot();
+        $prefix = !is_null($prefix) ? $prefix : self::$prefix;
+        if ($prefix) {
+            unset($_SESSION[$prefix]);
+        } else {
+            $_SESSION = [];
+        }
+    }
+
+    /**
+     * 判断session数据
+     * @param string        $name session名称
+     * @param string|null   $prefix
+     * @return bool
+     */
+    public static function has($name, $prefix = null)
+    {
+        empty(self::$init) && self::boot();
+        $prefix = !is_null($prefix) ? $prefix : self::$prefix;
+        if (strpos($name, '.')) {
+            // 支持数组
+            list($name1, $name2) = explode('.', $name);
+            return $prefix ? isset($_SESSION[$prefix][$name1][$name2]) : isset($_SESSION[$name1][$name2]);
+        } else {
+            return $prefix ? isset($_SESSION[$prefix][$name]) : isset($_SESSION[$name]);
+        }
+    }
+
+    /**
+     * 添加数据到一个session数组
+     * @param  string  $key
+     * @param  mixed   $value
+     * @return void
+     */
+    public static function push($key, $value)
+    {
+        $array = self::get($key);
+        if (is_null($array)) {
+            $array = [];
+        }
+        $array[] = $value;
+        self::set($key, $array);
+    }
+
+    /**
+     * 启动session
+     * @return void
+     */
+    public static function start()
+    {
+        session_start();
+        self::$init = true;
+    }
+
+    /**
+     * 销毁session
+     * @return void
+     */
+    public static function destroy()
+    {
+        if (!empty($_SESSION)) {
+            $_SESSION = [];
+        }
+        session_unset();
+        session_destroy();
+        self::$init = null;
+    }
+
+    /**
+     * 重新生成session_id
+     * @param bool $delete 是否删除关联会话文件
+     * @return void
+     */
+    public static function regenerate($delete = false)
+    {
+        session_regenerate_id($delete);
+    }
+
+    /**
+     * 暂停session
+     * @return void
+     */
+    public static function pause()
+    {
+        // 暂停session
+        session_write_close();
+        self::$init = false;
+    }
+}

Різницю між файлами не показано, бо вона завелика
+ 1147 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Template.php


+ 329 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Url.php

@@ -0,0 +1,329 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think;
+
+class Url
+{
+    // 生成URL地址的root
+    protected static $root;
+    protected static $bindCheck;
+
+    /**
+     * URL生成 支持路由反射
+     * @param string            $url 路由地址
+     * @param string|array      $vars 参数(支持数组和字符串)a=val&b=val2... ['a'=>'val1', 'b'=>'val2']
+     * @param string|bool       $suffix 伪静态后缀,默认为true表示获取配置值
+     * @param boolean|string    $domain 是否显示域名 或者直接传入域名
+     * @return string
+     */
+    public static function build($url = '', $vars = '', $suffix = true, $domain = false)
+    {
+        if (false === $domain && Route::rules('domain')) {
+            $domain = true;
+        }
+        // 解析URL
+        if (0 === strpos($url, '[') && $pos = strpos($url, ']')) {
+            // [name] 表示使用路由命名标识生成URL
+            $name = substr($url, 1, $pos - 1);
+            $url  = 'name' . substr($url, $pos + 1);
+        }
+        if (false === strpos($url, '://') && 0 !== strpos($url, '/')) {
+            $info = parse_url($url);
+            $url  = !empty($info['path']) ? $info['path'] : '';
+            if (isset($info['fragment'])) {
+                // 解析锚点
+                $anchor = $info['fragment'];
+                if (false !== strpos($anchor, '?')) {
+                    // 解析参数
+                    list($anchor, $info['query']) = explode('?', $anchor, 2);
+                }
+                if (false !== strpos($anchor, '@')) {
+                    // 解析域名
+                    list($anchor, $domain) = explode('@', $anchor, 2);
+                }
+            } elseif (strpos($url, '@') && false === strpos($url, '\\')) {
+                // 解析域名
+                list($url, $domain) = explode('@', $url, 2);
+            }
+        }
+
+        // 解析参数
+        if (is_string($vars)) {
+            // aaa=1&bbb=2 转换成数组
+            parse_str($vars, $vars);
+        }
+
+        if ($url) {
+            $rule = Route::name(isset($name) ? $name : $url . (isset($info['query']) ? '?' . $info['query'] : ''));
+            if (is_null($rule) && isset($info['query'])) {
+                $rule = Route::name($url);
+                // 解析地址里面参数 合并到vars
+                parse_str($info['query'], $params);
+                $vars = array_merge($params, $vars);
+                unset($info['query']);
+            }
+        }
+        if (!empty($rule) && $match = self::getRuleUrl($rule, $vars)) {
+            // 匹配路由命名标识
+            $url = $match[0];
+            // 替换可选分隔符
+            $url = preg_replace(['/(\W)\?$/', '/(\W)\?/'], ['', '\1'], $url);
+            if (!empty($match[1])) {
+                $domain = $match[1];
+            }
+            if (!is_null($match[2])) {
+                $suffix = $match[2];
+            }
+        } elseif (!empty($rule) && isset($name)) {
+            throw new \InvalidArgumentException('route name not exists:' . $name);
+        } else {
+            // 检查别名路由
+            $alias      = Route::rules('alias');
+            $matchAlias = false;
+            if ($alias) {
+                // 别名路由解析
+                foreach ($alias as $key => $val) {
+                    if (is_array($val)) {
+                        $val = $val[0];
+                    }
+                    if (0 === strpos($url, $val)) {
+                        $url        = $key . substr($url, strlen($val));
+                        $matchAlias = true;
+                        break;
+                    }
+                }
+            }
+            if (!$matchAlias) {
+                // 路由标识不存在 直接解析
+                $url = self::parseUrl($url, $domain);
+            }
+            if (isset($info['query'])) {
+                // 解析地址里面参数 合并到vars
+                parse_str($info['query'], $params);
+                $vars = array_merge($params, $vars);
+            }
+        }
+
+        // 检测URL绑定
+        if (!self::$bindCheck) {
+            $type = Route::getBind('type');
+            if ($type) {
+                $bind = Route::getBind($type);
+                if (0 === strpos($url, $bind)) {
+                    $url = substr($url, strlen($bind) + 1);
+                }
+            }
+        }
+        // 还原URL分隔符
+        $depr = Config::get('pathinfo_depr');
+        $url  = str_replace('/', $depr, $url);
+
+        // URL后缀
+        $suffix = in_array($url, ['/', '']) ? '' : self::parseSuffix($suffix);
+        // 锚点
+        $anchor = !empty($anchor) ? '#' . $anchor : '';
+        // 参数组装
+        if (!empty($vars)) {
+            // 添加参数
+            if (Config::get('url_common_param')) {
+                $vars = http_build_query($vars);
+                $url .= $suffix . '?' . $vars . $anchor;
+            } else {
+                $paramType = Config::get('url_param_type');
+                foreach ($vars as $var => $val) {
+                    if ('' !== trim($val)) {
+                        if ($paramType) {
+                            $url .= $depr . urlencode($val);
+                        } else {
+                            $url .= $depr . $var . $depr . urlencode($val);
+                        }
+                    }
+                }
+                $url .= $suffix . $anchor;
+            }
+        } else {
+            $url .= $suffix . $anchor;
+        }
+        // 检测域名
+        $domain = self::parseDomain($url, $domain);
+        // URL组装
+        $url = $domain . rtrim(self::$root ?: Request::instance()->root(), '/') . '/' . ltrim($url, '/');
+
+        self::$bindCheck = false;
+        return $url;
+    }
+
+    // 直接解析URL地址
+    protected static function parseUrl($url, &$domain)
+    {
+        $request = Request::instance();
+        if (0 === strpos($url, '/')) {
+            // 直接作为路由地址解析
+            $url = substr($url, 1);
+        } elseif (false !== strpos($url, '\\')) {
+            // 解析到类
+            $url = ltrim(str_replace('\\', '/', $url), '/');
+        } elseif (0 === strpos($url, '@')) {
+            // 解析到控制器
+            $url = substr($url, 1);
+        } else {
+            // 解析到 模块/控制器/操作
+            $module  = $request->module();
+            $domains = Route::rules('domain');
+            if (true === $domain && 2 == substr_count($url, '/')) {
+                $current = $request->host();
+                $match   = [];
+                $pos     = [];
+                foreach ($domains as $key => $item) {
+                    if (isset($item['[bind]']) && 0 === strpos($url, $item['[bind]'][0])) {
+                        $pos[$key] = strlen($item['[bind]'][0]) + 1;
+                        $match[]   = $key;
+                        $module    = '';
+                    }
+                }
+                if ($match) {
+                    $domain = current($match);
+                    foreach ($match as $item) {
+                        if (0 === strpos($current, $item)) {
+                            $domain = $item;
+                        }
+                    }
+                    self::$bindCheck = true;
+                    $url             = substr($url, $pos[$domain]);
+                }
+            } elseif ($domain) {
+                if (isset($domains[$domain]['[bind]'][0])) {
+                    $bindModule = $domains[$domain]['[bind]'][0];
+                    if ($bindModule && !in_array($bindModule[0], ['\\', '@'])) {
+                        $module = '';
+                    }
+                }
+            }
+            $module = $module ? $module . '/' : '';
+
+            $controller = Loader::parseName($request->controller());
+            if ('' == $url) {
+                // 空字符串输出当前的 模块/控制器/操作
+                $url = $module . $controller . '/' . $request->action();
+            } else {
+                $path       = explode('/', $url);
+                $action     = Config::get('url_convert') ? strtolower(array_pop($path)) : array_pop($path);
+                $controller = empty($path) ? $controller : (Config::get('url_convert') ? Loader::parseName(array_pop($path)) : array_pop($path));
+                $module     = empty($path) ? $module : array_pop($path) . '/';
+                $url        = $module . $controller . '/' . $action;
+            }
+        }
+        return $url;
+    }
+
+    // 检测域名
+    protected static function parseDomain(&$url, $domain)
+    {
+        if (!$domain) {
+            return '';
+        }
+        $request    = Request::instance();
+        $rootDomain = Config::get('url_domain_root');
+        if (true === $domain) {
+            // 自动判断域名
+            $domain = Config::get('app_host') ?: $request->host();
+
+            $domains = Route::rules('domain');
+            if ($domains) {
+                $route_domain = array_keys($domains);
+                foreach ($route_domain as $domain_prefix) {
+                    if (0 === strpos($domain_prefix, '*.') && strpos($domain, ltrim($domain_prefix, '*.')) !== false) {
+                        foreach ($domains as $key => $rule) {
+                            $rule = is_array($rule) ? $rule[0] : $rule;
+                            if (is_string($rule) && false === strpos($key, '*') && 0 === strpos($url, $rule)) {
+                                $url    = ltrim($url, $rule);
+                                $domain = $key;
+                                // 生成对应子域名
+                                if (!empty($rootDomain)) {
+                                    $domain .= $rootDomain;
+                                }
+                                break;
+                            } elseif (false !== strpos($key, '*')) {
+                                if (!empty($rootDomain)) {
+                                    $domain .= $rootDomain;
+                                }
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+
+        } else {
+            if (empty($rootDomain)) {
+                $host       = Config::get('app_host') ?: $request->host();
+                $rootDomain = substr_count($host, '.') > 1 ? substr(strstr($host, '.'), 1) : $host;
+            }
+            if (substr_count($domain, '.') < 2 && !strpos($domain, $rootDomain)) {
+                $domain .= '.' . $rootDomain;
+            }
+        }
+        if (false !== strpos($domain, '://')) {
+            $scheme = '';
+        } else {
+            $scheme = $request->isSsl() || Config::get('is_https') ? 'https://' : 'http://';
+        }
+        return $scheme . $domain;
+    }
+
+    // 解析URL后缀
+    protected static function parseSuffix($suffix)
+    {
+        if ($suffix) {
+            $suffix = true === $suffix ? Config::get('url_html_suffix') : $suffix;
+            if ($pos = strpos($suffix, '|')) {
+                $suffix = substr($suffix, 0, $pos);
+            }
+        }
+        return (empty($suffix) || 0 === strpos($suffix, '.')) ? $suffix : '.' . $suffix;
+    }
+
+    // 匹配路由地址
+    public static function getRuleUrl($rule, &$vars = [])
+    {
+        foreach ($rule as $item) {
+            list($url, $pattern, $domain, $suffix) = $item;
+            if (empty($pattern)) {
+                return [$url, $domain, $suffix];
+            }
+            $type = Config::get('url_common_param');
+            foreach ($pattern as $key => $val) {
+                if (isset($vars[$key])) {
+                    $url = str_replace(['[:' . $key . ']', '<' . $key . '?>', ':' . $key . '', '<' . $key . '>'], $type ? $vars[$key] : urlencode($vars[$key]), $url);
+                    unset($vars[$key]);
+                    $result = [$url, $domain, $suffix];
+                } elseif (2 == $val) {
+                    $url    = str_replace(['/[:' . $key . ']', '[:' . $key . ']', '<' . $key . '?>'], '', $url);
+                    $result = [$url, $domain, $suffix];
+                } else {
+                    break;
+                }
+            }
+            if (isset($result)) {
+                return $result;
+            }
+        }
+        return false;
+    }
+
+    // 指定当前生成URL地址的root
+    public static function root($root)
+    {
+        self::$root = $root;
+        Request::instance()->root($root);
+    }
+}

Різницю між файлами не показано, бо вона завелика
+ 1294 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/Validate.php


+ 0 - 0
Thinkphp5整合excel导入导出/thinkphp/library/think/View.php


Деякі файли не було показано, через те що забагато файлів було змінено