瀏覽代碼

初始化

moonsflyer 10 月之前
父節點
當前提交
97c2c14e8d
共有 100 個文件被更改,包括 26837 次插入0 次删除
  1. 11 0
      .bowerrc
  2. 11 0
      .env
  3. 11 0
      .env.sample
  4. 1 0
      .gitignore
  5. 1 0
      .htaccess
  6. 7 0
      404.html
  7. 191 0
      LICENSE
  8. 93 0
      README.md
  9. 1 0
      addons/.gitkeep
  10. 1 0
      addons/.htaccess
  11. 0 0
      addons/qingdong/.addonrc
  12. 134 0
      addons/qingdong/Qingdong.php
  13. 二進制
      addons/qingdong/__MACOSX/uniapp/._crm.zip
  14. 23 0
      addons/qingdong/config.php
  15. 57 0
      addons/qingdong/config/cache.php
  16. 8951 0
      addons/qingdong/config/menu.php
  17. 361 0
      addons/qingdong/controller/Achievement.php
  18. 216 0
      addons/qingdong/controller/Approval.php
  19. 1355 0
      addons/qingdong/controller/Attendance.php
  20. 713 0
      addons/qingdong/controller/Autotask.php
  21. 298 0
      addons/qingdong/controller/Business.php
  22. 172 0
      addons/qingdong/controller/Common.php
  23. 142 0
      addons/qingdong/controller/Consume.php
  24. 200 0
      addons/qingdong/controller/Contacts.php
  25. 362 0
      addons/qingdong/controller/Contract.php
  26. 564 0
      addons/qingdong/controller/Customer.php
  27. 327 0
      addons/qingdong/controller/Daily.php
  28. 23 0
      addons/qingdong/controller/ErrorCode.php
  29. 206 0
      addons/qingdong/controller/Event.php
  30. 257 0
      addons/qingdong/controller/ExamineRecord.php
  31. 30 0
      addons/qingdong/controller/File.php
  32. 463 0
      addons/qingdong/controller/Index.php
  33. 258 0
      addons/qingdong/controller/Leads.php
  34. 199 0
      addons/qingdong/controller/Leadspool.php
  35. 250 0
      addons/qingdong/controller/Message.php
  36. 52 0
      addons/qingdong/controller/Notice.php
  37. 29 0
      addons/qingdong/controller/Operation.php
  38. 156 0
      addons/qingdong/controller/Product.php
  39. 207 0
      addons/qingdong/controller/Receivables.php
  40. 112 0
      addons/qingdong/controller/ReceivablesPlan.php
  41. 368 0
      addons/qingdong/controller/Record.php
  42. 103 0
      addons/qingdong/controller/Setting.php
  43. 595 0
      addons/qingdong/controller/Staff.php
  44. 325 0
      addons/qingdong/controller/StaffApi.php
  45. 906 0
      addons/qingdong/controller/Statistics.php
  46. 55 0
      addons/qingdong/controller/Wx.php
  47. 68 0
      addons/qingdong/controller/Wxbizdatacrypt.php
  48. 532 0
      addons/qingdong/helper.php
  49. 10 0
      addons/qingdong/info.ini
  50. 1268 0
      addons/qingdong/install.sql
  51. 3 0
      addons/qingdong/lang/zh-cn.php
  52. 38 0
      addons/qingdong/lang/zh-cn/staff.php
  53. 100 0
      addons/qingdong/library/Ding.php
  54. 113 0
      addons/qingdong/library/Ku.php
  55. 95 0
      addons/qingdong/library/PhpWord/Collection/AbstractCollection.php
  56. 27 0
      addons/qingdong/library/PhpWord/Collection/Bookmarks.php
  57. 27 0
      addons/qingdong/library/PhpWord/Collection/Charts.php
  58. 27 0
      addons/qingdong/library/PhpWord/Collection/Comments.php
  59. 27 0
      addons/qingdong/library/PhpWord/Collection/Endnotes.php
  60. 27 0
      addons/qingdong/library/PhpWord/Collection/Footnotes.php
  61. 27 0
      addons/qingdong/library/PhpWord/Collection/Titles.php
  62. 181 0
      addons/qingdong/library/PhpWord/ComplexType/FootnoteProperties.php
  63. 106 0
      addons/qingdong/library/PhpWord/ComplexType/ProofState.php
  64. 59 0
      addons/qingdong/library/PhpWord/ComplexType/TblWidth.php
  65. 166 0
      addons/qingdong/library/PhpWord/ComplexType/TrackChangesView.php
  66. 316 0
      addons/qingdong/library/PhpWord/Element/AbstractContainer.php
  67. 507 0
      addons/qingdong/library/PhpWord/Element/AbstractElement.php
  68. 60 0
      addons/qingdong/library/PhpWord/Element/Bookmark.php
  69. 77 0
      addons/qingdong/library/PhpWord/Element/Cell.php
  70. 129 0
      addons/qingdong/library/PhpWord/Element/Chart.php
  71. 72 0
      addons/qingdong/library/PhpWord/Element/CheckBox.php
  72. 122 0
      addons/qingdong/library/PhpWord/Element/Comment.php
  73. 41 0
      addons/qingdong/library/PhpWord/Element/Endnote.php
  74. 299 0
      addons/qingdong/library/PhpWord/Element/Field.php
  75. 116 0
      addons/qingdong/library/PhpWord/Element/Footer.php
  76. 89 0
      addons/qingdong/library/PhpWord/Element/Footnote.php
  77. 195 0
      addons/qingdong/library/PhpWord/Element/FormField.php
  78. 41 0
      addons/qingdong/library/PhpWord/Element/Header.php
  79. 602 0
      addons/qingdong/library/PhpWord/Element/Image.php
  80. 53 0
      addons/qingdong/library/PhpWord/Element/Line.php
  81. 180 0
      addons/qingdong/library/PhpWord/Element/Link.php
  82. 111 0
      addons/qingdong/library/PhpWord/Element/ListItem.php
  83. 85 0
      addons/qingdong/library/PhpWord/Element/ListItemRun.php
  84. 169 0
      addons/qingdong/library/PhpWord/Element/OLEObject.php
  85. 31 0
      addons/qingdong/library/PhpWord/Element/PageBreak.php
  86. 98 0
      addons/qingdong/library/PhpWord/Element/PreserveText.php
  87. 107 0
      addons/qingdong/library/PhpWord/Element/Row.php
  88. 190 0
      addons/qingdong/library/PhpWord/Element/SDT.php
  89. 307 0
      addons/qingdong/library/PhpWord/Element/Section.php
  90. 88 0
      addons/qingdong/library/PhpWord/Element/Shape.php
  91. 169 0
      addons/qingdong/library/PhpWord/Element/TOC.php
  92. 174 0
      addons/qingdong/library/PhpWord/Element/Table.php
  93. 153 0
      addons/qingdong/library/PhpWord/Element/Text.php
  94. 60 0
      addons/qingdong/library/PhpWord/Element/TextBox.php
  95. 130 0
      addons/qingdong/library/PhpWord/Element/TextBreak.php
  96. 80 0
      addons/qingdong/library/PhpWord/Element/TextRun.php
  97. 108 0
      addons/qingdong/library/PhpWord/Element/Title.php
  98. 101 0
      addons/qingdong/library/PhpWord/Element/TrackChange.php
  99. 46 0
      addons/qingdong/library/PhpWord/Escaper/AbstractEscaper.php
  100. 33 0
      addons/qingdong/library/PhpWord/Escaper/EscaperInterface.php

+ 11 - 0
.bowerrc

@@ -0,0 +1,11 @@
+{
+  "directory": "public/assets/libs",
+  "ignoredDependencies": [
+    "es6-promise",
+    "file-saver",
+    "html2canvas",
+    "jspdf",
+    "jspdf-autotable",
+    "pdfmake"
+  ]
+}

+ 11 - 0
.env

@@ -0,0 +1,11 @@
+[app]
+debug = false
+trace = false
+
+[database]
+hostname = 127.0.0.1
+database = crm
+username = crm
+password = crm2025
+hostport = 3306
+prefix = fa_

+ 11 - 0
.env.sample

@@ -0,0 +1,11 @@
+[app]
+debug = false
+trace = false
+
+[database]
+hostname = 127.0.0.1
+database = fastadmin
+username = root
+password = root
+hostport = 3306
+prefix = fa_

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+/runtime/*

+ 1 - 0
.htaccess

@@ -0,0 +1 @@
+ 

+ 7 - 0
404.html

@@ -0,0 +1,7 @@
+<html>
+<head><title>404 Not Found</title></head>
+<body>
+<center><h1>404 Not Found</h1></center>
+<hr><center>nginx</center>
+</body>
+</html>

+ 191 - 0
LICENSE

@@ -0,0 +1,191 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work
+
+To apply the Apache License to your work, attach the following boilerplate
+notice, with the fields enclosed by brackets "{}" replaced with your own
+identifying information. (Don't include the brackets!) The text should be
+enclosed in the appropriate comment syntax for the file format. We also
+recommend that a file or class name and description of purpose be included on
+the same "printed page" as the copyright notice for easier identification within
+third-party archives.
+
+   Copyright 2017 Karson
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 93 - 0
README.md

@@ -0,0 +1,93 @@
+FastAdmin是一款基于ThinkPHP+Bootstrap的极速后台开发框架。
+
+
+## 主要特性
+
+* 基于`Auth`验证的权限管理系统
+    * 支持无限级父子级权限继承,父级的管理员可任意增删改子级管理员及权限设置
+    * 支持单管理员多角色
+    * 支持管理子级数据或个人数据
+* 强大的一键生成功能
+    * 一键生成CRUD,包括控制器、模型、视图、JS、语言包、菜单、回收站等
+    * 一键压缩打包JS和CSS文件,一键CDN静态资源部署
+    * 一键生成控制器菜单和规则
+    * 一键生成API接口文档
+* 完善的前端功能组件开发
+    * 基于`AdminLTE`二次开发
+    * 基于`Bootstrap`开发,自适应手机、平板、PC
+    * 基于`RequireJS`进行JS模块管理,按需加载
+    * 基于`Less`进行样式开发
+* 强大的插件扩展功能,在线安装卸载升级插件
+* 通用的会员模块和API模块
+* 共用同一账号体系的Web端会员中心权限验证和API接口会员权限验证
+* 二级域名部署支持,同时域名支持绑定到应用插件
+* 多语言支持,服务端及客户端支持
+* 支持大文件分片上传、剪切板粘贴上传、拖拽上传,进度条显示,图片上传前压缩
+* 支持表格固定列、固定表头、跨页选择、Excel导出、模板渲染等功能
+* 强大的第三方应用模块支持([CMS](https://www.fastadmin.net/store/cms.html)、[CRM](https://www.fastadmin.net/store/facrm.html)、[企业网站管理系统](https://www.fastadmin.net/store/ldcms.html)、[知识库文档系统](https://www.fastadmin.net/store/knowbase.html)、[在线投票系统](https://www.fastadmin.net/store/vote.html)、[B2C商城](https://www.fastadmin.net/store/shopro.html)、[B2B2C商城](https://www.fastadmin.net/store/wanlshop.html))
+* 整合第三方短信接口(阿里云、腾讯云短信)
+* 无缝整合第三方云存储(七牛云、阿里云OSS、腾讯云存储、又拍云)功能,支持云储存分片上传
+* 第三方富文本编辑器支持(Summernote、百度编辑器)
+* 第三方登录(QQ、微信、微博)整合
+* 第三方支付(微信、支付宝)无缝整合,微信支持PC端扫码支付
+* 丰富的插件应用市场
+
+## 安装使用
+
+https://doc.fastadmin.net
+
+## 在线演示
+
+https://demo.fastadmin.net
+
+用户名:admin
+
+密 码:123456
+
+提 示:演示站数据无法进行修改,请下载源码安装体验全部功能
+
+## 界面截图
+![控制台](https://images.gitee.com/uploads/images/2020/0929/202947_8db2d281_10933.gif "控制台")
+
+## 问题反馈
+
+在使用中有任何问题,请使用以下联系方式联系我们
+
+问答社区: https://ask.fastadmin.net
+
+Github: https://github.com/karsonzhang/fastadmin
+
+Gitee: https://gitee.com/karson/fastadmin
+
+## 特别鸣谢
+
+感谢以下的项目,排名不分先后
+
+ThinkPHP:http://www.thinkphp.cn
+
+AdminLTE:https://adminlte.io
+
+Bootstrap:http://getbootstrap.com
+
+jQuery:http://jquery.com
+
+Bootstrap-table:https://github.com/wenzhixin/bootstrap-table
+
+Nice-validator: https://validator.niceue.com
+
+SelectPage: https://github.com/TerryZ/SelectPage
+
+Layer: https://layuion.com/layer/
+
+DropzoneJS: https://www.dropzonejs.com
+
+
+## 版权信息
+
+FastAdmin遵循Apache2开源协议发布,并提供免费使用。
+
+本项目包含的第三方源码和二进制文件之版权信息另行标注。
+
+版权所有Copyright © 2017-2024 by FastAdmin (https://www.fastadmin.net)
+
+All rights reserved。

+ 1 - 0
addons/.gitkeep

@@ -0,0 +1 @@
+

+ 1 - 0
addons/.htaccess

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

文件差異過大導致無法顯示
+ 0 - 0
addons/qingdong/.addonrc


+ 134 - 0
addons/qingdong/Qingdong.php

@@ -0,0 +1,134 @@
+<?php
+
+namespace addons\qingdong;
+
+use app\admin\model\AuthRule;
+use app\common\library\Menu;
+use think\Addons;
+use think\Exception;
+use think\exception\PDOException;
+
+
+/**
+ * 插件
+ */
+class Qingdong extends Addons
+{
+
+    /**
+     * 插件安装方法
+     * @return bool
+     */
+    public function install()
+    {
+        $menu = self::getMenu();
+        Menu::create($menu['new']);
+        return true;
+    }
+
+    /**
+     * 插件卸载方法
+     * @return bool
+     */
+    public function uninstall()
+    {
+        Menu::delete('qingdong');
+        return true;
+    }
+
+    /**
+     * 插件启用方法
+     * @return bool
+     */
+    public function enable()
+    {
+        Menu::enable('qingdong');
+        return true;
+    }
+
+    /**
+     * 插件禁用方法
+     * @return bool
+     */
+    public function disable()
+    {
+        Menu::disable('qingdong');
+        return true;
+    }
+
+    /**
+     * 插件更新方法
+     */
+    public function upgrade()
+    {
+        $menu = self::getMenu();
+        if (method_exists(Menu::class, 'upgrade')) {
+            Menu::upgrade('qingdong', $menu['new']);
+        } else {
+            self::menuCreateOrUpdate($menu['new'], $menu['old']);
+        }
+
+        return true;
+    }
+
+    private static function getMenu()
+    {
+        $newMenu = [];
+        $config_file = ADDON_PATH . "qingdong" . DS . 'config' . DS . "menu.php";
+        if (is_file($config_file)) {
+            $newMenu = include $config_file;
+        }
+        $oldMenu = AuthRule::where('name', 'like', "qingdong%")->select();
+        $oldMenu = array_column($oldMenu, null, 'name');
+        return ['new' => $newMenu, 'old' => $oldMenu];
+    }
+
+    private static function menuCreateOrUpdate($newMenu, $oldMenu, $parent = 0)
+    {
+        if (!is_numeric($parent)) {
+            $parentRule = AuthRule::getByName($parent);
+            $pid = $parentRule ? $parentRule['id'] : 0;
+        } else {
+            $pid = $parent;
+        }
+        $allow = array_flip(['file', 'name', 'title', 'icon', 'condition', 'remark', 'ismenu', 'weigh']);
+        foreach ($newMenu as $k => $v) {
+            $hasChild = isset($v['sublist']) && $v['sublist'] ? true : false;
+            $data = array_intersect_key($v, $allow);
+            $data['ismenu'] = isset($data['ismenu']) ? $data['ismenu'] : ($hasChild ? 1 : 0);
+            $data['icon'] = isset($data['icon']) ? $data['icon'] : ($hasChild ? 'fa fa-list' : 'fa fa-circle-o');
+            $data['pid'] = $pid;
+            $data['status'] = 'normal';
+            try {
+                if (!isset($oldMenu[$data['name']])) {
+                    $menu = AuthRule::create($data);
+                } else {
+                    $menu = $oldMenu[$data['name']];
+                }
+                if ($hasChild) {
+                    self::menuCreateOrUpdate($v['sublist'], $oldMenu, $menu['id']);
+                }
+            } catch (PDOException $e) {
+                throw new Exception($e->getMessage());
+            }
+        }
+    }
+
+    /**
+     * 应用初始化
+     */
+    public function appInit()
+    {
+        // 公共方法
+        require_once __DIR__ . '/helper.php';
+        if(!class_exists("\dingding\TopSdk")){
+            \think\Loader::addNamespace('dingding', ADDON_PATH . 'qingdong' . DS . 'library' . DS . 'dingding' . DS);
+        }
+        if(!class_exists("\WeWork\App")){
+            \think\Loader::addNamespace('WeWork', ADDON_PATH . 'qingdong' . DS . 'library' . DS . 'wework' . DS);
+        }
+        if(!class_exists("\PhpOffice\PhpWord\PhpWord")){
+            \think\Loader::addNamespace('PhpOffice\PhpWord', ADDON_PATH . 'qingdong' . DS . 'library' . DS . 'PhpWord' . DS);
+        }
+    }
+}

二進制
addons/qingdong/__MACOSX/uniapp/._crm.zip


+ 23 - 0
addons/qingdong/config.php

@@ -0,0 +1,23 @@
+<?php
+
+return [
+    [
+        //配置名称,该值在当前数组配置中确保唯一
+        'name'    => 'mobile_name',
+        //配置标题
+        'title'   => '网站名称',
+        //配置类型,支持string/text/number/datetime/array/select/selects/image/images/file/files/checkbox/radio/bool
+        'type'    => 'string',
+        //分组选项卡
+        'group'    => '分组1',
+        //配置值
+        'value'   => 'CRM',
+        //配置验证规则,更之规则可参考nice-validator文件
+        'rule'    => 'required',
+        'msg'     => '请输入网站名称',
+        'tip'     => 'h5或小程序登录页标题',
+        'ok'      => '验证成功',
+        'extend'  => ''
+    ],
+
+];

文件差異過大導致無法顯示
+ 57 - 0
addons/qingdong/config/cache.php


+ 8951 - 0
addons/qingdong/config/menu.php

@@ -0,0 +1,8951 @@
+<?php
+/**
+ * 菜单配置文件
+ */
+
+return array (
+  0 => 
+  array (
+    'type' => 'file',
+    'name' => 'qingdong',
+    'title' => '青动CRM',
+    'icon' => 'fa fa-home',
+    'url' => '',
+    'condition' => '',
+    'remark' => '',
+    'ismenu' => 1,
+    'menutype' => 'addtabs',
+    'extend' => '',
+    'py' => 'qdC',
+    'pinyin' => 'qingdongCRM',
+    'weigh' => 999,
+    'sublist' => 
+    array (
+      0 => 
+      array (
+        'type' => 'file',
+        'name' => 'qingdong/department',
+        'title' => '员工管理',
+        'icon' => 'fa fa-paint-brush',
+        'url' => '',
+        'condition' => '',
+        'remark' => '',
+        'ismenu' => 1,
+        'menutype' => NULL,
+        'extend' => '',
+        'py' => 'yggl',
+        'pinyin' => 'yuangongguanli',
+        'weigh' => 10,
+        'sublist' => 
+        array (
+          0 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/department/group',
+            'title' => '组织架构',
+            'icon' => 'fa fa-group',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'zzjg',
+            'pinyin' => 'zuzhijiagou',
+            'weigh' => 109,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/group/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/group/edit',
+                'title' => '修改',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xg',
+                'pinyin' => 'xiugai',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/group/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/group/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/group/roletree',
+                'title' => '角色树',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'jss',
+                'pinyin' => 'jueseshu',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          1 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/department/staff',
+            'title' => '员工管理',
+            'icon' => 'fa fa-address-card-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'yggl',
+            'pinyin' => 'yuangongguanli',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/staff/index',
+                'title' => '首页',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sy',
+                'pinyin' => 'shouye',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/staff/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/staff/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/staff/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/staff/update_status',
+                'title' => '修改状态',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xgzt',
+                'pinyin' => 'xiugaizhuangtai',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          2 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/department/role',
+            'title' => '角色管理',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'jsgl',
+            'pinyin' => 'jueseguanli',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/role/rule',
+                'title' => '权限配置',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'qxpz',
+                'pinyin' => 'quanxianpeizhi',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/role/roletree',
+                'title' => '获取菜单',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqcd',
+                'pinyin' => 'huoqucaidan',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/role/getstaff',
+                'title' => 'GetStaff',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'G',
+                'pinyin' => 'GetStaff',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/role/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/role/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/role/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/role/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/role/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              8 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/department/role/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+        ),
+      ),
+      1 => 
+      array (
+        'type' => 'file',
+        'name' => 'qingdong/general',
+        'title' => '企业管理',
+        'icon' => 'fa fa-institution',
+        'url' => '',
+        'condition' => '',
+        'remark' => '',
+        'ismenu' => 1,
+        'menutype' => NULL,
+        'extend' => '',
+        'py' => 'qygl',
+        'pinyin' => 'qiyeguanli',
+        'weigh' => 6,
+        'sublist' => 
+        array (
+          0 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/general/email/index',
+            'title' => '邮箱模板配置',
+            'icon' => 'fa fa-envelope-square',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'yxmbpz',
+            'pinyin' => 'youxiangmubanpeizhi',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/email/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/email/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/email/send_email',
+                'title' => '发送邮件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'fsyj',
+                'pinyin' => 'fasongyoujian',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/email/batch_send_email',
+                'title' => '批量发送邮件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plfsyj',
+                'pinyin' => 'piliangfasongyoujian',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/email/get_detail',
+                'title' => '详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xq',
+                'pinyin' => 'xiangqing',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          1 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/general/sms/index',
+            'title' => '短信模板配置',
+            'icon' => 'fa fa-telegram',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'dxmbpz',
+            'pinyin' => 'duanxinmubanpeizhi',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/sms/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/sms/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/sms/send_sms',
+                'title' => '发送短信',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'fsdx',
+                'pinyin' => 'fasongduanxin',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/sms/batch_send_sms',
+                'title' => '批量发送',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plfs',
+                'pinyin' => 'piliangfasong',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/sms/get_detail',
+                'title' => '详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xq',
+                'pinyin' => 'xiangqing',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          2 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/work/formapproval',
+            'title' => '办公审批设置',
+            'icon' => 'fa fa-puzzle-piece',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'bgspsz',
+            'pinyin' => 'bangongshenpishezhi',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/formapproval/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/formapproval/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/formapproval/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/formapproval/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          3 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/work/flow',
+            'title' => '审批流程',
+            'icon' => 'fa fa-server',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'splc',
+            'pinyin' => 'shenpiliucheng',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/flow/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/flow/add',
+                'title' => '新增',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xz',
+                'pinyin' => 'xinzeng',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/flow/edit',
+                'title' => '修改',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xg',
+                'pinyin' => 'xiugai',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/flow/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/flow/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          4 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/general/remind',
+            'title' => '提醒人管理',
+            'icon' => 'fa fa-user',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'txrgl',
+            'pinyin' => 'tixingrenguanli',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/remind/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/remind/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/remind/getstaff',
+                'title' => '获取客户列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqkhlb',
+                'pinyin' => 'huoqukehuliebiao',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/remind/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/remind/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/remind/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/remind/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          5 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/general/ratio',
+            'title' => '员工业绩比例分割',
+            'icon' => 'fa fa-users',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'ygyjblfg',
+            'pinyin' => 'yuangongyejibilifenge',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/ratio/import',
+                'title' => '导入',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'dr',
+                'pinyin' => 'daoru',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/ratio/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/ratio/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/ratio/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/ratio/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/ratio/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          6 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/general/notice_template',
+            'title' => '通知模板',
+            'icon' => 'fa fa-tumblr',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'tzmb',
+            'pinyin' => 'tongzhimuban',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/notice_template/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/notice_template/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/notice_template/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/notice_template/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/notice_template/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          7 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/general/seastype',
+            'title' => '公海设置',
+            'icon' => 'fa fa-gears',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => 'addtabs',
+            'extend' => '',
+            'py' => 'ghsz',
+            'pinyin' => 'gonghaishezhi',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/seastype/add',
+                'title' => '添加公海设置',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tjghsz',
+                'pinyin' => 'tianjiagonghaishezhi',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/seastype/edit',
+                'title' => '修改公海设置',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xgghsz',
+                'pinyin' => 'xiugaigonghaishezhi',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/seastype/getarea',
+                'title' => '获取区域',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqqy',
+                'pinyin' => 'huoququyu',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/seastype/getstaff',
+                'title' => 'GetStaff',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'G',
+                'pinyin' => 'GetStaff',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/seastype/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/seastype/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/seastype/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/seastype/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+        ),
+      ),
+      2 => 
+      array (
+        'type' => 'file',
+        'name' => 'qingdong/dashboard/index',
+        'title' => '控制台',
+        'icon' => 'fa fa-dashboard',
+        'url' => '',
+        'condition' => '',
+        'remark' => '',
+        'ismenu' => 1,
+        'menutype' => NULL,
+        'extend' => '',
+        'py' => 'kzt',
+        'pinyin' => 'kongzhitai',
+        'weigh' => 10000,
+      ),
+      3 => 
+      array (
+        'type' => 'file',
+        'name' => 'qingdong/customer/need/index',
+        'title' => '待办事项',
+        'icon' => 'fa fa-calendar-check-o',
+        'url' => '',
+        'condition' => '',
+        'remark' => '',
+        'ismenu' => 1,
+        'menutype' => NULL,
+        'extend' => '',
+        'py' => 'dbsx',
+        'pinyin' => 'daibanshixiang',
+        'weigh' => 999,
+        'sublist' => 
+        array (
+          0 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/customer/need/get_need_number',
+            'title' => '待办角标',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 0,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'dbjb',
+            'pinyin' => 'daibanjiaobiao',
+            'weigh' => 0,
+          ),
+        1 =>
+            array (
+                'type' => 'file',
+                'name' => 'qingdong/base/upload',
+                'title' => '公共文件上传',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'ggwjsc',
+                'pinyin' => 'gonggongwenjianshangchuan',
+                'weigh' => 0,
+            ),
+        ),
+      ),
+      4 => 
+      array (
+        'type' => 'file',
+        'name' => 'qingdong/synchronizate',
+        'title' => '商业合作',
+        'icon' => 'fa fa-handshake-o',
+        'url' => '',
+        'condition' => '',
+        'remark' => '',
+        'ismenu' => 1,
+        'menutype' => NULL,
+        'extend' => '',
+        'py' => 'syhz',
+        'pinyin' => 'shangyehezuo',
+        'weigh' => 9,
+        'sublist' => 
+        array (
+          0 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/synchronizate/fauser',
+            'title' => ' Fast同步',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'Ftb',
+            'pinyin' => 'Fasttongbu',
+            'weigh' => 100,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/synchronizate/fauser/index',
+                'title' => '列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'lb',
+                'pinyin' => 'liebiao',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/synchronizate/fauser/edit',
+                'title' => '单个同步',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'dgtb',
+                'pinyin' => 'dangetongbu',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/synchronizate/fauser/batch',
+                'title' => '批量同步',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'pltb',
+                'pinyin' => 'piliangtongbu',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/synchronizate/fauser/source',
+                'title' => '获取来源',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqly',
+                'pinyin' => 'huoqulaiyuan',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          1 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/dingding',
+            'title' => '钉钉同步',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'ddtb',
+            'pinyin' => 'dingdingtongbu',
+            'weigh' => 99,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/dingding/department/index',
+                'title' => '部门同步',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bmtb',
+                'pinyin' => 'bumentongbu',
+                'weigh' => 0,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/dingding/dingding/index',
+                    'title' => '钉钉同步',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'ddtb',
+                    'pinyin' => 'dingdingtongbu',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/dingding/department/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                  2 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/dingding/department/batch',
+                    'title' => '同步到CRM',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tbdC',
+                    'pinyin' => 'tongbudaoCRM',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/dingding/staff/index',
+                'title' => '员工同步',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'ygtb',
+                'pinyin' => 'yuangongtongbu',
+                'weigh' => 0,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/dingding/dingding/staffinfo',
+                    'title' => '钉钉同步',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'ddtb',
+                    'pinyin' => 'dingdingtongbu',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/dingding/staff/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                  2 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/dingding/staff/batch',
+                    'title' => '同步到CRM',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tbdC',
+                    'pinyin' => 'tongbudaoCRM',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/dingding/customer/index',
+                'title' => ' 客户同步',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'khtb',
+                'pinyin' => 'kehutongbu',
+                'weigh' => 0,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/dingding/dingding/customer',
+                    'title' => '钉钉同步',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'ddtb',
+                    'pinyin' => 'dingdingtongbu',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/dingding/customer/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                  2 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/dingding/customer/batch',
+                    'title' => '同步到CRM',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tbdC',
+                    'pinyin' => 'tongbudaoCRM',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/dingding/contacts/index',
+                'title' => '联系人同步',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'lxrtb',
+                'pinyin' => 'lianxirentongbu',
+                'weigh' => 0,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/dingding/dingding/contacts',
+                    'title' => '钉钉同步',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'ddtb',
+                    'pinyin' => 'dingdingtongbu',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/dingding/contacts/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                  2 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/dingding/contacts/batch',
+                    'title' => '同步到CRM',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tbdC',
+                    'pinyin' => 'tongbudaoCRM',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/dingding/record/index',
+                'title' => '跟进记录同步',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'gjjltb',
+                'pinyin' => 'genjinjilutongbu',
+                'weigh' => 0,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/dingding/dingding/record',
+                    'title' => '钉钉同步',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'ddtb',
+                    'pinyin' => 'dingdingtongbu',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/dingding/record/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                  2 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/dingding/record/batch',
+                    'title' => '同步到CRM',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tbdC',
+                    'pinyin' => 'tongbudaoCRM',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+            ),
+          ),
+          2 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/weixin',
+            'title' => '企业微信同步',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'qywxtb',
+            'pinyin' => 'qiyeweixintongbu',
+            'weigh' => 80,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/weixin/department/index',
+                'title' => '部门同步',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bmtb',
+                'pinyin' => 'bumentongbu',
+                'weigh' => 10,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/weixin/weixin/index',
+                    'title' => '企业微信同步',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'qywxtb',
+                    'pinyin' => 'qiyeweixintongbu',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/weixin/department/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                  2 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/weixin/department/batch',
+                    'title' => '同步到CRM',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tbdC',
+                    'pinyin' => 'tongbudaoCRM',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/weixin/staff/index',
+                'title' => '员工同步',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'ygtb',
+                'pinyin' => 'yuangongtongbu',
+                'weigh' => 9,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/weixin/weixin/staffinfo',
+                    'title' => '企业微信同步',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'qywxtb',
+                    'pinyin' => 'qiyeweixintongbu',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/weixin/staff/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                  2 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/weixin/staff/batch',
+                    'title' => '同步到CRM',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tbdC',
+                    'pinyin' => 'tongbudaoCRM',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/weixin/customer/index',
+                'title' => ' 客户同步',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'khtb',
+                'pinyin' => 'kehutongbu',
+                'weigh' => 8,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/weixin/weixin/customer',
+                    'title' => '企业微信同步',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'qywxtb',
+                    'pinyin' => 'qiyeweixintongbu',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/weixin/customer/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                  2 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/weixin/customer/batch',
+                    'title' => '同步到CRM',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tbdC',
+                    'pinyin' => 'tongbudaoCRM',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/weixin/contacts/index',
+                'title' => '联系人同步',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'lxrtb',
+                'pinyin' => 'lianxirentongbu',
+                'weigh' => 7,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/weixin/contacts/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/weixin/contacts/batch',
+                    'title' => '同步到CRM',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tbdC',
+                    'pinyin' => 'tongbudaoCRM',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+            ),
+          ),
+          3 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/synchronizate/ku/index',
+            'title' => '酷柚进销存同步',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'kyjxctb',
+            'pinyin' => 'kuyoujinxiaocuntongbu',
+            'weigh' => 0,
+          ),
+        ),
+      ),
+      5 => 
+      array (
+        'type' => 'file',
+        'name' => 'qingdong/working',
+        'title' => '办公管理',
+        'icon' => 'fa fa-windows',
+        'url' => '',
+        'condition' => '',
+        'remark' => '',
+        'ismenu' => 1,
+        'menutype' => NULL,
+        'extend' => '',
+        'py' => 'bggl',
+        'pinyin' => 'bangongguanli',
+        'weigh' => 888,
+        'sublist' => 
+        array (
+          0 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/notice',
+            'title' => '公告管理',
+            'icon' => 'fa fa-bullhorn',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'gggl',
+            'pinyin' => 'gonggaoguanli',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/notice/notice',
+                'title' => '公告信息',
+                'icon' => 'fa fa-bullhorn',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'gggl',
+                'pinyin' => 'gonggaoguanli',
+                'weigh' => 0,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/notice/notice/index',
+                    'title' => '查看',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'zk',
+                    'pinyin' => 'zhakan',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/notice/notice/add',
+                    'title' => '添加',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tj',
+                    'pinyin' => 'tianjia',
+                    'weigh' => 0,
+                  ),
+                  2 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/notice/notice/edit',
+                    'title' => '编辑',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'bj',
+                    'pinyin' => 'bianji',
+                    'weigh' => 0,
+                  ),
+                  3 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/notice/notice/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                  4 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/notice/notice/multi',
+                    'title' => '批量更新',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'plgx',
+                    'pinyin' => 'pilianggengxin',
+                    'weigh' => 0,
+                  ),
+                  5 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/notice/notice/select',
+                    'title' => '选择',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'xz',
+                    'pinyin' => 'xuanze',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/notice/feedback',
+                'title' => '意见反馈',
+                'icon' => 'fa fa-bell-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'yjfk',
+                'pinyin' => 'yijianfankui',
+                'weigh' => 0,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/notice/feedback/index',
+                    'title' => '查看',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'zk',
+                    'pinyin' => 'zhakan',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/notice/feedback/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+            ),
+          ),
+          1 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/report/daily',
+            'title' => '工作报告',
+            'icon' => 'fa fa-rebel',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'gzbg',
+            'pinyin' => 'gongzuobaogao',
+            'weigh' => 19,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/report/daily/index',
+                'title' => '报告列表',
+                'icon' => 'fa fa-angle-right',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bglb',
+                'pinyin' => 'baogaoliebiao',
+                'weigh' => 85,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/report/daily/add',
+                    'title' => '添加报告',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tjbg',
+                    'pinyin' => 'tianjiabaogao',
+                    'weigh' => 100,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/report/daily/detail',
+                    'title' => '详情',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'xq',
+                    'pinyin' => 'xiangqing',
+                    'weigh' => 100,
+                  ),
+                ),
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/report/comment',
+                'title' => '评论',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'pl',
+                'pinyin' => 'pinglun',
+                'weigh' => 0,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/report/comment/index',
+                    'title' => '首页',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sy',
+                    'pinyin' => 'shouye',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/report/comment/add',
+                    'title' => '添加',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tj',
+                    'pinyin' => 'tianjia',
+                    'weigh' => 0,
+                  ),
+                  2 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/report/comment/edit',
+                    'title' => '编辑',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'bj',
+                    'pinyin' => 'bianji',
+                    'weigh' => 0,
+                  ),
+                  3 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/report/comment/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                  4 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/report/comment/multi',
+                    'title' => '批量更新',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'plgx',
+                    'pinyin' => 'pilianggengxin',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+            ),
+          ),
+          2 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/examine/examine',
+            'title' => '审批管理',
+            'icon' => 'fa fa-handshake-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'spgl',
+            'pinyin' => 'shenpiguanli',
+            'weigh' => 90,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/examine/examine/index',
+                'title' => '合同审批',
+                'icon' => 'fa fa-angle-right',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'htsp',
+                'pinyin' => 'hetongshenpi',
+                'weigh' => 100,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/examine/examine/consume',
+                'title' => '费用审批',
+                'icon' => 'fa fa-angle-right',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'fysp',
+                'pinyin' => 'feiyongshenpi',
+                'weigh' => 100,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/examine/examine/receivables',
+                'title' => '回款审批',
+                'icon' => 'fa fa-angle-right',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hksp',
+                'pinyin' => 'huikuanshenpi',
+                'weigh' => 100,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/examine/examine/achievement',
+                'title' => '业绩目标审批',
+                'icon' => 'fa fa-angle-right',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'yjmbsp',
+                'pinyin' => 'yejimubiaoshenpi',
+                'weigh' => 100,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/examine/examine_record/examine',
+                'title' => '审核',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sh',
+                'pinyin' => 'shenhe',
+                'weigh' => 100,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/examine/examine/work',
+                'title' => '办公审核',
+                'icon' => 'fa fa-angle-right',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bgsh',
+                'pinyin' => 'bangongshenhe',
+                'weigh' => 100,
+              ),
+            ),
+          ),
+          3 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/canlendar/canlendar',
+            'title' => '日程管理',
+            'icon' => 'fa fa-calendar-times-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'rcgl',
+            'pinyin' => 'richengguanli',
+            'weigh' => 19,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/canlendar/canlendar/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/canlendar/canlendar/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/canlendar/canlendar/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/canlendar/canlendar/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/canlendar/canlendar/customer',
+                'title' => '关联客户',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'glkh',
+                'pinyin' => 'guanliankehu',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/canlendar/canlendar/contacts',
+                'title' => '关联联系人',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'gllxr',
+                'pinyin' => 'guanlianlianxiren',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/canlendar/canlendar/contract',
+                'title' => '关联合同',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'glht',
+                'pinyin' => 'guanlianhetong',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/canlendar/canlendar/leads',
+                'title' => '关联线索',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'glxs',
+                'pinyin' => 'guanlianxiansuo',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          4 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/work/approval',
+            'title' => '办公审批',
+            'icon' => 'fa fa-user-md',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'bgsp',
+            'pinyin' => 'bangongshenpi',
+            'weigh' => 15,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/approval/index',
+                'title' => '首页',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sy',
+                'pinyin' => 'shouye',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/approval/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/approval/detail',
+                'title' => '详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xq',
+                'pinyin' => 'xiangqing',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/approval/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/approval/getstaff',
+                'title' => '获取审批人列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqsprlb',
+                'pinyin' => 'huoqushenpirenliebiao',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/approval/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/approval/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/work/approval/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+        ),
+      ),
+      6 => 
+      array (
+        'type' => 'file',
+        'name' => 'qingdong/customer',
+        'title' => '客户管理',
+        'icon' => 'fa fa-group',
+        'url' => '',
+        'condition' => '',
+        'remark' => '',
+        'ismenu' => 1,
+        'menutype' => NULL,
+        'extend' => '',
+        'py' => 'khgl',
+        'pinyin' => 'kehuguanli',
+        'weigh' => 777,
+        'sublist' => 
+        array (
+          0 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/customer/customer',
+            'title' => '我的客户',
+            'icon' => 'fa fa-users',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'wdkh',
+            'pinyin' => 'wodekehu',
+            'weigh' => 85,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/list',
+                'title' => '客户信息',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'khxx',
+                'pinyin' => 'kehuxinxi',
+                'weigh' => 98,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/log/index',
+                    'title' => '日志',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'rz',
+                    'pinyin' => 'rizhi',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/edit',
+                'title' => '修改',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xg',
+                'pinyin' => 'xiugai',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/stafflist',
+                'title' => '搜索下拉列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'ssxllb',
+                'pinyin' => 'sousuoxialaliebiao',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/change',
+                'title' => '转移客户',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zykh',
+                'pinyin' => 'zhuanyikehu',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/detail',
+                'title' => '客户详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'khxq',
+                'pinyin' => 'kehuxiangqing',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/import',
+                'title' => '导入客户',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'drkh',
+                'pinyin' => 'daorukehu',
+                'weigh' => 0,
+              ),
+              8 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/get_contacts',
+                'title' => '获取相关联系人',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqxglxr',
+                'pinyin' => 'huoquxiangguanlianxiren',
+                'weigh' => 0,
+              ),
+              9 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/get_contract',
+                'title' => '获取相关合同',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqxght',
+                'pinyin' => 'huoquxiangguanhetong',
+                'weigh' => 0,
+              ),
+              10 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/get_consume',
+                'title' => '获取费用',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqfy',
+                'pinyin' => 'huoqufeiyong',
+                'weigh' => 0,
+              ),
+              11 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/get_receivables_plan',
+                'title' => '获取回款计划',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqhkjh',
+                'pinyin' => 'huoquhuikuanjihua',
+                'weigh' => 0,
+              ),
+              12 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/get_receivables',
+                'title' => '获取回款记录',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqhkjl',
+                'pinyin' => 'huoquhuikuanjilu',
+                'weigh' => 0,
+              ),
+              13 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/get_file',
+                'title' => '获取附件记录',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqfjjl',
+                'pinyin' => 'huoqufujianjilu',
+                'weigh' => 0,
+              ),
+              14 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/seas',
+                'title' => '移入公海',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'yrgh',
+                'pinyin' => 'yirugonghai',
+                'weigh' => 0,
+              ),
+              15 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/receive',
+                'title' => '领取客户',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'lqkh',
+                'pinyin' => 'lingqukehu',
+                'weigh' => 0,
+              ),
+              16 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              17 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/batch_change',
+                'title' => '批量转移客户',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plzykh',
+                'pinyin' => 'piliangzhuanyikehu',
+                'weigh' => 0,
+              ),
+              18 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/map',
+                'title' => '地图',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'dt',
+                'pinyin' => 'ditu',
+                'weigh' => 0,
+              ),
+              19 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/get_sign',
+                'title' => '获取签到记录',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqqdjl',
+                'pinyin' => 'huoquqiandaojilu',
+                'weigh' => 0,
+              ),
+              20 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/get_sign_detail',
+                'title' => '获取签到记录',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqqdjl',
+                'pinyin' => 'huoquqiandaojilu',
+                'weigh' => 0,
+              ),
+              21 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/record',
+                'title' => '跟进记录',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'gjjl',
+                'pinyin' => 'genjinjilu',
+                'weigh' => 0,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/record/index',
+                    'title' => '客户跟进记录',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'khgjjl',
+                    'pinyin' => 'kehugenjinjilu',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/record/add',
+                    'title' => '添加跟进',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tjgj',
+                    'pinyin' => 'tianjiagenjin',
+                    'weigh' => 0,
+                  ),
+                  2 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/record/detail',
+                    'title' => '跟进详情',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'gjxq',
+                    'pinyin' => 'genjinxiangqing',
+                    'weigh' => 0,
+                  ),
+                  3 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/record/comment',
+                    'title' => '评论',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'pl',
+                    'pinyin' => 'pinglun',
+                    'weigh' => 0,
+                  ),
+                  4 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/record/getstaff',
+                    'title' => 'GetStaff',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'G',
+                    'pinyin' => 'GetStaff',
+                    'weigh' => 0,
+                  ),
+                  5 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/record/upload',
+                    'title' => '上传文件',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'scwj',
+                    'pinyin' => 'shangchuanwenjian',
+                    'weigh' => 0,
+                  ),
+                  6 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/record/edit',
+                    'title' => '编辑',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'bj',
+                    'pinyin' => 'bianji',
+                    'weigh' => 0,
+                  ),
+                  7 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/record/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                  8 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/record/multi',
+                    'title' => '批量更新',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'plgx',
+                    'pinyin' => 'pilianggengxin',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+              22 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/comment',
+                'title' => '客户评论',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'khpl',
+                'pinyin' => 'kehupinglun',
+                'weigh' => 0,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/comment/index',
+                    'title' => '首页',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sy',
+                    'pinyin' => 'shouye',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/comment/add',
+                    'title' => '添加评论',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tjpl',
+                    'pinyin' => 'tianjiapinglun',
+                    'weigh' => 0,
+                  ),
+                  2 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/comment/getstaff',
+                    'title' => '员工信息',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'ygxx',
+                    'pinyin' => 'yuangongxinxi',
+                    'weigh' => 0,
+                  ),
+                  3 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/comment/upload',
+                    'title' => '上传文件',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'scwj',
+                    'pinyin' => 'shangchuanwenjian',
+                    'weigh' => 0,
+                  ),
+                  4 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/comment/edit',
+                    'title' => '编辑',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'bj',
+                    'pinyin' => 'bianji',
+                    'weigh' => 0,
+                  ),
+                  5 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/comment/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                  6 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/comment/multi',
+                    'title' => '批量更新',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'plgx',
+                    'pinyin' => 'pilianggengxin',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+              23 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/add_consume',
+                'title' => '添加费用',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tjfy',
+                'pinyin' => 'tianjiafeiyong',
+                'weigh' => 0,
+              ),
+              24 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/getteam',
+                'title' => '获取团队成员',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqtdcy',
+                'pinyin' => 'huoqutuanduichengyuan',
+                'weigh' => 0,
+              ),
+              25 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/addteam',
+                'title' => '添加团队成员',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tjtdcy',
+                'pinyin' => 'tianjiatuanduichengyuan',
+                'weigh' => 0,
+              ),
+              26 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/editteam',
+                'title' => '修改团队成员',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xgtdcy',
+                'pinyin' => 'xiugaituanduichengyuan',
+                'weigh' => 0,
+              ),
+              27 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/delteam',
+                'title' => '删除团队成员',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sctdcy',
+                'pinyin' => 'shanchutuanduichengyuan',
+                'weigh' => 0,
+              ),
+              28 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/getstaff',
+                'title' => '获取团队人员列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqtdrylb',
+                'pinyin' => 'huoqutuanduirenyuanliebiao',
+                'weigh' => 0,
+              ),
+              29 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              30 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/recyclebin',
+                'title' => '回收站',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hsz',
+                'pinyin' => 'huishouzhan',
+                'weigh' => 0,
+              ),
+              31 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/destroy',
+                'title' => '真实删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zssc',
+                'pinyin' => 'zhenshishanchu',
+                'weigh' => 0,
+              ),
+              32 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/restore',
+                'title' => '还原',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hy',
+                'pinyin' => 'huanyuan',
+                'weigh' => 0,
+              ),
+              33 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+              34 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/get_business',
+                'title' => '获取相关商机',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqxgsj',
+                'pinyin' => 'huoquxiangguanshangji',
+                'weigh' => 0,
+              ),
+              35 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/template',
+                'title' => '模板',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'mb',
+                'pinyin' => 'muban',
+                'weigh' => 0,
+              ),
+              36 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/export',
+                'title' => '导出信息',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'dcxx',
+                'pinyin' => 'daochuxinxi',
+                'weigh' => 0,
+              ),
+              37 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/customer/words',
+                'title' => '导出Word',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'W',
+                'pinyin' => 'Words',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          1 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/customer/cnki',
+            'title' => '客户查重',
+            'icon' => 'fa fa-address-book-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'khcz',
+            'pinyin' => 'kehuchazhong',
+            'weigh' => 84,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/cnki/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/cnki/edit',
+                'title' => '合并客户',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hbkh',
+                'pinyin' => 'hebingkehu',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/cnki/getstaff',
+                'title' => 'GetStaff',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'G',
+                'pinyin' => 'GetStaff',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/cnki/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/cnki/recyclebin',
+                'title' => '回收站',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hsz',
+                'pinyin' => 'huishouzhan',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/cnki/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/cnki/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/cnki/destroy',
+                'title' => '真实删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zssc',
+                'pinyin' => 'zhenshishanchu',
+                'weigh' => 0,
+              ),
+              8 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/cnki/restore',
+                'title' => '还原',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hy',
+                'pinyin' => 'huanyuan',
+                'weigh' => 0,
+              ),
+              9 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/cnki/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          2 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/customer/contacts',
+            'title' => '客户联系人',
+            'icon' => 'fa fa-user-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'khlxr',
+            'pinyin' => 'kehulianxiren',
+            'weigh' => 83,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contacts/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contacts/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contacts/edit',
+                'title' => '修改',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xg',
+                'pinyin' => 'xiugai',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contacts/detail',
+                'title' => '联系人详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'lxrxq',
+                'pinyin' => 'lianxirenxiangqing',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contacts/get_file',
+                'title' => '获取附件记录',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqfjjl',
+                'pinyin' => 'huoqufujianjilu',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contacts/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contacts/import',
+                'title' => '导入客户',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'drkh',
+                'pinyin' => 'daorukehu',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contacts/template',
+                'title' => '模板',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'mb',
+                'pinyin' => 'muban',
+                'weigh' => 0,
+              ),
+              8 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contacts/export',
+                'title' => '导出信息',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'dcxx',
+                'pinyin' => 'daochuxinxi',
+                'weigh' => 0,
+              ),
+              9 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contacts/getstaff',
+                'title' => 'GetStaff',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'G',
+                'pinyin' => 'GetStaff',
+                'weigh' => 0,
+              ),
+              10 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contacts/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              11 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contacts/recyclebin',
+                'title' => '回收站',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hsz',
+                'pinyin' => 'huishouzhan',
+                'weigh' => 0,
+              ),
+              12 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contacts/destroy',
+                'title' => '真实删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zssc',
+                'pinyin' => 'zhenshishanchu',
+                'weigh' => 0,
+              ),
+              13 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contacts/restore',
+                'title' => '还原',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hy',
+                'pinyin' => 'huanyuan',
+                'weigh' => 0,
+              ),
+              14 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contacts/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          3 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/customer/seas',
+            'title' => '客户公海',
+            'icon' => 'fa fa-map',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'khgh',
+            'pinyin' => 'kehugonghai',
+            'weigh' => 97,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/seas/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/seas/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/seas/detail',
+                'title' => '公海详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'ghxq',
+                'pinyin' => 'gonghaixiangqing',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/seas/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/seas/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/base/get_staff',
+                'title' => '公共员工信息',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'ggygxx',
+                'pinyin' => 'gonggongyuangongxinxi',
+                'weigh' => 0,
+              ),
+              6 =>
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/seas/getstaff',
+                'title' => 'GetStaff',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'G',
+                'pinyin' => 'GetStaff',
+                'weigh' => 0,
+              ),
+              7 =>
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/seas/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              8 =>
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/seas/recyclebin',
+                'title' => '回收站',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hsz',
+                'pinyin' => 'huishouzhan',
+                'weigh' => 0,
+              ),
+              9 =>
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/seas/destroy',
+                'title' => '真实删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zssc',
+                'pinyin' => 'zhenshishanchu',
+                'weigh' => 0,
+              ),
+              10 =>
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/seas/restore',
+                'title' => '还原',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hy',
+                'pinyin' => 'huanyuan',
+                'weigh' => 0,
+              ),
+              11 =>
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/seas/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          4 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/customer/leads',
+            'title' => '我的线索',
+            'icon' => 'fa fa-search-plus',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'wdxs',
+            'pinyin' => 'wodexiansuo',
+            'weigh' => 99,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/list',
+                'title' => '线索列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xslb',
+                'pinyin' => 'xiansuoliebiao',
+                'weigh' => 85,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/edit',
+                'title' => '修改',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xg',
+                'pinyin' => 'xiugai',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/detail',
+                'title' => '线索详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xsxq',
+                'pinyin' => 'xiansuoxiangqing',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/get_file',
+                'title' => '获取附件记录',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqfjjl',
+                'pinyin' => 'huoqufujianjilu',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/convert_customer',
+                'title' => '转为客户',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zwkh',
+                'pinyin' => 'zhuanweikehu',
+                'weigh' => 0,
+              ),
+              8 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/import',
+                'title' => '导入',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'dr',
+                'pinyin' => 'daoru',
+                'weigh' => 0,
+              ),
+              9 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/leads/record/index',
+                'title' => '跟进记录',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'gjjl',
+                'pinyin' => 'genjinjilu',
+                'weigh' => 0,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/leads/record/add',
+                    'title' => '添加',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tj',
+                    'pinyin' => 'tianjia',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+              10 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/leads/comment',
+                'title' => '评论',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'pl',
+                'pinyin' => 'pinglun',
+                'weigh' => 0,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/leads/comment/index',
+                    'title' => '首页',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sy',
+                    'pinyin' => 'shouye',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/leads/comment/add',
+                    'title' => '添加',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tj',
+                    'pinyin' => 'tianjia',
+                    'weigh' => 0,
+                  ),
+                  2 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/leads/comment/edit',
+                    'title' => '编辑',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'bj',
+                    'pinyin' => 'bianji',
+                    'weigh' => 0,
+                  ),
+                  3 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/leads/comment/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                  4 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/leads/comment/multi',
+                    'title' => '批量更新',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'plgx',
+                    'pinyin' => 'pilianggengxin',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+              11 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/transfer',
+                'title' => '转移线索',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zyxs',
+                'pinyin' => 'zhuanyixiansuo',
+                'weigh' => 0,
+              ),
+              12 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/getstaff',
+                'title' => 'GetStaff',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'G',
+                'pinyin' => 'GetStaff',
+                'weigh' => 0,
+              ),
+              13 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              14 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/recyclebin',
+                'title' => '回收站',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hsz',
+                'pinyin' => 'huishouzhan',
+                'weigh' => 0,
+              ),
+              15 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/destroy',
+                'title' => '真实删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zssc',
+                'pinyin' => 'zhenshishanchu',
+                'weigh' => 0,
+              ),
+              16 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/restore',
+                'title' => '还原',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hy',
+                'pinyin' => 'huanyuan',
+                'weigh' => 0,
+              ),
+              17 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+              18 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/template',
+                'title' => '模板',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'mb',
+                'pinyin' => 'muban',
+                'weigh' => 0,
+              ),
+              19 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leads/export',
+                'title' => '导出信息',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'dcxx',
+                'pinyin' => 'daochuxinxi',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          5 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/customer/contract',
+            'title' => '合同订单',
+            'icon' => 'fa fa-paste',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'htdd',
+            'pinyin' => 'hetongdingdan',
+            'weigh' => 78,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/get_product',
+                'title' => '获取产品',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqcp',
+                'pinyin' => 'huoquchanpin',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/get_product_price',
+                'title' => '获取产品价格',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqcpjg',
+                'pinyin' => 'huoquchanpinjiage',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/get_product_part',
+                'title' => '获取产品配置',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqcppz',
+                'pinyin' => 'huoquchanpinpeizhi',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/list',
+                'title' => '合同列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'htlb',
+                'pinyin' => 'hetongliebiao',
+                'weigh' => 85,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/edit',
+                'title' => '修改合同',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xght',
+                'pinyin' => 'xiugaihetong',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/get_file',
+                'title' => '获取附件记录',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqfjjl',
+                'pinyin' => 'huoqufujianjilu',
+                'weigh' => 0,
+              ),
+              8 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/detail',
+                'title' => '合同详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'htxq',
+                'pinyin' => 'hetongxiangqing',
+                'weigh' => 0,
+              ),
+              9 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/get_receivables_plan',
+                'title' => '获取回款计划',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqhkjh',
+                'pinyin' => 'huoquhuikuanjihua',
+                'weigh' => 0,
+              ),
+              10 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/get_receivables',
+                'title' => '获取回款记录',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqhkjl',
+                'pinyin' => 'huoquhuikuanjilu',
+                'weigh' => 0,
+              ),
+              11 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              12 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/get_contacts_list',
+                'title' => '获取联系人select',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqlxrs',
+                'pinyin' => 'huoqulianxirenselect',
+                'weigh' => 0,
+              ),
+              13 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/contract/record/index',
+                'title' => '跟进记录',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'gjjl',
+                'pinyin' => 'genjinjilu',
+                'weigh' => 0,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/contract/record/add',
+                    'title' => '增加',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'zj',
+                    'pinyin' => 'zengjia',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+              14 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/contract/comment',
+                'title' => '评论',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'pl',
+                'pinyin' => 'pinglun',
+                'weigh' => 0,
+                'sublist' => 
+                array (
+                  0 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/contract/comment/index',
+                    'title' => '首页',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sy',
+                    'pinyin' => 'shouye',
+                    'weigh' => 0,
+                  ),
+                  1 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/contract/comment/getstaff',
+                    'title' => '员工信息',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'ygxx',
+                    'pinyin' => 'yuangongxinxi',
+                    'weigh' => 0,
+                  ),
+                  2 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/contract/comment/upload',
+                    'title' => '上传文件',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'scwj',
+                    'pinyin' => 'shangchuanwenjian',
+                    'weigh' => 0,
+                  ),
+                  3 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/contract/comment/add',
+                    'title' => '添加',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'tj',
+                    'pinyin' => 'tianjia',
+                    'weigh' => 0,
+                  ),
+                  4 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/contract/comment/edit',
+                    'title' => '编辑',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'bj',
+                    'pinyin' => 'bianji',
+                    'weigh' => 0,
+                  ),
+                  5 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/contract/comment/del',
+                    'title' => '删除',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sc',
+                    'pinyin' => 'shanchu',
+                    'weigh' => 0,
+                  ),
+                  6 => 
+                  array (
+                    'type' => 'file',
+                    'name' => 'qingdong/contract/comment/multi',
+                    'title' => '批量更新',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'plgx',
+                    'pinyin' => 'pilianggengxin',
+                    'weigh' => 0,
+                  ),
+                ),
+              ),
+              15 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/getstaff',
+                'title' => '获取审批人列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqsprlb',
+                'pinyin' => 'huoqushenpirenliebiao',
+                'weigh' => 0,
+              ),
+              16 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              17 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/recyclebin',
+                'title' => '回收站',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hsz',
+                'pinyin' => 'huishouzhan',
+                'weigh' => 0,
+              ),
+              18 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/destroy',
+                'title' => '真实删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zssc',
+                'pinyin' => 'zhenshishanchu',
+                'weigh' => 0,
+              ),
+              19 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/restore',
+                'title' => '还原',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hy',
+                'pinyin' => 'huanyuan',
+                'weigh' => 0,
+              ),
+              20 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+              21 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/get_contract_product',
+                'title' => '获取产品明细',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqcpmx',
+                'pinyin' => 'huoquchanpinmingxi',
+                'weigh' => 0,
+              ),
+              22 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/get_business_product',
+                'title' => '获取商机关联产品',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqsjglcp',
+                'pinyin' => 'huoqushangjiguanlianchanpin',
+                'weigh' => 0,
+              ),
+              23 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/import',
+                'title' => '导入合同',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'drht',
+                'pinyin' => 'daoruhetong',
+                'weigh' => 0,
+              ),
+              24 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/template',
+                'title' => '模板',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'mb',
+                'pinyin' => 'muban',
+                'weigh' => 0,
+              ),
+              25 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/export',
+                'title' => '导出信息',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'dcxx',
+                'pinyin' => 'daochuxinxi',
+                'weigh' => 0,
+              ),
+              26 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/import_product',
+                'title' => '导入产品明细',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'drcpmx',
+                'pinyin' => 'daoruchanpinmingxi',
+                'weigh' => 0,
+              ),
+              27 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/template_product',
+                'title' => '模板',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'mb',
+                'pinyin' => 'muban',
+                'weigh' => 0,
+              ),
+              28 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/contract/export_product',
+                'title' => '导出信息',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'dcxx',
+                'pinyin' => 'daochuxinxi',
+                'weigh' => 0,
+              ),
+              29 =>
+              array (
+                        'type' => 'file',
+                        'name' => 'qingdong/customer/contract/words',
+                        'title' => '导出Word',
+                        'icon' => 'fa fa-circle-o',
+                        'url' => '',
+                        'condition' => '',
+                        'remark' => '',
+                        'ismenu' => 0,
+                        'menutype' => NULL,
+                        'extend' => '',
+                        'py' => 'W',
+                        'pinyin' => 'Words',
+                        'weigh' => 0,
+                    ),
+            ),
+          ),
+          6 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/customer/receivables',
+            'title' => '合同回款',
+            'icon' => 'fa fa-yen',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'hthk',
+            'pinyin' => 'hetonghuikuan',
+            'weigh' => 20,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/detail',
+                'title' => '回款详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hkxq',
+                'pinyin' => 'huikuanxiangqing',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/getcustomer',
+                'title' => '获取客户列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqkhlb',
+                'pinyin' => 'huoqukehuliebiao',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/getcontract',
+                'title' => '获取合同列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqhtlb',
+                'pinyin' => 'huoquhetongliebiao',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/getstaff',
+                'title' => '获取审批人列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqsprlb',
+                'pinyin' => 'huoqushenpirenliebiao',
+                'weigh' => 0,
+              ),
+              8 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              9 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/recyclebin',
+                'title' => '回收站',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hsz',
+                'pinyin' => 'huishouzhan',
+                'weigh' => 0,
+              ),
+              10 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/destroy',
+                'title' => '真实删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zssc',
+                'pinyin' => 'zhenshishanchu',
+                'weigh' => 0,
+              ),
+              11 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/restore',
+                'title' => '还原',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hy',
+                'pinyin' => 'huanyuan',
+                'weigh' => 0,
+              ),
+              12 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+              13 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/import',
+                'title' => '导入回款信息',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'drhkxx',
+                'pinyin' => 'daoruhuikuanxinxi',
+                'weigh' => 0,
+              ),
+              14 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/template',
+                'title' => '模板',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'mb',
+                'pinyin' => 'muban',
+                'weigh' => 0,
+              ),
+              15 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivables/export',
+                'title' => '导出信息',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'dcxx',
+                'pinyin' => 'daochuxinxi',
+                'weigh' => 0,
+              ),
+            16 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/customer/receivables/plan',
+                    'title' => '回款计划',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'dcxxplan',
+                    'pinyin' => 'daochuxinxiplan',
+                    'weigh' => 0,
+                ),
+            ),
+          ),
+          7 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/customer/consume',
+            'title' => '支出费用',
+            'icon' => 'fa fa-money',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'zcfy',
+            'pinyin' => 'zhichufeiyong',
+            'weigh' => 10,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/consume/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/consume/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/consume/edit',
+                'title' => '修改费用',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xgfy',
+                'pinyin' => 'xiugaifeiyong',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/consume/detail',
+                'title' => '费用详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'fyxq',
+                'pinyin' => 'feiyongxiangqing',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/consume/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/consume/getstaff',
+                'title' => 'GetStaff',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'G',
+                'pinyin' => 'GetStaff',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/consume/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/consume/recyclebin',
+                'title' => '回收站',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hsz',
+                'pinyin' => 'huishouzhan',
+                'weigh' => 0,
+              ),
+              8 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/consume/destroy',
+                'title' => '真实删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zssc',
+                'pinyin' => 'zhenshishanchu',
+                'weigh' => 0,
+              ),
+              9 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/consume/restore',
+                'title' => '还原',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hy',
+                'pinyin' => 'huanyuan',
+                'weigh' => 0,
+              ),
+              10 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/consume/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          8 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/customer/receivablesplan',
+            'title' => '回款计划',
+            'icon' => 'fa fa-circle-o
+',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'hkjh',
+            'pinyin' => 'huikuanjihua',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivablesplan/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 80,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivablesplan/edit',
+                'title' => '修改回款计划',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xghkjh',
+                'pinyin' => 'xiugaihuikuanjihua',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivablesplan/add',
+                'title' => '添加回款计划',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tjhkjh',
+                'pinyin' => 'tianjiahuikuanjihua',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivablesplan/getcustomer',
+                'title' => '获取客户列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqkhlb',
+                'pinyin' => 'huoqukehuliebiao',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivablesplan/getcontract',
+                'title' => '获取合同',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqht',
+                'pinyin' => 'huoquhetong',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivablesplan/getstaff',
+                'title' => 'GetStaff',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'G',
+                'pinyin' => 'GetStaff',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivablesplan/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivablesplan/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              8 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/receivablesplan/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          9 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/customer/leadspool',
+            'title' => '线索池',
+            'icon' => 'fa fa-th',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => 'addtabs',
+            'extend' => '',
+            'py' => 'xsc',
+            'pinyin' => 'xiansuochi',
+            'weigh' => 100,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leadspool/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leadspool/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leadspool/edit',
+                'title' => '修改',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xg',
+                'pinyin' => 'xiugai',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leadspool/detail',
+                'title' => '线索详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xsxq',
+                'pinyin' => 'xiansuoxiangqing',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leadspool/get_file',
+                'title' => '获取附件记录',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqfjjl',
+                'pinyin' => 'huoqufujianjilu',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leadspool/transfer',
+                'title' => '分配线索',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'fpxs',
+                'pinyin' => 'fenpeixiansuo',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leadspool/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leadspool/import',
+                'title' => '导入',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'dr',
+                'pinyin' => 'daoru',
+                'weigh' => 0,
+              ),
+              8 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leadspool/getstaff',
+                'title' => '获取员工',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqyg',
+                'pinyin' => 'huoquyuangong',
+                'weigh' => 0,
+              ),
+              9 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leadspool/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              10 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leadspool/recyclebin',
+                'title' => '回收站',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hsz',
+                'pinyin' => 'huishouzhan',
+                'weigh' => 0,
+              ),
+              11 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leadspool/destroy',
+                'title' => '真实删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zssc',
+                'pinyin' => 'zhenshishanchu',
+                'weigh' => 0,
+              ),
+              12 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leadspool/restore',
+                'title' => '还原',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hy',
+                'pinyin' => 'huanyuan',
+                'weigh' => 0,
+              ),
+              13 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/leadspool/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          10 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/customer/business',
+            'title' => '商机管理',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'sjgl',
+            'pinyin' => 'shangjiguanli',
+            'weigh' => 79,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => 'addtabs',
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 82,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => 'addtabs',
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/edit',
+                'title' => '修改',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => 'addtabs',
+                'extend' => '',
+                'py' => 'xg',
+                'pinyin' => 'xiugai',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/detail',
+                'title' => '详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => 'addtabs',
+                'extend' => '',
+                'py' => 'xq',
+                'pinyin' => 'xiangqing',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/record',
+                'title' => '添加跟进',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => 'addtabs',
+                'extend' => '',
+                'py' => 'tjgj',
+                'pinyin' => 'tianjiagenjin',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/batch_change',
+                'title' => '批量转移商机',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => 'addtabs',
+                'extend' => '',
+                'py' => 'plzysj',
+                'pinyin' => 'piliangzhuanyishangji',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/product',
+                'title' => '产品信息',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => 'addtabs',
+                'extend' => '',
+                'py' => 'cpxx',
+                'pinyin' => 'chanpinxinxi',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/get_contract',
+                'title' => '获取相关合同',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => 'addtabs',
+                'extend' => '',
+                'py' => 'hqxght',
+                'pinyin' => 'huoquxiangguanhetong',
+                'weigh' => 0,
+              ),
+              8 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/delete',
+                'title' => '删除商机',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => 'addtabs',
+                'extend' => '',
+                'py' => 'scsj',
+                'pinyin' => 'shanchushangji',
+                'weigh' => 0,
+              ),
+              9 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/batch_status',
+                'title' => '推进商机',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tjsj',
+                'pinyin' => 'tuijinshangji',
+                'weigh' => 0,
+              ),
+              10 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/get_business_status',
+                'title' => '获取推进商机',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqtjsj',
+                'pinyin' => 'huoqutuijinshangji',
+                'weigh' => 0,
+              ),
+              11 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/import',
+                'title' => '导入客户',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'drkh',
+                'pinyin' => 'daorukehu',
+                'weigh' => 0,
+              ),
+              12 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/template',
+                'title' => '模板',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'mb',
+                'pinyin' => 'muban',
+                'weigh' => 0,
+              ),
+              13 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/export',
+                'title' => '导出信息',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'dcxx',
+                'pinyin' => 'daochuxinxi',
+                'weigh' => 0,
+              ),
+              14 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/import_product',
+                'title' => '导入产品明细',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'drcpmx',
+                'pinyin' => 'daoruchanpinmingxi',
+                'weigh' => 0,
+              ),
+              15 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/template_product',
+                'title' => '模板',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'mb',
+                'pinyin' => 'muban',
+                'weigh' => 0,
+              ),
+              16 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/export_product',
+                'title' => '导出信息',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'dcxx',
+                'pinyin' => 'daochuxinxi',
+                'weigh' => 0,
+              ),
+              17 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/getstaff',
+                'title' => 'GetStaff',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'G',
+                'pinyin' => 'GetStaff',
+                'weigh' => 0,
+              ),
+              18 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              19 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/recyclebin',
+                'title' => '回收站',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hsz',
+                'pinyin' => 'huishouzhan',
+                'weigh' => 0,
+              ),
+              20 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              21 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/destroy',
+                'title' => '真实删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zssc',
+                'pinyin' => 'zhenshishanchu',
+                'weigh' => 0,
+              ),
+              22 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/restore',
+                'title' => '还原',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hy',
+                'pinyin' => 'huanyuan',
+                'weigh' => 0,
+              ),
+              23 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/customer/business/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+        ),
+      ),
+      7 => 
+      array (
+        'type' => 'file',
+        'name' => 'qingdong/department/achievement',
+        'title' => '业绩目标',
+        'icon' => 'fa fa-bar-chart',
+        'url' => '',
+        'condition' => '',
+        'remark' => '',
+        'ismenu' => 1,
+        'menutype' => NULL,
+        'extend' => '',
+        'py' => 'yjmb',
+        'pinyin' => 'yejimubiao',
+        'weigh' => 10,
+        'sublist' => 
+        array (
+          0 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/department/achievement/index',
+            'title' => '业绩目标列表',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 0,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'yjmblb',
+            'pinyin' => 'yejimubiaoliebiao',
+            'weigh' => 0,
+          ),
+          1 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/department/achievement/edit',
+            'title' => '修改业绩目标',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 0,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'xgyjmb',
+            'pinyin' => 'xiugaiyejimubiao',
+            'weigh' => 0,
+          ),
+          2 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/department/achievement/add',
+            'title' => '新建业绩目标',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 0,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'xjyjmb',
+            'pinyin' => 'xinjianyejimubiao',
+            'weigh' => 0,
+          ),
+          3 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/department/achievement/del',
+            'title' => '删除',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 0,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'sc',
+            'pinyin' => 'shanchu',
+            'weigh' => 0,
+          ),
+          4 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/department/achievement/multi',
+            'title' => '批量更新',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 0,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'plgx',
+            'pinyin' => 'pilianggengxin',
+            'weigh' => 0,
+          ),
+          5 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/department/achievement/personal',
+            'title' => '个人目标',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 0,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'grmb',
+            'pinyin' => 'gerenmubiao',
+            'weigh' => 0,
+          ),
+          6 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/department/achievement/records',
+            'title' => '业绩目标修改日志',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 0,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'yjmbxgrz',
+            'pinyin' => 'yejimubiaoxiugairizhi',
+            'weigh' => 0,
+          ),
+          7 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/department/achievement/getstaff',
+            'title' => '获取审批人列表',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 0,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'hqsprlb',
+            'pinyin' => 'huoqushenpirenliebiao',
+            'weigh' => 0,
+          ),
+          8 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/department/achievement/edit_personal',
+            'title' => '团队目标',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 0,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'tdmb',
+            'pinyin' => 'tuanduimubiao',
+            'weigh' => 0,
+          ),
+          9 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/department/achievement/upload',
+            'title' => '上传文件',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 0,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'scwj',
+            'pinyin' => 'shangchuanwenjian',
+            'weigh' => 0,
+          ),
+        ),
+      ),
+      8 => 
+      array (
+        'type' => 'file',
+        'name' => 'qingdong/product',
+        'title' => '商品管理',
+        'icon' => 'fa fa-product-hunt',
+        'url' => '',
+        'condition' => '',
+        'remark' => '',
+        'ismenu' => 1,
+        'menutype' => 'addtabs',
+        'extend' => '',
+        'py' => 'cpgl',
+        'pinyin' => 'chanpinguanli',
+        'weigh' => 15,
+        'sublist' => 
+        array (
+          0 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/product/product',
+            'title' => '产品列表',
+            'icon' => 'fa fa-angle-right',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'cplb',
+            'pinyin' => 'chanpinliebiao',
+            'weigh' => 7,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/product/index',
+                'title' => '产品列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'cplb',
+                'pinyin' => 'chanpinliebiao',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/product/add',
+                'title' => '添加产品',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tjcp',
+                'pinyin' => 'tianjiachanpin',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/product/edit',
+                'title' => '修改产品',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xgcp',
+                'pinyin' => 'xiugaichanpin',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/product/detail',
+                'title' => '产品详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'cpxq',
+                'pinyin' => 'chanpinxiangqing',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/product/del',
+                'title' => '删除产品',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sccp',
+                'pinyin' => 'shanchuchanpin',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/product/part_list',
+                'title' => '配件列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'pjlb',
+                'pinyin' => 'peijianliebiao',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/product/add_part',
+                'title' => '添加配件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tjpj',
+                'pinyin' => 'tianjiapeijian',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/product/edit_part',
+                'title' => '修改配件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xgpj',
+                'pinyin' => 'xiugaipeijian',
+                'weigh' => 0,
+              ),
+              8 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/product/del_part',
+                'title' => '删除配件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scpj',
+                'pinyin' => 'shanchupeijian',
+                'weigh' => 0,
+              ),
+              9 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/product/recyclebin',
+                'title' => '回收站',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hsz',
+                'pinyin' => 'huishouzhan',
+                'weigh' => 0,
+              ),
+              10 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/product/destroy',
+                'title' => '真实删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zssc',
+                'pinyin' => 'zhenshishanchu',
+                'weigh' => 0,
+              ),
+              11 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/product/restore',
+                'title' => '还原',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hy',
+                'pinyin' => 'huanyuan',
+                'weigh' => 0,
+              ),
+              12 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/product/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+              13 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/product/get_type',
+                'title' => '产品分类',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'cpfl',
+                'pinyin' => 'chanpinfenlei',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          1 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/product/producttype',
+            'title' => '商品分类',
+            'icon' => 'fa fa-angle-right',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'cpfl',
+            'pinyin' => 'chanpinfenlei',
+            'weigh' => 6,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/producttype/import',
+                'title' => '导入',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'dr',
+                'pinyin' => 'daoru',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/producttype/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/producttype/recyclebin',
+                'title' => '回收站',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hsz',
+                'pinyin' => 'huishouzhan',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/producttype/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/producttype/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/producttype/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/producttype/destroy',
+                'title' => '真实删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zssc',
+                'pinyin' => 'zhenshishanchu',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/producttype/restore',
+                'title' => '还原',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hy',
+                'pinyin' => 'huanyuan',
+                'weigh' => 0,
+              ),
+              8 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/producttype/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          2 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/product/goods',
+            'title' => '商品信息',
+            'icon' => 'fa fa-angle-right',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => 'addtabs',
+            'extend' => '',
+            'py' => 'cpgl',
+            'pinyin' => 'chanpinguanli',
+            'weigh' => 10,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/goods/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/goods/add',
+                'title' => '新增',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'xz',
+                'pinyin' => 'xinzeng',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/goods/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/goods/detail',
+                'title' => '商品详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'spxq',
+                'pinyin' => 'shangpinxiangqing',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/goods/get_product',
+                'title' => '获取商品产品列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqspcplb',
+                'pinyin' => 'huoqushangpinchanpinliebiao',
+                'weigh' => 0,
+              ),
+              5 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/goods/get_product_type',
+                'title' => '获取产品分类',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqcpfl',
+                'pinyin' => 'huoquchanpinfenlei',
+                'weigh' => 0,
+              ),
+              6 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/goods/get_producttype',
+                'title' => '获取规格',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqgg',
+                'pinyin' => 'huoquguige',
+                'weigh' => 0,
+              ),
+              7 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/goods/get_producttype_detail',
+                'title' => '获取规格详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqggxq',
+                'pinyin' => 'huoquguigexiangqing',
+                'weigh' => 0,
+              ),
+              8 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/goods/del',
+                'title' => '删除商品',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scsp',
+                'pinyin' => 'shanchushangpin',
+                'weigh' => 0,
+              ),
+              9 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/goods/getstaff',
+                'title' => '获取员工',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'hqyg',
+                'pinyin' => 'huoquyuangong',
+                'weigh' => 0,
+              ),
+              10 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/goods/upload',
+                'title' => '上传文件',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'scwj',
+                'pinyin' => 'shangchuanwenjian',
+                'weigh' => 0,
+              ),
+              11 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/product/goods/import',
+                'title' => '导入',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            12 =>
+            array (
+                'type' => 'file',
+                'name' => 'qingdong/product/goods/get_specs',
+                'title' => '获取规格',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+            ),
+            13 =>
+            array (
+                'type' => 'file',
+                'name' => 'qingdong/product/goods/get_specs_detail',
+                'title' => '获取规格详情',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+            ),
+            ),
+          ),
+          3 =>
+          array (
+                'type' => 'file',
+                'name' => 'qingdong/product/specs',
+                'title' => '商品规格',
+                'icon' => 'fa fa-angle-right',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'cpfl',
+                'pinyin' => 'chanpinfenlei',
+                'weigh' => 5,
+                'sublist' =>
+                    array (
+                        0 =>
+                            array (
+                                'type' => 'file',
+                                'name' => 'qingdong/product/specs/import',
+                                'title' => '导入',
+                                'icon' => 'fa fa-circle-o',
+                                'url' => '',
+                                'condition' => '',
+                                'remark' => '',
+                                'ismenu' => 0,
+                                'menutype' => NULL,
+                                'extend' => '',
+                                'py' => 'dr',
+                                'pinyin' => 'daoru',
+                                'weigh' => 0,
+                            ),
+                        1 =>
+                            array (
+                                'type' => 'file',
+                                'name' => 'qingdong/product/specs/index',
+                                'title' => '查看',
+                                'icon' => 'fa fa-circle-o',
+                                'url' => '',
+                                'condition' => '',
+                                'remark' => '',
+                                'ismenu' => 0,
+                                'menutype' => NULL,
+                                'extend' => '',
+                                'py' => 'zk',
+                                'pinyin' => 'zhakan',
+                                'weigh' => 0,
+                            ),
+                        2 =>
+                            array (
+                                'type' => 'file',
+                                'name' => 'qingdong/product/specs/recyclebin',
+                                'title' => '回收站',
+                                'icon' => 'fa fa-circle-o',
+                                'url' => '',
+                                'condition' => '',
+                                'remark' => '',
+                                'ismenu' => 0,
+                                'menutype' => NULL,
+                                'extend' => '',
+                                'py' => 'hsz',
+                                'pinyin' => 'huishouzhan',
+                                'weigh' => 0,
+                            ),
+                        3 =>
+                            array (
+                                'type' => 'file',
+                                'name' => 'qingdong/product/specs/add',
+                                'title' => '添加',
+                                'icon' => 'fa fa-circle-o',
+                                'url' => '',
+                                'condition' => '',
+                                'remark' => '',
+                                'ismenu' => 0,
+                                'menutype' => NULL,
+                                'extend' => '',
+                                'py' => 'tj',
+                                'pinyin' => 'tianjia',
+                                'weigh' => 0,
+                            ),
+                        4 =>
+                            array (
+                                'type' => 'file',
+                                'name' => 'qingdong/product/specs/edit',
+                                'title' => '编辑',
+                                'icon' => 'fa fa-circle-o',
+                                'url' => '',
+                                'condition' => '',
+                                'remark' => '',
+                                'ismenu' => 0,
+                                'menutype' => NULL,
+                                'extend' => '',
+                                'py' => 'bj',
+                                'pinyin' => 'bianji',
+                                'weigh' => 0,
+                            ),
+                        5 =>
+                            array (
+                                'type' => 'file',
+                                'name' => 'qingdong/product/specs/del',
+                                'title' => '删除',
+                                'icon' => 'fa fa-circle-o',
+                                'url' => '',
+                                'condition' => '',
+                                'remark' => '',
+                                'ismenu' => 0,
+                                'menutype' => NULL,
+                                'extend' => '',
+                                'py' => 'sc',
+                                'pinyin' => 'shanchu',
+                                'weigh' => 0,
+                            ),
+                    ),
+            ),
+          4 =>
+          array (
+                'type' => 'file',
+                'name' => 'qingdong/product/unit',
+                'title' => '商品单位',
+                'icon' => 'fa fa-angle-right',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 1,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'cpfl',
+                'pinyin' => 'chanpinfenlei',
+                'weigh' => 5,
+                'sublist' =>
+                    array (
+                        0 =>
+                            array (
+                                'type' => 'file',
+                                'name' => 'qingdong/product/unit/import',
+                                'title' => '导入',
+                                'icon' => 'fa fa-circle-o',
+                                'url' => '',
+                                'condition' => '',
+                                'remark' => '',
+                                'ismenu' => 0,
+                                'menutype' => NULL,
+                                'extend' => '',
+                                'py' => 'dr',
+                                'pinyin' => 'daoru',
+                                'weigh' => 0,
+                            ),
+                        1 =>
+                            array (
+                                'type' => 'file',
+                                'name' => 'qingdong/product/unit/index',
+                                'title' => '查看',
+                                'icon' => 'fa fa-circle-o',
+                                'url' => '',
+                                'condition' => '',
+                                'remark' => '',
+                                'ismenu' => 0,
+                                'menutype' => NULL,
+                                'extend' => '',
+                                'py' => 'zk',
+                                'pinyin' => 'zhakan',
+                                'weigh' => 0,
+                            ),
+                        2 =>
+                            array (
+                                'type' => 'file',
+                                'name' => 'qingdong/product/unit/recyclebin',
+                                'title' => '回收站',
+                                'icon' => 'fa fa-circle-o',
+                                'url' => '',
+                                'condition' => '',
+                                'remark' => '',
+                                'ismenu' => 0,
+                                'menutype' => NULL,
+                                'extend' => '',
+                                'py' => 'hsz',
+                                'pinyin' => 'huishouzhan',
+                                'weigh' => 0,
+                            ),
+                        3 =>
+                            array (
+                                'type' => 'file',
+                                'name' => 'qingdong/product/unit/add',
+                                'title' => '添加',
+                                'icon' => 'fa fa-circle-o',
+                                'url' => '',
+                                'condition' => '',
+                                'remark' => '',
+                                'ismenu' => 0,
+                                'menutype' => NULL,
+                                'extend' => '',
+                                'py' => 'tj',
+                                'pinyin' => 'tianjia',
+                                'weigh' => 0,
+                            ),
+                        4 =>
+                            array (
+                                'type' => 'file',
+                                'name' => 'qingdong/product/unit/edit',
+                                'title' => '编辑',
+                                'icon' => 'fa fa-circle-o',
+                                'url' => '',
+                                'condition' => '',
+                                'remark' => '',
+                                'ismenu' => 0,
+                                'menutype' => NULL,
+                                'extend' => '',
+                                'py' => 'bj',
+                                'pinyin' => 'bianji',
+                                'weigh' => 0,
+                            ),
+                        5 =>
+                            array (
+                                'type' => 'file',
+                                'name' => 'qingdong/product/unit/del',
+                                'title' => '删除',
+                                'icon' => 'fa fa-circle-o',
+                                'url' => '',
+                                'condition' => '',
+                                'remark' => '',
+                                'ismenu' => 0,
+                                'menutype' => NULL,
+                                'extend' => '',
+                                'py' => 'sc',
+                                'pinyin' => 'shanchu',
+                                'weigh' => 0,
+                            ),
+                    ),
+            ),
+        ),
+      ),
+      9 => 
+      array (
+        'type' => 'file',
+        'name' => 'qingdongsystem',
+        'title' => '系统配置',
+        'icon' => 'fa fa-cog',
+        'url' => '',
+        'condition' => '',
+        'remark' => '',
+        'ismenu' => 1,
+        'menutype' => NULL,
+        'extend' => '',
+        'py' => 'xtpz',
+        'pinyin' => 'xitongpeizhi',
+        'weigh' => 0,
+        'sublist' => 
+        array (
+          0 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/general/adminconfig/index',
+            'title' => '规则设置',
+            'icon' => 'fa fa-arrows-alt',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'gzsz',
+            'pinyin' => 'guizeshezhi',
+            'weigh' => 20,
+          ),
+          1 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/general/adminconfig/wechat',
+            'title' => '参数设置',
+            'icon' => 'fa fa-cogs',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'cssz',
+            'pinyin' => 'canshushezhi',
+            'weigh' => 19,
+          ),
+          2 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/general/form',
+            'title' => '字段设置',
+            'icon' => 'fa fa-certificate',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'zdsz',
+            'pinyin' => 'ziduanshezhi',
+            'weigh' => 18,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/form/index',
+                'title' => '查看',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zk',
+                'pinyin' => 'zhakan',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/form/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/form/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/form/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/form/getinfo',
+                'title' => '字段设计',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'zdsj',
+                'pinyin' => 'ziduansheji',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          3 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/general/field',
+            'title' => '字段类型管理',
+            'icon' => 'fa fa-dedent',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'zdlxgl',
+            'pinyin' => 'ziduanleixingguanli',
+            'weigh' => 17,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/field/index',
+                'title' => '列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'lb',
+                'pinyin' => 'liebiao',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/general/field/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+        ),
+      ),
+      10 => 
+      array (
+        'type' => 'file',
+        'name' => 'qingdong/statistic/analytics',
+        'title' => '数据报表',
+        'icon' => 'fa fa-laptop',
+        'url' => '',
+        'condition' => '',
+        'remark' => '',
+        'ismenu' => 1,
+        'menutype' => NULL,
+        'extend' => '',
+        'py' => 'sjbb',
+        'pinyin' => 'shujubaobiao',
+        'weigh' => 0,
+        'sublist' => 
+        array (
+          0 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/statistic/analytics/index',
+            'title' => '数据报表',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 0,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'sjbb',
+            'pinyin' => 'shujubaobiao',
+            'weigh' => 0,
+          ),
+            1 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/achievement/index',
+                    'title' => '业绩目标完成',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            2 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/contract/newadd',
+                    'title' => '新增合同',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            3 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/contract/money',
+                    'title' => '合同金额统计',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            4 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/contract/receivables',
+                    'title' => '回款金额统计',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            5 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/customers/index',
+                    'title' => '客户总量分析',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            6 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/customers/record',
+                    'title' => '跟进次数分析',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            7 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/customers/recordtype',
+                    'title' => '客户跟进方式分析',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            8 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/customers/ratio',
+                    'title' => '客户跟进方式分析',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+
+            9 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/customers/ratios',
+                    'title' => '客户跟进方式分析',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            10 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/customers/customize',
+                    'title' => '客户自定义分析',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            11 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/customers/getstaff',
+                    'title' => '获取员工列表',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            12 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/ranking/index',
+                    'title' => '合同金额分析',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            13 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/ranking/contract',
+                    'title' => '回款金额分析',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            14 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/ranking/customer',
+                    'title' => '新增客户数分析',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            15 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/ranking/record',
+                    'title' => '跟进次数分析',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            16 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/work/report',
+                    'title' => '工作报告',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            17 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/work/record',
+                    'title' => '沟通日志',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+            18 =>
+                array (
+                    'type' => 'file',
+                    'name' => 'qingdong/statistic/work/record_list',
+                    'title' => '沟通日志列表',
+                    'icon' => 'fa fa-circle-o',
+                    'url' => '',
+                    'condition' => '',
+                    'remark' => '',
+                    'ismenu' => 0,
+                    'menutype' => NULL,
+                    'extend' => '',
+                    'py' => 'sjbb',
+                    'pinyin' => 'shujubaobiao',
+                    'weigh' => 0,
+                ),
+        ),
+      ),
+      11 => 
+      array (
+        'type' => 'file',
+        'name' => 'qingdong/attendance',
+        'title' => '考勤管理',
+        'icon' => 'fa fa-calendar',
+        'url' => '',
+        'condition' => '',
+        'remark' => '',
+        'ismenu' => 1,
+        'menutype' => 'addtabs',
+        'extend' => '',
+        'py' => 'kqgl',
+        'pinyin' => 'kaoqinguanli',
+        'weigh' => 5,
+        'sublist' => 
+        array (
+          0 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/attendance/card',
+            'title' => '我的补卡记录',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'wdbkjl',
+            'pinyin' => 'wodebukajilu',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/card/index',
+                'title' => '我的补卡记录',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'wdbkjl',
+                'pinyin' => 'wodebukajilu',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/card/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/card/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/card/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/card/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          1 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/attendance/out',
+            'title' => '我的外勤打卡记录',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'wdwqdkjl',
+            'pinyin' => 'wodewaiqindakajilu',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/out/index',
+                'title' => '外勤打卡记录',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'wqdkjl',
+                'pinyin' => 'waiqindakajilu',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/out/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/out/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/out/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/out/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          2 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/attendance/attendance',
+            'title' => '我的打卡记录',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'wddkjl',
+            'pinyin' => 'wodedakajilu',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/attendance/index',
+                'title' => '打卡记录列表',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'dkjllb',
+                'pinyin' => 'dakajiluliebiao',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/attendance/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/attendance/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/attendance/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/attendance/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          3 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/attendance/statisc',
+            'title' => '我的考勤统计',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'wdkqtj',
+            'pinyin' => 'wodekaoqintongji',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/statisc/index',
+                'title' => '我的考勤统计',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'wdkqtj',
+                'pinyin' => 'wodekaoqintongji',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/statisc/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/statisc/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/statisc/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/statisc/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+          4 => 
+          array (
+            'type' => 'file',
+            'name' => 'qingdong/attendance/leave',
+            'title' => '我的请假记录',
+            'icon' => 'fa fa-circle-o',
+            'url' => '',
+            'condition' => '',
+            'remark' => '',
+            'ismenu' => 1,
+            'menutype' => NULL,
+            'extend' => '',
+            'py' => 'wdqjjl',
+            'pinyin' => 'wodeqingjiajilu',
+            'weigh' => 0,
+            'sublist' => 
+            array (
+              0 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/leave/index',
+                'title' => '我的请假记录',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'wdqjjl',
+                'pinyin' => 'wodeqingjiajilu',
+                'weigh' => 0,
+              ),
+              1 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/leave/add',
+                'title' => '添加',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'tj',
+                'pinyin' => 'tianjia',
+                'weigh' => 0,
+              ),
+              2 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/leave/edit',
+                'title' => '编辑',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'bj',
+                'pinyin' => 'bianji',
+                'weigh' => 0,
+              ),
+              3 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/leave/del',
+                'title' => '删除',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'sc',
+                'pinyin' => 'shanchu',
+                'weigh' => 0,
+              ),
+              4 => 
+              array (
+                'type' => 'file',
+                'name' => 'qingdong/attendance/leave/multi',
+                'title' => '批量更新',
+                'icon' => 'fa fa-circle-o',
+                'url' => '',
+                'condition' => '',
+                'remark' => '',
+                'ismenu' => 0,
+                'menutype' => NULL,
+                'extend' => '',
+                'py' => 'plgx',
+                'pinyin' => 'pilianggengxin',
+                'weigh' => 0,
+              ),
+            ),
+          ),
+        ),
+      ),
+    ),
+  ),
+);

+ 361 - 0
addons/qingdong/controller/Achievement.php

@@ -0,0 +1,361 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Achievement as AchievementModel;
+use addons\qingdong\model\AchievementRecords;
+use addons\qingdong\model\ExamineRecord;
+use addons\qingdong\model\Flow;
+use addons\qingdong\model\Message;
+use addons\qingdong\model\StaffDepartment;
+use addons\qingdong\model\Staff;
+use think\Db;
+use think\Exception;
+
+/**
+ * 业绩管理接口
+ */
+class Achievement extends StaffApi {
+	protected $noNeedLogin = [];
+	protected $noNeedRight = [];
+
+
+    /**
+     * 部门列表
+     */
+	public function getDepartment() {
+		$department = StaffDepartment::where([])->field('id,name')->select();
+		$department = array_merge([['id' => 0, 'name' => '全部']], $department);
+
+		$this->success('请求成功', ['department' => $department, 'years' => getYears()]);
+	}
+
+
+    /**
+     * 获取员工业绩目标
+     */
+	public function getStaffList() {
+		$department_id = input('department_id');
+		$year          = input('year', date('Y'), 'intval');
+		$status        = input('status', 1);
+		$where         = [];
+		if ($department_id) {
+			$where['department_id'] = $department_id;
+		}
+		$where['status'] = 1;
+		$staffModel      = new Staff();
+		$staffs          = $staffModel->where($where)->field('id,name,img,post')->with([
+			'achievement' => function ($query) use ($year, $status) {
+				$query->where(['year' => $year, 'status' => $status])->field('yeartarget,obj_id');
+			},
+			'department'
+		])->select();
+
+		foreach ($staffs as $k => $v) {
+			if (empty($v['achievement'])) {
+				$v['achievement'] = ['yeartarget' => 0];
+			}
+			$staffs[$k] = $v;
+		}
+
+		$this->success('请求成功', $staffs);
+	}
+
+
+    /**
+     * 获取部门业绩列表
+     */
+	public function getDepartmentList() {
+		$year   = input('year', date('Y'), 'intval');
+		$status = input('status', 1);
+
+		$departmentModel = new StaffDepartment();
+		$staffs          = $departmentModel->where([])->field('id,name')->with([
+			'achievement' => function ($query) use ($year, $status) {
+				$query->where(['year' => $year, 'status' => $status])->field('yeartarget,obj_id');
+			},
+		])->select();
+
+		foreach ($staffs as $k => $v) {
+			if (empty($v['achievement'])) {
+				$v['achievement'] = ['yeartarget' => 0];
+			}
+			$staffs[$k] = $v;
+		}
+
+		$this->success('请求成功', $staffs);
+	}
+
+
+    /**
+     * 获取团队业绩
+     */
+	public function getTeamList() {
+		$year   = input('year', date('Y'), 'intval');
+		$status = input('status', 1);
+
+		$staffModel = new Staff();
+		//1最高管理员 2公司管理员 3部门经理 4部门主管 5组长 6员工
+		$staffs = $staffModel->where([
+			'role'     => ['in', [1, 2, 3, 4, 5]]
+		])->field('id,name,img,post')->with([
+			'teamAchievement' => function ($query) use ($year, $status) {
+				//团队
+				$query->where(['year' => $year, 'status' => $status])->field('yeartarget,obj_id');
+			},
+		])->select();
+		$staffs = collection($staffs)->toArray();
+		foreach ($staffs as $k => $v) {
+			$v['achievement'] = $v['team_achievement'] ?? ['yeartarget' => 0];
+			unset($v['team_achievement']);
+			$staffs[$k] = $v;
+		}
+
+		$this->success('请求成功', $staffs);
+	}
+
+
+    /**
+     * 获取公司目标
+     */
+	public function getCompanyAchievement() {
+		$year         = input('year', date('Y'), 'intval');
+		$status       = input('status', 1);//1销售(目标)2回款(目标)
+		$model        = new AchievementModel();
+		$achievements = $model->where([
+			'type'     => 1,
+			'obj_id'   => 1,
+			'year'     => $year,
+			'status'   => $status
+		])->find();
+		if (empty($achievements)) {
+			$model->save(['type' => 1, 'year' => $year, 'status' => $status]);
+			$achievements = $model->where(['type' => 1, 'year' => $year, 'status' => $status])->find();
+		}
+
+		$this->success('请求成功', $achievements);
+	}
+
+
+    /**
+     * 获取目标
+     */
+	public function getMyAchievementDetail() {
+		$year   = input('year', date('Y'), 'intval');
+		$status = input('status', 1);//1销售(目标)2回款(目标)
+
+		$model = new AchievementModel();
+		$row   = $model->where([
+			'obj_id'   => $this->auth->id,
+			'type'     => 3,
+			'year'     => $year,
+			'status'   => $status
+		])->find();
+		$this->success('请求成功', $row);
+	}
+
+    /**
+     * 获取目标详情
+     */
+	public function getAchievementDetail() {
+		$type   = input('type');
+		$year   = input('year', date('Y'), 'intval');
+		$status = input('status', 1);//1销售(目标)2回款(目标)
+		$ids    = input('ids');
+		if (empty($ids)) {
+			$this->error('参数不能为空');
+		}
+		$ids   = explode(',', $ids);
+		$model = new AchievementModel();
+		$row   = $model->where([
+			'obj_id'   => $ids[0],
+			'type'     => $type,
+			'year'     => $year,
+			'status'   => $status
+		])->find();
+		$this->success('请求成功', $row);
+	}
+
+
+    /**
+     * 添加或修改目标
+     */
+	public function addAchievement() {
+		$type         = input('type');
+		$year         = input('year', date('Y'), 'intval');
+		$status       = input('status', 1);//1销售(目标)2回款(目标)
+		$achievements = input('achievements/a');
+		$ids          = input('ids');
+		$yeartarget          = input('yeartarget',0);
+		$model        = new AchievementModel();
+		$ids          = explode(',', $ids);
+		$insertAll    = [];
+		foreach ($ids as $id) {
+			$insertAll[] = [
+				'type'       => $type,
+				'year'       => $year,
+				'status'     => $status,
+				'obj_id'     => $id,
+				'january'    => $achievements['january'] ?? 0,
+				'february'   => $achievements['february'] ?? 0,
+				'march'      => $achievements['march'] ?? 0,
+				'april'      => $achievements['april'] ?? 0,
+				'june'       => $achievements['june'] ?? 0,
+				'may'        => $achievements['may'] ?? 0,
+				'july'       => $achievements['july'] ?? 0,
+				'august'     => $achievements['august'] ?? 0,
+				'september'  => $achievements['september'] ?? 0,
+				'october'    => $achievements['october'] ?? 0,
+				'november'   => $achievements['november'] ?? 0,
+				'december'   => $achievements['december'] ?? 0,
+				'yeartarget' => $yeartarget,
+				'createtime' => time(),
+				'updatetime' => time()
+			];
+		}
+		Db::startTrans();
+		try {
+			$model->where([
+				'obj_id'   => ['in', $ids],
+				'type'     => $type,
+				'year'     => $year,
+				'status'   => $status
+			])->delete();
+
+			if ($model->insertAll($insertAll) == false) {
+				throw new Exception('提交失败');
+			}
+			Db::commit();;
+		} catch (Exception $e) {
+			Db::rollback();
+			$this->error($e->getMessage());
+		}
+
+		$this->success('提交成功!');
+	}
+
+
+    /**
+     * 获取目标详情
+     */
+	public function staffEditAchievement() {
+		$type         = 3;//员工
+		$year         = input('year', date('Y'), 'intval');
+		$status       = input('status', 1);//1销售(目标)2回款(目标)
+		$achievements = input('achievements/a');
+		$flow_staff_id = input('flow_staff_ids');
+        $yeartarget          = input('yeartarget',0);
+
+		$model        = new AchievementRecords();
+		$id = $this->auth->id;
+		$params = [
+			'type'          => $type,
+			'year'          => $year,
+			'status'        => $status,
+			'obj_id'        => $id,
+			'january'       => $achievements['january'] ?? 0,
+			'february'      => $achievements['february'] ?? 0,
+			'march'         => $achievements['march'] ?? 0,
+			'april'         => $achievements['april'] ?? 0,
+			'june'          => $achievements['june'] ?? 0,
+			'may'           => $achievements['may'] ?? 0,
+			'july'          => $achievements['july'] ?? 0,
+			'august'        => $achievements['august'] ?? 0,
+			'september'     => $achievements['september'] ?? 0,
+			'october'       => $achievements['october'] ?? 0,
+			'november'      => $achievements['november'] ?? 0,
+			'december'      => $achievements['december'] ?? 0,
+			'flow_staff_ids' => $flow_staff_id,
+            'owner_staff_id'=> $this->auth->id,
+			'check_status'  => 0,
+			'yeartarget'    => $yeartarget,
+			'createtime'    => time(),
+			'updatetime'    => time()
+		];
+
+		Db::startTrans();
+		try {
+
+            $flow = Flow::getsteplist(Flow::ACHIEVEMENT_STATUS);
+            $params['flow_id'] = $flow['flow_id'];
+            $params['order_id'] = $flow['order_id'];
+
+            if ($flow['status'] == 0) {//发起人自选
+                if (empty($params['flow_staff_ids'])) {
+                    throw new Exception('审批人必须选择');
+                }
+                $params['flow_staff_ids'] = trim($params['flow_staff_ids']);
+            } else {
+                if (empty($flow['flow_staff_ids'])) {
+                    throw new Exception('没有直属上级无法审批,请联系管理员!');
+                }
+                $params['flow_staff_ids'] = trim($flow['flow_staff_ids']);
+            }
+
+			if ($model->insert($params) === false) {
+				throw new Exception('添加失败');
+			}
+			$lastId     = $model->getLastInsID();
+
+            if ($flow['status'] == 1) {//固定审批
+                //发送审批通知
+                Flow::sendStepRecord($flow,Flow::ACHIEVEMENT_STATUS, $lastId);
+            } else {//发起人自选 依次审批
+                $staff_id   = explode(',', $params['flow_staff_ids'])[0];
+                if ($staff_id) {
+                    ExamineRecord::addExaminse(ExamineRecord::ACHIEVEMENT_TYPE, $lastId, $staff_id);
+                }
+            }
+			Db::commit();;
+		} catch (Exception $e) {
+			Db::rollback();
+			$this->error($e->getMessage());
+		}
+
+		$this->success('提交成功,等待审核!');
+	}
+
+    /**
+     * 员工自己修改目标
+     */
+	public function editRecords(){
+		$department_id = input('department_id');
+		$year          = input('year', date('Y'), 'intval');
+		$status        = input('status', 1);
+		$limit         = input("limit/d", 10);
+		$where         = [];
+		if ($department_id) {
+			$where['department_id'] = $department_id;
+		}
+		$where['year'] = $year;
+		$where['status'] = $status;
+
+		$model        = new AchievementRecords();
+
+		$list = $model->where(['type'=>3,'obj_id'=>$this->auth->id])->where($where)->with(['staff'])->order('id desc')->paginate($limit);
+		
+		$this->success('请求成功',$list);
+	}
+
+    /**
+     * 获取业绩详情表
+     */
+	public function getRecordsDetail(){
+		$id=input('id');
+		$model        = new AchievementRecords();
+
+		$records = $model->where(['id'=>$id])->with(['staff'])->find();
+		if (empty($records)) {
+			$this->error('业绩目标不存在');
+		}
+
+		if ($records['check_status'] == 0 || $records['check_status'] == 1) {
+			$records['is_examine'] = ExamineRecord::isExaminse(ExamineRecord::ACHIEVEMENT_TYPE, $id);
+		} else {
+			$records['is_examine'] = 0;
+		}
+		//标记通知已读
+		Message::setRead(Message::ACHIEVEMENT_TYPE, $id, $this->auth->id);
+		$this->success('请求成功', $records);
+	}
+}

+ 216 - 0
addons/qingdong/controller/Approval.php

@@ -0,0 +1,216 @@
+<?php
+
+namespace  addons\qingdong\controller;
+
+
+use  addons\qingdong\model\Approval as ApprovalModel;
+use  addons\qingdong\model\ExamineRecord;
+use addons\qingdong\model\File;
+use  addons\qingdong\model\FormApproval;
+use  addons\qingdong\model\Message;
+use  addons\qingdong\model\Staff;
+use  addons\qingdong\model\Form;
+use think\Db;
+use think\Exception;
+
+/**
+ * 工作审批
+ */
+class Approval extends StaffApi {
+	protected $noNeedLogin = [];
+	protected $noNeedRight = [];
+
+
+    /**
+     * 审核审核记录
+     */
+	public function examineApprovalList(){
+        $check_status=input('check_status');//1审核中、2审核通过、3审核未通过
+        $formapproval_id=input('formapproval_id');//
+        $times=input('times');//
+        $where=[];
+        if($formapproval_id){
+            $where['formapproval_id']=$formapproval_id;
+        }
+        if($times){
+            $times = explode(',', $times);
+            $where['createtime']=['between',[strtotime($times[0]),strtotime($times[1])+86400-1]];
+        }
+        if ($check_status) {
+            //0待审核、1审核中、2审核通过、3审核未通过、4撤销
+            if ($check_status == 1) {
+                $where['check_status'] = ['in', [0, 1]];
+            } elseif ($check_status == 2) {
+                $where['check_status'] = 2;
+            } elseif ($check_status == 3) {
+                $where['check_status'] = 3;
+            } elseif ($check_status == 4) {
+                $where['check_status'] = 4;
+            } elseif ($check_status == 9) {
+                $where['check_status'] = 9;
+            }
+        }
+        $type       = input('type', 0);// 0 全部 1 我创建 2 下属创建
+        if ($type == 1) {//我的客户
+            $where['create_staff_id'] = $this->auth->id;
+        } elseif ($type == 2) {//下属负责的客户
+            $where['create_staff_id'] = ['in', Staff::getLowerStaffId()];
+        }else{
+            $where['create_staff_id'] = ['in', Staff::getMyStaffIds()];
+        }
+
+        $staff_id=$this->auth->id;
+        $approvals= ApprovalModel::where($where)->where(function ($query) use ($staff_id){
+            $query->where('create_staff_id',$staff_id)
+                ->whereOr('','exp', Db::raw('FIND_IN_SET(' . $staff_id. ',flow_staff_ids)'));
+        })->with(['createStaff','formapproval'])->order('id desc')->paginate();
+
+       $this->success('请求成功',$approvals);
+    }
+
+    /**
+     * 获取工作列表
+     */
+	public function getList() {
+		$list = FormApproval::where([])->field('id,name,img')->select();
+
+		$this->success('请求成功', $list);
+	}
+
+
+    /**
+     * 获取form表单
+     */
+	public function getFormapproval() {
+		$id = input('id');
+		$form = FormApproval::where(['id' => $id])->find();
+        $staff = Staff::where(['id' => ['in',explode(',', $form['flow_staff_ids'])]])->field('id,name,img')->select();
+        $forminfo = Form::where(array('id'=>$form['form_id']))->find();
+        $data=json_decode($forminfo['data'], true)['data']??[];
+		$this->success('请求成功',['data'=>$data,'staff'=>$staff] );
+	}
+
+
+    /**
+     * 添加审批
+     */
+	public function addApproval() {
+		$params          = $this->request->post();
+        if(empty( $params['data'])){
+            $this->error('数据不能为空');
+        }
+        if(empty( $params['formapproval_id'])){
+            $this->error('表单id不能为空');
+        }
+
+		$result = ApprovalModel::createApproval($params);
+
+		$this->success('保存成功');
+	}
+
+    /**
+     * 获取审批详情
+     */
+	public function getDetail(){
+        $id       = input('id');
+        if(empty($id)){
+            $this->error('参数不能为空');
+        }
+        $approval=ApprovalModel::where(['id'=>$id])->with(['formapproval'])->find()->toArray();
+        $type = Form::where(array('id'=>$approval['formapproval']['form_id']))->value('type');
+
+        $form = Form::getDataValue($type,$approval['content']);
+        foreach($form as $k=>$v){
+            if($v['component'] == 'uploadImage' || $v['component'] == 'uploadFile'){
+                if(key_exists($v['id'],$approval['content'])){
+                    if(isset($approval['content'][$v['id']]) && $approval['content'][$v['id']]){
+                        $whereT['id'] = array('in',$approval['content'][$v['id']]);
+                        $fileinfo = File::where($whereT)->field('id,name,file_path')->select();
+                        if($fileinfo){
+                            $approval['content'][$v['id']] = $fileinfo;
+                        }
+                    }
+                }
+            }elseif($v['component'] == 'select'){
+                if(isset($v['config']['multiple']) &&  $v['config']['multiple'] == true){
+                    if(key_exists($v['id'],$approval['content'])){
+                        if(is_array($approval['content'][$v['id']]) && $approval['content'][$v['id']]){
+                            $approval['content'][$v['id']] = implode(',',$approval['content'][$v['id']]);
+                        }
+                    }
+                }
+            }
+        }
+        if ($approval['check_status'] == 0 || $approval['check_status'] == 1) {
+            $approval['is_examine'] = ExamineRecord::isExaminse(ExamineRecord::APPROVAL_TYPE, $id);
+        } else {
+            $approval['is_examine'] = 0;
+        }
+        $approval['is_operation']=0;
+        if($approval['create_staff_id'] == $this->auth->id){
+            //是否可以操作
+            $approval['is_operation']=1;
+        }
+        Message::setRead(Message::APPROVAL_TYPE,$id,$this->auth->id);
+        $this->success('请求成功',$approval);
+    }
+
+    /**
+     * 修改审批
+     */
+    public function editApproval(){
+        $id     = input('id');
+        $params = $this->request->post();
+        $row    = ApprovalModel::where(['id' => $id, 'check_status' => ['in', [3, 4]]])->find();
+        if (empty($row)) {
+            $this->error('审批信息不存在');
+        }
+        if(empty( $params['data'])){
+            $this->error('数据不能为空');
+        }
+        if(empty( $params['formapproval_id'])){
+            $this->error('表单id不能为空');
+        }
+        if(empty( $params['relation_type'])){
+            $this->error('关联类型不能为空');
+        }
+
+        Db::startTrans();
+        try {
+            $result = ApprovalModel::updateApproval($params);
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        $this->success('修改信息成功');
+    }
+
+    /**
+     * 撤回审批
+     */
+	public function cancel(){
+        $id       = input('id');
+        $customer = ApprovalModel::where(['id' => $id, 'check_status' => ['in', [0, 1]]])->find();
+        if (empty($customer)) {
+            $this->error('信息不存在');
+        }
+
+        Db::startTrans();
+        try {
+
+            ApprovalModel::where(['id' => $id])->update(['check_status' => 4]);
+
+            ExamineRecord::cancelExaminse(ExamineRecord::APPROVAL_TYPE,$id);
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();;
+            $this->error($e->getMessage());
+        }
+
+
+        $this->success('撤回成功');
+    }
+
+
+}

+ 1355 - 0
addons/qingdong/controller/Attendance.php

@@ -0,0 +1,1355 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+
+use addons\qingdong\model\Approval;
+use  addons\qingdong\model\Attendance as AttendanceModel;
+use  addons\qingdong\model\AttendanceRule;
+use addons\qingdong\model\AttendanceAddress;
+use  addons\qingdong\model\AttendanceTime;
+use  addons\qingdong\model\AttendanceCard;
+use addons\qingdong\model\ExamineRecord;
+use  addons\qingdong\model\AttendanceStatisc;
+use addons\qingdong\model\File;
+use addons\qingdong\model\Form;
+use addons\qingdong\model\FormApproval;
+use addons\qingdong\model\Leave;
+use addons\qingdong\model\Message;
+use  addons\qingdong\model\Staff;
+use  addons\qingdong\model\Flow;
+use think\Db;
+use think\Exception;
+
+/**
+ * 考勤
+ */
+class Attendance extends StaffApi
+{
+    protected $noNeedLogin = ['autotask'];
+    protected $noNeedRight = [];
+
+    //规则列表
+    public function rule_list()
+    {
+        $list = AttendanceRule::where([])->select();
+        foreach ($list as $k => $v) {
+            $address = AttendanceAddress::where([])->limit(6)->column('address');
+            $list[$k]['address_info'] = '';
+            if ($address) {
+                $list[$k]['address_info'] = implode(',', $address);
+            }
+            $list[$k]['staff_info'] = '';
+            $staff = Staff::where(array('id' => array('in', $v['staff_id'])))->limit(6)->column('name');
+            if ($staff) {
+                $list[$k]['staff_info'] = implode(',', $staff);
+            }
+            $time = AttendanceTime::where([])->limit(6)->select();
+            $monday = false;
+            $tuesday = false;
+            $wednesday = false;
+            $thursday = false;
+            $friday = false;
+            $saturday = false;
+            $weekday = false;
+
+            foreach ($time as $ks => $vs) {
+                if ($vs['monday'] == 1) {
+                    $monday = true;
+                }
+                if ($vs['tuesday'] == 1) {
+                    $tuesday = true;
+                }
+                if ($vs['wednesday'] == 1) {
+                    $wednesday = true;
+                }
+                if ($vs['thursday'] == 1) {
+                    $thursday = true;
+                }
+                if ($vs['friday'] == 1) {
+                    $friday = true;
+                }
+                if ($vs['saturday'] == 1) {
+                    $saturday = true;
+                }
+                if ($vs['weekday'] == 1) {
+                    $weekday = true;
+                }
+
+            }
+            $list[$k]['time_info'] = '';
+            if ($monday && $tuesday && $wednesday && $thursday && !$friday && !$saturday && !$weekday) {
+                $list[$k]['time_info'] = '周一至周四';
+            } elseif ($monday && $tuesday && $wednesday && $thursday && $friday && !$saturday && !$weekday) {
+                $list[$k]['time_info'] = '周一至周五';
+            } elseif ($monday && $tuesday && $wednesday && $thursday && $friday && $saturday && !$weekday) {
+                $list[$k]['time_info'] = '周一至周六';
+            } elseif ($monday && $tuesday && $wednesday && $thursday && $friday && $saturday && $weekday) {
+                $list[$k]['time_info'] = '周一至周日';
+            } else {
+                $timeArr = array(
+                    $monday ? '周一' : '',
+                    $tuesday ? '周二' : '',
+                    $wednesday ? '周三' : '',
+                    $thursday ? '周四' : '',
+                    $friday ? '周五' : '',
+                    $saturday ? '周六' : '',
+                    $weekday ? '周日' : '',
+                );
+                $timeArr = array_filter($timeArr);
+                if ($timeArr) {
+                    $list[$k]['time_info'] = implode(',', $timeArr);
+                }
+
+            }
+        }
+        $this->success('请求成功', $list);
+    }
+
+    //规则详情
+    public function rule_detail()
+    {
+        $params = $this->request->post();
+        $id = $params['id'];
+        if (!isset($params['id']) || !$params['id']) {
+            $this->error('ID不能为空');
+        }
+        $list = AttendanceRule::where(['id' => $id])->find();
+        if ($list) {
+            $address = AttendanceAddress::where([])->limit(6)->column('address');
+            $list['address_info'] = '';
+            if ($address) {
+                $list['address_info'] = implode(',', $address);
+            }
+            $list['staff_info'] = [];
+            $staff = Staff::where(array('id' => array('in', $list['staff_id'])))->field('id,img,name')->select();
+            if ($staff) {
+                $list['staff_info'] = $staff;
+            }
+            $time = AttendanceTime::where([])->limit(6)->select();
+            $monday = false;
+            $tuesday = false;
+            $wednesday = false;
+            $thursday = false;
+            $friday = false;
+            $saturday = false;
+            $weekday = false;
+            $list['time_info'] = '';
+            if ($time) {
+                foreach ($time as $ks => $vs) {
+                    if ($vs['monday'] == 1) {
+                        $monday = true;
+                    }
+                    if ($vs['tuesday'] == 1) {
+                        $tuesday = true;
+                    }
+                    if ($vs['wednesday'] == 1) {
+                        $wednesday = true;
+                    }
+                    if ($vs['thursday'] == 1) {
+                        $thursday = true;
+                    }
+                    if ($vs['friday'] == 1) {
+                        $friday = true;
+                    }
+                    if ($vs['saturday'] == 1) {
+                        $saturday = true;
+                    }
+                    if ($vs['weekday'] == 1) {
+                        $weekday = true;
+                    }
+
+                }
+
+                if ($monday && $tuesday && $wednesday && $thursday && !$friday && !$saturday && !$weekday) {
+                    $list['time_info'] = '周一至周四';
+                } elseif ($monday && $tuesday && $wednesday && $thursday && $friday && !$saturday && !$weekday) {
+                    $list['time_info'] = '周一至周五';
+                } elseif ($monday && $tuesday && $wednesday && $thursday && $friday && $saturday && !$weekday) {
+                    $list['time_info'] = '周一至周六';
+                } elseif ($monday && $tuesday && $wednesday && $thursday && $friday && $saturday && $weekday) {
+                    $list['time_info'] = '周一至周日';
+                } else {
+                    $timeArr = array(
+                        $monday ? '周一' : '',
+                        $tuesday ? '周二' : '',
+                        $wednesday ? '周三' : '',
+                        $thursday ? '周四' : '',
+                        $friday ? '周五' : '',
+                        $saturday ? '周六' : '',
+                        $weekday ? '周日' : '',
+                    );
+                    $timeArr = array_filter($timeArr);
+                    if ($timeArr) {
+                        $list['time_info'] = implode(',', $timeArr);
+                    }
+
+                }
+            }
+
+        }
+
+        $this->success('请求成功', $list);
+    }
+
+    //规则添加
+    public function rule_add()
+    {
+        $params = $this->request->post();
+
+        if (!isset($params['name']) || !$params['name']) {
+            $this->error('规则名称不能为空');
+        }
+        if (!isset($params['staff_id']) || !$params['staff_id']) {
+            $this->error('打卡人员不能为空');
+        }
+
+
+        $ret = array(
+            'name' => $params['name'],
+            'staff_id' => $params['staff_id'],
+            'type' => $params['type'],
+        );
+        Db::startTrans();
+        try {
+            $result = AttendanceRule::create($ret);
+            if (!$result) {
+                throw new Exception('添加失败');
+            }
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+
+        $this->success('添加成功');
+    }
+
+    //规则修改
+    public function rule_update()
+    {
+        $params = $this->request->post();
+        $id = $params['id'];
+        if (!isset($params['id']) || !$params['id']) {
+            $this->error('ID不能为空');
+        }
+        if (!isset($params['name']) || !$params['name']) {
+            $this->error('规则名称不能为空');
+        }
+        if (!isset($params['staff_id']) || !$params['staff_id']) {
+            $this->error('打卡人员不能为空');
+        }
+
+        $ret = array(
+            'name' => $params['name'],
+            'staff_id' => $params['staff_id'],
+            'type' => $params['type'],
+        );
+        Db::startTrans();
+        try {
+
+            $result = AttendanceRule::where(array('id' => $id))->update($ret);
+            if ($result === false) {
+                throw new Exception('修改失败');
+            }
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+
+        $this->success('修改成功');
+    }
+
+    //规则删除
+    public function rule_dels()
+    {
+        $params = $this->request->post();
+        $id = $params['id'];
+        if (!isset($params['id']) || !$params['id']) {
+            $this->error('ID不能为空');
+        }
+
+        $ret = array(
+            'updatetime' => time(),
+            'deletetime' => time(),
+        );
+        Db::startTrans();
+        try {
+
+            $result = AttendanceRule::where(array('id' => $id))->update($ret);
+
+            if (!$result) {
+                throw new Exception('删除失败');
+            }
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+
+        $this->success('修改成功');
+    }
+
+    //时间段列表
+    public function time_list()
+    {
+        $list = AttendanceTime::where([])->select();
+
+        $datainfo = [];
+        $number = '';
+        $timeR = '';
+        $kinfo = 0;
+        foreach ($list as $k => $v) {
+            $monday = false;
+            $tuesday = false;
+            $wednesday = false;
+            $thursday = false;
+            $friday = false;
+            $saturday = false;
+            $weekday = false;
+            if ($v['monday'] == 1) {
+                $monday = true;
+            }
+            if ($v['tuesday'] == 1) {
+                $tuesday = true;
+            }
+            if ($v['wednesday'] == 1) {
+                $wednesday = true;
+            }
+            if ($v['thursday'] == 1) {
+                $thursday = true;
+            }
+            if ($v['friday'] == 1) {
+                $friday = true;
+            }
+            if ($v['saturday'] == 1) {
+                $saturday = true;
+            }
+            if ($v['weekday'] == 1) {
+                $weekday = true;
+            }
+            $time_info = '';
+
+            $timeR = $v['start_time'];
+            if ($number != $v['number']) {
+                if ($monday && $tuesday && $wednesday && $thursday && !$friday && !$saturday && !$weekday) {
+                    $time_info = '周一至周四';
+                } elseif ($monday && $tuesday && $wednesday && $thursday && $friday && !$saturday && !$weekday) {
+                    $time_info = '周一至周五';
+                } elseif ($monday && $tuesday && $wednesday && $thursday && $friday && $saturday && !$weekday) {
+                    $time_info = '周一至周六';
+                } elseif ($monday && $tuesday && $wednesday && $thursday && $friday && $saturday && $weekday) {
+                    $time_info = '周一至周日';
+                } else {
+                    $timeArr = array(
+                        $monday ? '周一' : '',
+                        $tuesday ? '周二' : '',
+                        $wednesday ? '周三' : '',
+                        $thursday ? '周四' : '',
+                        $friday ? '周五' : '',
+                        $saturday ? '周六' : '',
+                        $weekday ? '周日' : '',
+                    );
+                    $timeArr = array_filter($timeArr);
+                    if ($timeArr) {
+                        $time_info = implode(',', $timeArr);
+                    }
+
+                }
+                $datainfo[] = array(
+                    'number' => $v['number'],
+                    'week' => $time_info,
+                    'time' => $timeR . '-' . $v['end_time'],
+                );
+                $kinfo = $k;
+            } else {
+                $datainfo[$kinfo]['time'] = $timeR . '-' . $v['end_time'];
+            }
+            $number = $v['number'];
+        }
+
+
+        $this->success('请求成功', $datainfo);
+    }
+
+    //时间段详情
+    public function time_detail()
+    {
+        $params = $this->request->post();
+        if (!isset($params['number']) || !$params['number']) {
+            $this->error('参数不正确');
+        }
+        $list = AttendanceTime::where(array('number' => $params['number']))->select();
+        $data = [];
+        $time = [];
+        if ($list) {
+            foreach ($list as $k => $v) {
+                $time[] = array(
+                    'start_time' => $v['start_time'],
+                    'end_time' => $v['end_time'],
+                    'ustart_time' => $v['ustart_time'],
+                    'uend_time' => $v['uend_time'],
+                    'dstart_time' => $v['dstart_time'],
+                    'dend_time' => $v['dend_time'],
+                    'start_status' => $v['start_status'],
+                    'end_status' => $v['end_status'],
+                    'start_next' => $v['start_next'],
+                    'end_next' => $v['end_next'],
+                );
+            }
+            $settime = '';
+            if ($time) {
+                $count = count($time);
+                if ($time[0]['start_next'] == 1) {
+                    $set_starttime = '次日' . $time[0]['start_time'];
+                } else {
+                    $set_starttime = $time[0]['start_time'];
+                }
+                if ($time[$count - 1]['end_next'] == 1) {
+                    $set_endtime = '次日' . $time[$count - 1]['end_time'];
+                } else {
+                    $set_endtime = $time[$count - 1]['end_time'];
+                }
+                $settime = $set_starttime . '-' . $set_endtime;
+            }
+            $data = array(
+                'number' => $params['number'],
+                'time' => $time,
+                'settime' => $settime,
+
+                'monday' => $list[0]['monday'],
+                'tuesday' => $list[0]['tuesday'],
+                'wednesday' => $list[0]['wednesday'],
+                'thursday' => $list[0]['thursday'],
+                'friday' => $list[0]['friday'],
+                'saturday' => $list[0]['saturday'],
+                'weekday' => $list[0]['weekday'],
+            );
+        }
+
+        $this->success('请求成功', $data);
+    }
+
+    //时间段增加
+    public function time_add()
+    {
+        $params = $this->request->post();
+        if (!isset($params['time']) || !$params['time'] || !is_array($params['time'])) {
+            //    $this->error('请设置打卡时段');
+        }
+
+        $number = time() . rand(11111, 99999);
+        $resultTime = false;
+        foreach ($params['time'] as $k => $v) {
+            $rettime = array(
+                'number' => $number,
+                'start_time' => $v['start_time'],
+                'end_time' => $v['end_time'],
+                'ustart_time' => $v['ustart_time'],
+                'uend_time' => $v['uend_time'],
+                'dstart_time' => $v['dstart_time'],
+                'dend_time' => $v['dend_time'],
+                'start_status' => $v['start_status'],
+                'end_status' => $v['end_status'],
+                'start_next' => $v['start_next'],
+                'end_next' => $v['end_next'],
+                'monday' => $params['monday'],
+                'tuesday' => $params['tuesday'],
+                'wednesday' => $params['wednesday'],
+                'thursday' => $params['thursday'],
+                'friday' => $params['friday'],
+                'saturday' => $params['saturday'],
+                'weekday' => $params['weekday'],
+            );
+            $resultTime = AttendanceTime::create($rettime);
+            $ids[] = AttendanceTime::getLastInsID();
+
+        }
+
+        if (!$resultTime) {
+            $this->error('添加失败');
+        }
+        $this->success('添加成功', ['id' => implode(',', $ids)]);
+    }
+
+    //时间段修改
+    public function time_update()
+    {
+        $params = $this->request->post();
+        if (!isset($params['number']) || !$params['number']) {
+            $this->error('时间段编号不能为空');
+        }
+        if (!isset($params['time']) || !$params['time'] || !is_array($params['time'])) {
+            $this->error('请设置打卡时段');
+        }
+        AttendanceTime::where(['number' => $params['number']])->update(array('deletetime' => time()));
+        $number = time() . rand(11111, 99999);
+        $resultTime = false;
+        foreach ($params['time'] as $k => $v) {
+            $rettime = array(
+                'number' => $number,
+                'start_time' => $v['start_time'],//开始时间
+                'end_time' => $v['end_time'],//结束时间
+                'ustart_time' => $v['ustart_time'],//可打卡开始时间
+                'uend_time' => $v['uend_time'],//可打卡结束时间
+                'dstart_time' => $v['dstart_time'],//下班可打卡开始时间
+                'dend_time' => $v['dend_time'],//下班可打卡结束时间
+                'start_next' => $v['start_next'],//0:非次日   1:次日
+                'end_next' => $v['end_next'],//0:非次日   1:次日
+                'start_status' => $v['start_status'],//上班打卡0:开启 1:关闭
+                'end_status' => $v['end_status'],//下班打卡0:开启 1:关闭
+                'monday' => $params['monday'],//周一  0未选择 1:已选择
+                'tuesday' => $params['tuesday'],
+                'wednesday' => $params['wednesday'],
+                'thursday' => $params['thursday'],
+                'friday' => $params['friday'],
+                'saturday' => $params['saturday'],
+                'weekday' => $params['weekday'],//周日
+            );
+            $resultTime = AttendanceTime::create($rettime);
+            $ids[] = AttendanceTime::getLastInsID();
+        }
+        $rule = AttendanceRule::where([])->find();
+        if ($rule) {
+//            AttendanceRule::where(array('id' => ['egt', 1]))->update(array('time_id' => implode(',', $ids)));
+        }
+        if (!$resultTime) {
+            $this->error('修改失败');
+        }
+        $this->success('修改成功', ['id' => implode(',', $ids)]);
+    }
+
+    //时间段删除
+    public function time_del()
+    {
+        $params = $this->request->post();
+        if (!isset($params['number']) || !$params['number']) {
+            $this->error('参数不正确');
+        }
+        $number = $params['number'];
+
+        $resultTime = AttendanceTime::where(array('number' => $number))->update(array('deletetime' => time()));
+        if (!$resultTime) {
+            $this->error('删除失败');
+        }
+        $this->success('删除成功');
+    }
+
+    //星期是否设置
+    public function is_week()
+    {
+        $list = AttendanceTime::where([])->select();
+        $monday = 0;
+        $tuesday = 0;
+        $wednesday = 0;
+        $thursday = 0;
+        $friday = 0;
+        $saturday = 0;
+        $weekday = 0;
+        foreach ($list as $k => $v) {
+            if ($v['monday'] == 1) {
+                $monday = 1;
+            }
+            if ($v['tuesday'] == 1) {
+                $tuesday = 1;
+            }
+            if ($v['wednesday'] == 1) {
+                $wednesday = 1;
+            }
+            if ($v['thursday'] == 1) {
+                $thursday = 1;
+            }
+            if ($v['friday'] == 1) {
+                $friday = 1;
+            }
+            if ($v['saturday'] == 1) {
+                $saturday = 1;
+            }
+            if ($v['weekday'] == 1) {
+                $weekday = 1;
+            }
+
+        }
+        $data = array(
+            'monday' => $monday,
+            'tuesday' => $tuesday,
+            'wednesday' => $wednesday,
+            'thursday' => $thursday,
+            'friday' => $friday,
+            'saturday' => $saturday,
+            'weekday' => $weekday,
+        );
+
+
+        $this->success('请求成功', $data);
+    }
+
+    //地址列表
+    public function address_list()
+    {
+        $list = AttendanceAddress::where([])->select();
+        $this->success('请求成功', $list);
+    }
+
+    //地址详情
+    public function address_detail()
+    {
+        $params = $this->request->post();
+        if (!isset($params['id']) || !$params['id']) {
+            $this->error('参数不正确');
+        }
+        $list = AttendanceAddress::where(array('id' => ['in', $params['id']]))->find();
+        $this->success('请求成功', $list);
+    }
+
+    //地址增加
+    public function address_add()
+    {
+        $params = $this->request->post();
+        if (!$params['address']) {
+            $this->error('地址不能为空');
+        }
+        if (!$params['distance']) {
+            $this->error('距离不能为空');
+        }
+        if (!$params['lng'] || !$params['lat']) {
+            $this->error('经纬度不能为空');
+        }
+        $retaddr = array(
+            'address' => $params['address'],
+            'address_detail' => $params['address_detail'],
+            'distance' => $params['distance'],
+            'lng' => $params['lng'],
+            'lat' => $params['lat'],
+        );
+        $resultAddr = AttendanceAddress::create($retaddr);
+        if (!$resultAddr) {
+            $this->error('添加失败');
+        }
+        $id = AttendanceAddress::getLastInsID();
+        $this->success('添加成功', ['id' => $id]);
+    }
+
+    //地址修改
+    public function address_update()
+    {
+        $params = $this->request->post();
+        if (!$params['id']) {
+            $this->error('参数不正确');
+        }
+        if (!$params['address']) {
+            $this->error('地址不能为空');
+        }
+        if (!$params['distance']) {
+            $this->error('距离不能为空');
+        }
+        if (!$params['lng'] || !$params['lat']) {
+            $this->error('经纬度不能为空');
+        }
+        $retaddr = array(
+            'address' => $params['address'],
+            'address_detail' => $params['address_detail'],
+            'distance' => $params['distance'],
+            'lng' => $params['lng'],
+            'lat' => $params['lat'],
+        );
+        $resultAddr = AttendanceAddress::where(array('id' => $params['id']))->update($retaddr);
+        if (!$resultAddr) {
+            $this->error('修改失败');
+        }
+        $this->success('修改成功');
+    }
+
+    //地址删除
+    public function address_del()
+    {
+        $params = $this->request->post();
+        if (!isset($params['id']) || !$params['id']) {
+            $this->error('参数不正确');
+        }
+        $id = $params['id'];
+        $resultTime = AttendanceAddress::where(array('id' => $id))->update(array('deletetime' => time()));
+        if (!$resultTime) {
+            $this->error('删除失败');
+        }
+        $this->success('删除成功');
+    }
+
+    /**
+     * 打卡
+     */
+    public function card_add()
+    {
+        $params = $this->request->post();
+        if (!isset($params['type'])) { //0:上下班 1:外出
+            $this->error('类型不能为空');
+        }
+        if (!$params['lng'] || !$params['lat']) {
+            $this->error('经纬度不能为空');
+        }
+        //判断距离
+        $address = AttendanceAddress::where([])->select();
+        $disinfo = false;
+        foreach ($address as $k => $v) {
+            $distance = getdistance($params['lng'], $params['lat'], $v['lng'], $v['lat']);
+            if ($v['distance'] >= $distance) {
+                $disinfo = true;
+                $address = $v['address'];
+            }
+        }
+        if (!$disinfo) {
+            $this->error('您不在打卡范围');
+        }
+        $id = input('id', 0, 'intval');
+        $find = AttendanceStatisc::where(['id' => $id])->find();
+        if (empty($find)) {
+            $this->error('打卡信息不存在');
+        }
+        //判断打卡是否为次日
+        $today = AttendanceStatisc::where(['time' => $find['time']])->select();
+        $today = collection($today)->toArray();
+        $start = $today[0]['ustart_time'];
+        $nowtime = time();
+        //当天首次打卡时间
+        $todaytime1 = strtotime($find['time'] . $start);
+
+        //上班
+        $s1 = strtotime($find['time'] . $find['start_time']);
+        //下班打卡
+        $s2 = strtotime($find['time'] . $find['end_time']);
+        $s1 = ($s1 < $todaytime1) ? $s1 + 86400 : $s1;//是否为次日
+        $s2 = ($s2 < $todaytime1) ? $s2 + 86400 : $s2;//
+
+        //早退
+        $staff = Staff::info();
+        $row = array(
+            'staff_id' => $staff->id,
+            'statisc_id' => $id,
+            'type' => $params['type'],
+            'time' => date('Y-m-d H:i:s'),
+            'address' => $address,
+            'type_name' => $params['type_name'],
+            'lng' => $params['lng'],
+            'lat' => $params['lat'],
+            'remarks' => $params['remarks']??'',
+            'file_ids' => $params['file_ids']??'',
+
+        );
+        Db::startTrans();
+        try {
+            $statisc = new AttendanceStatisc();
+            if ($params['type'] == 0) {//上下班打卡
+                if ($params['type_name'] == 0) {//上班打卡
+                    if ($nowtime > $s1) {
+                        $clock_in_status=3;//迟到
+                        $row['late'] = 1;//迟到
+                        $row['late_time'] = intval(($nowtime - $s1) / 60);//分
+                    } else {
+                        $row['late'] = 0;
+                        $row['late_time'] = 0;
+                        $clock_in_status=0;//正常
+                    }
+                    $statisc->save(['clock_in' => date('Y-m-d H:i:s'),
+                        'clock_in_status'=>$clock_in_status,
+                        'late_time' => $row['late_time']], ['id' => $id]);
+                } elseif ($params['type_name'] == 1) {//下班打卡
+                    if ($nowtime < $s2) {
+                        $row['leaver'] = 1;//早退
+                        $row['leaver_time'] = intval(($s2 - $nowtime) / 60);//分
+                        $clock_out_status=3;
+                    } else {
+                        $row['leaver'] = 0;
+                        $row['leaver_time'] = 0;
+                        $clock_out_status=0;
+                    }
+                    $statisc->save(['clock_out' => date('Y-m-d H:i:s'),
+                        'clock_out_status'=>$clock_out_status,
+                        'leaver_time' => $row['leaver_time']], ['id' => $id]);
+                }
+            }
+            $model = new AttendanceModel();
+            $result = $model->save($row);
+            $row['id'] = $model->id;
+            if (!$result) {
+                throw new Exception('打卡失败');
+            }
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+
+
+        $this->success('打卡成功', $row);
+    }
+
+    /**
+     * 获取打卡详情
+     */
+    public function get_attendance_detail(){
+        $id=input('id',0,'intval');
+
+        $cards=AttendanceModel::where(['id'=>$id])->order('id desc')->with(['createStaff'])->find();
+        if($cards['file_ids']){
+            $cards['file_ids'] = File::where(['id' => ['in', $cards['file_ids']]])
+                ->field('id,types,name,file_path')->select();
+        }
+
+        //标记通知已读
+        Message::setRead(Message::CARD_TYPE, $id, $this->auth->id);
+
+        $this->success('请求成功',$cards);
+    }
+    /**
+     * 外勤打卡
+     */
+    public function other_card()
+    {
+        $params = $this->request->post();
+        if (!isset($params['type'])) { //0:上下班 1:外出
+            $this->error('类型不能为空');
+        }
+        if (!$params['lng'] || !$params['lat']) {
+            $this->error('经纬度不能为空');
+        }
+
+        $staff = Staff::info();
+        $row = array(
+            'staff_id' => $staff->id,
+            'type' => $params['type'],
+            'time' => date('Y-m-d H:i:s'),
+            'address' => $params['address'],
+            'type_name' => $params['type_name'],
+            'lng' => $params['lng'],
+            'lat' => $params['lat'],
+            'remarks' => $params['remarks']??'',
+            'file_ids' => $params['file_ids']??'',
+        );
+        Db::startTrans();
+        try {
+            $result = AttendanceModel::create($row);
+            if (!$result) {
+                throw new Exception('打卡失败');
+            }
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+
+
+        $this->success('打卡成功', $row);
+    }
+
+    /**
+     * 补卡
+     */
+    public function card_late()
+    {
+        $params = $this->request->post();
+        if (empty($params['statisc_id'])) {
+            $this->error('打卡ID不能为空');
+        }
+        if (empty($params['title'])) {
+            $this->error('补卡原因不能为空');
+        }
+        if (empty($params['time'])) {
+            $this->error('补卡时间不能为空');
+        }
+        if (empty($params['remark'])) {
+            $this->error('补卡事由不能为空');
+        }
+        $ret = array(
+            'statisc_id' => $params['statisc_id'],
+            'type' => $params['type'],
+            'time' => $params['time'],
+            'remark' => $params['remark'],
+            'file_ids' => $params['file_ids'],
+        );
+
+        $staff = Staff::info();
+        if (!empty($staff)) {
+            $ret['create_staff_id'] = $staff->id;
+        }
+
+        $flow = Flow::getsteplist(Flow::CARD_STATUS);
+        if (!$flow) {
+            $this->error('请先配置补卡审批流');
+        }
+        $ret['flow_id'] = $flow['flow_id'];
+        $ret['order_id'] = $flow['order_id'];
+        if ($flow['status'] == 0) {//发起人自选
+            $ret['flow_staff_ids'] = trim($params['flow_staff_ids']);
+        } else {
+            $ret['flow_staff_ids'] = trim($flow['flow_staff_ids']);
+        }
+        Db::startTrans();
+        try {
+            $result = AttendanceCard::create($ret);
+            if (!$result) {
+                throw new Exception('补卡失败');
+            }
+
+            $lastId = AttendanceCard::getLastInsID();
+            if ($flow['status'] == 1) {//固定审批
+                if (empty($params['flow_staff_ids'])) {
+                    throw new Exception('审批人必须选择');
+                }
+                //发送审批通知
+                Flow::sendStepRecord($flow, Flow::CARD_STATUS, $lastId);
+            } else {//发起人自选 依次审批
+                $staff_id = explode(',', $params['flow_staff_ids'])[0];
+                if ($staff_id) {
+                    ExamineRecord::addExaminse(ExamineRecord::CARD_TYPE, $lastId, $staff_id);
+                }
+            }
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+
+        $this->success('补卡成功');
+    }
+
+    /**
+     * 获取补卡记录
+     */
+    public function get_card_late(){
+        $limit = input("limit/d", 10);
+
+        $cards=AttendanceCard::where(['create_staff_id'=>$this->auth->id])->order('id desc')->with(['createStaff'])->paginate($limit);
+
+        $this->success('请求成功',$cards);
+    }
+
+    /**
+     * 获取补卡详情
+     */
+    public function get_card_detail(){
+        $id=input('id',0,'intval');
+
+        $cards=AttendanceCard::where(['id'=>$id])->order('id desc')->with(['createStaff'])->find();
+        $cards['file_ids'] = File::where(['id' => ['in', explode(',', $cards['file_ids'])]])->field('id,types,name,file_path')->select();
+
+        //标记通知已读
+        Message::setRead(Message::CARD_TYPE, $id, $this->auth->id);
+
+        $this->success('请求成功',$cards);
+    }
+    /*
+     * 获取考勤详情
+     */
+    public function get_statisc()
+    {
+        $statisc_id = input('statisc_id');
+        $statisc = AttendanceStatisc::where(['id' => $statisc_id])->find();
+        if (empty($statisc)) {
+            $this->error('数据不存在');
+        }
+
+        $this->success('请求成功', $statisc);
+    }
+
+    /**
+     * 是否可以打卡
+     */
+    public function is_card()
+    {
+        $params = $this->request->post();
+        if (!$params['lng'] || !$params['lat']) {
+            $this->error('经纬度不能为空');
+        }
+        //判断距离
+        $address = AttendanceAddress::where([])->select();
+        $disinfo = false;
+        foreach ($address as $k => $v) {
+            $distance = getdistance($params['lng'], $params['lat'], $v['lng'], $v['lat']);
+            if ($v['distance'] >= $distance) {
+                $disinfo = true;
+            }
+        }
+        if (!$disinfo) {
+            $this->success('请求成功', ['is_card' => 0, 'msg' => '不在打卡范围内!']);
+        }
+        //判断打卡是否为次日
+        $today = AttendanceStatisc::where(['time' => date('Y-m-d')])->select();
+        $today = collection($today)->toArray();
+        if (empty($today)) {
+            $this->success('请求成功', ['is_card' => 0, 'msg' => '不在打卡范围内!!']);
+        }
+        $start = $today[0]['ustart_time'];
+        $nowtime = time();
+        //当天首次打卡时间
+        $todaytime1 = strtotime(date('Y-m-d ') . $start);
+        if ($nowtime < $todaytime1) {//如果小于开始打卡时间 说明是次日
+            $clockDate = date('Y-m-d ', strtotime('-1 day'));
+        } else {
+            $clockDate = date('Y-m-d ');
+        }
+        $staff = Staff::info();
+        //判断是否打卡时间 0未选择 1:已选择
+        $statisc = AttendanceStatisc::where(['time' => $clockDate, 'staff_id' => $staff->id])->select();
+        $statisc = collection($statisc)->toArray();
+        if (empty($statisc)) {
+            $this->success('请求成功', ['is_card' => 0, 'msg' => '不在打卡时间范围内!']);
+        }
+        $intime = null;
+        $is_end = null;
+        foreach ($statisc as $v) {
+            //上班
+            $s1 = strtotime($clockDate . $v['ustart_time']);
+            $s2 = strtotime($clockDate . $v['uend_time']);
+            //下班打卡
+            $d1 = strtotime($clockDate . $v['dstart_time']);
+            $d2 = strtotime($clockDate . $v['dend_time']);
+
+            $s1 = ($s1 < $todaytime1) ? $s1 + 86400 : $s1;//是否为次日
+            $s2 = ($s2 < $todaytime1) ? $s2 + 86400 : $s2;//是否为次日
+
+            if ($nowtime >= $s1 && $nowtime <= $s2 && $v['start_status'] == 0) {
+
+                if (empty($v['clock_in'])) {
+                    $intime = ['type' => '上班打卡', 'time' => $v['start_time'], 'id' => $v['id'],
+                        'text' => "请在{$v['start_time']}之前打卡", 'type_name' => 0];
+                    break;
+                }
+            }
+            $d1 = ($d1 < $todaytime1) ? $d1 + 86400 : $d1;//是否为次日
+            $d2 = ($d2 < $todaytime1) ? $d2 + 86400 : $d2;//是否为次日
+
+            if ($nowtime >= $d1 && $nowtime <= $d2 && $v['end_status'] == 0) {
+                $e = strtotime($clockDate . $v['end_time']);
+                $e = ($e < $todaytime1) ? $e + 86400 : $e;//是否为次日
+                if ($e > $nowtime) {
+                    $is_leaver = $e - $nowtime;
+                } else {
+                    $is_leaver = 0;
+                }
+                if (empty($v['clock_out'])) {
+                    $intime = ['type' => '下班打卡', 'time' => $v['end_time'], 'id' => $v['id'], 'is_leaver' => $is_leaver,
+                        'text' => "请在{$v['end_time']}之后打卡", 'type_name' => 1];
+                    break;
+                }
+            }
+            if ((empty($v['clock_in']) || empty($v['clock_out'])) && empty($is_end)) {
+                $is_end = $v;
+            }
+        }
+        if (!empty($is_end) && empty($intime)) {//还需要打卡 且没有打卡
+            if (empty($is_end['clock_in'])) {
+                $this->success('请求成功', ['is_card' => 0, 'msg' => '不在上班打卡时间范围内!!']);
+            } else {
+                $this->success('请求成功', ['is_card' => 0, 'msg' => '不在下班打卡时间范围内!!']);
+            }
+        }
+        if (empty($intime)) {
+            //最后一次打卡
+            $attendance = AttendanceModel::where([
+                'staff_id' => $staff->id,
+                'time' => ['like', date('Y-m-d') . '%']])->order('id desc')->find();
+            $this->success('请求成功', ['is_card' => 2, 'msg' => '今日打卡已完成',
+                'intime' => $intime, 'attendance' => $attendance]);
+        }
+
+        $this->success('请求成功', ['is_card' => 1, 'msg' => '您已在打卡范围内', 'intime' => $intime]);
+    }
+
+    /**
+     * 统计
+     */
+    public function statistics()
+    {
+        $date = input('date');
+        if (empty($date)) {
+            $this->error('日期不存在');
+        }
+        $staff = Staff::info();
+        $date = date('Y-m-d', strtotime($date));
+        $staff_id = $staff->id;
+
+        $statisc = AttendanceStatisc::where(['time' => $date, 'staff_id' => $staff_id])->select();
+        $other = AttendanceModel::where(['type' => 1, 'staff_id' => $staff_id,
+            'time' => ['like', "{$date}%"]])->select();
+
+        $this->success('请求成功', ['statisc' => $statisc, 'other' => $other]);
+    }
+
+    /**
+     * 月统计
+     */
+    public function month_statistics()
+    {
+        $month = input('month');
+        if (empty($month)) {
+            $this->error('月统计不存在');
+        }
+        $month = date('Y-m', strtotime($month));
+        $staff = Staff::info();
+        $statisc = AttendanceStatisc::where(['time' => ['like', "{$month}%"], 'staff_id' => $staff->id])->select();
+        $data = [];
+        foreach ($statisc as $v) {
+            $data[$v['time']][] = [
+                'clock_in' => $v['clock_in'],//上班打卡
+                'leaver_time' => $v['leaver_time'],
+                'clock_out' => $v['clock_out'],
+                'late_time' => $v['late_time'],//迟到时间
+                'start_time' => $v['start_time'],
+                'end_time' => $v['end_time'],
+            ];
+        }
+        $leave = 0;//早退
+        $leave_time = 0;//早退时间
+        $late = 0;//迟到
+        $late_time = 0;//迟到时间
+        $work = 0;//旷工
+        $work_time = 0;//旷工时间
+        $card = 0;//缺卡
+        $normal = 0;//正常
+        $error = 0;//异常
+        $overtime=0;//加班
+        foreach ($data as $day => $time) {
+            $is_normal = 1;//正常
+            $is_error = 0;//异常
+            foreach ($time as $t) {
+                if (empty($t['clock_in']) && !empty($t['clock_out'])) {//缺卡
+                    $card += 1;
+                }
+                if (empty($t['clock_out']) && !empty($t['clock_in'])) {//缺卡
+                    $card += 1;
+                }
+                if (empty($t['clock_in']) && empty($t['clock_out'])) {
+                    $work += 1;
+                    $end_time = strtotime(date('Y-m-d ') . $v['end_time']);
+                    $start_time = strtotime(date('Y-m-d ') . $v['start_time']);
+                    $end_time = $end_time > $start_time ? $end_time : $end_time + 86400;
+                    //旷工时长
+                    $wtime = intval(($end_time - $start_time) / 60);
+                    $work_time += $wtime;
+                }
+                if ($t['leaver_time'] > 0) {//早退
+                    $leave += 1;
+                    $leave_time += $t['leaver_time'];
+                }
+                if ($t['late_time'] > 0) {//迟到
+                    $late += 1;
+                    $late_time += $t['late_time'];
+                }
+
+                if (empty($t['clock_in']) || empty($t['clock_out'])
+                    || $t['late_time'] != 0 || $t['leaver_time'] != 0) {//不正常卡
+                    $is_normal = 0;
+                    $is_error = 1;
+                }
+
+                //工作日加班
+                if ($t['clock_out'] && $leave_time == 0) {
+                    $clock_out = strtotime($t['clock_out']);
+                    $date = date('Y-m-d ', $clock_out);
+                    $end_time = $date . $t['end_time'];
+                    $end_time = strtotime($end_time);
+                    if ($end_time < $clock_out) {
+                        $end_time = $end_time + 86400;
+                    }
+                    $overtime += intval(($end_time - $clock_out) / 60);
+                }
+            }
+            if ($is_normal == 1) {
+                $normal += 1;
+            }
+            if ($is_error == 1) {
+                $error += 1;
+            }
+        }
+        //外勤
+        $other = AttendanceModel::where(['type' => 1, 'staff_id' => $staff->id, 'time' => ['like', "{$month}%"]])->count();
+
+        $this->success('请求成功', [
+            'leave' => $leave,
+            'leave_time' => $leave_time,
+            'late' => $late,
+            'late_time' => $late_time,
+            'work' => $work,
+            'work_time' => $work_time,
+            'card' => $card,
+            'normal' => $normal,
+            'error' => $error,
+            'other' => $other,
+            'overtime' => $overtime,
+        ]);
+    }
+
+    /**
+     * 日统计
+     */
+    public function day_statistics(){
+        $month = input('month');
+        $type=input('type');//类型 leave 早退 late 迟到  work 旷工 card 缺卡
+        if (empty($month)) {
+            $this->error('月统计不存在');
+        }
+        if (empty($type)) {
+            $this->error('类型不存在');
+        }
+        $month = date('Y-m', strtotime($month));
+        $staff = Staff::info();
+        $statisc = AttendanceStatisc::where(['time' => ['like', "{$month}%"], 'staff_id' => $staff->id])->select();
+        $data = [];
+        foreach ($statisc as $v) {
+            $data[$v['time']][] = [
+                'clock_in' => $v['clock_in'],//上班打卡
+                'leaver_time' => $v['leaver_time'],
+                'clock_out' => $v['clock_out'],
+                'late_time' => $v['late_time'],//迟到时间
+                'start_time' => $v['start_time'],
+                'end_time' => $v['end_time'],
+            ];
+        }
+        $result=[];
+        foreach ($data as $day=>$time) {
+
+            $leave = 0;//早退
+            $leave_time = 0;//早退时间
+            $late = 0;//迟到
+            $late_time = 0;//迟到时间
+            $work = 0;//旷工
+            $work_time = 0;//旷工时间
+            $card = 0;//缺卡
+
+            foreach ($time as $t) {
+                if (empty($t['clock_in']) && !empty($t['clock_out'])) {//缺卡
+                    $card += 1;
+                }
+                if (empty($t['clock_out']) && !empty($t['clock_in'])) {//缺卡
+                    $card += 1;
+                }
+                if (empty($t['clock_in']) && empty($t['clock_out'])) {
+                    $work += 1;
+                    $end_time = strtotime(date('Y-m-d ') . $v['end_time']);
+                    $start_time = strtotime(date('Y-m-d ') . $v['start_time']);
+                    $end_time = $end_time > $start_time ? $end_time : $end_time + 86400;
+                    //旷工时长
+                    $wtime = intval(($end_time - $start_time) / 60);
+                    $work_time += $wtime;
+                }
+                if ($t['leaver_time'] > 0) {//早退
+                    $leave += 1;
+                    $leave_time += $t['leaver_time'];
+                }
+                if ($t['late_time'] > 0) {//迟到
+                    $late += 1;
+                    $late_time += $t['late_time'];
+                }
+            }
+            if($type == 'leave' && $leave_time > 0 ){//早退
+                $result[]=['day'=>$day,'msg'=>'早退'.$leave_time.'分钟'];
+            }
+            if($type == 'late' && $late_time > 0){//迟到
+                $result[]=['day'=>$day,'msg'=>'迟到'.$late_time.'分钟'];
+            }
+            if($type == 'work' && $work_time > 0){//旷工
+                $result[]=['day'=>$day,'msg'=>'旷工'.$work_time.'分钟'];
+            }
+            if ($type == 'card' && $card > 0) {//缺卡
+                $result[] = ['day' => $day, 'msg' => '缺卡' . $card . '次'];
+            }
+
+        }
+
+        $this->success('请求成功',$result);
+    }
+
+    /**
+     * 请假
+     */
+    public function leave()
+    {
+        $data = $this->request->post();
+        if (empty($data)) {
+            $this->error('数据不能为空');
+        }
+
+        try {
+            //请假单
+            Leave::createLeave($data);
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        $this->success('提交成功');
+    }
+
+    /**
+     * 获取请假记录
+     */
+    public function get_leave(){
+        $limit = input("limit/d", 10);
+        $type=input('type');
+        $cards=Leave::where(['create_staff_id'=>$this->auth->id])->order('id desc')->with(['createStaff'])->paginate($limit);
+
+        $this->success('请求成功',$cards);
+    }
+
+    /**
+     * 获取请假详情
+     */
+    public function get_leave_detail(){
+        $id=input('id',0,'intval');
+
+        $leave=Leave::where(['id'=>$id])->order('id desc')->with(['createStaff'])->find();
+        $leave['file_ids'] = File::where(['id' => ['in', explode(',', $leave['file_ids'])]])->field('id,types,name,file_path')->select();
+        //标记通知已读
+        Message::setRead(Message::LEAVE_TYPE, $id, $this->auth->id);
+        $this->success('请求成功',$leave);
+    }
+    /**
+     * 计算请假时间
+     */
+    public function getleavetime()
+    {
+        $start_time = input('start_time');
+        $end_time = input('end_time');
+        if(empty($start_time) || empty($end_time)){
+            $this->error('参数错误');
+        }
+        $start_time= strtotime($start_time);
+        $end_time= strtotime($end_time);
+        $start_date = strtotime(date('Y-m-d', $start_time));
+        $end_date = strtotime(date('Y-m-d', $end_time));
+        $fields = [
+            1 => 'monday',
+            2 => 'tuesday',
+            3 => 'wednesday',
+            4 => 'thursday',
+            5 => 'friday',
+            6 => 'saturday',
+            0 => 'weekday',
+        ];
+        $hour=0;
+        for ($start_date; $start_date <= $end_date; $start_date = $start_date + 86400) {
+            $w = date('w', $start_date);
+            $attendances = AttendanceTime::where([$fields[$w] => 1])->select();
+            foreach ($attendances as $a) {
+                $start = strtotime(date('Y-m-d ', $start_date) . $a['start_time']);
+                $end = strtotime(date('Y-m-d ', $start_date) . $a['end_time']);
+                $end = $start < $end ? $end : $end + 86400;
+                if ($start_time < $start && $end_time > $end) {
+                    $hour += ceil(($end - $start) / (60 * 60));
+                }
+                if ($start_time < $start && $end_time < $end) {
+                    $hour += ceil(($end_time - $start) / (60 * 60));
+                }
+                if ($start_time > $start && $end_time > $end) {
+                    $hour += ceil(($end - $start_time) / (60 * 60));
+                }
+                if ($start_time > $start && $end_time < $end) {
+                    $hour += ceil(($end_time - $start_time) / (60 * 60));
+                }
+
+            }
+        }
+        $this->success('请求成功',['hour'=>$hour]);
+    }
+}

+ 713 - 0
addons/qingdong/controller/Autotask.php

@@ -0,0 +1,713 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\AdminConfig;
+use addons\qingdong\model\AttendanceRule;
+use addons\qingdong\model\AttendanceStatisc;
+use addons\qingdong\model\AttendanceTime;
+use addons\qingdong\model\Message;
+use addons\qingdong\model\Customer;
+use addons\qingdong\model\Event;
+use addons\qingdong\model\Staff;
+use addons\qingdong\model\Leads;
+use addons\qingdong\model\Attendance;
+use think\Db;
+use think\Exception;
+use think\Log;
+use think\Session;
+use addons\qingdong\model\StaffDepartment;
+use addons\qingdong\model\DingStaff;
+use addons\qingdong\model\DingCustomer;
+use addons\qingdong\model\DingContacts;
+use addons\qingdong\model\DingRecord;
+use addons\qingdong\library\Ding;
+use addons\qingdong\library\Wechat;
+use addons\qingdong\library\WechatEnterprise;
+use addons\qingdong\model\WechatOpenid;
+
+/**
+ * 定时任务
+ */
+class Autotask extends \think\addons\Controller
+{
+    protected $noNeedLogin = ["*"];
+    protected $layout = '';
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        if (!$this->request->isCli()) {
+            $this->error('只允许在终端进行操作!');
+        }
+    }
+
+    /**
+     * 合同
+     */
+    public function contract()
+    {
+        $endDate = date('Y-m-d', strtotime('+3 day'));
+        $contracts = \addons\qingdong\model\Contract::where(['check_status' => 2, 'contract_status' => 0, 'end_time' => ['lt', $endDate]])->select();
+        try {
+            //合同即将到期通知
+            foreach ($contracts as $v) {
+                Message::addMessage(Message::CONTRACT_EXPIRE_TYPE, $v['id'], $v['owner_staff_id'], '');
+            }
+        } catch (Exception $e) {
+            return $e->getMessage();
+        }
+        $this->plan();
+        return 'success';
+    }
+
+    /**
+     * 回款计划通知
+     */
+    public function plan()
+    {
+        $endDate = date('Y-m-d', strtotime('+1 day'));
+        //进行中 -- 待回款
+        $plans = \addons\qingdong\model\ReceivablesPlan::where(['status' => 0, 'remind_date' => ['lt', $endDate]])->select();
+
+        try {
+            //回款计划即将到期通知
+            foreach ($plans as $v) {
+                Message::addMessage(Message::PLAN_EXPIRE_TYPE, $v['contract_id'], $v['owner_staff_id'], '');
+            }
+        } catch (Exception $e) {
+            return $e->getMessage();
+        }
+
+        return 'success';
+    }
+
+    /**
+     * 公海
+     */
+    public function seas()
+    {
+
+        if (AdminConfig::getConfigValue('auto', AdminConfig::TYPE_SEAS)) {//自动回收客户
+            if (AdminConfig::getConfigValue('genjing', AdminConfig::TYPE_SEAS) == 1) {//未跟进客户回收
+                $day = AdminConfig::getConfigValue('genjing_day', AdminConfig::TYPE_SEAS);
+                $where['last_time'] = ['<', date('Y-m-d H:i:s', strtotime('-' . $day . ' day'))];
+                if (AdminConfig::getConfigValue('genjing_success', AdminConfig::TYPE_SEAS) == 1) {
+                    $where['contract_status'] = 0;
+                }
+                $customers = Customer::where($where)->field('id,name,owner_staff_id')->select();
+                try {
+                    foreach ($customers as $c) {
+                        Customer::moveSeas($c['id']);
+                        Message::addMessage(Message::SEAS_TYPE, $c['id'], $c['owner_staff_id'], 0);
+                    }
+                } catch (Exception $e) {
+                    Log::error($e->getMessage());
+                }
+            }
+            if (AdminConfig::getConfigValue('chengjiao', AdminConfig::TYPE_SEAS) == 1) {//未成交客户回收
+                $day = AdminConfig::getConfigValue('chengjiao_day', AdminConfig::TYPE_SEAS);
+                $where = [
+                    'receivetime' => ['<', date('Y-m-d H:i:s', strtotime('-' . $day . ' day'))],
+                    'contract_status' => 0
+                ];
+                $customers = Customer::where($where)->field('id,name,owner_staff_id')->select();
+                try {
+                    foreach ($customers as $c) {
+                        Customer::moveSeas($c['id']);
+                        Message::addMessage(Message::SEAS_TYPE, $c['id'], $c['owner_staff_id'], 0);
+                    }
+                } catch (Exception $e) {
+                    Log::error($e->getMessage());
+                }
+            }
+        }
+
+        return 'success';
+    }
+
+    /**
+     * 日程提醒
+     * @return string
+     */
+    public function event()
+    {
+        $endDate = date('Y-m-d H:i:s');
+        $events = Event::where(['status' => 0, 'remind_time' => ['lt', $endDate]])->select();
+
+        $endIds = Event::where([
+            'status' => ['in', [0, 1]],
+            'auto_end' => 1,
+            'end_time' => ['lt', $endDate]
+        ])->column('id');
+
+        try {
+            //日程自动结束
+            Event::where(['id' => ['in', $endIds]])->update(['status' => 2]);
+
+            //日程时间提醒
+            foreach ($events as $v) {
+                if (Message::where([
+                    'relation_type' => Message::EVENT_TYPE,
+                    'relation_id' => $v['id'],
+                    'to_staff_id' => $v['staff_id']
+                ])->count()) {
+                    //已经提醒过了
+                    continue;
+                }
+                Message::addMessage(Message::EVENT_TYPE, $v['id'], $v['staff_id'], 0);
+            }
+        } catch (Exception $e) {
+            return $e->getMessage();
+        }
+        return 'success';
+    }
+
+    /**
+     * 打卡定时任务
+     */
+    public function attendance()
+    {
+        $w = date('w');
+        $date = [
+            1 => 'monday',
+            2 => 'tuesday',
+            3 => 'wednesday',
+            4 => 'thursday',
+            5 => 'friday',
+            6 => 'saturday',
+            0 => 'weekday',
+        ];
+        $weekname = $date[$w];
+        $times = AttendanceTime::where([$weekname => 1])->select();
+        if (empty($times)) {
+            return '未设置规则';
+        }
+        $row = AttendanceStatisc::where(['time' => date('Y-m-d')])->find();
+        if (!empty($row)) {
+            return '规则已生成';
+        }
+        $times = collection($times)->toArray();
+        $rule = AttendanceRule::where([])->find();
+
+        $statiscs = AttendanceStatisc::where(['time' => date('Y-m-d', strtotime('-1 day'))])->select();
+        foreach ($statiscs as $v) {
+            $update = [];
+            if (empty($t['clock_in']) && !empty($t['clock_out'])) {//缺卡
+                $update['clock_in_status'] = 1;
+            }
+            if (empty($t['clock_out']) && !empty($t['clock_in'])) {//缺卡
+                $update['clock_out_status'] = 1;
+            }
+            if (empty($t['clock_in']) && empty($t['clock_out'])) {//旷工
+                $update['clock_in_status'] = 2;
+                $update['clock_out_status'] = 2;
+            }
+            if ($update) {
+                $statiscModel = new AttendanceStatisc();
+                $statiscModel->save($update, ['id' => $v['id']]);
+            }
+
+        }
+        $staff_ids = explode(',', $rule['staff_id']);
+
+        $statisc = [];
+        foreach ($staff_ids as $sid) {
+            foreach ($times as $t) {
+                $statisc[] = [
+                    'staff_id' => $sid,
+                    'number' => $t['number'],
+                    'time' => date('Y-m-d'),
+                    'start_time' => $t['start_time'],
+                    'end_time' => $t['end_time'],
+                    'ustart_time' => $t['ustart_time'],
+                    'uend_time' => $t['uend_time'],
+                    'dstart_time' => $t['dstart_time'],
+                    'dend_time' => $t['dend_time'],
+                    'start_status' => $t['start_status'],
+                    'end_status' => $t['end_status'],
+                ];
+            }
+        }
+        $statiscModel = new AttendanceStatisc();
+        $result = $statiscModel->allowField(true)->saveAll($statisc);
+        if (empty($result)) {
+            return '生成规则失败';
+        }
+        return '生成规则成功';
+    }
+
+    /*
+     * 线索池分配
+     */
+    public function leadpool(){
+        if(AdminConfig::getConfigValue('leadauto', AdminConfig::TYPE_LEAD)){
+            $leadauto = AdminConfig::getConfigValue('leadauto', AdminConfig::TYPE_LEAD);
+            $lead_day = AdminConfig::getConfigValue('lead_day', AdminConfig::TYPE_LEAD);
+            $attendance = AdminConfig::getConfigValue('leadcard', AdminConfig::TYPE_LEAD);
+            $department = AdminConfig::getConfigValue('department', AdminConfig::TYPE_LEAD);
+
+            //开启分配
+            if($leadauto == 1 && $lead_day>0 && $department){
+                $leadpool = Leads::where('owner_staff_id is null or owner_staff_id = 0')->order('id desc')->limit(100)->column('id');
+               if($leadpool){
+                   $department = explode(',',$department);
+                   $staffinfo = array();
+                   foreach($department as $k=>$v){
+                       $staffids = Staff::where('', 'exp', Db::raw('FIND_IN_SET(' . $v . ',group_ids)'))->where(['status'=>1])->column('id');
+                       $staffinfo[] = $staffids;
+                   }
+                   if(!$staffinfo){
+                       return '无数据';
+                   }
+                   $staffinfos =[];
+                   foreach($staffinfo as $k=>$v){
+                       foreach($v as $ks=>$vs){
+                           $staffinfos[] = $vs;
+                       }
+                   }
+                   $staff = array_unique($staffinfos);
+                   foreach($leadpool as $ks=>$vs){
+                       $stafflead =[];
+                       foreach($staff as $k=>$v){
+                           if($attendance == 1){ //打卡
+                               $whereC['staff_id']= $v;
+                               $whereC['createtime'] = array(array('egt',strtotime(date('Y-m-d 00:00:00'))),array('elt',strtotime(date('Y-m-d 23:59:59'))));
+                               $leadcard = Attendance::where($whereC)->find();
+                               if(!$leadcard){//未打卡不分配
+                                   continue;
+                               }
+                           }
+                           $wherelead['owner_staff_id'] = $v;
+                           $wherelead['receive_time'] = array(array('egt',strtotime('-'.$lead_day.' days',time())),array('elt',time()));
+                           $lead = Leads::where($wherelead)->count();
+                           $stafflead[] = array(
+                               'id'=>$v,
+                               'num'=>$lead
+                           );
+                       }
+                       if($stafflead){
+                           $num_count = array_column($stafflead,'num');//返回数组中指定的一列
+                           array_multisort($num_count,SORT_ASC,$stafflead);
+                           Leads::where(array('id'=>$vs))->update(array('owner_staff_id'=>$stafflead[0]['id'],'receive_time'=>time()));
+                       }
+                   }
+
+               }
+
+            }
+        }
+        return 'success';
+    }
+
+    /**
+     * 钉钉批量获取客户
+     */
+    public function dingcustomer(){
+        date_default_timezone_set('Asia/Shanghai');
+        $ding=new Ding();
+        //获取access_token
+        $token = $ding->getAccessToken();
+        if($token->errcode != 0){
+            $this->error($token->errmsg);
+        }
+        $ding=new Ding();
+        $accessToken = $token->access_token;
+        $DingStaff = DingStaff::where(array('type'=>0))->select();
+        if(!$DingStaff){
+            $this->error('员工为空,请先同步员工为空');
+        }
+
+        foreach($DingStaff as $k=>$v){
+            if(Session::get($v['user_id']."dingcustomer")){
+                $startnum = intval(Session::get($v['user_id']."dingcustomer")/2-1);
+                $endnum = Session::get($v['user_id']."dingcustomer");
+            }else{
+                $startnum = 0;
+                $endnum =100;
+            }
+            $customer = $ding->customerBatch($accessToken,$v['user_id'],$startnum,$endnum);
+
+            if($customer->errcode != 0 || !$customer->result->values){
+                continue;
+            }
+            foreach($customer->result->values as $ks=>$vs){
+                $customerFind = DingCustomer::where(array('instance_id'=>$vs->instance_id,'type'=>0))->find();
+                if($customerFind){
+                    continue;
+                }
+                $data = json_decode($vs->data,true);
+                $instance_id = $vs->instance_id;
+                $customers = isset($data['customer_name']) ? $data['customer_name'] : '';
+                $adressinfo = isset($data['address']['extendValue']) ? json_decode($data['address']['extendValue'],true) : '';
+                $address_detail = '';
+                $address = '';
+                if($adressinfo){
+                    $province = isset($adressinfo['province']['name']) ? $adressinfo['province']['name'] : '';
+                    $city  = isset($adressinfo['city']['name']) ? $adressinfo['city']['name'] : '';
+                    $district  = isset($adressinfo['district']['name']) ? $adressinfo['district']['name'] : '';
+                    $address_detail  = isset($adressinfo['detail']['name']) ? $adressinfo['detail']['name'] : '';
+                    $address = $province.$city.$district;
+                }
+                $remark = isset($data['TextareaField-K55CWZ2E']) ? $data['TextareaField-K55CWZ2E'] : '';
+                $source = isset($data['DDSelectField-K2U5GX3B']['value']) ? $data['DDSelectField-K2U5GX3B']['value'] : '';
+                $owner_staff_id=$vs->permission->owner_userid_list[0];
+                $create_staff_id=$vs->creator_userid;
+                $createtime = strtotime($vs->gmt_create);
+                $updatetime = strtotime($vs->gmt_modified);
+                $customerData = array(
+                    'instance_id'=>$instance_id,
+                    'user_id'=>$create_staff_id,
+                    'name'=>$customers,
+                    'address'=>$address,
+                    'address_detail'=>$address_detail,
+                    'source'=>$source,
+                    'remark'=>$remark,
+                    'owner_staff_id'=>$owner_staff_id,
+                    'create_staff_id'=>$create_staff_id,
+                    'createtime'=>$createtime,
+                    'updatetime'=>$updatetime,
+                );
+                DingCustomer::create($customerData);
+            }
+
+
+            if(Session::get($v['user_id']."dingcustomer")){
+                Session::set($v['user_id']."dingcustomer", 100*2);
+            }else{
+                Session::set($v['user_id']."dingcustomer", 100);
+            }
+
+        }
+        $this->success('同步成功');
+
+    }
+    /**
+     * 钉钉批量获取联系人
+     */
+    public function dingcontacts(){
+        date_default_timezone_set('Asia/Shanghai');
+        $ding=new Ding();
+        //获取access_token
+        $token = $ding->getAccessToken();
+        if($token->errcode != 0){
+            $this->error($token->errmsg);
+        }
+        $ding=new Ding();
+        $accessToken = $token->access_token;
+        $DingStaff = DingStaff::where(array('type'=>0))->select();
+        if(!$DingStaff){
+            $this->error('员工为空,请先同步员工为空');
+        }
+        foreach($DingStaff as $k=>$v){
+            if(Session::get($v['user_id']."dingcontacts")){
+                $startnum = intval(Session::get($v['user_id']."dingcontacts")/2-1);
+                $endnum = Session::get($v['user_id']."dingcontacts");
+            }else{
+                $startnum = 0;
+                $endnum =100;
+            }
+            $customer = $ding->contactsBatch($accessToken,$v['user_id'],$startnum,$endnum);
+            if($customer->errcode != 0 || !$customer->result->values){
+                continue;
+            }
+            foreach($customer->result->values as $ks=>$vs){
+                $customerFind = DingContacts::where(array('instance_id'=>$vs->instance_id))->find();
+                if($customerFind){
+                    continue;
+                }
+                $data = json_decode($vs->data,true);
+                $contact_related_customer = json_decode($data['contact_related_customer']['extendValue'],true);
+                $instanceId = isset($contact_related_customer['list'][0]['instanceId']) ? $contact_related_customer['list'][0]['instanceId'] : '';
+                if(!$instanceId){
+                    continue;
+                }
+                $customerId = DingCustomer::where(array('instance_id'=>$instanceId))->value('id');
+                if(!$customerId){
+                    continue;
+                }
+                $instance_id = $vs->instance_id;
+                $contact_name = isset($data['contact_name']) ? $data['contact_name'] : '';
+                $post = isset($data['contact_position']['extendValue']) ? json_decode($data['contact_position']['extendValue'],true)[0]['label'] : '';
+                $email = isset($data['TextField-K55DPXC9']) ? $data['TextField-K55DPXC9'] : '';
+                $mobile = isset($data['contact_phone']['value']) ? $data['contact_phone']['value'] : '';
+                $remark = isset($data['TextareaField-K2UG1B59']) ? $data['TextareaField-K2UG1B59'] : '';
+                $owner_staff_id=$vs->permission->owner_userid_list[0];
+                $create_staff_id=$vs->creator_userid;
+                $createtime = strtotime($vs->gmt_create);
+                $updatetime = strtotime($vs->gmt_modified);
+                $customerData = array(
+                    'instance_id'=>$instance_id,
+                    'customer_id'=>$customerId,
+                    'name'=>$contact_name,
+                    'post'=>$post,
+                    'email'=>$email,
+                    'mobile'=>$mobile,
+                    'remarks'=>$remark,
+                    'owner_staff_id'=>$owner_staff_id,
+                    'create_staff_id'=>$create_staff_id,
+                    'createtime'=>$createtime,
+                    'updatetime'=>$updatetime,
+                );
+                DingContacts::create($customerData);
+            }
+
+            if(Session::get($v['user_id']."dingcontacts")){
+                Session::set($v['user_id']."dingcontacts", 100*2);
+            }else{
+                Session::set($v['user_id']."dingcontacts", 100);
+            }
+
+        }
+        $this->success('同步成功');
+    }
+    /**
+     * 钉钉批量获取跟进记录
+     */
+    public function dingrecord(){
+
+        date_default_timezone_set('Asia/Shanghai');
+        $ding=new Ding();
+        //获取access_token
+        $token = $ding->getAccessToken();
+        if($token->errcode != 0){
+            $this->error($token->errmsg);
+        }
+        $ding=new Ding();
+        $accessToken = $token->access_token;
+
+        $DingStaff = DingStaff::select();
+        if(!$DingStaff){
+            $this->error('员工为空,请先同步员工为空');
+        }
+        foreach($DingStaff as $k=>$v){
+            if(Session::get($v['user_id']."dingrecord")){
+                $startnum = intval(Session::get($v['user_id']."dingrecord")/2-1);
+                $endnum = Session::get($v['user_id']."dingrecord");
+            }else{
+                $startnum = 0;
+                $endnum =100;
+            }
+            $customer = $ding->recordBatch($accessToken,$v['user_id'],$startnum,$endnum);
+            if($customer->errcode != 0 || !$customer->result->values){
+                continue;
+            }
+            foreach($customer->result->values as $ks=>$vs){
+                $customerFind = DingRecord::where(array('instance_id'=>$vs->instance_id))->find();
+                if($customerFind){
+                    continue;
+                }
+                $data = json_decode($vs->data,true);
+                $contact_related_customer = json_decode($data['follow_record_related_customer']['extendValue'],true);
+                $instanceId = isset($contact_related_customer['list'][0]['instanceId']) ? $contact_related_customer['list'][0]['instanceId'] : '';
+                if(!$instanceId){
+                    continue;
+                }
+                $customerId = DingCustomer::where(array('instance_id'=>$instanceId))->value('id');
+                if(!$customerId){
+                    continue;
+                }
+                $instance_id = $vs->instance_id;
+                $content = isset($data['TextareaField-K2U5UJAF']) ? $data['TextareaField-K2U5UJAF'] : '';
+                $create_staff_id=$vs->creator_userid;
+                $createtime = strtotime($vs->gmt_create);
+                $updatetime = strtotime($vs->gmt_modified);
+                $customerData = array(
+                    'instance_id'=>$instance_id,
+                    'customer_id'=>$customerId,
+                    'content'=>$content,
+                    'create_staff_id'=>$create_staff_id,
+                    'createtime'=>$createtime,
+                    'updatetime'=>$updatetime,
+                );
+                DingRecord::create($customerData);
+            }
+            if(Session::get($v['user_id']."dingrecord")){
+                Session::set($v['user_id']."dingrecord", 100*2);
+            }else{
+                Session::set($v['user_id']."dingrecord", 100);
+            }
+        }
+        $this->success('同步成功');
+    }
+
+    /**
+     * 企业微信批量获取客户
+     */
+    public function wxcustomer(){
+        $this->corpid =AdminConfig::where(array('field'=>'corpid'))->value('value');
+        $corpsecret=AdminConfig::where(array('field'=>'corpsecret'))->value('value');
+        $url ='https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid='.$this->corpid.'&corpsecret='.$corpsecret;
+        $token = $this->http_get($url);
+        $token = json_decode($token,true);
+        if($token['errcode'] != 0){
+            $this->error($token['errmsg']);
+        }
+
+        $DingStaff = DingStaff::where(array('type'=>1))->limit(100)->select();
+        if(!$DingStaff){
+            $this->error('员工为空,请先同步员工为空');
+        }
+        $staffUser = array();
+        foreach($DingStaff as $k=>$v){
+            $staffUser[] = $v['user_id'];
+        }
+        $user = array(
+            'userid_list'=>$staffUser,
+            'cursor'=>Session::get("wxcustomer"),
+            'limit'=>100
+        );
+        $url ='https://qyapi.weixin.qq.com/cgi-bin/externalcontact/batch/get_by_user?access_token='.$token['access_token'];
+        $customer = $this->http_post($url,json_encode($user));
+        $customer = json_decode($customer,true);
+        if($customer['errcode'] != 0){
+            $this->error($customer['errmsg']);
+        }
+        Session::set("wxcustomer", $customer['next_cursor']);
+        foreach($customer['external_contact_list'] as $ks=>$vs){
+            $customerFind = DingCustomer::where(array('instance_id'=>$vs['external_contact']['external_userid']))->find();
+            if($customerFind){
+                continue;
+            }
+            $data = $vs;
+            $instance_id = isset($data['external_contact']['external_userid']) ? $data['external_contact']['external_userid'] : '';
+            $customerName = isset($data['external_contact']['name']) ? addslashes(filter_Emoji($data['external_contact']['name'])) : '';
+            $owner_staff_id=isset($data['follow_info']['userid']) ? $data['follow_info']['userid'] : '';
+            $create_staff_id=isset($data['follow_info']['userid']) ? $data['follow_info']['userid'] : '';
+            $createtime = isset($data['follow_info']['createtime']) ? $data['follow_info']['createtime'] : '';
+            $updatetime = isset($data['follow_info']['createtime']) ? $data['follow_info']['createtime'] : '';
+
+            $customerData = array(
+                'type' => 1,
+                'instance_id'=>$instance_id,
+                'user_id'=>$create_staff_id,
+                'name'=>$customerName,
+                'owner_staff_id'=>$owner_staff_id,
+                'create_staff_id'=>$create_staff_id,
+                'createtime'=>$createtime,
+                'updatetime'=>$updatetime,
+            );
+            $customers = DingCustomer::create($customerData);
+            $customerId = DingCustomer::getLastInsID();
+            //同步联系人
+            $contactFind = DingContacts::where(array('instance_id'=>$instance_id))->find();
+            if($contactFind){
+                DingContacts::where(array('id'=>$contactFind['id']))->update(array('customer_id' =>$customerId));
+                continue;
+            }
+            $contactData = array(
+                'type' =>1,
+                'instance_id' =>$instance_id,
+                'customer_id' =>$customerId,
+                'name' =>$customerName,
+                'mobile' =>isset($data['follow_info']['remark_mobiles'][0]) ? $data['follow_info']['remark_mobiles'][0] : '',
+                'create_staff_id' =>$owner_staff_id,
+                'owner_staff_id' =>$create_staff_id,
+            );
+            DingContacts::create($contactData);
+        }
+
+        $this->success('同步成功');
+
+    }
+    /**
+     * curl请求
+     */
+    private function http_get($url){
+        $oCurl = curl_init();
+        if(stripos($url,"https://")!==FALSE){
+            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
+            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
+            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
+        }
+        curl_setopt($oCurl, CURLOPT_URL, $url);
+        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
+        $sContent = curl_exec($oCurl);
+        $aStatus = curl_getinfo($oCurl);
+        curl_close($oCurl);
+        if(intval($aStatus["http_code"])==200){
+            return $sContent;
+        }else{
+            return false;
+        }
+    }
+    /**
+     * curl请求
+     */
+    private function http_post($url,$param,$post_file=false){
+        $oCurl = curl_init();
+        if(stripos($url,"https://")!==FALSE){
+            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
+            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
+            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
+        }
+        if (is_string($param) || $post_file) {
+            $strPOST = $param;
+        } else {
+            $aPOST = array();
+            foreach($param as $key=>$val){
+                $aPOST[] = $key."=".urlencode($val);
+            }
+            $strPOST =  join("&", $aPOST);
+        }
+        curl_setopt($oCurl, CURLOPT_URL, $url);
+        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
+        curl_setopt($oCurl, CURLOPT_POST,true);
+        curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST);
+        $sContent = curl_exec($oCurl);
+        $aStatus = curl_getinfo($oCurl);
+        curl_close($oCurl);
+        if(intval($aStatus["http_code"])==200){
+            return $sContent;
+        }else{
+            return false;
+        }
+    }
+
+    public function sycn_openid()
+    {
+        $wechat2 = new Wechat('wxOfficialAccount');
+        $batch = $wechat2->getUsers();
+        if (empty($batch['data'])) {
+            return '微信配置有误!';
+        }
+
+        $openid = $batch['data']['openid'];
+        $model = new Staff();
+        $old_openid = $model->where([])->column('openid');
+        foreach ($openid as $k => $v) {
+            if (in_array($v, $old_openid)) {
+                unset($openid[$k]);
+            }
+        }
+        $openid = array_values($openid);
+        $openids = array_chunk($openid, 100);
+        $weopen = new WechatOpenid();
+        foreach ($openids as $o_ids) {
+            $insertAll = [];
+            $result = $wechat2->getBatchget($o_ids);
+            if (empty($result['user_info_list'])) {
+                return '微信配置有误!';
+            }
+            foreach ($result['user_info_list'] as $index => $item) {
+                $unionid = $weopen->where(['unionid'=>$item['unionid']])->find();
+                if(!$unionid){
+                    if (isset($item['unionid'])) {
+                        $model->where(['unionid'=>$item['unionid']])->update(['wx_openid'=>$item['openid']]);
+                        $insertAll[] = [
+                            'openid' => $item['openid'],
+                            'unionid' => $item['unionid']
+                        ];
+                    }
+                }
+
+
+            }
+
+            $weopen->insertAll($insertAll);
+        }
+
+        return 'success';
+    }
+
+}

+ 298 - 0
addons/qingdong/controller/Business.php

@@ -0,0 +1,298 @@
+<?php
+namespace addons\qingdong\controller;
+use addons\qingdong\model\Business as BusinessModel;
+use addons\qingdong\model\BusinessOther;
+use addons\qingdong\model\FormField;
+use addons\qingdong\model\Staff;
+use addons\qingdong\model\Message;
+use addons\qingdong\model\Contract;
+use addons\qingdong\model\BusinessStatus;
+use addons\qingdong\model\File;
+use think\Db;
+use think\Exception;
+/**
+ * 商机接口
+ */
+class Business extends StaffApi
+{
+    protected $noNeedLogin = [];
+    protected $noNeedRight = [];
+
+
+    //创建商机
+    public function addBusiness()
+    {
+        $params = $this->request->post();
+
+        $result = FormField::checkFields(FormField::BUSINESS_TYPE, $params);
+        if ($result !== true) {
+            $this->error($result);
+        }
+        Db::startTrans();
+        try {
+
+            $result = BusinessModel::createBusiness($params);
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if ($result) {
+            $this->success('添加商机成功');
+        }
+    }
+
+
+    //获取商机列表
+    public function getList()
+    {
+        $limit = input("limit/d", 10);
+        $customer_id = input('customer_id');
+        $params = $this->request->post();
+
+        $where= FormField::updateWhereField(FormField::BUSINESS_TYPE,$params);
+
+        if (isset($params['createtime']) && $params['createtime']) {//
+            $createtime = $params['createtime'];
+            $createtime = explode(',', $createtime);
+            $where['createtime'] = ['between', [strtotime($createtime[0]), strtotime($createtime[1]) + 86400 - 1]];
+        }
+        if (isset($params['staff_id']) && $params['staff_id']) {//下级员工筛选
+            $where['owner_staff_id'] = $params['staff_id'];
+        } else {
+            $where['owner_staff_id'] = ['in', Staff::getMyStaffIds()];
+            if (isset($params['type']) && $params['type']) {//客户分类
+                if ($params['type'] == 1) {//我的创建
+                    $where['owner_staff_id'] = $this->auth->id;
+                } elseif ($params['type'] == 2) {//下属创建
+                    $where['owner_staff_id'] = ['in', Staff::getLowerStaffId()];
+                }
+            }
+        }
+        $wheres =[];
+        if (isset($params['contract_status']) && $params['contract_status']) {
+            if($params['contract_status'] == 1){
+                $wheres['contract_status'] = 0;
+            }
+            if($params['contract_status'] == 2){
+                $wheres['contract_status'] = 1;
+            }
+        }
+
+        if ($customer_id) {
+            $where['customer_id'] = $customer_id;
+        }
+        $records = BusinessModel::where($where)->where($wheres)->with([
+            'customer',
+            'ownerStaff',
+        ])->order('id desc')->paginate($limit)->toArray();
+        $data=[];
+        foreach($records['data'] as $k=>$v){
+            $types = BusinessStatus::where(array('business_id'=>$v['id']))->order('id desc')->value('type');
+            if($types){
+                $v['type'] = (int)$types;
+            }else{
+                $v['type'] = 0;
+            }
+            $data[$k] = $v;
+        }
+        $allMoney = BusinessModel::where($where)->where($wheres)->sum('money');
+        $moneyinfo['repayment_money'] = BusinessModel::where($where)->where(array('contract_status'=>1))->sum('money'); //成交金额
+        $moneyinfo['no_money'] = sprintf("%.2f",$allMoney)-sprintf("%.2f",$moneyinfo['repayment_money']);//未成交金额
+        $moneyinfo['allmoney'] = $allMoney;//合同总金额
+        $this->success('请求成功', ['moneyinfo' => $moneyinfo, 'total' => $records['total'], 'per_page' => $records['per_page'], 'current_page' => $records['current_page'], 'last_page' => $records['last_page'], 'data' => $data]);
+
+    }
+
+    //获取商机详情
+    public function getDetail()
+    {
+        $id = input('id');
+        $contract = BusinessModel::where(['id' => $id])->with([
+            'customer',
+            'ownerStaff',
+            'product',
+        ])->find();
+        if (empty($contract)) {
+            $this->error('商机不存在');
+        }
+        $contract = $contract->toArray();
+        $contract = BusinessOther::getOther($contract);
+        $type = BusinessStatus::where(array('business_id'=>$contract['id']))->order('id desc')->value('type');
+        $contract['type'] = $type ? (int)$type : 0;
+        //产品删除不显示
+        if(isset($contract['product']) && $contract['product']){
+            foreach($contract['product'] as $k=>$v){
+                if(!$v['name'] && !$v['num']){
+                    unset($contract['product'][$k]);
+                }
+            }
+        }
+        //标记通知已读
+        Message::setRead(Message::BUSINESS_TYPE, $id, $this->auth->id);
+
+        $this->success('请求成功', $contract);
+    }
+
+    //修改商机
+    public function editBusiness()
+    {
+        $id = input('id');
+        $params = $this->request->post();
+        $row = BusinessModel::where(['id' => $id])->find();
+        if (empty($row)) {
+            $this->error('商机信息不存在');
+        }
+
+        $result = FormField::checkFields(FormField::BUSINESS_TYPE, $params,$id);
+        if ($result !== true) {
+            $this->error($result);
+        }
+        Db::startTrans();
+        try {
+            $result = BusinessModel::updateBusiness($params);
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        $this->success('修改商机成功');
+    }
+
+    /**
+     * 转移商机
+     */
+    public function batch_change()
+    {
+        $ids = input('id');
+        $staff_id = input('owner_staff_id');
+        if(!$ids || !$staff_id){
+            $this->error('参数不正确');
+        }
+        $ids = BusinessModel::where([
+            'id' => $ids
+        ])->column('id');
+        if (empty($ids)) {
+            $this->error('商机不存在');
+        }
+        $result = BusinessModel::batchTransfer($ids, $staff_id);
+        if(!$result){
+            $this->error('操作失败');
+        }
+        $this->success('操作成功');
+    }
+    //删除商机
+    public function delete()
+    {
+        $ids = input('id');
+        if(!$ids){
+            $this->error('参数不正确');
+        }
+        $data = BusinessModel::where([
+            'id' => $ids
+        ])->column('id');
+        if (empty($data)) {
+            $this->error('商机不存在');
+        }
+        $result = BusinessModel::where(array('id'=>$ids))->update(array('updatetime'=>time(),'deletetime'=>time()));
+        if(!$result){
+            $this->error('删除失败');
+        }
+        $this->success('删除成功');
+    }
+    //关联商机列表
+    public function business_list(){
+        $ids = input('customer_id');
+        if(!$ids){
+            $this->error('参数不正确');
+        }
+        $data= BusinessModel::where(['customer_id'=>$ids,'owner_staff_id'=>['in',Staff::getMyStaffIds()]])->field('id,name')->select();
+
+        $this->success('请求成功',$data);
+    }
+    //商机合同
+    public function contract(){
+        $limit = input("limit/d", 10);
+        $ids = input('id');
+        if(!$ids){
+            $this->error('参数不正确');
+        }
+        $contract = Contract::where(array('business_id'=>$ids))->with([
+            'customer',
+            'contacts',
+            'ownerStaff',
+            'orderStaff',
+            'receivables'
+        ])->order('id desc')->paginate($limit)->toArray();
+        $data = isset($contract['data'])?$contract['data']:[];
+        if($data){
+            foreach ($data as $k => $v) {
+                if (empty($v['receivables'])) {
+                    $v['receivables'] = [
+                        'repayment_money' => 0,
+                        'be_money' => $v['money'],
+                        'ratio' => 0
+                    ];
+                } else {
+                    $be_money = $v['money'] - $v['receivables']['repayment_money'];
+                    $be_money =   ($be_money > 0) ? $be_money : 0;
+                    $v['receivables'] = [
+                        'repayment_money' => $v['receivables']['repayment_money'],
+                        'be_money' =>$be_money,
+                        'ratio' => round($v['receivables']['repayment_money'] / $v['money'] * 100, 2)
+                    ];
+                }
+                $data[$k] = $v;
+            }
+        }
+        $this->success('请求成功', ['total' => $contract['total'], 'per_page' => $contract['per_page'], 'current_page' => $contract['current_page'], 'last_page' => $contract['last_page'], 'data' => $data]);
+
+    }
+    //商机状态
+    public function business_status(){
+        $id = input('id');
+        $type = input('type',0);
+        $remark = input('remark');
+        $file = input('file');
+        if(!$id){
+            $this->error('参数不正确');
+        }
+        $data = array(
+            'id'=>$id,
+            'type'=>$type,
+            'remark'=>$remark,
+            'file'=>$file,
+        );
+        $business =BusinessModel::batchStatus($data);
+        if(!$business){
+            $this->error('操作失败');
+        }
+        $this->success('操作成功');
+    }
+    //商机历史
+    public function business_history(){
+        $id = input('id');
+        if(!$id){
+            $this->error('参数不正确');
+        }
+        $business = BusinessStatus::where(array('business_id'=>$id))->order('id desc')->select();
+        foreach($business as $k=>$v){
+            $business[$k]['createtime'] = date('Y-m-d H:i:s',$v['createtime']);
+            if($v['file']){
+                $business[$k]['file'] = File::where(array('id'=>['in',$v['file']]))->field('id,types,name,save_name,size,file_path')->select();
+            }
+        }
+        $this->success('请求成功',$business);
+    }
+    //查询商机列表
+    public function get_select_list(){
+        $limit = input("limit/d", 10);
+        $params = $this->request->post();
+        $where = [];
+        if(isset($params['name']) && $params['name']){
+            $where['name'] = array('like','%'.$params['name'].'%');
+        }
+        $data= BusinessModel::where(['owner_staff_id'=>['in',Staff::getMyStaffIds()]])->where($where)->field('id,name')->order('id desc')->paginate($limit)->toArray();;
+        $this->success('请求成功',$data);
+    }
+}

+ 172 - 0
addons/qingdong/controller/Common.php

@@ -0,0 +1,172 @@
+<?php
+
+namespace addons\qingdong\controller;
+use addons\qingdong\model\AdminConfig;
+use addons\qingdong\model\FormField;
+use app\common\library\Upload;
+use app\common\exception\UploadException;
+use app\common\model\Area;
+use addons\qingdong\model\Field;
+use addons\qingdong\model\Form;
+use app\common\model\Version;
+use think\Config;
+use think\Hook;
+
+/**
+ *  * 操作文档:https://doc.fastadmin.net/qingdong
+ * 软件介绍:https://www.fastadmin.net/store/qingdong.html
+ * 售后微信:qingdong_crm
+ * 公共接口
+ */
+class Common extends StaffApi {
+	protected $noNeedLogin = ['init','getConfig'];
+	protected $noNeedRight = '*';
+
+
+	/**
+	 * 加载初始化
+	 * @param string $version 版本号
+	 * @param string $lng 经度
+	 * @param string $lat 纬度
+	 */
+	public function init() {
+		if ($version = $this->request->request('version')) {
+			$lng = $this->request->request('lng');
+			$lat = $this->request->request('lat');
+
+			//配置信息
+			$upload = Config::get('upload');
+			//如果非服务端中转模式需要修改为中转
+			if ($upload['storage'] != 'local' && isset($upload['uploadmode']) && $upload['uploadmode'] != 'server') {
+				//临时修改上传模式为服务端中转
+				set_addon_config($upload['storage'], ["uploadmode" => "server"], false);
+
+				$upload = \app\common\model\Config::upload();
+				// 上传信息配置后
+				Hook::listen("upload_config_init", $upload);
+
+				$upload = Config::set('upload', array_merge(Config::get('upload'), $upload));
+			}
+
+			$upload['cdnurl']    = $upload['cdnurl'] ? $upload['cdnurl'] : cdnurl('', true);
+			$upload['uploadurl'] = preg_match("/^((?:[a-z]+:)?\/\/)(.*)/i", $upload['uploadurl']) ? $upload['uploadurl'] : url($upload['storage'] == 'local' ? '/api/common/upload' : $upload['uploadurl'], '', false, true);
+
+			$content = [
+				'citydata'    => Area::getCityFromLngLat($lng, $lat),
+				'versiondata' => Version::check($version),
+				'uploaddata'  => $upload,
+				'coverdata'   => Config::get("cover"),
+			];
+			$this->success('', $content);
+		} else {
+			$this->error(__('Invalid parameters'));
+		}
+	}
+
+
+	/**
+	 * 上传文件
+	 * @ApiMethod (POST)
+	 * @param File $file 文件流
+	 */
+	public function upload() {
+
+		$attachment = null;
+		//默认普通上传文件
+		$file = $this->request->file('file');
+		$name = input('name','');
+        try {
+            $upload     = new Upload($file);
+            $attachment = $upload->upload();
+            $info = $attachment->toArray();
+            $file = new \addons\qingdong\model\File();
+            $params = [
+                'name'          =>  $name ? $name :$info['filename'],
+                'save_name'     =>  $info['url'],
+                'size'          =>  isset($info['filesize']) ? $info['filesize'] : 0,
+                'types'         =>  $info['mimetype'],
+                'file_path'     =>  $info['url'],
+                'create_staff_id'     =>  empty($staff)?0:$staff->id,
+            ];
+            $file->data(array_filter($params));
+            $file->save();
+            $fileId = $file->id;
+
+        } catch (UploadException $e) {
+            return json_encode(['code' => 0, 'msg' => $e->getMessage()]);
+        }
+        $this->success(__('Uploaded successful'), [
+            'id'  => $fileId,
+            'flie_url' => $params['file_path'],
+            'url' => cdnurl($params['file_path'], true)
+        ]);
+	}
+
+
+	//select 字段表
+	public function selectOption() {
+
+		$fields = Field::where([])->select();
+		$data   = [];
+		foreach ($fields as $v) {
+			$data[$v['name']] = json_decode($v['data'],true);
+		}
+
+		$this->success('请求成功', $data);
+	}
+
+
+	//获取form表单
+	public function getForm() {
+		$type = input('type', 'leads');//leads 线索 customer 客户 contacts 联系人 contract 合同 examine回款 product产品
+		$form = Form::where(['type' => $type])->find();
+
+		$this->success('请求成功', json_decode($form['data'], true));
+	}
+
+
+	//获取员工
+	public function getSelectStaff() {
+		$name  = input('name');
+		$where = ['status' => 1];
+		if ($name) {
+			$where['name'] = ['like', "%{$name}%"];
+		}
+
+		$staffs = \addons\qingdong\model\Staff::where($where)->with(['department'])->field('id,name,department_id,nickname,post,img')->select();
+
+		$this->success('请求成功', $staffs);
+	}
+
+    /**
+     * 获取后台配置
+     */
+    public function getConfig(){
+        $config=get_addon_config('qingdong');
+        $data=[
+            'map_key'=>AdminConfig::getConfigValue('map_key','wechat'),
+            'appid'=>AdminConfig::getConfigValue('appid','wechat'),
+            'mobile_name'=>$config['mobile_name']??'CRM'
+        ];
+        $this->success('请求成功',$data);
+    }
+
+    /**
+     * 获取时间
+     */
+    public function getTimes()
+    {
+        $times = input('times');
+        $times = setTimes($times, 'date');
+        $this->success('请求成功', ['times' => $times]);
+    }
+
+    /**
+     * 获取搜索字段
+     */
+    public function getSearchFields(){
+        $type=input('type');//leads
+        $fields=FormField::where(['types'=>$type,'field'=>['like',"main_%"],'list_show'=>1,'info_type'=>'main'])->select();
+        $this->success('请求成功',$fields);
+    }
+}

+ 142 - 0
addons/qingdong/controller/Consume.php

@@ -0,0 +1,142 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\ExamineRecord;
+use addons\qingdong\model\Consume as ConsumeModel;
+use addons\qingdong\model\Message;
+use addons\qingdong\model\File;
+use addons\qingdong\model\Staff;
+use think\Db;
+use think\Exception;
+
+/**
+ * 费用接口
+ */
+class Consume extends StaffApi
+{
+    protected $noNeedLogin = [];
+    protected $noNeedRight = [];
+
+
+    //添加费用
+    public function addConsume()
+    {
+        $params = $this->request->post();
+
+        // 表单验证
+        if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) {
+            $this->error($result);
+        }
+        Db::startTrans();
+        try {
+            $result = ConsumeModel::createConsume($params);
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if ($result) {
+            $this->success('添加费用成功');
+        }
+    }
+
+    //编辑费用
+    public function editConsume()
+    {
+        $params = $this->request->post();
+
+        // 表单验证
+        if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) {
+            $this->error($result);
+        }
+        Db::startTrans();
+        try {
+            $result = ConsumeModel::updateConsume($params);
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if ($result) {
+            $this->success('添加费用成功');
+        }
+    }
+
+    //获取费用列表
+    public function getList()
+    {
+        $limit = input("limit/d", 10);
+        $customer_id = input('customer_id', '', 'intval');
+        $times = input('times', '');
+        $status = input('check_status',0);
+        $where = [];
+
+        $params = $this->request->post();
+        if ($times) {//
+            $times = explode(',', $times);
+            $where['createtime'] = ['between', [strtotime($times[0]), strtotime($times[1]) + 86400 - 1]];
+        }
+        if (isset($params['staff_id']) && $params['staff_id']) {//下级员工筛选
+            $where['staff_id'] = $params['staff_id'];
+        } else {
+            $where['staff_id'] = ['in', Staff::getMyStaffIds()];
+            if (isset($params['type']) && $params['type']) {//客户分类
+                if ($params['type'] == 1) {//我的客户
+                    $where['staff_id'] = $this->auth->id;
+                } elseif ($params['type'] == 2) {//下属负责的客户
+                    $where['staff_id'] = ['in', Staff::getLowerStaffId()];
+                }
+            }
+        }
+
+        if ($status) {
+            if($status == 1){//待审核
+                $where['check_status']=['in',[0,1]];
+            }elseif($status == 2){//通过
+                $where['check_status']=2;
+            }elseif($status == 3){//审核拒绝
+                $where['contract_status']=['in',[3,4]];
+            }
+        }
+        if($customer_id){
+            $where['customer_id'] = $customer_id;
+        }
+        $records = ConsumeModel::where($where)->with(['staff','customer'])->order('id desc')->paginate($limit)->toArray();
+        $remoney = ConsumeModel::where(['staff_id'=>$where['staff_id']])
+            ->where(array('check_status'=>2))->sum('money');
+        $inmoney = ConsumeModel::where(['staff_id'=>$where['staff_id']])
+            ->where(array('check_status'=>['in',[0,1]]))->sum('money');
+        $nomoney = ConsumeModel::where(['staff_id'=>$where['staff_id']])
+            ->where(array('check_status'=>['in',[3,4]]))->sum('money');
+        $moneyinfo['remoney'] = $remoney;//已回款
+        $moneyinfo['inmoney'] = $inmoney;//回款中
+        $moneyinfo['nomoney'] = $nomoney;//未回款
+        $moneyinfo['allmoney'] = $remoney+$inmoney+$nomoney;//总金额
+        $records['moneyinfo']=$moneyinfo;
+        $this->success('请求成功', $records);
+    }
+
+
+    //获取费用详情
+    public function getDetail()
+    {
+        $id = input('id', '', 'intval');
+        $consume = ConsumeModel::where(['id' => $id])->with(['staff','customer'])->find();
+        if(empty($consume)){
+            $this->error('数据不存在');
+        }
+        $consume['files'] = File::where(['id' => ['in', explode(',', $consume['file_ids'])]])->field('id,types,name,file_path')->select();
+
+        if ($consume['check_status'] == 0 || $consume['check_status'] == 1) {
+            $consume['is_examine'] = ExamineRecord::isExaminse(ExamineRecord::CONSUME_TYPE, $id);
+        } else {
+            $consume['is_examine'] = 0;
+        }
+        //标记通知已读
+        Message::setRead(Message::CONSUME_TYPE, $id, $this->auth->id);
+
+        $this->success('请求成功', $consume);
+    }
+
+}

+ 200 - 0
addons/qingdong/controller/Contacts.php

@@ -0,0 +1,200 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Contacts as ContactsModel;
+use addons\qingdong\model\ContactsFile;
+use addons\qingdong\model\ContactsOther;
+use addons\qingdong\model\FormField;
+use addons\qingdong\model\Record;
+use addons\qingdong\model\Event as EventModel;
+use addons\qingdong\model\OperationLog;
+use addons\qingdong\model\Staff;
+use think\Db;
+use think\Exception;
+
+/**
+ * 联系人接口
+ */
+class Contacts extends StaffApi {
+	protected $noNeedLogin = [];
+	protected $noNeedRight = [];
+
+
+	//创建联系人
+	public function addContacts() {
+		$params = $this->request->post();
+		if (empty($params['contacts'])) {
+			$this->error('联系人信息不能为空');
+		}
+		// 表单验证
+        if (($result = $this->qingdongValidate($params['contacts'], get_class(), 'create')) !== true) {
+            $this->error($result);
+        }
+        $result = FormField::checkFields(FormField::CONTACTS_TYPE,$params['contacts']);
+        if ($result !== true) {
+            $this->error($result);
+        }
+		if (ContactsModel::where([
+			'mobile'      => $params['contacts']['mobile'],
+			'customer_id' => $params['contacts']['customer_id']
+		])->find()) {
+			$this->error('联系人手机号已存在');
+		}
+		Db::startTrans();
+		try {
+			$mobile =$params['contacts']['mobile'];
+			$email =$params['contacts']['email']??'';
+			if(empty($mobile) && empty($email)){
+				$this->error('手机号码和邮箱至少填写一项!');
+			}
+			$rule = '^1(3|4|5|7|8)[0-9]\d{8}$^';
+			$rule2 = '^[0-9]+$^';
+			if (preg_match($rule, $mobile) == false && preg_match($rule2, $mobile) ==false) {
+				$this->error('手机号格式错误,国外手机号请填写区号,例如 86XXXX');
+			}
+
+            $contactsId = ContactsModel::createContacts($params['contacts']);
+			if (isset($params['is_event']) && $params['is_event'] == 1) {//跟进任务
+				$event                  = $params['event'];
+				$event['type']          = 2;//任务
+				$event['relation_type'] = EventModel::CONTACTS_TYPE;//联系人
+				$event['relation_id']   = $contactsId;
+				$event['end_time']      = $event['start_time'];
+				$event['level']         = 1;
+				$result                 = EventModel::createEvent($event);
+			}
+			Db::commit();
+		} catch (Exception $e) {
+			Db::rollback();
+			$this->error($e->getMessage());
+		}
+		if ($result) {
+			$this->success('创建联系人成功');
+		}
+	}
+
+
+	//编辑联系人
+	public function editContacts() {
+		$id     = input('id');
+		$params = $this->request->post();
+		$row    = ContactsModel::where(['id' => $id])->find();
+		if (empty($row)) {
+			$this->error('客户信息不存在');
+		}
+		// 表单验证
+        if (($result = $this->qingdongValidate($params, get_class(), 'edit')) !== true) {
+            $this->error($result);
+        }
+        $result = FormField::checkFields(FormField::CONTACTS_TYPE,$params,$id);
+        if ($result !== true) {
+            $this->error($result);
+        }
+		if (ContactsModel::where([
+			'mobile'      => $params['mobile'],
+			'customer_id' => $row['customer_id'],
+			'id'          => ['neq', $params['id']]
+		])->find()) {
+			$this->error('联系人手机号已存在');
+		}
+		Db::startTrans();
+		try {
+			$result = ContactsModel::updateContacts($params);
+			Db::commit();
+		} catch (Exception $e) {
+			Db::rollback();
+			$this->error($e->getMessage());
+		}
+
+		$this->success('编辑联系人成功');
+	}
+
+
+	//删除联系人
+	public function delContacts() {
+		$id = input('id');
+
+		$row = ContactsModel::where(['id' => $id, 'owner_staff_id' => $this->auth->id])->find();
+		if (empty($row)) {
+			$this->error('您不是客户归属人,无法删除当前联系人');
+		}
+		$model = new ContactsModel();
+		if ($model->destroy(['id' => $id])) {
+			$this->success('删除成功');
+		}
+		Record::quickCreateRecord(Record::CUSTOMER_TYPE, $row['customer_id'],
+            '删除联系人:' . $row['name']);
+		OperationLog::createLog(OperationLog::CUSTOMER_TYPE, $row['customer_id'], '删除联系人:' . $row['name']);
+		$this->error('删除失败');
+	}
+
+
+	//获取联系人列表
+	public function getList() {
+		$limit       = input("limit/d", 10);
+		$customer_id = input('customer_id');
+		$name        = input('name');
+
+        $params = input();
+        $where = FormField::updateWhereField(FormField::CONTACTS_TYPE, $params);
+        if ($customer_id) {
+			$where['customer_id'] = $customer_id;
+		}else{
+			$where['owner_staff_id'] = ['in', Staff::getMyStaffIds()];
+		}
+		if ($name) {
+			$where['name'] = ['like', "%{$name}%"];
+		}
+		$records                 = ContactsModel::where($where)->with(['customer'])->order('id desc')->paginate($limit);
+		$this->success('请求成功', $records);
+	}
+
+
+	//获取select联系人列表
+	public function getSelectList() {
+		$customer_id = input('customer_id');
+        $name = input('name','');
+		$where       = [];
+		if ($customer_id) {
+			$where['customer_id'] = $customer_id;
+		}
+        if ($name) {
+            $where['name'] = ['like',"%$name%"];
+        }
+		$list                    = ContactsModel::where($where)->with(['customer'])->field('id,customer_id,name,mobile')->select();
+		$list                    = collection($list)->toArray();
+		foreach ($list as $k => $v) {
+			$v['new_mobile'] = $v['mobile'];
+			$list[$k]        = $v;
+		}
+		$this->success('请求成功', $list);
+	}
+
+
+	//获取联系人详情
+	public function getDetail() {
+		$id       = input('id');
+		$contract = ContactsModel::where(['id' => $id])->with([
+			'customer',
+			'ownerStaff'
+		])->find();
+
+		if (empty($contract)) {
+			$this->error('信息不存在');
+		}
+		$contract               = $contract->toArray();
+        $contract=ContactsOther::getOther($contract);
+
+		$this->success('请求成功', $contract);
+	}
+
+
+	//获取附件列表
+	public function getFilesList() {
+		$id = input('contacts_id');
+
+		$files = ContactsFile::where(['contacts_id' => $id])->field('file_id')->with(['file'])->select();
+		$this->success('请求成功', $files);
+	}
+}

+ 362 - 0
addons/qingdong/controller/Contract.php

@@ -0,0 +1,362 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Contract as ContractModel;
+use addons\qingdong\model\ContractFile;
+use addons\qingdong\model\ContractOther;
+use addons\qingdong\model\ExamineRecord;
+use addons\qingdong\model\FormField;
+use addons\qingdong\model\Ratio;
+use addons\qingdong\model\Receivables;
+use addons\qingdong\model\Message;
+use addons\qingdong\model\Staff;
+use think\Db;
+use think\Exception;
+
+/**
+ * 合同接口
+ */
+class Contract extends StaffApi
+{
+    protected $noNeedLogin = [];
+    protected $noNeedRight = [];
+
+
+    //创建合同
+    public function addContract()
+    {
+        $params = $this->request->post();
+
+        // 表单验证
+        if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) {
+            $this->error($result);
+        }
+        $result = FormField::checkFields(FormField::CONTRACT_TYPE, $params);
+        if ($result !== true) {
+            $this->error($result);
+        }
+        if (isset($params['num'])) {
+            if (empty($params['num'])) {
+                $params['num'] = ContractModel::getNum();
+            }
+            $contract = ContractModel::where(['num' => $params['num']])->find();
+            if ($contract) {
+                $this->error('合同编号已存在');
+            }
+        } else {
+            $params['num'] = ContractModel::getNum();
+        }
+        Db::startTrans();
+        try {
+
+            $result = ContractModel::createContract($params);
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if ($result) {
+            $this->success('添加合同成功');
+        }
+    }
+
+
+    //获取select合同列表
+    public function getSelectList()
+    {
+        $customer_id = input('customer_id');
+        $name = input('name','');
+        $where = [];
+        if ($customer_id) {
+            $where['customer_id'] = $customer_id;
+        }
+        if ($name) {
+            $where['name'] = ["like","%$name%"];
+        }
+        $records = ContractModel::where($where)->where(['check_status'=>2])->with(['ownerStaff'])->field('id,name,num,order_date,money')->order('id desc')->select();
+        $this->success('请求成功', $records);
+    }
+
+
+    //获取合同列表
+    public function getList()
+    {
+        $limit = input("limit/d", 10);
+        $customer_id = input('customer_id');
+        $contacts_id = input('contacts_id');
+        $status = input('status',0);
+
+        $params = $this->request->post();
+
+        $whereT =[];
+        $where= FormField::updateWhereField(FormField::CONTRACT_TYPE,$params);
+        if (isset($params['createtime']) && $params['createtime']) {//跟进状态
+            $createtime = $params['createtime'];
+            $createtime = explode(',', $createtime);
+            $where['order_date'] = ['between', [date('Y-m-d 00:00:00',strtotime($createtime[0])), date('Y-m-d 23:59:59',strtotime($createtime[1]) + 86400 - 1)]];
+        }
+        if (isset($params['staff_id']) && $params['staff_id']) {//下级员工筛选
+            $where['owner_staff_id'] = $params['staff_id'];
+        } else {
+            $where['owner_staff_id'] = ['in', Staff::getMyStaffIds()];
+            if (isset($params['type']) && $params['type']) {//客户分类
+                if ($params['type'] == 1) {//我的客户
+                    $where['owner_staff_id'] = $this->auth->id;
+                } elseif ($params['type'] == 2) {//下属负责的客户
+                    $where['owner_staff_id'] = ['in', Staff::getLowerStaffId()];
+                }
+            }
+        }
+
+        if ($status) {
+            if($status == 1){//待审核
+                $where['check_status']=['in',[0,1]];
+            }elseif($status == 2){//待回款
+                $where['check_status']=2;
+                $where['contract_status']=0;
+            }elseif($status == 3){//已回款
+                $where['check_status']=2;
+                $where['contract_status']=1;
+            }
+        }
+        if ($customer_id) {
+            $where['customer_id'] = $customer_id;
+        }
+        if ($contacts_id) {
+            $where['contacts_id'] = $contacts_id;
+        }
+        $records = ContractModel::where($where)->with([
+            'customer',
+            'contacts',
+            'ownerStaff',
+            'orderStaff',
+            'receivables'
+        ])->order('id desc')->paginate($limit)->toArray();
+        $data = $records['data'];
+
+        foreach ($data as $k => $v) {
+            if (empty($v['receivables'])) {
+                $v['receivables'] = [
+                    'repayment_money' => 0,
+                    'be_money' => $v['money'],
+                    'ratio' => 0
+                ];
+            } else {
+                $be_money = $v['money'] - $v['receivables']['repayment_money'];
+                $be_money =   ($be_money > 0) ? $be_money : 0;
+                $ratio_m = 0;
+                if($v['money'] >0){
+                    $ratio_m = round($v['receivables']['repayment_money'] / $v['money'] * 100, 2);
+                }
+                $v['receivables'] = [
+                    'repayment_money' => $v['receivables']['repayment_money'],
+                    'be_money' =>$be_money,
+                    'ratio' => $ratio_m
+                ];
+            }
+            $data[$k] = $v;
+        }
+
+        $whereT['owner_staff_id']=$where['owner_staff_id'];
+        $noMoney = ContractModel::where($whereT)->where(array('check_status'=>2))->sum('money');
+        $moneyinfo['repayment_money'] = Receivables::where($whereT)->where(array('check_status'=>2))->sum('money'); //已回款
+        $moneyinfo['be_money'] = sprintf("%.2f",$noMoney)-sprintf("%.2f",$moneyinfo['repayment_money']);//未回款
+        $moneyinfo['allmoney'] = $noMoney;//合同总金额
+        $this->success('请求成功', ['moneyinfo' => $moneyinfo, 'total' => $records['total'], 'per_page' => $records['per_page'], 'current_page' => $records['current_page'], 'last_page' => $records['last_page'], 'data' => $data]);
+    }
+
+
+    //获取客户相关合同列表
+    public function getCustomerContacts()
+    {
+        $customer_id = input('customer_id');
+        $contacts_id = input('contacts_id');
+        $where = [];
+        if ($customer_id) {
+            $where['customer_id'] = $customer_id;
+        }
+        if ($contacts_id) {
+            $where['contacts_id'] = $contacts_id;
+        }
+        $records = ContractModel::where($where)->with(['receivables'])->field('id,name,money,num,check_status,order_date')->order('id desc')->select();
+        $records = collection($records)->toArray();
+        foreach ($records as $k => $v) {
+            if (empty($v['receivables'])) {
+                $v['receivables'] = [
+                    'repayment_money' => 0,
+                    'be_money' => $v['money'],
+                    'ratio' => 0
+                ];
+            } else {
+                $be_money = $v['money'] - $v['receivables']['repayment_money'];
+                $v['receivables'] = [
+                    'repayment_money' => $v['receivables']['repayment_money'],
+                    'be_money' => ($be_money > 0) ? $be_money : 0,
+                    'ratio' => round($v['receivables']['repayment_money'] / $v['money'] * 100, 2)
+                ];
+            }
+            $records[$k] = $v;
+        }
+        $this->success('请求成功', $records);
+    }
+
+
+    //获取合同详情
+    public function getDetail()
+    {
+        $id = input('id');
+        $contract = ContractModel::where(['id' => $id])->with([
+            'customer',
+            'contacts',
+            'ownerStaff',
+            'orderStaff',
+            'product',
+            'receivables',
+            'business'
+        ])->find();
+        if (empty($contract)) {
+            //标记通知已读
+            Message::setRead(Message::CONTRACT_TYPE, $id);
+            $this->error('合同不存在');
+        }
+        $contract = $contract->toArray();
+        $contract = ContractOther::getOther($contract);
+        $receivablesMoney = Receivables::where(['contract_id' => $contract['id'], 'check_status' => 2])->sum('money');
+        //回款金额
+        $contract['receivables_money'] = $receivablesMoney;
+        $contract['ratios'] = json_decode($contract['ratios'],true);
+        if($contract['ratios']){
+            foreach ($contract['ratios'] as $k => $v) {
+                $v['staff'] = Staff::where(['id' => $v['staff_id']])->field('id,name,img,post')->find()->toArray();
+                $v['money'] = $contract['money'] * ($v['ratio'] / 100);
+                $contract['ratios'][$k] = $v;
+            }
+        }
+        if (empty($contract['receivables'])) {
+            $contract['receivables'] = [
+                'repayment_money' => 0,
+                'be_money' => $contract['money'],
+                'ratio' => 0
+            ];
+        } else {
+            $be_money = $contract['money'] - $contract['receivables']['repayment_money'];
+            $be_ratio = 0;
+            if($contract['money'] > 0){
+                $be_ratio =round($contract['receivables']['repayment_money'] / $contract['money'] * 100, 2);
+            }
+
+            $contract['receivables'] = [
+                'repayment_money' => $contract['receivables']['repayment_money'],
+                'be_money' => ($be_money > 0) ? $be_money : 0,
+                'ratio' => $be_ratio
+            ];
+        }
+        //产品删除不显示
+        if(isset($contract['product']) && $contract['product']){
+            foreach($contract['product'] as $k=>$v){
+                if(!$v['name'] && !$v['num']){
+                    unset($contract['product'][$k]);
+                }
+            }
+        }
+        //标记通知已读
+        Message::setRead(Message::CONTRACT_TYPE, $id, $this->auth->id);
+
+        $this->success('请求成功', $contract);
+    }
+
+
+    //获取附件列表
+    public function getFilesList()
+    {
+        $id = input('contract_id');
+
+        $files = ContractFile::where(['contract_id' => $id])->field('file_id')->with(['file'])->select();
+        $this->success('请求成功', $files);
+    }
+
+
+    //撤回审核
+    public function cancel()
+    {
+        $id = input('id');
+        $customer = ContractModel::where(['id' => $id, 'check_status' => ['in', [0, 1]]])->find();
+        if (empty($customer)) {
+            $this->error('合同信息不存在');
+        }
+        $record = ExamineRecord::where([
+            'relation_type' => ExamineRecord::CONTRACT_TYPE,
+            'relation_id' => $id,
+            'status' => 0
+        ])->find();
+        Db::startTrans();
+        try {
+            if ($message = Message::where(['relation_type' => 'examine', 'relation_id' => $record['id'], 'from_staff_id' => $this->auth->id])->find()) {
+                Message::where(['id' => $message['id']])->update(['status' => 1, 'read_time' => time()]);
+            }
+            ContractModel::where(['id' => $id])->update(['check_status' => 4]);
+            ExamineRecord::where([
+                'relation_type' => ExamineRecord::CONTRACT_TYPE,
+                'relation_id' => $id,
+                'status' => 0
+            ])->update(['status' => 3]);
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();;
+            $this->error($e->getMessage());
+        }
+
+
+        $this->success('撤回成功');
+    }
+
+
+    //修改合同
+    public function editContract()
+    {
+        $id = input('id');
+        $params = $this->request->post();
+        $row = ContractModel::where(['id' => $id, 'check_status' => ['in', [3, 4]]])->find();
+        if (empty($row)) {
+            $this->error('合同信息不存在');
+        }
+        // 表单验证
+        if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) {
+            $this->error($result);
+        }
+        $result = FormField::checkFields(FormField::CONTRACT_TYPE, $params,$id);
+        if ($result !== true) {
+            $this->error($result);
+        }
+        Db::startTrans();
+        try {
+            $params['owner_staff_id'] = $row['owner_staff_id'];
+            $result = ContractModel::updateContract($params);
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        $this->success('修改合同信息成功');
+    }
+    //获取合同编号
+    public function getContractNumber()
+    {
+        $this->success('请求成功', ['number' => ContractModel::getNum()]);
+    }
+
+    /**
+     * 获取业绩分割比例
+     */
+    public function getRatio()
+    {
+        $ratios = Ratio::where(['status' => 1])->field('name,ratio')->select();
+        $ratios = collection($ratios)->toArray();
+        foreach ($ratios as $k => $v) {
+            $v['ratio'] = json_decode($v['ratio'], true);
+            $ratios[$k] = $v;
+        }
+        $this->success('请求成功', $ratios);
+    }
+}

+ 564 - 0
addons/qingdong/controller/Customer.php

@@ -0,0 +1,564 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Contacts;
+use addons\qingdong\model\Customer as CustomerModel;
+use addons\qingdong\model\CustomerFile;
+use addons\qingdong\model\CustomerOther;
+use addons\qingdong\model\Business;
+use addons\qingdong\model\Contract;
+use addons\qingdong\model\FormField;
+use addons\qingdong\model\StaffSignIn;
+use addons\qingdong\model\Consume;
+use addons\qingdong\model\Receivables;
+use addons\qingdong\model\OperationLog;
+use addons\qingdong\model\Form;
+use addons\qingdong\model\Record;
+use addons\qingdong\model\Record as RecordModel;
+use addons\qingdong\model\Staff;
+use addons\qingdong\model\StaffCollect;
+use addons\qingdong\model\Message;
+use think\Db;
+use think\Exception;
+use function EasyWeChat\Kernel\Support\get_client_ip;
+
+/**
+ * 操作文档:https://doc.fastadmin.net/qingdong
+ * 软件介绍:https://www.fastadmin.net/store/qingdong.html
+ * 售后微信:qingdong_crm
+ * 客户接口
+ */
+class Customer extends StaffApi
+{
+    protected $noNeedLogin = [];
+    protected $noNeedRight = [];
+
+
+    //获取select客户列表
+    public function getSelectList()
+    {
+        $name = input('name');
+        $where = [];
+        if ($name) {
+            $where['name'] = ['like', "%{$name}%"];
+        }
+
+        $staff_id=$this->auth->id;
+        $list = CustomerModel::where($where)->where(function ($query) use ($staff_id) {
+            $query->where('ro_staff_id', 'like', "%,{$staff_id},%")
+                ->whereOr('rw_staff_id', 'like', "%,{$staff_id},%")
+                ->whereOr('owner_staff_id', 'in', Staff::getMyStaffIds());
+        })->with(['ownerStaff'])->field('id,name,owner_staff_id,follow')->select();
+        $this->success('请求成功', $list);
+    }
+
+    //获取客户列表
+    public function getList()
+    {
+        $limit = input("limit/d", 10);
+        $params = $this->request->post();
+
+        $where= FormField::updateWhereField(FormField::CUSTOMER_TYPE,$params);
+
+        $whereStaff = [];
+        if (isset($params['name']) && $params['name']) {//客户名称
+            if(is_numeric($params['name'])){
+                $whereContact['mobile'] = ['like', "%".$params['name']."%"];
+                $customer_id= Contacts::where($whereContact)->column('customer_id');
+                $where['id'] = array('in',$customer_id);
+            }else{
+                $where['name|subname'] = ['like', "%{$params['name']}%"];
+            }
+        }
+        if (isset($params['level']) && $params['level']) {//客户星级
+            $where['level'] = $params['level'];
+        }
+        if (isset($params['source']) && $params['source']) {//客户来源
+            $where['source'] = $params['source'];
+        }
+        if (isset($params['follow']) && $params['follow']) {//跟进状态
+            $where['follow'] = $params['follow'];
+        }
+        if (isset($params['group_id']) && $params['group_id']) {//角色组
+            $ids = Staff::getGroupStaffIds($params['group_id']);
+            $where['id'] = ['in', $ids];
+        }
+        if (isset($params['createtime']) && $params['createtime']) {//
+            $createtime = $params['createtime'];
+            $createtime = explode(',', $createtime);
+            $where['createtime'] = ['between', [strtotime($createtime[0]), strtotime($createtime[1]) + 86400 - 1]];
+        }
+        $order = 'id desc';
+        if (isset($params['sort']) && $params['sort']) {
+            switch ($params['sort']) {
+                case 1://名称正序
+                    $order = 'name asc';
+                    break;
+                case 2://名称倒序
+                    $order = 'name desc';
+                    break;
+                case 3://创建时间正序
+                    $order = 'createtime asc';
+                    break;
+                case 4://创建时间倒序
+                    $order = 'createtime desc';
+                    break;
+                case 5://下次跟进时间正序
+                    $order = 'next_time asc';
+                    break;
+                case 6://下次跟进时间倒序
+                    $order = 'next_time desc';
+                    break;
+            }
+        }
+
+        if (isset($params['next_time']) && $params['next_time']) {//下次联系时间
+            $next_time = $params['next_time'];
+            $next_time = explode(',', $next_time);
+            $where['next_time'] = ['between', [$next_time[0], $next_time[1]]];
+        }
+        if (isset($params['staff_id']) && $params['staff_id']) {//下级员工筛选
+            $where['owner_staff_id'] = $params['staff_id'];
+        } else {
+            $staff_id = $this->auth->id;
+            $type = $params['type'] ?? 0;
+            if ($type == 1) {//我的客户
+                $whereStaff['owner_staff_id'] = $this->auth->id;
+            } elseif ($type == 2) {//下属负责的客户
+                $whereStaff['owner_staff_id'] = ['in', Staff::getLowerStaffId()];
+            } elseif ($type == 3) {//我参与的客户
+                $whereStaff = function ($query) use ($staff_id) {
+                    $query->where('ro_staff_id', 'like', "%,{$staff_id},%")
+                        ->whereOr('rw_staff_id', 'like', "%,{$staff_id},%");
+                };
+            }else{
+                $whereStaff = function ($query) use ($staff_id) {
+                    $query->where(['ro_staff_id' => ['like', "%,{$staff_id},%"]])
+                        ->whereOr('rw_staff_id', 'like', "%,{$staff_id},%")
+                        ->whereOr(['owner_staff_id' => ['in', Staff::getMyStaffIds()]]);
+                };
+            }
+
+        }
+        $whereSeas = ['owner_staff_id' => ['neq', 0]];
+        if (isset($params['is_seas']) && $params['is_seas'] == 1) {//公海
+            //公海权限
+            $whereSeas=[];
+            $where['owner_staff_id'] = 0;
+            //公海权限
+            $rules=Staff::getStaffRule('seas');
+            $whereStaff = function ($query) use ($rules) {
+                foreach ($rules as $rule) {
+                    $query->whereOr(['seas_id' => ['like', "%,{$rule},%"]]);
+                }
+            };
+            $order = 'sea_time desc';
+        }
+        if(is_array($whereStaff)){
+            //查询会冲突
+            $whereSeas=[];
+        }
+
+        if (isset($params['contract_status']) && $params['contract_status'] !== "") {
+            $where['contract_status'] = $params['contract_status'];
+        }
+        $list = CustomerModel::where($where)->where($whereStaff)->where($whereSeas)->with([
+            'ownerStaff',
+            'contacts'
+        ])->field('id,name,next_time,owner_staff_id,level,follow')->order($order)->paginate($limit);
+        $this->success('请求成功', $list);
+    }
+
+
+    //查重客户名称
+    public function selectName()
+    {
+        $name = input('name');
+        if (CustomerModel::where(['name' => $name])->find()) {
+            $this->error('客户名称已存在');
+        }
+        $this->success('当前客户名称可使用');
+    }
+
+
+    //新增客户
+    public function addCustomer()
+    {
+        $params = $this->request->post();
+        if (empty($params['customer'])) {
+            $this->error('客户信息不能为空');
+        }
+
+        // 表单验证
+        if (($result = $this->qingdongValidate($params['customer'], get_class(), 'create')) !== true) {
+            $this->error($result);
+        }
+        $result = FormField::checkFields(FormField::CUSTOMER_TYPE,$params['customer']);
+        if ($result !== true) {
+            $this->error($result);
+        }
+        if (CustomerModel::where(['name' => $params['customer']['name']])->find()) {
+            $this->error('客户名称已存在');
+        }
+
+        if (isset($params['is_event']) && $params['is_event'] == 1) {//是否创建跟进任务
+            if (empty($params['event'])) {
+                $this->error('跟进任务信息不能为空');
+            }
+            // 表单验证
+            if (($result = $this->qingdongValidate($params['event'], str_replace(ucwords($this->request->controller()), 'Event', get_class()), 'create_task')) !== true) {
+                $this->error($result);
+            }
+
+        }
+
+        Db::startTrans();
+        try {
+            //线索转化
+            $leads_id = '';
+            if(isset($params['leads_id'])){
+                $leads_id=$params['leads_id'];
+            }
+            $customerId = CustomerModel::createCustomer($params['customer'],$leads_id,$params['record']);
+            if(isset($params['customer']['mobile']) && $params['customer']['mobile']){
+                $retC = array(
+                    'customer_id'=>$customerId,
+                    'is_major'=>1,
+                    'name'=>$params['customer']['name'],
+                    'mobile'=>$params['customer']['mobile'],
+                    'next_time'=>date('Y-m-d H:i:s'),
+                );
+                Contacts::createContacts($retC);
+            }
+
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if ($result) {
+            $this->success('新增客户成功',array('id'=>$customerId));
+        }
+    }
+
+
+    //编辑客户
+    public function editCustomer()
+    {
+        $id = input('id');
+        $params = $this->request->post();
+        $row = CustomerModel::where(['id' => $id])->find();
+        if (empty($row)) {
+            $this->error('客户信息不存在');
+        }
+        // 表单验证
+        if (($result = $this->qingdongValidate($params, get_class(), 'edit')) !== true) {
+            $this->error($result);
+        }
+        $result = FormField::checkFields(FormField::CUSTOMER_TYPE,$params,$id);
+        if ($result !== true) {
+            $this->error($result);
+        }
+        Db::startTrans();
+        try {
+            $result = CustomerModel::updateCustomer($params);
+            if(isset($params['mobile']) && $params['mobile']){
+                Contacts::where(array('customer_id'=>$id,'is_major'=>1))->update(array('mobile'=>$params['mobile'],'updatetime'=>time()));
+            }
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        $this->success('修改客户成功');
+    }
+
+
+    //获取子公司
+    public function getLowerCustomer()
+    {
+        $id = input('id');
+        $customers = CustomerModel::where(['parent_id' => $id])->with([
+            'ownerStaff',
+            'contacts'
+        ])->field('id,name,next_time,owner_staff_id,level,follow')->select();
+
+        $this->success('请求成功', $customers);
+    }
+
+
+    //客户详情
+    public function customerDetail()
+    {
+        $id = input('id');
+        $customer = CustomerModel::where(['id' => $id])->with([
+            'createStaff',
+            'ownerStaff',
+            'contacts'
+        ])->find();
+        if (empty($customer)) {
+            $this->error('信息不存在');
+        }
+        $customer = $customer->toArray();
+        $customer['is_collect'] = StaffCollect::isCollect(StaffCollect::CUSTOMER_TYPE, $customer['id']) ? 1 : 0;
+
+        if ($customer['owner_staff_id'] == $this->auth->id ||
+            in_array($customer['owner_staff_id'],Staff::getLowerStaffId()) ||
+        in_array($this->auth->id, explode(',', $customer['rw_staff_id'])) ) {
+            $customer['operation'] = 'update';//修改权限
+        } else {
+            $customer['operation'] = 'read';//只读权限
+        }
+
+        $customer = CustomerOther::getOther($customer);
+        $form = Form::getDataValue('customer',$customer);
+        foreach($form as $ks=>$vs){
+            //备注显示
+            if($vs['component'] == 'textarea' && ($vs['config']['label'] == '备注信息' || $vs['config']['label'] == '备注')){
+                $customer[$vs['id']] = isset($customer[$vs['id']]) ? $customer[$vs['id']] :$customer['remarks'];
+            }
+        }
+        //商机数量
+        $customer['bussinessCount'] = Business::where(['customer_id'=>$id])->count();
+        //联系人数量
+        $customer['contactsCount'] = Contacts::where(['customer_id'=>$id])->count();
+        //签到数量
+        $customer['signCount'] = StaffSignIn::where(['customer_id'=>$id])->count();
+        //合同数量
+        $customer['contractCount'] = Contract::where(['customer_id'=>$id])->count();
+        //费用数量
+        $customer['consumeCount'] = Consume::where(['customer_id'=>$id])->count();
+        //回款数量
+        $customer['receivalbleCount'] = Receivables::where(['customer_id'=>$id])->count();
+        //子公司
+        $customer['companyCount'] = CustomerModel::where(['parent_id'=>$id])->count();
+        //团队
+        $ro_staff_id = [];
+        if($customer['ro_staff_id']){
+            $ro_staff_id = array_unique(array_filter(explode(',',$customer['ro_staff_id'])));
+        }
+        $rw_staff_id = [];
+        if($customer['rw_staff_id']){
+            $rw_staff_id = array_unique(array_filter(explode(',',$customer['rw_staff_id'])));
+        }
+        $customer['teamCount'] = count($ro_staff_id)+count($rw_staff_id);
+        //附件
+        $customer['fileCount'] = CustomerFile::where(['customer_id'=>$id])->count();
+        //操作记录
+        $customer['operateCount'] = OperationLog::where(['relation_id'=>$id,'relation_type'=>1,'operation_type' => 1])->count();
+        //标记通知已读
+        Message::setRead(Message::CUSTOMER_TYPE, $id, $this->auth->id);
+        $this->success('请求成功', $customer);
+    }
+
+
+    //移入公海
+    public function moveSeas()
+    {
+        $id = input('id');
+        $row = CustomerModel::where(['id' => $id, 'owner_staff_id' => $this->auth->id])->find();
+        if (empty($row)) {
+            $this->error('您不是负责人暂无权限移除');
+        }
+        Db::startTrans();
+        try {
+            CustomerModel::moveSeas($id);
+
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        $this->success('放入成功');
+    }
+
+
+    //转移客户
+    public function transfer()
+    {
+        $id = input('id');
+        $staff_id = input('staff_id');
+        if (empty($staff_id)) {
+            $this->error('参数错误');
+        }
+        $staff = Staff::get($staff_id);
+        if (empty($staff)) {
+            $this->error('接收对象不存在');
+        }
+        $row = CustomerModel::where(['id' => $id])->find();
+        if (empty($row)) {
+            $this->error('客户不存在');
+        }
+        try {
+            CustomerModel::transfer($id, $staff_id);
+        } catch (Exception $e) {
+            $this->error($e->getMessage());
+        }
+        $this->success('转移客户成功');
+    }
+
+
+    //领取公海客户
+    public function receive()
+    {
+        $customer_id = input('customer_id');
+        $where = ['owner_staff_id' => 0];
+        if ($customer_id) {
+            $where['id'] = $customer_id;
+        }
+        $customers = CustomerModel::where($where)->count();
+        if ($customers == 0) {
+            $this->error('公海内暂无客户');
+        }
+        try {
+            $id = CustomerModel::receive($customer_id);
+        } catch (Exception $e) {
+            $this->error($e->getMessage());
+        }
+        $this->success('领取成功', ['id' => $id]);
+    }
+
+
+    //重点关注客户
+    public function collect()
+    {
+        $customer_id = input('customer_id');
+        try {
+            StaffCollect::addCollect(StaffCollect::CUSTOMER_TYPE, $customer_id);
+        } catch (Exception $e) {
+            $this->error($e->getMessage());
+        }
+        $this->success('重点关注成功');
+    }
+
+
+    //取消重点关注
+    public function cancelCollect()
+    {
+        $customer_id = input('customer_id');
+        try {
+            StaffCollect::cancel(StaffCollect::CUSTOMER_TYPE, $customer_id);
+        } catch (Exception $e) {
+            $this->error($e->getMessage());
+        }
+        $this->success('取消重点关注成功');
+    }
+
+
+    //重点关注客户列表
+    public function collectList()
+    {
+        $limit = input("limit/d", 10);
+        $ids = StaffCollect::where(['staff_id' => $this->auth->id, 'relation_type' => 1])->column('relation_id');
+        $list = CustomerModel::where(['id' => ['in', $ids]])->with([
+            'ownerStaff',
+            'contacts'
+        ])->field('id,name,next_time,owner_staff_id,level,follow')->order('id desc')->paginate($limit);
+
+        $this->success('请求成功', $list);
+    }
+
+
+    //获取附件列表
+    public function getFilesList()
+    {
+        $id = input('customer_id');
+
+        $files = CustomerFile::where(['customer_id' => $id])->field('file_id')->with(['file'])->select();
+        $this->success('请求成功', $files);
+    }
+
+
+    //周围客户
+    public function nearby()
+    {
+        $lng = input('lng');
+        $lat = input('lat');
+        //我的客户
+        $type = input('type',0);
+        //距离
+        $distance = input('distance', 5, 'intval');
+        $name = input('name', '', 'trim');
+
+        if (empty($lng) && empty($lat)) {
+            $this->error('参数错误');
+        }
+
+        $range = 180 / pi() * $distance / 6372.797; //里面的 1 就代表搜索 1km 之内,单位km
+        $lngR = $range / cos($lat * pi() / 180);
+        $maxLat = $lat + $range; //最大纬度
+        $minLat = $lat - $range; //最小纬度
+        $maxLng = $lng + $lngR; //最大经度
+        $minLng = $lng - $lngR; //最小经度
+        $where = ['lng' => ['between', [$minLng, $maxLng]], 'lat' => ['between', [$minLat, $maxLat]]];
+        //客户分类
+        $whereStaff=[];
+        $staff_id=$this->auth->id;
+        if ($type == 1) {//我的客户
+            $whereStaff['owner_staff_id'] = $this->auth->id;
+        } elseif ($type == 2) {//下属负责的客户
+            $whereStaff['owner_staff_id'] = ['in', Staff::getLowerStaffId()];
+        } elseif ($type == 3) {//我参与的客户
+            $whereStaff = function ($query) use ($staff_id) {
+                $query->where('ro_staff_id', 'like', "%,{$staff_id},%")
+                    ->whereOr('rw_staff_id', 'like', ",{$staff_id},");
+            };
+        }else{
+            $whereStaff = function ($query) use ($staff_id) {
+                $query->where('ro_staff_id', 'like', "%,{$staff_id},%")
+                    ->whereOr('rw_staff_id', 'like', "%,{$staff_id},%")
+                    ->whereOr('owner_staff_id', 'in', Staff::getMyStaffIds());
+            };
+        }
+        if ($name) {
+            $where['name'] = ['like', "%{$name}%"];
+        }
+        $customers = CustomerModel::where($where)->where($whereStaff)->field('id,owner_staff_id,name,location,next_time,lng,lat,address_detail,follow')->with('ownerStaff')->select();
+        $data = [];
+        //所属员工列表
+        $myStaffIds = Staff::getMyStaffIds();
+        foreach ($customers as $k => $v) {
+            if ($v['owner_staff_id'] == 0) {
+                $v['type'] = 0;//公海
+            } elseif ($v['owner_staff_id'] == $this->auth->id) {
+                $v['type'] = 1;//自己的
+            } elseif (in_array($v['owner_staff_id'], $myStaffIds)) {
+                $v['type'] = 2;//团队的
+            } else {
+                $v['type'] = 3;//其他人
+            }
+            $v['juli_num'] = getdistance($lng, $lat, $v['lng'], $v['lat']);
+            $v['juli'] = float_number($v['juli_num']);
+            $data[$v['juli']][] = $v;
+        }
+        ksort($data);
+
+
+        $result = [];
+        foreach ($data as $v) {
+
+            $result = array_merge($result, array_values($v));
+        }
+        $this->success('请求成功', $result);
+    }
+
+
+    //获取搜索员工列表
+    public function getSearchStaffList()
+    {
+        $name = input('name','');
+        $where = [];
+        if($name){
+            $where['name'] = ['like',"%$name%"];
+        }
+        $ids = Staff::getMyStaffIds();
+
+        $staff = Staff::where([
+            'id' => ['in', $ids],
+            'status' => 1
+        ])->where($where)->field('id,name,img,post')->select();
+        $this->success('请求成功', $staff);
+    }
+
+}

+ 327 - 0
addons/qingdong/controller/Daily.php

@@ -0,0 +1,327 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Daily as DailyModel;
+use addons\qingdong\model\DailyRead;
+use addons\qingdong\model\File;
+use addons\qingdong\model\Form;
+use addons\qingdong\model\Staff;
+use addons\qingdong\model\Message;
+use addons\qingdong\model\DailyDraft;
+use think\Db;
+use think\Exception;
+/**
+ * 工作报告接口
+ */
+class Daily extends StaffApi {
+	protected $noNeedLogin = [];
+	protected $noNeedRight = [];
+
+
+    //创建
+    public function createDaily()
+    {
+        $params = $this->request->post();
+
+        Db::startTrans();
+        try {
+            $params['create_staff_id'] = $this->auth->id;
+            $dailyId = DailyModel::createDaily($params);
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        $this->success('创建工作报告成功');
+    }
+
+
+    //获取
+    public function getList()
+    {
+        $limit = input("limit/d", 10);
+        $is_read = input('is_read', 0);
+        $staff_ids = input('staff_id', 0);
+        $type = input('type', 0);
+        $times = input('times', '');
+
+        $where = [];
+        $where['create_staff_id'] = ['in', Staff::getMyStaffIds()];
+
+        if ($staff_ids) {
+            $where['create_staff_id'] = $staff_ids;
+        }
+
+        if ($type) {
+            $where['type'] = $type;
+        }
+        if ($times) {//筛选时间
+            $times = explode(',', $times);
+            $where['createtime'] = ['between', [strtotime($times[0]), strtotime($times[1]) + 86400 - 1]];
+        }
+        $staff_id = $this->auth->id;
+        if ($is_read == 1) {//已读
+            $ids = DailyRead::where(['staff_id' => $staff_id])->column('daily_id');
+            $where['id'] = ['in', $ids];
+        } elseif ($is_read == 2) {//未读
+            $ids = DailyRead::where(['staff_id' => $staff_id])->column('daily_id');
+            $where['id'] = ['not in', $ids];
+        }
+        $followWhere = [];
+        $elseWhere = [];
+        if (!$staff_ids) {
+            $followWhere[] = ['exp', Db::raw('FIND_IN_SET(' . $this->auth->id . ',reminds_id)')];
+            if ($type) {
+                $elseWhere['type'] = ['eq', $type];
+            }
+            if ($is_read == 1) {//已读
+                $elseWhere['id'] = ['in', $ids];
+            } elseif ($is_read == 2) {//未读
+                $elseWhere['id'] = ['not in', $ids];
+            }
+        }
+
+
+        $records = DailyModel::where($where)->whereOr(function ($query) use ($followWhere, $elseWhere) {
+            $query->where($followWhere)->where($elseWhere);
+        })->with([
+            'staff',
+            'read' => function ($query) use ($staff_id) {
+                $query->where(['staff_id' => $staff_id]);
+            }
+        ])->order('id desc')->paginate($limit)->toArray();
+
+        $data = $records['data'];
+        foreach ($data as $k => $v) {
+            if (!empty($v['read'])) {
+                $v['is_read'] = 1;
+            } else {
+                $v['is_read'] = 0;
+            }
+            $data[$k] = $v;
+        }
+        $this->success('请求成功', [
+            'total' => $records['total'],
+            'per_page' => $records['per_page'],
+            'current_page' => $records['current_page'],
+            'last_page' => $records['last_page'],
+            'data' => $data
+        ]);
+
+        $this->success('请求成功', $records);
+    }
+
+
+    //获取详情
+    public function getDailyDetail()
+    {
+        $id = input('id');
+        if (empty($id)) {
+            $this->error('参数不能为空');
+        }
+        $record = DailyModel::where(['id' => $id])->with([
+            'staff',
+        ])->find();
+        if (empty($record)) {
+            $this->error('记录不存在');
+        }
+
+        $record = $record->toArray();
+        $reminds_id = $record['reminds_id'];
+        $reminds_id = explode(',', $reminds_id);
+        $names = Staff::where(['id' => ['in', $reminds_id]])->column('name');
+        $record['staff_name'] = implode(',', $names);
+        if ($record['other']) {
+            if(is_array($record['other'])){
+                $other  = $record['other'];
+            }else{
+                $other = json_decode($record['other'], true);
+            }
+        } else {
+            $other = [];
+        }
+        $record = array_merge($record, $other);
+        switch($record['type']){
+            case '日报':
+                $type = 'daily';
+                break;
+            case '周报':
+                $type ='weekly';
+                break;
+            case '月报':
+                $type = 'monthly';
+                break;
+            case '季报':
+                $type = 'quarterly';
+                break;
+            case '年报':
+                $type = 'yearly';
+                break;
+            default:
+                $type = 'daily';
+                break;
+        }
+
+        $form = Form::getDataValue($type,$record);
+        foreach($form as $k=>$v){
+            if($v['component'] == 'uploadImage' || $v['component'] == 'uploadFile'){
+                if(key_exists($v['id'],$record)){
+                    if(isset($record[$v['id']]) && $record[$v['id']]){
+                        $whereT['id'] = array('in',$record[$v['id']]);
+                        $fileinfo = File::where($whereT)->field('id,name,file_path')->select();
+                        if($fileinfo){
+                            $record[$v['id']] = $fileinfo;
+                        }
+                    }
+                }
+            }
+        }
+        //标记通知已读
+        Message::setRead(Message::DAILY_TYPE, $id, $this->auth->id);
+        //添加阅读记录
+        DailyRead::addRead($id, $this->auth->id);
+
+        $this->success('请求成功', $record);
+    }
+
+
+    //获取工作报告已读 未读
+    public function getDailyRead()
+    {
+        $id = input('id');
+        if (empty($id)) {
+            $this->error('参数错误');
+        }
+        $daily = DailyModel::where(['id' => $id])->find();
+        if (empty($daily)) {
+            $this->error('记录不存在');
+        }
+        $create_staff_id = $daily['create_staff_id'];
+
+        $read = DailyRead::where(['daily_id' => $id])->group('staff_id')->field('id,staff_id')->with(['staff'])->select();
+        $staffIds = [];
+        foreach ($read as $v) {
+            $staffIds[] = $v['staff_id'];
+        }
+        //全部可看数据的人
+        $allids = explode(',', $daily->reminds_id);
+        $not_ids = array_diff($allids, $staffIds);
+
+        $notRead = Staff::where(['id' => ['in', $not_ids]])
+            ->field('id,name,img')->select();
+        $this->success('请求成功', ['read' => $read, 'not_read' => $notRead]);
+    }
+
+    //草稿创建
+    public function daily_draft()
+    {
+        $params = $this->request->post();
+
+        Db::startTrans();
+        try {
+            $params['create_staff_id'] = $this->auth->id;
+            //自定义字段
+            $other = [];
+            foreach ($params as $name => $val) {
+                if (strstr($name, 'other_') !== false) {
+                    if(is_array($val)){
+                        $other[$name] = implode(',',$val);
+                    }else{
+                        $other[$name] = $val;
+                    }
+                    unset($params[$name]);
+                }
+            }
+            $params['other'] = json_encode($other);
+            $where['create_staff_id'] = $this->auth->id;
+            $where['type'] = $params['type'];
+            $info = DailyDraft::where($where)->find();
+            if ($info) {
+                $result = DailyDraft::where(array('id' => $info['id']))->update($params);
+            } else {
+                $result = DailyDraft::create($params);
+            }
+
+            if (false === $result) {
+                // 验证失败 输出错误信息
+                throw new Exception('草稿保存失败');
+            }
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        $this->success('草稿保存成功');
+    }
+
+    //获取详情
+    public function getDailyDraftDetail()
+    {
+        $type = input('type');
+        if (!$type) {
+            $this->error('参数不正确');
+        }
+        $where['create_staff_id'] = $this->auth->id;
+        $where['type'] = $type;
+        $record = DailyDraft::where($where)->find();
+        if (empty($record)) {
+            $this->success('记录不存在');
+        }
+        switch ($record['type']) {
+            case '日报':
+                $record['type_index'] = 0;
+                break;
+            case '周报':
+                $record['type_index'] = 1;
+                break;
+            case '月报':
+                $record['type_index'] = 2;
+                break;
+            case '季报':
+                $record['type_index'] = 3;
+                break;
+            case '年报':
+                $record['type_index'] = 4;
+                break;
+            default:
+                $record['type_index'] = 0;
+                break;
+        }
+        $record = $record->toArray();
+        $reminds_id = $record['reminds_id'];
+        $reminds_id = explode(',', $reminds_id);
+        $names = Staff::where(['id' => ['in', $reminds_id]])->field('id,img,name,post')->select();
+        $record['staff_info'] = $names;
+        if ($record['other']) {
+            $other = json_decode($record['other'], true);
+        } else {
+            $other = [];
+        }
+        $record = array_merge($record, $other);
+
+        $this->success('请求成功', $record);
+    }
+
+
+
+    //修改工作报告
+    public function updateDaily()
+    {
+        $params = $this->request->post();
+        if(empty($params['id'])){
+            $this->error('参数不能为空');
+        }
+
+        Db::startTrans();
+        try {
+            $dailyId = DailyModel::updateDaily($params);
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        $this->success('创建工作报告成功');
+    }
+
+}

+ 23 - 0
addons/qingdong/controller/ErrorCode.php

@@ -0,0 +1,23 @@
+<?php
+namespace addons\qingdong\controller;
+/**
+ * error code 说明.
+ * <ul>
+
+ *    <li>-41001: encodingAesKey 非法</li>
+ *    <li>-41003: aes 解密失败</li>
+ *    <li>-41004: 解密后得到的buffer非法</li>
+ *    <li>-41005: base64加密失败</li>
+ *    <li>-41016: base64解密失败</li>
+ * </ul>
+ */
+class ErrorCode
+{
+	public static $OK = 0;
+	public static $IllegalAesKey = -41001;
+	public static $IllegalIv = -41002;
+	public static $IllegalBuffer = -41003;
+	public static $DecodeBase64Error = -41004;
+}
+
+?>

+ 206 - 0
addons/qingdong/controller/Event.php

@@ -0,0 +1,206 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Event as EventModel;
+use addons\qingdong\model\File;
+use addons\qingdong\model\Form;
+use addons\qingdong\model\StaffSignIn;
+use addons\qingdong\model\Message;
+use addons\qingdong\model\Staff;
+use think\Db;
+use think\Exception;
+
+/**
+ * 日程接口
+ */
+class Event extends StaffApi
+{
+    protected $noNeedLogin = [];
+    protected $noNeedRight = [];
+
+
+    //获取日程
+    public function getEvent()
+    {
+        //开始时间
+        $start_day = input('start_day');
+        //结束时间
+        $end_day = input('end_day');;
+        if (empty($start_day) || empty($end_day)) {
+            $this->error('开始时间或结束时间不能为空');
+        }
+        if ($end_day < $start_day) {
+            $this->error('开始时间不能小于结束时间');
+        }
+        $this->success('请求成功', EventModel::getTimeList($start_day, $end_day));
+    }
+
+
+    //添加日程
+    public function addEvent()
+    {
+        $params = $this->request->post();
+        // 表单验证
+        if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) {
+            $this->error($result);
+        }
+        Db::startTrans();
+        try {
+            $params['type'] = 1;//日程
+            $result = EventModel::createEvent($params);
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if ($result) {
+            $this->success('添加日程成功');
+        }
+    }
+
+
+    //变更状态
+    public function changeStatus()
+    {
+        $id = input('id');
+        $status = input('status', 0);
+        if (empty($id)) {
+            $this->error('参数错误');
+        }
+        Db::startTrans();
+        try {
+            EventModel::changeStatus($id, $status);
+            Db::commit();
+        } catch (Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        $this->success('变更成功');
+    }
+
+
+    //
+    public function getList()
+    {
+        $relation_type = input('relation_type', '', 'intval');// 1客户 2联系人 3合同 4线索
+        $relation_id = input('relation_id', '', 'intval');
+        $limit = input("limit/d", 10);
+        $where = [];
+        $where['relation_type'] = $relation_type;
+        $where['relation_id'] = $relation_id;
+        $where['staff_id'] = $this->auth->id;
+        $records = EventModel::where($where)->with(['staff'])->field('id,staff_id,type,title,start_time,end_time,status,auto_end,level,remindtype,remark,color,createtime')->order('id desc')->paginate($limit);
+        $this->success('请求成功', $records);
+    }
+
+
+    //添加签到
+    public function addSign()
+    {
+        $params = $this->request->post();
+        $location = input('location');
+        $lng = input('lng');
+        $lat = input('lat');
+        $files = input('file_ids');
+        $customer_id = input('customer_id');
+        $content = input('content');
+        if (empty($lng) || empty($lat)) {
+            $this->error('地理位置不能为空');
+        }
+
+        //自定义字段
+        $other = [];
+        foreach ($params as $name => $val) {
+            if (strstr( $name,'other_') !== false) {
+                if(is_array($val)){
+                    $other[$name] = implode(',',$val);
+                }else{
+                    $other[$name] = $val;
+                }
+                unset($params[$name]);
+            }
+        }
+
+        $data = [
+            'location' => $location,
+            'lng' => $lng,
+            'lat' => $lat,
+            'file_ids' => $files,
+            'customer_id' => $customer_id,
+            'staff_id' => $this->auth->id,
+            'other' => json_encode($other, JSON_UNESCAPED_UNICODE)
+        ];
+        $model = new StaffSignIn();
+        if ($result = $model->save($data)) {
+            $lastId = $model->getLastInsID();
+            //通知上级
+            Message::addMessage(Message::SIGN_TYPE, $lastId, $this->auth->parent_id, $this->auth->id);
+            $this->success('签到成功');
+        }
+        $this->error('签到失败');
+    }
+
+
+    //获取签到信息
+    public function getSign()
+    {
+        $customer_id = input('customer_id', 0, 'intval');
+        $limit = input("limit/d", 10);
+        $where = [];
+        $type       = input('type', 0);// 0 全部 1 我创建 2 下属创建
+
+        if ($type == 1) {//我的客户
+            $where['staff_id'] = $this->auth->id;
+        } elseif ($type == 2) {//下属负责的客户
+            $where['staff_id'] = ['in', Staff::getLowerStaffId()];
+        }else{
+            $where['staff_id'] = ['in', Staff::getMyStaffIds()];
+        }
+        if ($customer_id) {
+            $where['customer_id'] = $customer_id;
+        }
+        $staffSign = StaffSignIn::where($where)->with(['staff', 'customer'])
+            ->order('id desc')->paginate($limit);
+        //标记通知已读
+        Message::setRead(Message::SIGN_TYPE,0, $this->auth->id);
+        $this->success('请求成功', $staffSign);
+    }
+
+    /**
+     * 获取签到详情
+     */
+    public function getSignDetail(){
+        $id = input('id', 0, 'intval');
+
+        $staffSign = StaffSignIn::where(['id'=>$id])->with(['staff', 'customer'])->find();
+        if(empty($staffSign)){
+            $this->error('数据不存在');
+        }
+        if($staffSign['other']){
+            $other = json_decode($staffSign['other'],true);
+            $form = Form::getDataValue('signin');
+            foreach($form as $k=>$v){
+                if($v['component'] == 'uploadImage' || $v['component'] == 'uploadFile'){
+                    $other[$v['id'].'_str'] = '';
+                    if(key_exists($v['id'],$other)){
+                        if(isset($other[$v['id']]) && $other[$v['id']]){
+                            $whereT['id'] = array('in',$other[$v['id']]);
+                            $fileinfo = File::where($whereT)->field('id,name,file_path,save_name')->select();
+                            if($fileinfo){
+                                $other[$v['id']] = $fileinfo;
+                                $fileinfodata = '';
+                                foreach($fileinfo as $kss=>$vss){
+                                    $fileinfodata = $vss['save_name'].','.$fileinfodata;
+                                }
+                                $other[$v['id'].'_str'] = rtrim($fileinfodata,',');
+                            }
+                        }
+                    }
+                }
+            }
+            $staffSign['other'] = $other;
+        }
+        $this->success('请求成功',$staffSign);
+    }
+}

+ 257 - 0
addons/qingdong/controller/ExamineRecord.php

@@ -0,0 +1,257 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\AchievementRecords;
+use addons\qingdong\model\AttendanceStatisc;
+use addons\qingdong\model\Business;
+use addons\qingdong\model\BusinessStatus;
+use addons\qingdong\model\Flow;
+use addons\qingdong\model\FormApproval;
+use addons\qingdong\model\Message;
+use addons\qingdong\model\Contract;
+use addons\qingdong\model\Consume;
+use addons\qingdong\model\Staff;
+use addons\qingdong\model\Receivables;
+use addons\qingdong\model\Achievement;
+use addons\qingdong\model\Approval;
+use addons\qingdong\model\ExamineRecord as ExamineRecordModel;
+use think\Cache;
+use think\Db;
+use think\Exception;
+use think\Log;
+
+/**
+ * 审批记录
+ */
+class ExamineRecord extends StaffApi {
+	protected $noNeedLogin = [];
+	protected $noNeedRight = [];
+
+
+	//审批记录
+	public function getList() {
+		$relation_type = input('relation_type');
+		$relation_id   = input('relation_id');
+
+		$list = ExamineRecordModel::where([
+			'relation_type' => $relation_type,
+			'relation_id'   => $relation_id
+		])->with('checkStaff')->select();
+		$this->success('请求成功', $list);
+	}
+
+
+	//审核
+	public function examine() {
+		$relation_type = input('relation_type');
+		$relation_id   = input('relation_id');
+		$content       = input('content');
+		$status        = input('status');
+        $record = ExamineRecordModel::where([
+            'relation_type' => $relation_type,
+            'relation_id' => $relation_id,
+            'status' => 0,
+            'check_staff_id' => $this->auth->id
+        ])->find();
+		if (empty($record)) {
+			$this->error('没有待审核数据');
+		}
+		$staff = Staff::info();
+		Db::startTrans();
+		try {
+			$model = new ExamineRecordModel();
+			if ($model->isUpdate(true)->save([
+					'status'     => $status,
+					'content'    => $content,
+					'check_time' => time()
+				], ['id' => $record['id']]) == false) {
+				throw new Exception('修改失败');
+			}
+			switch ($relation_type) {
+				case $model::CONSUME_TYPE://费用
+					$rowModel = new \addons\qingdong\model\Consume();
+					$row      = $rowModel->where(['id' => $relation_id])->find();
+				break;
+				case $model::CONTRACT_TYPE://合同
+					$rowModel = new \addons\qingdong\model\Contract();
+					$row      = $rowModel->where(['id' => $relation_id])->find();
+				break;
+				case $model::RECEIVABLES_TYPE://回款
+					$rowModel = new \addons\qingdong\model\Receivables();
+					$row      = $rowModel->where(['id' => $relation_id])->find();
+				break;
+				case $model::ACHIEVEMENT_TYPE://业绩目标
+					$rowModel = new \addons\qingdong\model\AchievementRecords();
+					$row      = $rowModel->where(['id' => $relation_id])->find()->toArray();
+				break;
+                case $model::APPROVAL_TYPE://审批
+                    $rowModel = new \addons\qingdong\model\Approval();
+                    $row = $rowModel->where(['id' => $relation_id])->find()->toArray();
+                    $row['staff_id'] = $row['create_staff_id'];
+                    break;
+                case $model::CARD_TYPE://补卡审核
+                    $rowModel = new \addons\qingdong\model\AttendanceCard();
+                    $row = $rowModel->where(['id' => $relation_id])->find()->toArray();
+                    $row['staff_id'] = $row['create_staff_id'];
+                    break;
+                case $model::LEAVE_TYPE://请假
+                    $rowModel = new \addons\qingdong\model\Leave();
+                    $row = $rowModel->where(['id' => $relation_id])->find()->toArray();
+                    $row['staff_id'] = $row['create_staff_id'];
+                    break;
+				default:
+					throw new Exception('参数错误');
+			}
+			if ($message = Message::where(['relation_type' => 'examine', 'relation_id' => $record['id'],'to_staff_id'=>$this->auth->id])->find()) {
+			    Message::where(['id' => $message['id']])->update(['status' => 1, 'read_time' => time()]);
+			}
+			$check_staff_ids   = explode(',', trim($row['check_staff_ids'], ','));
+			$check_staff_ids[] = $staff->id;
+			if ($status == 1) {//审核通过
+               $flow= Flow::getstepdetail($relation_type,$relation_id);
+                //给下一审核人发送通知
+                $result=Flow::sendStepRecord($flow,$relation_type, $relation_id,$check_staff_ids,$staff->id);
+
+				//已完成审核
+				if ($result['status']== true) {
+					$rowModel->save([
+						'check_status'   => 2,
+						'check_staff_ids' => implode(',', $check_staff_ids),
+                        'order_id'=>$result['order_id']
+					], ['id' => $relation_id]);
+					switch ($relation_type) {
+						case $model::CONTRACT_TYPE://合同
+							\addons\qingdong\model\Customer::where(['id'=>$row['customer_id']])->update(['contract_status'=>1]);
+                            //合同签署成功后商机变为赢单
+                            if($row['business_id']){
+                                BusinessStatus::create(array('business_id'=>$row['business_id'],'type'=>4,'remark'=>'合同签署'));
+                                Business::where(array('id'=>$row['business_id']))->update(array('contract_status'=>1,'updatetime'=>time()));
+                            }
+							break;
+						case $model::ACHIEVEMENT_TYPE://业绩目标
+							$m=new \addons\qingdong\model\Achievement();
+							$m->where(['type'=>$row['type'],'status'=>$row['status'],'obj_id'=>$row['obj_id']])->delete();
+							unset($row['id']);
+                            unset($row['createtime']);
+                            unset($row['updatetime']);
+                            unset($row['deletetime']);
+                            $m->allowField(true)->save($row);
+							$row['staff_id']=$row['obj_id'];
+						break;
+						case $model::RECEIVABLES_TYPE://回款
+							$m=new \addons\qingdong\model\Contract();
+                            $contract=$m->where(['id'=>$row['contract_id']])->with(['receivables'])->find();
+                            if($contract['receivables']['repayment_money'] >= $contract['money']){
+                                $m->save(['contract_status'=>1],['id'=>$row['contract_id']]);//已完成
+                            }
+						break;
+						case $model::CARD_TYPE://补卡
+                            if($row['type'] == 1){//早退
+                                $name='clock_out_status';
+                                $name_time='clock_out';
+                            }else{//迟到
+                                $name='clock_in_status';
+                                $name_time='clock_in';
+                            }
+                            AttendanceStatisc::where(['id'=>$row['statisc_id']])->update([$name=>5,$name_time=>$row['time']]);
+						break;
+						case $model::LEAVE_TYPE://请假
+						break;
+					}
+
+					Message::addMessage(Message::EXAMINE_ADOPT_TYPE,$record['id'],$row['owner_staff_id']?? $row['staff_id'],$staff->id);
+
+                    //删除 或签的待审批通知
+                    Message::setRead(Message::EXAMINE_TYPE,$record['id']);
+                    ExamineRecordModel::where([
+                        'relation_type' => $relation_type,
+                        'relation_id' => $relation_id,
+                        'status' => 0,
+                    ])->update(['status'=>3]);
+				} else {
+					$rowModel->save([
+                        'check_staff_ids' => implode(',', $check_staff_ids),
+                        'order_id'=>$result['order_id']
+                    ], ['id' => $relation_id]);
+				}
+			} else {
+				//审核未通过
+				$rowModel->save(['check_status' => 3, 'check_staff_ids' => ''], ['id' => $relation_id]);
+				Message::addMessage(Message::EXAMINE_REFUSE_TYPE,$record['id'],$row['owner_staff_id']?? $row['staff_id'],$staff->id,'');
+
+                //删除待审批通知
+                $ids = ExamineRecordModel::where([
+                    'relation_type' => $relation_type,
+                    'relation_id' => $relation_id,
+                    'status' => 0,
+                ])->column('id');
+                Message::where(['relation_type' => Message::EXAMINE_TYPE, 'relation_id' => ['in', $ids], 'status' => 0])->update(['read_time' => time(), 'status' => 1]);
+
+                ExamineRecordModel::where([
+                    'relation_type' => $relation_type,
+                    'relation_id' => $relation_id,
+                    'status' => 0,
+                ])->update(['status'=>3]);
+			}
+
+
+			Db::commit();
+		} catch (Exception $e) {
+			Db::rollback();
+            Log::record($e->getMessage());
+			$this->error($e->getMessage());
+		}
+
+
+		$this->success('审核成功');
+	}
+
+    /**
+     * 获取审批列表
+     */
+    public function get_examine_list()
+    {
+        $limit = input("limit/d", 10);
+        //合同审批,回款审批、业绩目标审批、办公审批 费用
+        $relation_type = input('type');
+        $status =  input('status',0);
+        if($status == 1){
+            $status = array('in','1,2');
+        }
+        $data = ExamineRecordModel::where(['relation_type' => $relation_type,
+            'status' => $status,
+            'check_staff_id' => $this->auth->id])->order('id desc')->paginate($limit)->toArray();
+        if($data['data']){
+            foreach($data['data'] as $k=>$v){
+                $data['data'][$k]['content_info'] = Message::where(array('relation_id'=>$v['id'],'relation_type'=>'examine'))->value('content');
+                if ($v['relation_type'] == ExamineRecordModel::CONSUME_TYPE) {
+                    $data['data'][$k]['relation_name'] = Consume::where(['id' => $v['relation_id']])->value('consume_type');
+                } elseif ($v['relation_type'] == ExamineRecordModel::CONTRACT_TYPE) {
+                    $data['data'][$k]['relation_name'] = Contract::where(['id' => $v['relation_id']])->value('name');
+                } elseif ($v['relation_type'] == ExamineRecordModel::RECEIVABLES_TYPE) {
+                    $data['data'][$k]['relation_name'] = Receivables::where(['id' => $v['relation_id']])->value('number');
+                } elseif($v['relation_type'] == ExamineRecordModel::ACHIEVEMENT_TYPE) {
+                    $data['data'][$k]['relation_name'] = $acchieve = AchievementRecords::where(['id' => $v['relation_id']])->value('year');;
+                } elseif($v['relation_type'] == ExamineRecordModel::APPROVAL_TYPE) {
+                    $approval = Approval::where(['id' => $v['relation_id']])->value('formapproval_id');
+                    $data['data'][$k]['relation_name'] = '';
+                    if($approval){
+                        $data['data'][$k]['relation_name'] = FormApproval::where(['id'=>$approval])->value('name');
+                    }
+
+                }elseif($v['relation_type'] == ExamineRecordModel::CARD_TYPE) {
+                    $data['data'][$k]['relation_name'] = '补卡';
+                }elseif($v['relation_type'] == ExamineRecordModel::LEAVE_TYPE) {
+                    $data['data'][$k]['relation_name'] = '请假';
+                }
+                else{
+                    $data['data'][$k]['relation_name']='';
+                }
+            }
+        }
+
+
+        $this->success('请求成功', $data);
+    }
+}

+ 30 - 0
addons/qingdong/controller/File.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\File as FileModel;
+
+/**
+ * 附件接口
+ */
+class File extends StaffApi {
+	protected $noNeedLogin = [];
+	protected $noNeedRight = [];
+
+
+	//修改附件名称
+	public function editName() {
+		$id        = input("id", 0);
+		$name      = input('name', '');
+		$filemodel = new FileModel();
+		$row       = $filemodel->get($id);
+		if (empty($row)) {
+			$this->error('附件不存在');
+		}
+		if ($row->save(['name' => $name])) {
+			$this->success('修改成功');
+		} else {
+			$this->error('修改失败');
+		}
+	}
+}

+ 463 - 0
addons/qingdong/controller/Index.php

@@ -0,0 +1,463 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Contract as ContractModel;
+use addons\qingdong\model\Event;
+use addons\qingdong\model\ExamineRecord;
+use addons\qingdong\model\Feedback;
+use addons\qingdong\model\ReceivablesPlan;
+use addons\qingdong\model\Customer;
+use addons\qingdong\model\Contacts;
+use addons\qingdong\model\Contract;
+use addons\qingdong\model\Leads;
+use addons\qingdong\model\Receivables;
+use addons\qingdong\model\Staff;
+use addons\qingdong\model\Record;
+use addons\qingdong\model\Message;
+use addons\qingdong\model\Business;
+
+/**
+ *  * 操作文档:https://doc.fastadmin.net/qingdong
+ * 软件介绍:https://www.fastadmin.net/store/qingdong.html
+ * 售后微信:qingdong_crm
+ * 首页接口
+ */
+class Index extends StaffApi
+{
+    protected $noNeedLogin = [];
+    protected $noNeedRight = ['*'];
+
+    public function index()
+    {
+        $this->error("当前插件暂无前台页面");
+    }
+
+    //搜索
+    public function search()
+    {
+        $keywords = input('keywords');
+        $type = input('type');
+        if (empty($keywords)) {
+            $this->error('筛选字段不能为空');
+        }
+        //客户
+        $customer = Customer::where([
+            'name' => ['like', "%$keywords%"],
+            'owner_staff_id' => ['in', Staff::getMyStaffIds()],
+        ])->with([
+            'ownerStaff',
+            'contacts'
+        ])->field('id,name,next_time,owner_staff_id,level,follow')->select();
+        //联系人
+        $contacts = Contacts::where([
+            'name' => ['like', "%$keywords%"],
+            'owner_staff_id' => ['in', Staff::getMyStaffIds()],
+        ])->with(['customer'])->field('id,name,mobile,customer_id')->select();
+        //线索
+        $leads = Leads::where([
+            'name' => ['like', "%$keywords%"],
+            'owner_staff_id' => ['in', Staff::getMyStaffIds()],
+        ])->with(['ownerStaff'])->field('id,owner_staff_id,name,follow,level,next_time,mobile')->select();
+
+        $this->success('请求成功', [
+            'customer' => $customer,
+            'contacts' => $contacts,
+            'leads' => $leads
+        ]);
+    }
+
+
+    //反馈
+    public function feedback()
+    {
+        $content = input('content', '', 'trim');
+        $file = input('file', '', 'trim');
+        if (empty($content)) {
+            $this->error('请输入反馈内容!');
+        }
+        $model = new Feedback();
+        $model->save([
+            'staff_id' => $this->auth->id,
+            'content' => $content,
+            'file_ids' => $file
+        ]);
+        $this->success('反馈成功');
+    }
+
+
+    //待办事项
+    public function agent()
+    {
+        $where['create_staff_id'] = $this->auth->id;
+        $where['next_time'] = array(array('egt', date('Y-m-d 00:00:00')), array('lt', date('Y-m-d 23:59:59')));
+        $where['follow_type'] = ['neq', '其它'];
+        $where['status'] = 0;
+        // 待跟进客户
+        $where1['relation_type'] = 1;
+        $customerlist = Record::where($where)->where($where1)->column('id');
+        $customerlist1 = 0;
+        if ($customerlist) {
+            $whereExit['id'] = array('in', $customerlist);
+            $whereExit['next_time'] = array('gt', date('Y-m-d 23:59:59'));
+            $customerlist1 = Record::where($whereExit)->count();
+        }
+        $customer = count($customerlist) - $customerlist1;
+
+        //待跟进合同
+        $where2['relation_type'] = 3;
+        $contractlist = Record::where($where)->where($where2)->column('id');
+        $contractlist1 = 0;
+        if ($contractlist) {
+            $whereExitC['id'] = array('in', $contractlist);
+            $whereExitC['next_time'] = array('gt', date('Y-m-d 23:59:59'));
+            $contractlist1 = Record::where($whereExitC)->count();
+        }
+        $contract = count($contractlist) - $contractlist1;
+        //待跟进线索
+        $where3['relation_type'] = 4;
+        $leadlist = Record::where($where)->where($where3)->column('id');
+        $leadlist1 = 0;
+        if ($leadlist) {
+            $whereExitL['id'] = array('in', $leadlist);
+            $whereExitL['next_time'] = array('gt', date('Y-m-d 23:59:59'));
+            $leadlist1 = Record::where($whereExitL)->count();
+        }
+        $lead = count($leadlist) - $leadlist1;
+        //待跟进联系人
+        $where4['relation_type'] = 2;
+        $contactslist = Record::where($where)->where($where4)->column('id');
+        $contactslist1 = 0;
+        if ($contactslist1) {
+            $whereExitCs['id'] = array('in', $contactslist);
+            $whereExitCs['next_time'] = array('gt', date('Y-m-d 23:59:59'));
+            $contactslist1 = Record::where($whereExitCs)->count();
+        }
+        $contacts = count($contactslist) - $contactslist1;
+        //待跟进商机
+        $where5['relation_type'] = 5;
+        $businesslist = Record::where($where)->where($where5)->column('id');
+        $businesslist1 = 0;
+        if ($businesslist1) {
+            $whereExitB['id'] = array('in', $businesslist);
+            $whereExitB['next_time'] = array('gt', date('Y-m-d 23:59:59'));
+            $businesslist1 = Record::where($whereExitB)->count();
+        }
+        $business = count($businesslist) - $businesslist1;
+
+        //待审核合同
+        $examine = ExamineRecord::where([
+            'relation_type' => ExamineRecord::CONTRACT_TYPE,
+            'status' => 0,
+            'check_staff_id' => $this->auth->id
+        ])->count();
+        //待审核回款
+        $receivables = ExamineRecord::where([
+            'relation_type' => ExamineRecord::RECEIVABLES_TYPE,
+            'status' => 0,
+            'check_staff_id' => $this->auth->id
+        ])->count();
+        //待回款提醒
+        $receivablesPlan = ReceivablesPlan::where([
+            'remind_date' => ['elt', date('Y-m-d')],
+            'status' => 0,
+            'owner_staff_id' => $this->auth->id
+        ])->count();
+        //待处理日程
+        $eventOne = Event::where([
+            'type' => 1,
+            'status' => ['in', [0, 1]],
+            'start_time' => ['lt', date('Y-m-d', strtotime('+1 day'))],
+            'staff_id|owner_staff_id' => $this->auth->id,
+        ])->count();
+        $this->success('请求成功', [
+            'customer' => $customer,
+            'business' => $business,
+            'contract' => $contract,
+            'lead' => $lead,
+            'contacts' => $contacts,
+            'event_one' => $eventOne,
+            'examine' => $examine,
+            'receivables' => $receivables,
+            'receivables_plan' => $receivablesPlan
+        ]);
+    }
+
+    //待处理日程
+    public function event_one()
+    {
+        // 待处理日程
+        $eventTask = Event::where([
+            'type' => 1,
+            'status' => ['in', [0, 1]],
+            'start_time' => ['lt', date('Y-m-d', strtotime('+1 day'))],
+            'staff_id|owner_staff_id' => $this->auth->id,
+        ])->order('id desc')->select();
+        //标记通知已读
+        Message::where([
+            'relation_type' => Message::EVENT_TYPE,
+            'to_staff_id' => $this->auth->id,
+            'status' => 0
+        ])->update(['read_time' => time(), 'status' => 1]);
+        foreach ($eventTask as &$ves) {
+            $ves['start_time'] = date('Y-m-d H:i', strtotime($ves['start_time']));
+            $ves['end_time'] = date('Y-m-d H:i', strtotime($ves['end_time']));
+        }
+        $this->success('请求成功', $eventTask);
+    }
+
+    //跟进任务
+    public function event_task()
+    {
+        // 待跟进任务
+        $eventTask = Event::where([
+            'type' => 2,
+            'status' => ['in', [0, 1]],
+            'start_time' => ['lt', date('Y-m-d', strtotime('+1 day'))],
+            'staff_id' => $this->auth->id
+        ])->select();
+        foreach ($eventTask as &$ves) {
+            $ves['start_time'] = date('Y-m-d H:i', strtotime($ves['start_time']));
+            $ves['end_time'] = date('Y-m-d H:i', strtotime($ves['end_time']));
+        }
+        $this->success('请求成功', $eventTask);
+    }
+
+
+    //待审核合同
+    public function examine_contract()
+    {
+        //待审核合同
+        $ids = ExamineRecord::where([
+            'relation_type' => ExamineRecord::CONTRACT_TYPE,
+            'status' => 0,
+            'check_staff_id' => $this->auth->id
+        ])->column('relation_id');
+        $contracts = ContractModel::where(['id' => ['in', $ids]])->with([
+            'customer',
+            'contacts',
+            'ownerStaff',
+            'orderStaff',
+            'receivables'
+        ])->order('id desc')->select();
+        $contracts = collection($contracts)->toArray();
+        foreach ($contracts as $k => $v) {
+            if (empty($v['receivables'])) {
+                $v['receivables'] = [
+                    'repayment_money' => 0,
+                    'be_money' => $v['money'],
+                    'ratio' => 0
+                ];
+            } else {
+                $be_money = $v['money'] - $v['receivables']['repayment_money'];
+                $v['receivables'] = [
+                    'repayment_money' => $v['receivables']['repayment_money'],
+                    'be_money' => ($be_money > 0) ? $be_money : 0,
+                    'ratio' => round($v['receivables']['repayment_money'] / $v['money'] * 100, 2)
+                ];
+            }
+            $contracts[$k] = $v;
+        }
+
+        $this->success('请求成功', $contracts);
+    }
+
+
+    //待审核回款
+    public function examine_receivables()
+    {
+        //待审核回款
+        $ids = ExamineRecord::where([
+            'relation_type' => ExamineRecord::RECEIVABLES_TYPE,
+            'status' => 0,
+            'check_staff_id' => $this->auth->id,
+        ])->column('relation_id');
+        $receivables = Receivables::where(['id' => ['in', $ids]])->with([
+            'contract',
+            'createStaff'
+        ])->order('id desc')->select();
+
+        $this->success('请求成功', $receivables);
+    }
+
+
+    //待回款提醒
+    public function examine_receivables_plan()
+    {
+        //待回款提醒
+        $receivablesPlan = ReceivablesPlan::where([
+            'remind_date' => ['elt', date('Y-m-d')],
+            'status' => 0,
+            'owner_staff_id' => $this->auth->id,
+        ])->order('id desc')->with(['contract', 'customer'])->select();
+
+        $this->success('请求成功', $receivablesPlan);
+    }
+
+
+    //数据简报
+    public function briefing()
+    {
+        $type = input('type', 0);//0 本人及下属 1 仅本人 2 仅下属
+        $times = input('times', '');
+        $times = explode(',', $times);
+        if (empty($times)) {
+            $this->error('参数不能为空');
+        }
+
+        $startDate=strtotime($times[0]);
+        $endDate=strtotime($times[1])+86400-1;
+
+		$where = [
+			'createtime' => ['between', [$startDate, $endDate]]
+		];
+        $whereC = [
+            'order_date' => ['between', [date('Y-m-d 00:00:00',$startDate), date('Y-m-d 23:59:59',$endDate)]]
+        ];
+        $whereR = [
+            'return_time' => ['between', [date('Y-m-d 00:00:00',$startDate), date('Y-m-d 23:59:59',$endDate)]]
+        ];
+		if ($type == 1) {
+			$where['owner_staff_id'] = $this->auth->id;
+            $whereC['owner_staff_id'] = $this->auth->id;
+            $whereR['owner_staff_id'] = $this->auth->id;
+		} elseif ($type == 2) {
+			$where['owner_staff_id'] = ['in', Staff::getLowerStaffId()];
+            $whereC['owner_staff_id'] = ['in', Staff::getLowerStaffId()];
+            $whereR['owner_staff_id'] = ['in', Staff::getLowerStaffId()];
+		} else {
+			$where['owner_staff_id'] = ['in', Staff::getMyStaffIds()];
+            $whereC['owner_staff_id'] = ['in', Staff::getMyStaffIds()];
+            $whereR['owner_staff_id'] = ['in', Staff::getMyStaffIds()];
+		}
+
+		//客户 线索 联系人 合同 回款 跟进次数 处理审批
+		$leads             = Leads::where($where)->count();
+		$customer          = Customer::where($where)->count();
+		$contacts          = Contacts::where($where)->count();
+		$contract          = Contract::where([])->where($whereC)->count();
+		$contract_money    = Contract::where(['check_status'=>2])->where($whereC)->sum('money');
+		$receivables_money = Receivables::where(['check_status'=>2])->where($whereR)->sum('money');
+		$record            = Record::where([
+            'create_staff_id' => $where['owner_staff_id'],
+            'createtime' => $where['createtime']
+        ])->where(['follow_type' => ['neq', '其它']])->count();
+        $examine = ExamineRecord::where([
+            'check_staff_id' => $where['owner_staff_id'],
+            'createtime' => $where['createtime']
+        ])->count();
+        //商机总数
+        $business = Business::where($where)->count();
+        //客户成交量
+        $customer_complate = Customer::where($where)->where(['contract_status' => 1])->count();
+        //客户未成交量
+        $customer_nocomplate = Customer::where($where)->where(['contract_status' => 0])->count();
+        //商机成交总数
+        $business_complate = Business::where($where)->where(['contract_status' => 1])->count();
+        //商机未成交总数
+        $business_nocomplate = Business::where($where)->where(['contract_status' => 0])->count();
+        //商机成交金额
+        $business_complate_money = Business::where($where)->where(['contract_status' => 1])->sum('money');
+        //商机未成交金额
+        $business_nocomplate_money = Business::where($where)->where(['contract_status' => 0])->sum('money');
+        $this->success('请求成功', [
+            'leads' => $leads,
+            'customer' => $customer,
+            'contacts' => $contacts,
+            'contract' => $contract,
+            'contract_money' => $contract_money,
+            'receivables' => $receivables_money,
+            'record' => $record,
+            'business' => $business,
+            'examine' => $examine,
+            'customer_complate' => $customer_complate,
+            'customer_nocomplate' => $customer_nocomplate,
+            'business_complate' => $business_complate,
+            'business_nocomplate' => $business_nocomplate,
+            'business_complate_money' => $business_complate_money,
+            'business_nocomplate_money' => $business_nocomplate_money,
+        ]);
+    }
+
+
+    /**
+     *交易额排行
+     */
+    public function contractRanding()
+    {
+        $date = input('date', date('Y-m'));
+
+        $type = input('type', 0);//0 本人及下属 1 仅本人 2 仅下属
+
+
+        //月底
+        $endDate = date('Y-m-d', strtotime('+1 month', strtotime(date($date . '-1'))) - 1);
+        $where = [
+            'order_date' => ['between', [$date . '-1', $endDate]],
+            'check_status' => 2,
+        ];
+
+        $contracts = Contract::where($where)->group('owner_staff_id')->field('owner_staff_id,sum(money) as money')->order('money desc')->select();
+        $list = [];
+        foreach ($contracts as $v) {
+            $list[$v['owner_staff_id']] = $v['money'];
+        }
+        $contracts = $list;
+        $data = [];
+        $staffs = Staff::getList();
+        foreach ($staffs as $v) {
+            if (isset($contracts[$v['id']])) {
+                $data[$v['id']] = $contracts[$v['id']];
+            } else {
+                $data[$v['id']] = 0;
+            }
+        }
+        arsort($data);
+        $staffs = Staff::getKeyList();
+        $result = [];
+        $i = 1;
+        $oneMoney = 0;
+        if ($type == 1) {//本人
+            $showStaffIds = [$this->auth->id];
+        } elseif ($type == 2) {//下属
+            $showStaffIds = Staff::getLowerStaffId();
+        } else {//全部
+            $showStaffIds = Staff::getMyStaffIds();
+        }
+
+        foreach ($data as $id => $money) {
+            if ($i == 1) {
+                $oneMoney = $money;
+            }
+            $val = $staffs[$id];
+            $val['money'] = $money;
+            $val['ratio'] = $oneMoney ? sprintf("%.2f", $money / $oneMoney * 100) : 0;
+            $val['rank'] = $i;
+            $i++;
+            if (in_array($id, $showStaffIds)) {
+                $result[] = $val;
+            }
+        }
+
+        if (count($result) >= 10) {
+            $top = array_slice($result, 0, 3);
+            $bottom = array_slice($result, -3, 3);
+            $middle = array_slice($result, 3, 4);
+            $result = array_merge($top, $bottom, $middle);
+        }
+
+
+        $this->success('请求成功', $result);
+    }
+
+
+    //服务协议
+    public function serviceContent()
+    {
+        $this->success('请求成功', [
+            'content' => "<h1>用户服务协议</h1>",
+            'name' => '青动时代',
+            'logo' => ''
+        ]);
+    }
+}

+ 258 - 0
addons/qingdong/controller/Leads.php

@@ -0,0 +1,258 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Event;
+use addons\qingdong\model\Form;
+use addons\qingdong\model\FormField;
+use addons\qingdong\model\Leads as LeadsModel;
+use addons\qingdong\model\LeadsFile;
+use addons\qingdong\model\LeadsOther;
+use addons\qingdong\model\Staff;
+use addons\qingdong\model\Record;
+use think\Db;
+use think\Exception;
+
+/**
+ * 线索接口
+ */
+class Leads extends StaffApi {
+    protected $noNeedLogin = [];
+    protected $noNeedRight = [];
+    public function _initialize()
+    {
+        parent::_initialize();
+        try{
+            \think\Db::execute("SET @@sql_mode='';");
+        }catch (Exception $e){
+
+        }
+    }
+
+    //添加线索
+    public function addLeads() {
+        $params = $this->request->post();
+        if (empty($params['leads'])) {
+            $this->error('线索信息不能为空');
+        }
+        // 表单验证
+        if (($result = $this->qingdongValidate($params['leads'], get_class(), 'create')) !== true) {
+            $this->error($result);
+        }
+        $result = FormField::checkFields(FormField::LEADS_TYPE, $params['leads']);
+        if ($result !== true) {
+            $this->error($result);
+        }
+        try {
+            $params['leads'] = Form::updateFormParams(Form::LEADS_TYPE, $params['leads']);
+            $leadsId                     = LeadsModel::createLeads($params['leads']);
+        } catch (Exception $e) {
+            $this->error($e->getMessage());
+        }
+        if ($result) {
+            $this->success('添加线索成功');
+        }
+    }
+
+
+    //获取线索列表
+    public function getList() {
+        $name   = input('name', '', 'trim');
+        $mobile = input('mobile', '', 'trim');
+        $limit  = input("limit/d", 10);
+        $params = $this->request->post();
+
+        $where= FormField::updateWhereField(FormField::LEADS_TYPE,$params);
+
+        if (isset($params['createtime']) && $params['createtime']) {//跟进状态
+            $createtime          = $params['createtime'];
+            $createtime          = explode(',', $createtime);
+            $where['createtime'] = ['between', [strtotime($createtime[0]), strtotime($createtime[1])+86400-1]];
+        }
+        $wheres=[];
+        //0:全部 1:我负责的 2:下属负责的 3:今日待跟进 4:今日已跟进 5:从未跟进的
+        $team = input('team',0);
+        switch($team){
+            case 1:
+                $staff = Staff::info();
+                $wheres['owner_staff_id'] =  $staff->id;
+                break;
+            case 2:
+                $wheres['owner_staff_id'] =  array('in',Staff::getLowerStaffId());
+                break;
+            case 3:
+                $start = date('Y-m-d 00:00:00');
+                $end = date('Y-m-d 23:59:59');
+                $record = collection(Record::where(array('status'=>0,'relation_type'=>4,'next_time'=>array(array('egt',$start),array('elt',$end))))->field("id,relation_id")->select())->toArray();
+                $relationId = [];
+                foreach($record as $k=>$v){
+                    $whereRe['id'] = array('gt',$v['id']);
+                    $whereRe['relation_id'] = $v['relation_id'];
+                    $recordData = Record::where($whereRe)->count();
+                    if($recordData == 0){
+                        $relationId[] = $v['relation_id'];
+                    }
+
+                }
+                $wheres['id'] =  array('in',$relationId);
+                $staff = Staff::info();
+                $wheres['owner_staff_id'] =  $staff->id;
+                break;
+            case 4:
+                $start = date('Y-m-d 00:00:00');
+                $end = date('Y-m-d 23:59:59');
+                $relationId = Record::where(array('status'=>1,'relation_type'=>4,'next_time'=>array(array('egt',$start),array('elt',$end))))->field("id,relation_id")->column('relation_id');
+                $wheres['id'] =  array('in',$relationId);
+                $staff = Staff::info();
+                $wheres['owner_staff_id'] =  $staff->id;
+                break;
+            case 5:
+                $record = collection(Record::where(array('relation_type'=>4))->column('relation_id'))->toArray();
+                $wheres['id'] =  array('not in',$record);
+                $staff = Staff::info();
+                $wheres['owner_staff_id'] =  $staff->id;
+                break;
+            default:
+                $wheres['owner_staff_id'] =  array('in',Staff::getMyStaffIds());
+                break;
+
+        }
+        if (isset($params['staff_id']) && $params['staff_id']) {//下级员工筛选
+            $wheres['owner_staff_id'] = $params['staff_id'];
+        }
+
+        if ($name) {
+            $where['name'] = ['like', "%{$name}%"];
+        }
+        if ($mobile) {
+            $where['mobile'] = ['like', "%{$mobile}%"];
+        }
+        $where['is_transform']=0;
+        $records           = LeadsModel::where($where)->where($wheres)->with(['ownerStaff'])->field('id,owner_staff_id,name,follow,mobile,level,next_time,source')->order('id desc')->paginate($limit);
+        $this->success('请求成功', $records);
+    }
+
+
+    //获取线索详情
+    public function getDetail() {
+        $id    = input('id', '', 'intval');
+        $leads = LeadsModel::where(['id' => $id])->with([
+            'createStaff',
+            'ownerStaff',
+            'tranferStaff'
+        ])->find();
+        if(empty($leads)){
+            $this->error('信息不存在');
+        }
+        $leads=$leads->toArray();
+        $leads=LeadsOther::getOther($leads);
+        $this->success('请求成功', $leads);
+    }
+
+
+    //获取选择列表
+    public function getSelectList() {
+        $name = input('name','');
+
+        $where   = ['owner_staff_id' => $this->auth->id,'is_transform'=>0];
+        if ($name) {
+            $where['name'] = ['like',"%$name%"];
+        }
+
+        $records = LeadsModel::where($where)->field('id,owner_staff_id,name,follow,mobile')->order('id desc')->select();
+        $this->success('请求成功', $records);
+    }
+
+
+    //转移线索
+    public function transfer()
+    {
+        $id = input('id');
+        $staff_id = input('staff_id');
+        if (!$staff_id || !$id) {
+            $this->error('参数错误');
+        }
+        $staff = Staff::get($staff_id);
+        if (empty($staff)) {
+            $this->error('接收对象不存在');
+        }
+        $row = LeadsModel::where(['id' => $id])->find();
+        if (empty($row)) {
+            $this->error('线索不存在');
+        }
+        try {
+            LeadsModel::transfer($id, $staff_id);
+        } catch (Exception $e) {
+            $this->error($e->getMessage());
+        }
+        $this->success('转移线索成功');
+    }
+
+
+    //修改线索
+    public function editLeads() {
+
+        $id     = input('id');
+        $params = $this->request->post();
+        $row    = LeadsModel::where(['id' => $id, 'owner_staff_id' => $this->auth->id])->find();
+        if (empty($row)) {
+            $this->error('您不是线索负责人无法修改信息');
+        }
+        // 表单验证
+        if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) {
+            $this->error($result);
+        }
+        $result = FormField::checkFields(FormField::LEADS_TYPE, $params,$id);
+        if ($result !== true) {
+            $this->error($result);
+        }
+        try {
+            $params= Form::updateFormParams(Form::LEADS_TYPE, $params);
+            LeadsModel::updateLeads($params);
+        } catch (Exception $e) {
+            $this->error($e->getMessage());
+        }
+        if ($result) {
+            $this->success('修改线索成功');
+        }
+    }
+
+
+    //删除线索
+    public function delLeads() {
+        $id    = input('id');
+        $model = new LeadsModel();
+        $row   = $model->where(['owner_staff_id' => $this->auth->id, 'id' => $id])->find();
+        if (empty($row)) {
+            $this->error('您没有权限删除线索');
+        }
+        if($row->owner_staff_id != $this->auth->id){
+            $this->error('您没有权限删除线索');
+        }
+        Db::startTrans();
+        try{
+            $model->where(['id' => $id])->delete();
+            $enentWhere = [
+                'relation_id'   =>  $id,
+                'type'          =>  2,
+                'relation_type'   =>  Event::LEADS_TYPE,
+            ];
+            Event::where($enentWhere)->delete();
+            Db::commit();
+        }catch (Exception $e){
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        $this->success('删除成功');
+    }
+
+
+    //获取附件列表
+    public function getFilesList() {
+        $id = input('leads_id');
+
+        $files = LeadsFile::where(['leads_id' => $id])->field('file_id')->with(['file'])->select();
+        $this->success('请求成功', $files);
+    }
+
+}

+ 199 - 0
addons/qingdong/controller/Leadspool.php

@@ -0,0 +1,199 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Event;
+use addons\qingdong\model\Leads as LeadsModel;
+use addons\qingdong\model\LeadsFile;
+use addons\qingdong\model\LeadsOther;
+use addons\qingdong\model\Staff;
+use addons\qingdong\model\Record;
+use think\Db;
+use think\Exception;
+
+/**
+ * 线索池接口
+ */
+class Leadspool extends StaffApi {
+    protected $noNeedLogin = [];
+    protected $noNeedRight = [];
+    public function _initialize()
+    {
+        parent::_initialize();
+        try{
+            \think\Db::execute("SET @@sql_mode='';");
+        }catch (Exception $e){
+
+        }
+    }
+
+    //添加线索
+    public function addLeads() {
+        $params = $this->request->post();
+        if (empty($params['leads'])) {
+            $this->error('线索信息不能为空');
+        }
+
+        try {
+            $leadsId                     = LeadsModel::createLeads($params['leads'],1);
+        } catch (Exception $e) {
+            $this->error($e->getMessage());
+        }
+        if ($leadsId) {
+            $this->success('添加线索成功');
+        }
+    }
+
+
+    //获取线索列表
+    public function getList() {
+        $name   = input('name', '', 'trim');
+        $mobile = input('mobile', '', 'trim');
+        $limit  = input("limit/d", 10);
+        $params = $this->request->post();
+        $where = [];
+
+        if (isset($params['createtime']) && $params['createtime']) {//跟进状态
+            $createtime          = $params['createtime'];
+            $createtime          = explode(',', $createtime);
+            $where['createtime'] = ['between', [strtotime($createtime[0]), strtotime($createtime[1])+86400-1]];
+        }
+
+
+        if ($name) {
+            $where['name'] = ['like', "%{$name}%"];
+        }
+        if ($mobile) {
+            $where['mobile'] = ['like', "%{$mobile}%"];
+        }
+        $records           = LeadsModel::where($where)->where('owner_staff_id is null or owner_staff_id = 0')->with(['createStaff'])->field('id,create_staff_id,name,follow,mobile,level,next_time,source')->order('id desc')->paginate($limit);
+        $this->success('请求成功', $records);
+    }
+
+
+    //获取线索详情
+    public function getDetail() {
+        $id    = input('id', '', 'intval');
+        $leads = LeadsModel::where(['id' => $id])->with([
+            'createStaff',
+        ])->find();
+        if(empty($leads)){
+            $this->error('信息不存在');
+        }
+        $leads=$leads->toArray();
+        $leads=LeadsOther::getOther($leads);
+        $this->success('请求成功', $leads);
+    }
+
+
+    //获取选择列表
+    public function getSelectList() {
+        $name = input('name','');
+
+        $where   = ['owner_staff_id' => $this->auth->id,'is_transform'=>0];
+        if ($name) {
+            $where['name'] = ['like',"%$name%"];
+        }
+
+        $records = LeadsModel::where($where)->field('id,owner_staff_id,name,follow,mobile')->order('id desc')->select();
+        $this->success('请求成功', $records);
+    }
+
+
+    //转移线索
+    public function transfer()
+    {
+        $id = input('id');
+        $staff_id = input('staff_id');
+        if (!$staff_id && !$id) {
+            $this->error('参数错误');
+        }
+        $row = LeadsModel::where(['id' =>['in',$id] ])->find();
+        if (empty($row)) {
+            $this->error('线索不存在');
+        }
+        $id = explode(',',$id);
+        try {
+            LeadsModel::transfer($id, $staff_id);
+        } catch (Exception $e) {
+            $this->error($e->getMessage());
+        }
+        $this->success('转移成功');
+    }
+
+
+    //修改线索
+    public function editLeads() {
+
+        $id     = input('id');
+        $params = $this->request->post();
+        $row    = LeadsModel::where(['id' => $id])->find();
+        if (empty($row)) {
+            $this->error('线索信息不存在');
+        }
+
+        try {
+            $result = LeadsModel::updateLeads($params);
+        } catch (Exception $e) {
+            $this->error($e->getMessage());
+        }
+        if ($result) {
+            $this->success('修改线索成功');
+        }
+    }
+
+
+    //删除线索
+    public function delLeads() {
+        $id    = input('id');
+        $model = new LeadsModel();
+        $row   = $model->where(['id' => $id])->find();
+        if (empty($row)) {
+            $this->error('线索不存在');
+        }
+
+        Db::startTrans();
+        try{
+            $model->where(['id' => $id])->delete();
+            $enentWhere = [
+                'relation_id'   =>  $id,
+                'type'          =>  2,
+                'relation_type'   =>  Event::LEADS_TYPE,
+            ];
+            Event::where($enentWhere)->delete();
+            Db::commit();
+        }catch (Exception $e){
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        $this->success('删除成功');
+    }
+
+
+    //获取附件列表
+    public function getFilesList() {
+        $id = input('leads_id');
+
+        $files = LeadsFile::where(['leads_id' => $id])->field('file_id')->with(['file'])->select();
+        $this->success('请求成功', $files);
+    }
+//领取线索
+    public function achieve()
+    {
+        $id = input('id');
+        if (empty($id)) {
+            $this->error('参数错误');
+        }
+        $row = LeadsModel::where(['id' =>$id ])->find();
+        if (empty($row)) {
+            $this->error('线索不存在');
+        }
+        try {
+            LeadsModel::transfer($id, $this->auth->id);
+        } catch (Exception $e) {
+            $this->error($e->getMessage());
+        }
+        $this->success('领取成功');
+    }
+
+}

+ 250 - 0
addons/qingdong/controller/Message.php

@@ -0,0 +1,250 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Event;
+use addons\qingdong\model\ExamineRecord;
+use addons\qingdong\model\Message as MessageModel;
+use addons\qingdong\model\Notice;
+use addons\qingdong\model\ReceivablesPlan;
+use addons\qingdong\model\Record;
+
+/**
+ * 通知接口
+ */
+class Message extends StaffApi
+{
+    protected $noNeedLogin = [];
+    protected $noNeedRight = [];
+
+
+    /**
+     * 获取通知列表
+     */
+    public function getList()
+    {
+        $limit = input("limit/d", 10);
+
+        $where = ['to_staff_id' => $this->auth->id ,'relation_type'=>['neq',MessageModel::EXAMINE_TYPE]];
+        $records = MessageModel::where($where)->with(['fromStaff', 'examine'])->order('status asc,id desc')->paginate($limit);
+
+        $this->success('请求成功', $records);
+    }
+
+    /**
+     * 获取审批列表
+     */
+    public function getExamineRecord()
+    {
+        $limit = input("limit/d", 10);
+        //合同审批,回款审批、业绩目标审批、办公审批 费用
+        $relation_type = input('type');
+        $status =  input('status',0);
+        if($status == 1){
+            $status = array('in','2,3');
+        }
+        $ids = ExamineRecord::where(['relation_type' => $relation_type,
+            'status' => $status,
+            'check_staff_id' => $this->auth->id])->column('id');
+        $where = ['to_staff_id' => $this->auth->id, 'relation_id' => ['in', $ids], 'relation_type' => MessageModel::EXAMINE_TYPE];
+
+        $records = MessageModel::where($where)->with(['fromStaff', 'examine'])->order('status asc,id desc')->paginate($limit);
+
+        $this->success('请求成功', $records);
+    }
+
+    /**
+     * 获取审批通知详情
+     */
+    public function getExamineInfo()
+    {
+
+        $data = [
+            ExamineRecord::CONTRACT_TYPE => ['count' => 0, 'msg' => '暂无消息'],
+            ExamineRecord::CONSUME_TYPE => ['count' => 0, 'msg' => '暂无消息'],
+            ExamineRecord::RECEIVABLES_TYPE => ['count' => 0, 'msg' => '暂无消息'],
+            ExamineRecord::APPROVAL_TYPE => ['count' => 0, 'msg' => '暂无消息'],
+            ExamineRecord::ACHIEVEMENT_TYPE => ['count' => 0, 'msg' => '暂无消息'],
+            ExamineRecord::CARD_TYPE => ['count' => 0, 'msg' => '暂无消息'],
+            ExamineRecord::LEAVE_TYPE => ['count' => 0, 'msg' => '暂无消息'],
+        ];
+        foreach ($data as $type=>$v) {
+            $ids = ExamineRecord::where(['status' => 0, 'check_staff_id' => $this->auth->id,
+                'relation_type' => $type
+            ])->column('id');
+            $count = MessageModel::where(['to_staff_id' => $this->auth->id,'relation_id' => ['in', $ids],
+                'relation_type' => MessageModel::EXAMINE_TYPE])
+                ->count();
+            if ($count) {
+                $msg = MessageModel::where(['to_staff_id' => $this->auth->id, 'relation_id' => ['in', $ids],
+                    'relation_type' => MessageModel::EXAMINE_TYPE])
+                    ->order('id desc')
+                    ->value('content');
+                $data[$type] = ['count' => $count, 'msg' => $msg];
+            }
+        }
+
+        $this->success('请求成功', $data);
+    }
+
+    /**
+     * 获取通知详情
+     */
+    public function getInfo()
+    {
+        $leadsCount = MessageModel::where(['to_staff_id' => $this->auth->id,
+            'relation_type' => ['neq', MessageModel::EXAMINE_TYPE], 'status' => 0])->count();
+        if ($leadsCount > 0) {//其他提醒消息
+            $leadsDetail = MessageModel::where([
+                'relation_type' => ['neq', MessageModel::EXAMINE_TYPE],
+                'to_staff_id' => $this->auth->id,
+                'status' => 0
+            ])->order('id desc')->find();
+        }
+
+        $noticeWhere['read_staff_ids'] = ['not like', "%,{$this->auth->id},%"];
+
+        $noticeCount = Notice::where($noticeWhere)->count();
+        if ($noticeCount > 0) {
+            $noticeDetail = Notice::where(['read_staff_ids' => ['not like', "%,{$this->auth->id},%"]])->order('id desc')->find();
+        }
+
+        $eventOne = Event::where([
+            'type' => 1,
+            'status' => ['in', [0, 1]],
+            'start_time' => ['lt', date('Y-m-d', strtotime('+1 day'))],
+            'staff_id|owner_staff_id' => $this->auth->id
+        ])->count();
+        //合同审批
+        $contract = ExamineRecord::where([
+            'relation_type' => ExamineRecord::CONTRACT_TYPE,
+            'status' => 0,
+            'check_staff_id' => $this->auth->id
+        ])->count();
+        //回款审批
+        $receivables = ExamineRecord::where([
+            'relation_type' => ExamineRecord::RECEIVABLES_TYPE,
+            'status' => 0,
+            'check_staff_id' => $this->auth->id
+        ])->count();
+        //费用审批
+        $consume = ExamineRecord::where([
+            'relation_type' => ExamineRecord::CONSUME_TYPE,
+            'status' => 0,
+            'check_staff_id' => $this->auth->id
+        ])->count();
+        //业绩目标审批
+        $achievement = ExamineRecord::where([
+            'relation_type' => ExamineRecord::ACHIEVEMENT_TYPE,
+            'status' => 0,
+            'check_staff_id' => $this->auth->id
+        ])->count();
+        //办公审批
+        $approval = ExamineRecord::where([
+            'relation_type' => ExamineRecord::APPROVAL_TYPE,
+            'status' => 0,
+            'check_staff_id' => $this->auth->id
+        ])->count();
+        //补卡审批
+        $card = ExamineRecord::where([
+            'relation_type' => ExamineRecord::CARD_TYPE,
+            'status' => 0,
+            'check_staff_id' => $this->auth->id
+        ])->count();
+        //请假审批
+        $leave = ExamineRecord::where([
+            'relation_type' => ExamineRecord::LEAVE_TYPE,
+            'status' => 0,
+            'check_staff_id' => $this->auth->id
+        ])->count();
+        $receivablesPlan = ReceivablesPlan::where([
+            'remind_date' => ['elt', date('Y-m-d')],
+            'status' => 0,
+            'owner_staff_id' => $this->auth->id
+        ])->count();
+
+        $eventsCount = Event::where([
+            'start_time' => ['lt', date('Y-m-d', strtotime('+1 day'))],
+            'end_time' => ['lt', date('Y-m-d', strtotime('+1 day'))],
+            'status' => ['in', [0, 1]],
+            'staff_id' => $this->auth->id,
+        ])->count();
+
+        $where['create_staff_id'] = $this->auth->id;
+        $where['next_time'] = array(array('egt',date('Y-m-d 00:00:00')),array('lt',date('Y-m-d 23:59:59')));
+        $where['follow_type'] = ['neq', '其它'];
+        $where['status'] = 0;
+        // 待跟进客户
+        $where1['relation_type'] = 1;
+        $customerlist = Record::where($where)->where($where1)->column('id');
+        $customerlist1 = 0;
+        if($customerlist){
+            $whereExit['id'] = array('in',$customerlist);
+            $whereExit['next_time'] = array('gt',date('Y-m-d 23:59:59'));
+            $customerlist1 = Record::where($whereExit)->count();
+        }
+        $customer = count($customerlist) - $customerlist1;
+
+        //待跟进合同
+        $where2['relation_type'] = 3;
+        $contractlist = Record::where($where)->where($where2)->column('id');
+        $contractlist1 = 0;
+        if($contractlist){
+            $whereExitC['id'] = array('in',$contractlist);
+            $whereExitC['next_time'] = array('gt',date('Y-m-d 23:59:59'));
+            $contractlist1 = Record::where($whereExitC)->count();
+        }
+        $contracts = count($contractlist)-$contractlist1;
+        //待跟进线索
+        $where3['relation_type'] = 4;
+        $leadlist = Record::where($where)->where($where3)->column('id');
+        $leadlist1 = 0;
+        if($leadlist){
+            $whereExitL['id'] = array('in',$leadlist);
+            $whereExitL['next_time'] = array('gt',date('Y-m-d 23:59:59'));
+            $leadlist1 = Record::where($whereExitL)->count();
+        }
+        $lead = count($leadlist)-$leadlist1;
+        //待跟进联系人
+        $where4['relation_type'] = 2;
+        $contactslist = Record::where($where)->where($where4)->column('id');
+        $contactslist1 = 0;
+        if($contactslist1){
+            $whereExitCs['id'] = array('in',$contactslist);
+            $whereExitCs['next_time'] = array('gt',date('Y-m-d 23:59:59'));
+            $contactslist1 = Record::where($whereExitCs)->count();
+        }
+        $contacts = count($contactslist)-$contactslist1;
+        //待跟进商机
+        $where5['relation_type'] = 5;
+        $businesslist = Record::where($where)->where($where5)->column('id');
+        $businesslist1 = 0;
+        if($businesslist1){
+            $whereExitB['id'] = array('in',$businesslist);
+            $whereExitB['next_time'] = array('gt',date('Y-m-d 23:59:59'));
+            $businesslist1 = Record::where($whereExitB)->count();
+        }
+        $business = count($businesslist)-$businesslist1;
+        //提醒消息
+        $data = [
+            'leads' => ['count' => $leadsCount, 'msg' => $leadsDetail['content'] ?? '暂无消息'],//提醒消息
+            'examine' => ['count' => $contract + $receivables+$consume+$achievement+$approval+$card+$leave,
+                        'msg' => '审批消息提醒'],//提醒消息
+            'notice' => ['count' => $noticeCount, 'msg' => $noticeDetail['title'] ?? '暂无消息'],//系统公告
+            'agent' => [
+                'count' => $eventOne  + $receivablesPlan+ $customer + $contracts + $lead + $contacts + $business,
+                'msg' => '您有新的待办事项需要处理!'
+            ],//待办事项
+            'task' => [
+                'count' => $eventsCount,
+                'msg' => '即将超时的任务提醒!'
+            ],//超时任务
+            'total' => $leadsCount + $noticeCount + $eventOne + $contract + $receivables + $receivablesPlan + $eventsCount+ $customer + $contracts + $lead + $contacts + $business+$consume+$achievement+$approval+$card+$leave,
+
+            'userinfo' => $this->auth->getUserinfo()
+        ];
+        $this->success('请求成功', $data);
+    }
+
+
+}

+ 52 - 0
addons/qingdong/controller/Notice.php

@@ -0,0 +1,52 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Notice as NoticeModel;
+
+/**
+ * 公告接口
+ */
+class Notice extends StaffApi {
+	protected $noNeedLogin = [];
+	protected $noNeedRight = [];
+
+
+	//公告列表
+	public function getList() {
+		$limit = input("limit/d", 10);
+
+
+		$records = NoticeModel::where([])->order('id desc')->paginate($limit);
+		$items   = $records->items();
+		foreach ($items as $k => $v) {
+			$read_staff_ids = explode(',', $v['read_staff_ids']);
+			$v['is_show']   = in_array($this->auth->id, $read_staff_ids);
+			$items[$k]      = $v;
+		}
+		$this->success('请求成功', $records);
+	}
+
+
+	//获取公告详情
+	public function getDetail() {
+		$id     = input('id', '', 'intval');
+		$notice = NoticeModel::where(['id' => $id,])->find();
+		if (empty($notice)) {
+			$this->error('公告不存在');
+		}
+        preg_match_all('/<img.+src=\"?(.+\.(jpg|gif|bmp|bnp|png))\"?.+>/i',$notice['content'],$match);
+        foreach ($match[1] as $v){
+            $notice['content']=str_replace($v,cdnurl($v,true),$notice['content']);
+        }
+		$read_staff_ids = explode(',', $notice['read_staff_ids']);
+		if (!in_array($this->auth->id, $read_staff_ids)) {
+			$read_staff_ids[] = $this->auth->id;
+			NoticeModel::where(['id' => $notice['id']])->update(['read_staff_ids' => implode(',', $read_staff_ids).',']);
+		}
+
+		$this->success('请求成功', $notice);
+	}
+
+
+}

+ 29 - 0
addons/qingdong/controller/Operation.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\OperationLog;
+/**
+ * 操作记录
+ */
+class Operation extends StaffApi {
+	protected $noNeedLogin = [];
+	protected $noNeedRight = [];
+
+
+	//
+	public function getList() {
+		$relation_type = input('relation_type', '');//1客户 2联系人 3合同
+		$relation_id   = input('relation_id', '');
+        if(empty($relation_type) || empty($relation_id)){
+            $this->error('参数不能为空');
+        }
+		//操作记录
+		$logs=OperationLog::where([
+			'relation_type'  => $relation_type,
+			'relation_id'    => $relation_id,
+			'operation_type' => 1
+		])->field('id,content,operation_id,createtime')->with(['staff'])->select();
+		$this->success('请求成功',$logs);
+	}
+}

+ 156 - 0
addons/qingdong/controller/Product.php

@@ -0,0 +1,156 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Product as ProductModel;
+use addons\qingdong\model\ProductPart;
+use addons\qingdong\model\Producttype;
+
+
+/**
+ * 产品
+ */
+class Product extends StaffApi
+{
+    protected $noNeedLogin = [];
+    protected $noNeedRight = [];
+
+
+    /**
+     * 获取select产品列表
+     */
+    public function getSelectList()
+    {
+        $name = input('name');
+        $type_id = input('type_id');
+        $where = [];
+        if ($name) {
+            $where['name|num'] = ['like', "%{$name}%"];
+        }
+        if ($type_id) {
+            $where['type_id'] = $type_id;
+        }
+        $list = ProductModel::where($where)->field('id,name,type,num,img,unit,price,min_price,status,cost_price,wholesale')->select();
+        $this->success('请求成功', $list);
+    }
+
+    /**
+     * 获取产品分类列表
+     */
+    public function getProducttypeList()
+    {
+        $name = input('name');
+        $where=[];
+        if ($name) {
+            $where['name'] = ['like', "%{$name}%"];
+        }
+        $list = Producttype::where($where)->field('id,name')->select();
+
+        $this->success('请求成功', $list);
+    }
+
+    /**
+     * 获取产品配置列表
+     */
+    public function getPartList()
+    {
+        $product_id = input('product_id');
+        $name = input('name');
+        $where = [];
+        if ($name) {
+            $where['name'] = ['like', "%{$name}%"];
+        }
+        $where['product_id'] = $product_id;
+        $list = ProductPart::where($where)->field('id,name,img,description')->select();
+        $this->success('请求成功', $list);
+    }
+
+    /**
+     * 获取产品详情
+     */
+    public function getProductDetail()
+    {
+        $id = input('id');
+        $product = ProductModel::where(['id' => $id])->find();
+        if (empty($product)) {
+            $this->error('产品不存在');
+        }
+        preg_match_all("/(<img .*?src=\")(.*?)(\".*?>)/is", $product['description'], $matchpic);
+        foreach ($matchpic[2] as $url) {
+            $img = cdnurl($url, true);
+            $product['description'] = str_replace($url, $img, $product['description']);
+        }
+        $this->success('请求成功', $product);
+    }
+
+    /**
+     * 添加产品
+     */
+    public function addProduct()
+    {
+        $params = $this->request->post();
+        if ($params) {
+            $parts = $params['parts'] ?? [];
+
+            $model = new ProductModel();
+            $model->allowField(true)->save($params);
+            $lastid = $model->getLastInsID();
+            $partModel = new ProductPart();
+            foreach ($parts as &$v) {
+                $v['product_id'] = $lastid;
+            }
+            $partModel->allowField(true)->saveAll($parts);
+            $this->success('添加产品成功');
+        }
+    }
+
+    /**
+     * 添加产品配件
+     */
+    public function addProductPart()
+    {
+        $params = $this->request->post();
+        if ($params) {
+            $partModel = new ProductPart();
+
+            $partModel->save($params);
+            $this->success('添加产品配置成功');
+        }
+    }
+
+    /**
+     * 修改产品信息
+     */
+    public function editProduct()
+    {
+        $params = $this->request->post();
+        if ($params) {
+            $model = new ProductModel();
+            $row = $model->get($params['id']);
+            if (empty($row)) {
+                $this->error('产品不存在');
+            }
+            $row->allowField(true)->save($params);
+
+            $this->success('添加产品成功');
+        }
+    }
+
+    /**
+     * 修改产品配件
+     */
+    public function editProductPart()
+    {
+        $params = $this->request->post();
+        if ($params) {
+            $partModel = new ProductPart();
+            $row = $partModel->get($params['id']);
+            if (empty($row)) {
+                $this->error('产品配置不存在');
+            }
+            $row->allowField(true)->save($params);
+
+            $this->success('修改产品配置成功');
+        }
+    }
+}

+ 207 - 0
addons/qingdong/controller/Receivables.php

@@ -0,0 +1,207 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\ExamineRecord;
+use addons\qingdong\model\FormField;
+use addons\qingdong\model\Message;
+use addons\qingdong\model\Receivables as ReceivablesModel;
+use addons\qingdong\model\ReceivablesOther;
+use addons\qingdong\model\Contract;
+use addons\qingdong\model\Staff;
+use think\Db;
+use think\Exception;
+
+/**
+ * 回款详情
+ */
+class Receivables extends StaffApi {
+	protected $noNeedLogin = [];
+	protected $noNeedRight = [];
+
+
+	//新增回款
+	public function addReceivables() {
+		$params = $this->request->post();
+
+		// 表单验证
+        if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) {
+            $this->error($result);
+        }
+
+        $result = FormField::checkFields(FormField::RECEIVABLES_TYPE, $params);
+        if ($result !== true) {
+            $this->error($result);
+        }
+		if (ReceivablesModel::where(['number' => $params['number'], 'contract_id' => $params['contract_id']])->find()) {
+			$this->error('回款编号已存在');
+		}
+		$contract=Contract::where(['id'=>$params['contract_id']])->find();
+		if(empty($contract)){
+			$this->error('合同不存在');
+		}
+		if($contract['check_status'] != 2){
+			$this->error('当前合同未审核通过');
+		}
+		Db::startTrans();
+		try {
+            $params['owner_staff_id'] = $contract['owner_staff_id'];
+
+			ReceivablesModel::createReceivables($params);
+
+			Db::commit();
+		} catch (Exception $e) {
+			Db::rollback();
+			$this->error($e->getMessage());
+		}
+		if ($result) {
+			$this->success('新增回款成功');
+		}
+	}
+
+
+	//获取回款列表
+    public function getList()
+    {
+        $customer_id = input('customer_id');
+        $contract_id = input('contract_id');
+        $times = input('times');
+        $staff_id = input('staff_id');
+        $check_status = input('check_status');
+        $limit = input('limit');
+        $type = input('type',0);
+        $params=input();
+        $where= FormField::updateWhereField(FormField::RECEIVABLES_TYPE,$params);
+        if ($customer_id) {
+            $where['customer_id'] = $customer_id;
+        }
+        if ($contract_id) {
+            $where['contract_id'] = $contract_id;
+        }
+        if ($staff_id) {
+            $where['owner_staff_id'] = $staff_id;
+        } else {
+
+            if ($type == 1) {//我的客户
+                $where['owner_staff_id'] = $this->auth->id;
+            } elseif ($type == 2) {//下属负责的客户
+                $where['owner_staff_id'] = ['in', Staff::getLowerStaffId()];
+            }else{
+                $where['owner_staff_id'] = ['in', Staff::getMyStaffIds()];
+            }
+        }
+
+        if ($times) {//回款日期
+            $times = explode(',', $times);
+            $where['return_time'] = ['between', [$times[0], $times[1]]];
+        }
+        if ($check_status) {
+            if ($check_status == 1) {//审核中
+                $where['check_status'] = ['in', [0, 1]];
+            } elseif ($check_status == 2) {//审核通过
+                $where['check_status'] = 2;
+            } elseif ($check_status == 3) {//其他
+                $where['check_status'] = ['in', [3, 4]];
+            }
+        }
+        $list = ReceivablesModel::where($where)->with(['contract'])->order('id desc')->paginate($limit)->toArray();
+
+        $remoney = ReceivablesModel::where(['owner_staff_id'=>$where['owner_staff_id']])
+            ->where(array('check_status'=>2))->sum('money');
+        $inmoney = ReceivablesModel::where(['owner_staff_id'=>$where['owner_staff_id']])
+            ->where(array('check_status'=>['in',[0,1]]))->sum('money');
+        $nomoney = ReceivablesModel::where(['owner_staff_id'=>$where['owner_staff_id']])
+            ->where(array('check_status'=>['in',[3,4]]))->sum('money');
+        $moneyinfo['remoney'] = $remoney;//已回款
+        $moneyinfo['inmoney'] = $inmoney;//回款中
+        $moneyinfo['nomoney'] = $nomoney;//未回款
+        $moneyinfo['allmoney'] = $remoney+$inmoney+$nomoney;//总金额
+        $list['moneyinfo']=$moneyinfo;
+        $this->success('请求成功',$list);
+    }
+
+
+	//回款详情
+	public function getDetail() {
+		$id       = input('id');
+		$receivables = ReceivablesModel::where(['id' => $id])->with([
+			'customer',
+			'contract',
+			'plan',
+			'ownerStaff',
+			'createStaff'
+		])->find();
+
+		if (empty($receivables)) {
+            //标记通知已读
+            Message::setRead(Message::RECEIVABLES_TYPE, $id, $this->auth->id);
+			$this->error('信息不存在');
+		}
+		$receivables=$receivables->toArray();
+
+        $receivables=ReceivablesOther::getOther($receivables);
+		//标记通知已读
+		Message::setRead(Message::RECEIVABLES_TYPE, $id, $this->auth->id);
+		$this->success('请求成功', $receivables);
+	}
+
+
+	//撤回审核
+	public function cancel() {
+		$id       = input('id');
+		$customer = ReceivablesModel::where(['id' => $id, 'check_status' => 1])->find();
+		if (empty($customer)) {
+			$this->error('回款信息不存在');
+		}
+		Db::startTrans();
+		try {
+
+			ReceivablesModel::where(['id' => $id])->update(['check_status' => 4]);
+			ExamineRecord::where([
+				'relation_type' => ExamineRecord::RECEIVABLES_TYPE,
+				'relation_id'   => $id,
+				'status'        => 0
+			])->update(['status' => 3]);
+			Db::commit();
+		} catch (Exception $e) {
+			Db::rollback();;
+			$this->error($e->getMessage());
+		}
+
+
+		$this->success('撤回成功');
+	}
+
+
+	//修改回款
+	public function editReceivables() {
+		$id     = input('id');
+		$params = $this->request->post();
+		$row    = ReceivablesModel::where(['id' => $id, 'check_status' => ['in', [3, 4]]])->find();
+		if (empty($row)) {
+			$this->error('回款信息不存在');
+		}
+		// 表单验证
+        if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) {
+            $this->error($result);
+        }
+        $result = FormField::checkFields(FormField::RECEIVABLES_TYPE, $params,$id);
+        if ($result !== true) {
+            $this->error($result);
+        }
+		Db::startTrans();
+		try {
+			ReceivablesModel::updateReceivables($params);
+			Db::commit();
+		} catch (Exception $e) {
+			Db::rollback();
+			$this->error($e->getMessage());
+		}
+		$this->success('修改回款信息成功');
+	}
+    //获取回款编号
+    public function getReceivablesNumber()
+    {
+        $this->success('请求成功', ['number' => ReceivablesModel::getNum()]);
+    }
+}

+ 112 - 0
addons/qingdong/controller/ReceivablesPlan.php

@@ -0,0 +1,112 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Message;
+use addons\qingdong\model\ReceivablesPlan as ReceivablesPlanModel;
+use addons\qingdong\model\Staff;
+use think\Db;
+use think\Exception;
+
+/**
+ * 回款计划
+ */
+class ReceivablesPlan extends StaffApi {
+	protected $noNeedLogin = [];
+	protected $noNeedRight = [];
+
+
+	//新增回款计划
+	public function addPlan() {
+		$params = $this->request->post();
+
+		// 表单验证
+        if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) {
+            $this->error($result);
+        }
+		if (ReceivablesPlanModel::where([
+            'num'         => $params['num'],
+            'contract_id' => $params['contract_id']
+		])->find()) {
+			$this->error('计划回款期数已存在');
+		}
+
+		Db::startTrans();
+		try {
+			ReceivablesPlanModel::createPlan($params);
+
+			Db::commit();
+		} catch (Exception $e) {
+			Db::rollback();
+			$this->error($e->getMessage());
+		}
+		if ($result) {
+			$this->success('新增回款计划成功');
+		}
+	}
+
+
+	//获取回款计划列表
+    public function getList()
+    {
+        $customer_id = input('customer_id');
+        $contract_id = input('contract_id');
+        $times = input('times');
+        $staff_id = input('staff_id');
+        $status = input('status', null);
+        $limit = input('limit');
+        $type = input('type',0);
+        $where = [];
+        if ($customer_id) {
+            $where['customer_id'] = $customer_id;
+        }
+        if ($contract_id) {
+            $where['contract_id'] = $contract_id;
+        }
+        if ($staff_id) {
+            $where['owner_staff_id'] = $staff_id;
+        } else {
+
+            if ($type == 1) {//我的客户
+                $where['owner_staff_id'] = $this->auth->id;
+            } elseif ($type == 2) {//下属负责的客户
+                $where['owner_staff_id'] = ['in', Staff::getLowerStaffId()];
+            }else{
+                $where['owner_staff_id'] = ['in', Staff::getMyStaffIds()];
+            }
+
+        }
+        if ($times) {//计划回款日期
+            $times = explode(',', $times);
+            $where['return_date'] = ['between', [$times[0], $times[1]]];
+        }
+        if($status !== null){
+            $where['status'] = $status;
+        }
+
+        $list = ReceivablesPlanModel::where($where)->with(['contract', 'customer', 'createStaff'])
+            ->order('id desc')->paginate($limit);
+        $this->success('请求成功', $list);
+    }
+
+
+	//获取select回款计划列表
+	public function getSelectList() {
+		$contract_id          = input('contract_id');
+		$where                = [];
+		$where['contract_id'] = $contract_id;
+		$where['status']      = 0;
+		$list                 = ReceivablesPlanModel::where($where)->field('id,num')->select();
+		$this->success('请求成功', $list);
+	}
+
+
+	//回款详情
+	public function getDetail() {
+		$id       = input('id');
+		$customer = ReceivablesPlanModel::where(['id' => $id])->with(['contract', 'customer', 'createStaff'])->find();
+		//标记通知已读
+		Message::setRead(Message::PLAN_TYPE, $id, $this->auth->id);
+		$this->success('请求成功', $customer);
+	}
+}

+ 368 - 0
addons/qingdong/controller/Record.php

@@ -0,0 +1,368 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Comment;
+use addons\qingdong\model\Contacts;
+use addons\qingdong\model\Message;
+use addons\qingdong\model\Record as RecordModel;
+use addons\qingdong\model\RecordRead;
+use addons\qingdong\model\Customer;
+use addons\qingdong\model\Contract;
+use addons\qingdong\model\Leads;
+use addons\qingdong\model\Staff;
+use addons\qingdong\model\Business;
+use think\Db;
+use think\Exception;
+use function EasyWeChat\Kernel\Support\get_client_ip;
+
+/**
+ * 跟进记录
+ */
+class Record extends StaffApi {
+	protected $noNeedLogin = [];
+	protected $noNeedRight = [];
+
+    /**
+     * 获取跟进记录
+     */
+	public function getList() {
+		$relation_type = input('relation_type', '', 'intval');// 1客户 2联系人 3合同 5商机
+		$relation_id   = input('relation_id', '', 'intval');
+		$limit         = input("limit/d", 10);
+		$is_read       = input('is_read', 0);
+		$type       = input('type', 0);// 0 全部 1 我创建 2 下属创建
+        $follow_type       = input('follow_type', '');
+        $times = input('times','');
+		$where         = [];
+		if ($relation_type) {
+			$where['relation_type'] = $relation_type;
+			if($relation_id){
+                $where['relation_id']   = $relation_id;
+            }
+
+		}
+        if ($type == 1) {//我的客户
+            $where['create_staff_id'] = $this->auth->id;
+        } elseif ($type == 2) {//下属负责的客户
+            $where['create_staff_id'] = ['in', Staff::getLowerStaffId()];
+        }else{
+            $where['create_staff_id'] = ['in', Staff::getMyStaffIds()];
+        }
+
+		if($follow_type){
+            $where['follow_type'] = $follow_type;
+        }else{
+            $where['follow_type'] = ['neq', '其它'];
+        }
+        if ($times) {
+            $times = explode(',', $times);
+            $where['createtime'] = ['between', [strtotime($times[0]), strtotime($times[1]) + 86400 - 1]];
+        }
+		$staff_id             = $this->auth->id;
+		if ($is_read == 1) {//已读
+			$ids         = RecordRead::where(['staff_id' => $staff_id])->column('record_id');
+			$where['id'] = ['in', $ids];
+		} elseif ($is_read == 2) {//未读
+			$ids         = RecordRead::where(['staff_id' => $staff_id])->column('record_id');
+			$where['id'] = ['not in', $ids];
+		}
+		$records = RecordModel::where($where)->with([
+			'staff',
+			'file',
+			'read' => function ($query) use ($staff_id) {
+				$query->where(['staff_id' => $staff_id]);
+			}
+		])->order('id desc')->paginate($limit)->toArray();
+
+		$data = $records['data'];
+		foreach ($data as $k => $v) {
+            $customerWhere['id'] = $v['relation_id']?? '';
+            $v['comment_num'] =0;//评论数
+
+            if($v['relation_type'] == RecordModel::CUSTOMER_TYPE) {
+                $v['comment_num'] =Comment::where(array('relation_type'=>1,'relation_id'=>$v['id']))->count();
+                $v['relation_name'] = Customer::where(['id' => $v['relation_id']])->value('name');
+            }elseif($v['relation_type'] == RecordModel::CONTACTS_TYPE) {
+                $v['comment_num'] =Comment::where(array('relation_type'=>2,'relation_id'=>$v['id']))->count();
+                $v['relation_name'] = Contacts::where(['id' => $v['relation_id']])->value('name');
+            }elseif($v['relation_type'] == RecordModel::CONTRACT_TYPE) {
+                $v['comment_num'] =Comment::where(array('relation_type'=>3,'relation_id'=>$v['id']))->count();
+                $v['relation_name'] = Contract::where(['id' => $v['relation_id']])->value('name');
+            }elseif($v['relation_type'] == RecordModel::LEADS_TYPE) {
+                $v['comment_num'] =Comment::where(array('relation_type'=>4,'relation_id'=>$v['id']))->count();
+                $v['relation_name'] = Leads::where(['id' => $v['relation_id']])->value('name');
+            } elseif($v['relation_type'] == RecordModel::BUSINESS_TYPE) {
+                $v['comment_num'] =Comment::where(array('relation_type'=>5,'relation_id'=>$v['id']))->count();
+                $v['relation_name'] = Business::where(['id' => $v['relation_id']])->value('name');
+            }else{
+                $v['customer']  = [];
+            }
+			if (!empty($v['read'])) {
+				$v['is_read'] = 1;
+			} else {
+				$v['is_read'] = 0;
+			}
+			if($v['staff_id']){
+                $v['staff'] = Staff::where(['id'=>$v['staff_id']])->field('id,img,name,post')->find();
+            }
+			$data[$k] = $v;
+		}
+		$this->success('请求成功', [
+			'total'        => $records['total'],
+			'per_page'     => $records['per_page'],
+			'current_page' => $records['current_page'],
+			'last_page'    => $records['last_page'],
+			'data'         => $data
+		]);
+
+		$this->success('请求成功', $records);
+	}
+
+
+    /**
+     * 创建跟进记录
+     */
+	public function createRecord() {
+		$params = $this->request->post();
+		// 表单验证
+        if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) {
+            $this->error($result);
+        }
+		Db::startTrans();
+		try {
+			$result             = RecordModel::createRecord($params);
+			Db::commit();
+		} catch (Exception $e) {
+			Db::rollback();
+			$this->error($e->getMessage());
+		}
+		if ($result) {
+			$this->success('创建跟进记录成功');
+		}
+	}
+
+
+    /**
+     * 获取根据记录详情
+     */
+	public function getRecordDetail() {
+		$id = input('id');
+		if (empty($id)) {
+			$this->error('参数不能为空');
+		}
+		$record = RecordModel::where(['id' => $id])->with([
+			'staff',
+			'file'
+		])->find();
+		if (empty($record)) {
+			$this->error('根据记录不存在');
+		}
+        $record = $record->toArray();
+
+		if ($record['relation_type'] == RecordModel::CUSTOMER_TYPE) {
+			$record['relation_name'] = Customer::where(['id' => $record['relation_id']])->value('name');
+		} elseif ($record['relation_type'] == RecordModel::CONTACTS_TYPE) {
+			$record['relation_name'] = Contacts::where(['id' => $record['relation_id']])->value('name');
+		} elseif ($record['relation_type'] == RecordModel::CONTRACT_TYPE) {
+			$record['relation_name'] = Contract::where(['id' => $record['relation_id']])->value('name');
+		} elseif($record['relation_type'] == RecordModel::LEADS_TYPE) {
+			$record['relation_name'] = Leads::where(['id' => $record['relation_id']])->value('name');
+		} elseif($record['relation_type'] == RecordModel::BUSINESS_TYPE) {
+            $record['relation_name'] = Business::where(['id' => $record['relation_id']])->value('name');
+        }else{
+            $record['relation_name']='';
+        }
+
+		$reminds_id           = $record['reminds_id'];
+		$reminds_id           = explode(',', $reminds_id);
+		$names                = Staff::where(['id' => ['in', $reminds_id]])->column('name');
+		$record['staff_name'] = implode(',', $names);
+        if($record['staff_id']){
+            $record['staff'] = Staff::where(['id'=>$record['staff_id']])->field('id,img,name,post')->find();
+        }
+		//标记通知已读
+		Message::setRead(Message::RECORD_TYPE, $id, $this->auth->id);
+		//添加阅读记录
+		RecordRead::addRead($id, $this->auth->id);
+
+		$this->success('请求成功', $record);
+	}
+
+
+    /**
+     * 添加评论
+     */
+	public function addComment() {
+		$content   = input('content');
+		$record_id = input('record_id');
+        $relation_type = input('relation_type');
+		if (empty($content)) {
+			$this->error('评论内容不能为空');
+		}
+		$data         = [
+			'relation_type' => $relation_type,
+			'relation_id'   => $record_id,
+			'staff_id'      => $this->auth->id,
+			'content'       => $content,
+			'status'        => 1,
+			'ip'            => get_client_ip(),
+		];
+
+
+		$commentModel = new Comment();
+		$commentModel->save($data);
+
+		$record = RecordModel::get($record_id);
+		Message::addMessage(Message::COMMENT_TYPE,$record_id,$record['create_staff_id'],$this->auth->id);
+
+		$staff_ids=$commentModel->where(['relation_type'=>$relation_type,'relation_id'=>$record_id])->group('staff_id')->column('staff_id');
+		foreach ($staff_ids as $staff_id) {
+			//发送通知
+			if($staff_id != $this->auth->id){
+				Message::addMessage(Message::COMMENT_TYPE,$record_id,$staff_id,$this->auth->id);
+			}
+		}
+		$this->success('评论成功');
+	}
+
+
+    /**
+     * 评论列表
+     */
+	public function commentList() {
+		$record_id = input('record_id');
+        $relation_type = input('relation_type');
+		$comments = Comment::where([
+			'relation_type' => $relation_type,
+			'relation_id'   => $record_id,
+			'status'        => 1
+		])->field('id,staff_id,content,createtime')->with(['staff'])->select();
+		$this->success('请求成功', $comments);
+	}
+
+    /**
+     * 获取跟进客户
+     */
+    public function getcustomerList() {
+        $limit         = input("limit/d", 10);
+        $time       = input('time', 0);
+        $type       = input('type', 1);
+
+        $where['create_staff_id'] = $this->auth->id;
+        if($type == 6){
+            $where['relation_type'] = 3;
+        }elseif($type == 7){
+            $where['relation_type'] = 4;
+        }elseif($type == 8){
+            $where['relation_type'] = 2;
+        }elseif($type == 9){
+            $where['relation_type'] = 5;
+        }else{
+            $where['relation_type'] = 1;
+        }
+        $where['follow_type'] = ['neq', '其它'];
+        $staff_id             = $this->auth->id;
+        if ($time == 1) {//7天
+            $where['next_time'] = array(array('egt',date('Y-m-d', strtotime('-7 day'))),array('lt',date('Y-m-d', strtotime('+1 day'))));
+        } elseif ($time == 2) {//14天
+            $where['next_time'] = array(array('egt',date('Y-m-d', strtotime('-14 day'))),array('lt',date('Y-m-d', strtotime('+1 day'))));
+        }elseif($time == 3){
+            $where['next_time'] = array(array('egt',date('Y-m-d', strtotime('-30 day'))),array('lt',date('Y-m-d', strtotime('+1 day'))));
+        }elseif($time == 4){ //今日
+            $where['next_time'] = array(array('egt',date('Y-m-d 00:00:00')),array('elt',date('Y-m-d 23:59:59')));
+        }
+        $where['status'] = 0;
+        $records = RecordModel::where($where)->with([
+            'staff',
+            'file',
+            'read' => function ($query) use ($staff_id) {
+                $query->where(['staff_id' => $staff_id]);
+            }
+        ])->order('id desc')->paginate($limit)->toArray();
+
+        $data = $records['data'];
+        foreach ($data as $k => $v) {
+            $customerWhere['id'] = $v['relation_id']?? '';
+            if($type == 6){
+                //合同
+                $v['customer']  = Contract::where($customerWhere)->find();
+            }elseif($type == 7){
+                //线索
+                $v['customer']  = Leads::where($customerWhere)->find();
+            }elseif($type == 8){
+                //联系人
+                $v['customer']  = Contacts::where($customerWhere)->find();
+            }elseif($type == 9){
+                //商机
+                $v['customer']  = Business::where($customerWhere)->find();
+            }
+            else{
+                $v['customer'] = Customer::where($customerWhere)->find();
+            }
+            if (!empty($v['read'])) {
+                $v['is_read'] = 1;
+            } else {
+                $v['is_read'] = 0;
+            }
+            $data[$k] = $v;
+        }
+        $this->success('请求成功', [
+            'total'        => $records['total'],
+            'per_page'     => $records['per_page'],
+            'current_page' => $records['current_page'],
+            'last_page'    => $records['last_page'],
+            'data'         => $data
+        ]);
+
+        $this->success('请求成功', $records);
+    }
+    /*
+     *待办跟进
+     */
+    public function record_add(){
+        $type = input('type',0);
+        $content   = input('remarks');
+        $record_id = input('record_id');
+        $relation_type = input('relation_type');
+        if (empty($content)) {
+            $this->error('备注不能为空');
+        }
+        $data         = [
+            'relation_type' => $relation_type,
+            'relation_id'   => $record_id,
+            'staff_id'      => $this->auth->id,
+            'content'       => $content,
+            'status'        => 1,
+            'ip'            => get_client_ip(),
+        ];
+        Db::startTrans();
+        $commentModel = new Comment();
+        $resultC = $commentModel->save($data);
+        $recordU = RecordModel::where(array('id'=>$record_id))->update(array('status'=>1,'updatetime'=>time()));
+        $resultR= true;
+        if($type ==1){
+
+            $params = $this->request->post();
+            // 表单验证
+            if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) {
+                $this->error($result);
+            }
+            try {
+                unset($params['type']);
+                unset($params['remarks']);
+                unset($params['record_id']);
+                $resultR             = RecordModel::createRecord($params);
+            } catch (Exception $e) {
+                Db::rollback();
+                $this->error($e->getMessage());
+            }
+        }
+        if(!$resultC || !$resultR || !$recordU){
+            Db::rollback();
+            $this->error('跟进失败');
+        }
+        Db::commit();
+        $this->success('跟进成功');
+    }
+}

+ 103 - 0
addons/qingdong/controller/Setting.php

@@ -0,0 +1,103 @@
+<?php
+// +----------------------------------------------------------------------
+// | Description: 客户模块设置
+// +----------------------------------------------------------------------
+// | Author: Michael_xu | gengxiaoxu@5kcrm.com 
+// +----------------------------------------------------------------------
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Customer;
+use addons\qingdong\model\Staff;
+
+/**
+ * 客户模块设置
+ */
+class Setting extends StaffApi
+{
+
+
+    /**
+     * 获取团队成员
+     */
+    public function team()
+    {
+        $id = input('id');
+        $customer = Customer::get($id);
+        if (empty($customer)) {
+            $this->error('客户不存在');
+        }
+        $owner_staff = Staff::where(['id' => $customer->owner_staff_id])->find();
+        $rw_staffs = Staff::where(['id' => ['in', explode(',', $customer->rw_staff_id)]])->select();
+        $ro_staffs = Staff::where(['id' => ['in', explode(',', $customer->ro_staff_id)]])->select();
+
+        $staffs = [];
+        if ($owner_staff) {
+            $staffs[] = [
+                'id' => $owner_staff->id,
+                'name' => $owner_staff->name,
+                'img' => $owner_staff->img,
+                'post' => $owner_staff->post,
+                'mobile' => $owner_staff->mobile,
+                'roles' => 1,
+                'is_edit' => 1,
+            ];
+        }
+        foreach ($rw_staffs as $v) {
+            $staffs[] = [
+                'id' => $v->id,
+                'name' => $v->name,
+                'img' => $v->img,
+                'post' => $v->post,
+                'mobile' => $v->mobile,
+                'roles' => 2,
+                'is_edit' => 1,
+            ];
+        }
+        foreach ($ro_staffs as $v) {
+            $staffs[] = [
+                'id' => $v->id,
+                'name' => $v->name,
+                'img' => $v->img,
+                'post' => $v->post,
+                'mobile' => $v->mobile,
+                'roles' => 2,
+                'is_edit' => 0,
+            ];
+        }
+
+        $this->success('请求成功', $staffs);
+    }
+
+    /**
+     * 修改团队成员
+     */
+    public function editShowStaff()
+    {
+        $id = input('id');
+        $staff = input('staff/a');
+        $model = Customer::get($id);
+        if (empty($model)) {
+            $this->error('客户不存在');
+        }
+        $ro_staff_id = [];
+        $rw_staff_id = [];
+        foreach ($staff as $v) {
+            if ($v['is_edit'] == 1) {
+                $rw_staff_id[] = $v['id'];
+            } else {
+                $ro_staff_id[] = $v['id'];
+            }
+        }
+        $ro_staff_id = array_diff($ro_staff_id, $rw_staff_id);
+        $rw_staff_id=implode(',', $rw_staff_id);
+        $ro_staff_id=implode(',', $ro_staff_id);
+        $result = $model->save(['rw_staff_id' => ",{$rw_staff_id},",
+            'ro_staff_id' => ",{$ro_staff_id},"]);
+        if ($result === false) {
+            $this->error('修改失败');
+        }
+        $this->success('修改成功');
+    }
+
+}

+ 595 - 0
addons/qingdong/controller/Staff.php

@@ -0,0 +1,595 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+
+use addons\qingdong\model\Contacts;
+use addons\qingdong\model\Contract;
+use addons\qingdong\model\Customer;
+use addons\qingdong\model\Flow;
+use addons\qingdong\model\Leads;
+use addons\qingdong\model\Receivables;
+use addons\qingdong\model\Remind;
+use addons\qingdong\model\Staff as StaffModel;
+use addons\qingdong\model\StaffDepartment;
+use addons\qingdong\library\Wechat;
+use addons\qingdong\model\Achievement;
+use addons\qingdong\model\Record;
+use fast\Http;
+use think\Exception;
+use think\Log;
+use think\Validate;
+
+/**
+ *  * 操作文档:https://doc.fastadmin.net/qingdong
+ * 软件介绍:https://www.fastadmin.net/store/qingdong.html
+ * 售后微信:qingdong_crm
+ * 员工登录 注册接口
+ */
+class Staff extends StaffApi
+{
+    protected $noNeedLogin = ['test', 'wxLogin', 'login','logintest'];
+    protected $noNeedRight = ['getInfo', 'editInfo', "use_phone"];
+
+
+    public function _initialize()
+    {
+        parent::_initialize();
+    }
+
+    //是否登录
+    public function isLogin()
+    {
+        $this->success('已登录', ['userinfo' => $this->auth->getUserinfo()]);
+    }
+
+
+
+    /**
+     * 会员登录
+     *
+     * @ApiMethod (POST)
+     * @param string $account 账号
+     * @param string $password 密码
+     */
+    public function login()
+    {
+        $account = $this->request->post('account');
+        $password = $this->request->post('password');
+        if (!$account || !$password) {
+            $this->error(__('Invalid parameters'));
+        }
+        $ret = $this->auth->login($account, $password);
+        if ($ret) {
+            $data = ['userinfo' => $this->auth->getUserinfo()];
+            $this->success(__('Logged in successful'), $data);
+        } else {
+            $this->error($this->auth->getError());
+        }
+    }
+
+    //获取个人基本信息
+    public function getInfo()
+    {
+        $staff = StaffModel::where(['id' => $this->auth->id])->with(['department', 'parent'])->find();
+        $group_ids=explode(',',$staff['group_ids']);
+        $staff['role_type'] = 1;//基础和团队
+        if (in_array(1, $group_ids)) {//超级管理员
+            $staff['role_type'] = 9;
+        }
+        $this->success('请求成功', $staff);
+    }
+
+    //员工绑定信息
+    public function staffBind(){
+        $staff=StaffModel::get($this->auth->id);
+        $data=[
+            'is_bind_wechat'=>$staff['openid']?1:($staff['wx_openid']?1:0)
+        ];
+        $this->success('请求成功',$data);
+    }
+
+    //绑定微信
+    public function wechatBind(){
+        $type=input('type');//applet小程序   web 网页授权
+        $code = input('code');
+        if($type == 'web'){
+            $wechat = new Wechat('wxOfficialAccount');
+            if(empty($wechat->config['app_id'])){
+                $this->error('微信公众号appid未设置');
+            }
+            if(empty($wechat->config['secret'])){
+                $this->error('微信公众号secret未设置');
+            }
+            $decryptSession = $wechat->getOfficialAccessToken($code);
+
+            if (isset($decryptSession['errcode']) && $decryptSession['errcode'] != 0) {
+                $this->error(__('解析失败!'));
+            }
+            $openid = $decryptSession['openid'];
+            $unionid = $decryptSession['unionid'] ?? '';
+
+            Log::info(json_encode($decryptSession,JSON_UNESCAPED_UNICODE));
+            //判断用户是否存在
+            $staff = StaffModel::where(['wx_openid' => $openid])->find();
+            if($staff){
+                $this->error('该微信号已绑定账号');
+            }
+            $staffModel=new StaffModel();
+            $result=$staffModel->save(['wx_openid'=>$openid,'unionid'=>$unionid],['id'=>$this->auth->id]);
+            if($result){
+                $this->success('绑定成功');
+            }
+            $this->error('绑定失败');
+        }elseif($type == 'applet'){
+            $wechat = new Wechat('wxMiniProgram');
+            if(empty($wechat->config['app_id'])){
+                $this->error('微信小程序appid未设置');
+            }
+            if(empty($wechat->config['secret'])){
+                $this->error('微信小程序secret未设置');
+            }
+            $decryptSession = $wechat->code($code);
+
+            if (isset($decryptSession['errcode']) && $decryptSession['errcode'] != 0) {
+                $this->error(__('解析失败!'));
+            }
+            $openid = $decryptSession['openid'];
+            $unionid = $decryptSession['unionid'] ?? '';
+            //判断用户是否存在
+            $staff = StaffModel::where(['openid' => $openid])->find();
+            if($staff){
+                $this->error('该微信号已绑定账号');
+            }
+            $staffModel=new StaffModel();
+            $result=$staffModel->save(['openid'=>$openid,'unionid'=>$unionid],['id'=>$this->auth->id]);
+            if($result){
+                $this->success('绑定成功');
+            }
+            $this->error('绑定失败');
+        }
+    }
+
+    //解绑微信
+    public function unboundWechat()
+    {
+        $staffId = $this->auth->id;
+        $model = new StaffModel();
+        $staff = $model->where(['id' => $staffId])->find();
+        if (empty($staff)) {
+            $this->error('员工不存在');
+        }
+        if ($model->isUpdate(true)->save(['id' => $staffId, 'wx_openid' => null,
+            'unionid' => null, 'openid' => null])) {
+            $this->success('解绑微信成功');
+        }
+        $this->error('操作失败');
+    }
+    //修改个人基本信息
+    public function editInfo()
+    {
+        $name = input('name');
+        $img = input('img');
+        $email = input('email');
+        $sex = input('sex');
+        $num = input('num');
+        $post = input('post');
+        $mobile = input('mobile');
+        $staffs = StaffModel::where(array('id' => $this->auth->id))->find();
+        $staffs->mobile = $mobile;
+        $staffs->img = $img;
+        $staffs->email = $email;
+        $staffs->sex = $sex;
+        $staffs->num = $num;
+        $staffs->post = $post;
+        $staffs->updatetime = time();
+        $result = $staffs->save();
+        if (!$result) {
+            $this->error('修改失败');
+        }
+        $this->success('修改成功');
+    }
+
+
+    //授权手机号
+    public function use_phone()
+    {
+        $code = $this->request->post('code','',null);
+        $encryptedData = $this->request->post('encryptedData','',null);
+        $iv = $this->request->post('iv','',null);
+        $config = new Wechat('wxMiniProgram');
+        $url = "https://api.weixin.qq.com/sns/jscode2session?appid=" . $config->config['app_id'] . "&secret=" . $config->config['secret'] . "&js_code=" . $code . "&grant_type=authorization_code";
+        $user = curl_getinfo($url);
+        $arr = json_decode($user, true);
+        if (isset($arr['errcode']) && $arr['errcode'] != 0) {
+            $this->error('操作失败!');
+        }
+        if (!isset($arr['openid']) || !isset($arr['session_key'])) {
+            $this->error('授权失败,请重新授权!');
+        }
+        $openId = $arr['openid'];
+        $pc = new Wxbizdatacrypt($config->config['app_id'], $arr['session_key']);
+        $errCode = $pc->decryptData($encryptedData, $iv, $data);
+        if ($errCode != 0) {
+            $this->error('授权失败,请重新授权!');
+        }
+        $decryptUserInfo = json_decode($data, true);
+        if (isset($decryptUserInfo['phoneNumber']) && !empty($decryptUserInfo['phoneNumber'])) {
+            $user_id = $this->auth->id;
+            $userInfo = StaffModel::where(array('id' => $user_id))->update(array('mobile' => $decryptUserInfo['phoneNumber']));
+            if ($userInfo === false) {
+                $this->error('绑定失败!');
+            }
+            $data = ['mobile' => $decryptUserInfo['phoneNumber']];
+            $this->success('绑定成功', $data);
+        } else {
+            $this->error('授权失败!');
+        }
+    }
+
+
+    //获取下级员工列表
+    public function getStaffList()
+    {
+        $ids = StaffModel::getLowerStaffId();
+        $staff = StaffModel::where([
+            'id' => ['in', $ids],
+            'status' => 1
+        ])->with(['parent'])->field('id,name,nickname,img,num,mobile,post,parent_id')->select();
+        $this->success('请求成功', $staff);
+    }
+
+
+    //获取员工详情
+    public function getStaffDetail()
+    {
+        $id = input('id');
+        if (empty($id)) {
+            $this->error('员工不存在');
+        }
+        $staff = StaffModel::with(['department', 'parent'])->where([
+            'id' => $id,
+        ])->find();
+        $this->success('请求成功', $staff);
+    }
+
+
+    //待审核员工列表
+    public function getCheckStaffList()
+    {
+        $staff = StaffModel::where([
+            'status' => 0,
+            'name' => ['neq', '']
+        ])->field('id,name,nickname,img,num,mobile,post,status')->select();
+        $this->success('请求成功', $staff);
+    }
+
+    //修改员工信息
+    public function updateStaff()
+    {
+        $name = input('name', '');
+        $img = input('img', '');
+        $email = input('email', '');
+        $sex = input('sex', 0);
+        $num = input('num', '');
+        $post = input('post', '');
+        $parent_id = input('parent_id', 0);
+        $id = input('id', 0, 'intval');
+        if (StaffModel::where(['id' => $id])->update([
+                'name' => $name,
+                'img' => $img,
+                'email' => $email,
+                'sex' => $sex,
+                'num' => $num,
+                'post' => $post,
+                'parent_id' => $parent_id,
+                'updatetime' => time()
+            ]) == false) {
+            $this->error('修改失败');
+        }
+        $this->success('修改成功');
+    }
+
+    //审核员工成功
+    public function checkStaffSuccess()
+    {
+        $name = input('name', '');
+        $img = input('img', '');
+        $email = input('email', '');
+        $sex = input('sex', 0);
+        $role = input('role', 0);
+        $num = input('num', '');
+        $post = input('post', '');
+        $mobile = input('mobile', '');
+        $department_id = input('department_id', 0);
+        $parent_id = input('parent_id', 0);
+        $id = input('id', 0, 'intval');
+        if (StaffModel::where(['id' => $id, 'status' => 0])->find() == false) {
+            $this->error('待审核员工不存在');
+        }
+        if (empty($department_id)) {
+            $this->error('请选择员工部门!');
+        }
+        if (StaffModel::where(['id' => $id])->update([
+                'name' => $name,
+                'img' => $img,
+                'email' => $email,
+                'sex' => $sex,
+                'num' => $num,
+                'role' => $role,
+                'mobile' => $mobile,
+                'post' => $post,
+                'parent_id' => $parent_id,
+                'department_id' => $department_id,
+                'status' => 1,
+                'updatetime' => time()
+            ]) == false) {
+            $this->error('审核失败');
+        }
+        $this->success('审核成功');
+    }
+
+    //审核员工拒绝
+    public function checkStaffError(){
+        $id = input('id');
+        if (StaffModel::where(['id' => $id, 'status' => 0])->find() == false) {
+            $this->error('待审核员工不存在');
+        }
+        if (StaffModel::where(['id' => $id, 'status' => 0])->update(['deletetime' => time()]) == false) {
+            $this->error('拒绝失败');
+        }
+        $this->success('审核成功');
+    }
+
+    //获取员工统计
+    public function getStaffStatistics()
+    {
+        $id = input('id');
+        if (empty($id)) {
+            $this->error('员工不存在');
+        }
+        $date = input('date', date('Y-m'));
+        //月底
+        $endDate = strtotime('+1 month', strtotime(date($date . '-1')));
+        $date = strtotime($date);
+        //客户 线索 联系人 合同 回款 跟进次数 处理审批
+        $leads = Leads::where([
+            'create_staff_id' => $id,
+            'createtime' => ['between', [$date, $endDate]],
+        ])->count();
+        $customer = Customer::where([
+            'create_staff_id' => $id,
+            'createtime' => ['between', [$date, $endDate]],
+        ])->count();
+        $contacts = Contacts::where([
+            'create_staff_id' => $id,
+            'createtime' => ['between', [$date, $endDate]],
+        ])->count();
+        $contract = Contract::where([
+            'create_staff_id' => $id,
+            'createtime' => ['between', [$date, $endDate]],
+            'check_status' => 2
+        ])->count();
+        $contract_money = Contract::where([
+            'create_staff_id' => $id,
+            'createtime' => ['between', [$date, $endDate]],
+            'check_status' => 2
+        ])->sum('money');
+        $receivables = Receivables::where([
+            'create_staff_id' => $id,
+            'createtime' => ['between', [$date, $endDate]],
+            'check_status' => 2
+        ])->count();
+        $receivables_money = Receivables::where([
+            'create_staff_id' => $id,
+            'createtime' => ['between', [$date, $endDate]],
+            'check_status' => 2
+        ])->sum('money');
+        $record = Record::where([
+            'create_staff_id' => $id,
+            'createtime' => ['between', [$date, $endDate]],
+        ])->count();
+
+        $field = Achievement::getMonthField(date('Y-m', $date));
+        $contractAchievement = Achievement::where([
+            'year' => date('Y', $date),
+            'type' => 3,
+            'obj_id' => $id,
+            'status' => 1
+        ])->value($field);
+
+        $receivablesAchievement = Achievement::where([
+            'year' => date('Y', $date),
+            'type' => 3,
+            'obj_id' => $id,
+            'status' => 2
+        ])->value($field);
+
+        $this->success('请求成功', [
+            'leads' => $leads,
+            'customer' => $customer,
+            'contacts' => $contacts,
+            'contract' => $contract,
+            'contract_money' => $contract_money,
+            'receivables' => $receivables,
+            'receivables_money' => $receivables_money,
+            'record' => $record,
+            'contractAchievement' => $contractAchievement ?: 0,
+            'receivablesAchievement' => $receivablesAchievement ?: 0,
+        ]);
+    }
+
+    //获取员工所属客户
+    public function getStaffCustomer()
+    {
+        $id = input('id');
+        $limit = input("limit/d", 10);
+        $row = StaffModel::get($id);
+        if (empty($row)) {
+            $this->error('员工不存在');
+        }
+        $where = [];
+        $where['owner_staff_id'] = $id;
+        $list = Customer::where($where)->with([
+            'ownerStaff',
+            'contacts'
+        ])->field('id,name,next_time,owner_staff_id,level,follow')->order('id desc')->paginate($limit);
+
+        $this->success('请求成功', $list);
+    }
+
+    //获取部门列表
+    public function getDepartment()
+    {
+
+        $this->success('请求成功', StaffDepartment::getDepartmentList());
+    }
+
+    //获取上级列表
+    public function getParentList()
+    {
+        $id = input('id');
+        if (empty($id)) {
+            $this->error('参数错误');
+        }
+        $this->success('请求成功', StaffModel::getList([$id]));
+    }
+
+
+    /**
+     * 获取用户上级IDs
+     */
+    public function getStaffIds()
+    {
+        // record 跟进  contract 合同  consume 费用  receivables 回款
+        $type = input('type');
+        $remind=Remind::where(['type'=>$type])->find();
+        if($remind){
+            $staff = StaffModel::where(['id' => ['in', $remind['staff_ids']]])->field('id,name,img')->select();
+            $this->success('请求成功', $staff);
+        }
+        $pid = StaffModel::where(['id' => $this->auth->id])->value('parent_id');
+        $pids = [$pid];
+        $staff = StaffModel::where(['id' => ['in', $pids]])->field('id,name,img')->select();
+        $this->success('请求成功', $staff);
+    }
+
+    /**
+     * 获取审批列表
+     */
+    public function getsteplist()
+    {
+        // record 跟进  contract 合同  consume 费用  receivables 回款 formapproval_1 审批
+        $type = input('type');
+
+        //获取审批
+        $data = Flow::getsteplist($type);
+        if (empty($data)) {
+            $this->error('无可用审批流,请联系管理员');
+        }
+        $this->success('请求成功', $data);
+    }
+    /**
+     * 获取审批详情
+     */
+    public function getstepdetail()
+    {
+        // record 跟进  contract 合同  consume 费用  receivables 回款
+        $type = input('type');
+        $relation_id=input('relation_id');
+        $data = Flow::getstepdetail($type,$relation_id);
+        if (empty($data)) {
+            $this->error('无可用审批流,请联系管理员');
+        }
+        $this->success('请求成功', $data);
+    }
+
+
+    //禁用账号
+    public function disable_user()
+    {
+        $id = input('id');
+        $status = 2;
+        $model = new StaffModel();
+        $staff = $model->where(['id' => $id])->find();
+        if (empty($staff)) {
+            $this->error('员工不存在');
+        }
+        if ($model->isUpdate(true)->save(['id' => $id, 'status' => $status])) {
+            $this->success('操作成功');
+        }
+        $this->error('操作失败');
+    }
+    /**
+     * 退出登录
+     * @ApiMethod (POST)
+     */
+    public function logout()
+    {
+        if (!$this->request->isPost()) {
+            $this->error(__('Invalid parameters'));
+        }
+        $this->auth->logout();
+        $this->success(__('Logout successful'));
+    }
+    /**
+     * 修改密码
+     */
+    public function changepwd()
+    {
+        if ($this->request->isPost()) {
+            $oldpassword = $this->request->post("oldpassword");
+            $newpassword = $this->request->post("newpassword");
+            $renewpassword = $this->request->post("renewpassword");
+            $rule = [
+                'oldpassword'   => 'require|length:6,30',
+                'newpassword'   => 'require|length:6,30',
+                'renewpassword' => 'require|length:6,30|confirm:newpassword',
+            ];
+
+            $msg = [
+                'renewpassword.confirm' =>'两次输入的密码不一致'
+            ];
+            $data = [
+                'oldpassword'   => $oldpassword,
+                'newpassword'   => $newpassword,
+                'renewpassword' => $renewpassword,
+            ];
+            $field = [
+                'oldpassword'   => '旧密码',
+                'newpassword'   => '新密码',
+                'renewpassword' => '确认密码'
+            ];
+            $validate = new Validate($rule, $msg, $field);
+            $result = $validate->check($data);
+            if (!$result) {
+                $this->error(__($validate->getError()));
+                return false;
+            }
+
+            $ret = $this->auth->changepwd($newpassword, $oldpassword);
+            if ($ret) {
+                $this->success('修改密码成功');
+            } else {
+                $this->error($this->auth->getError());
+            }
+        }
+    }
+    //直接体验
+    public function logintest()
+    {
+        $staff = StaffModel::where([])->order('id asc')->find();
+        if(!$staff){
+            $this->error('员工不存在');
+        }
+        $stafflogin= $this->auth->direct($staff['id']);
+        if ($stafflogin) {
+            $data = ['userinfo' => $this->auth->getUserinfo()];
+            $this->success(__('Logged in successful'), $data);
+        } else {
+            $this->error('登录失败');
+        }
+
+    }
+
+}

+ 325 - 0
addons/qingdong/controller/StaffApi.php

@@ -0,0 +1,325 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\library\StaffAuth;
+use think\Config;
+use think\exception\HttpResponseException;
+use think\exception\ValidateException;
+use think\Hook;
+use think\Lang;
+use think\Loader;
+use think\Request;
+use think\Response;
+use think\Validate;
+
+/**
+ * API控制器基类
+ */
+class StaffApi {
+    /**
+     * @var Request Request 实例
+     */
+    protected $request;
+    /**
+     * @var bool 验证失败是否抛出异常
+     */
+    protected $failException = false;
+    /**
+     * @var bool 是否批量验证
+     */
+    protected $batchValidate = false;
+    /**
+     * @var array 前置操作方法列表
+     */
+    protected $beforeActionList = [];
+    /**
+     * 无需登录的方法,同时也就不需要鉴权了
+     * @var array
+     */
+    protected $noNeedLogin = [];
+    /**
+     * 无需鉴权的方法,但需要登录
+     * @var array
+     */
+    protected $noNeedRight = [];
+    /**
+     * 权限Auth
+     * @var StaffAuth
+     */
+    protected $auth = null;
+
+    /**
+     * 默认响应输出类型,支持json/xml
+     * @var string
+     */
+    protected $responseType = 'json';
+
+
+    /**
+     * 构造方法
+     * @access public
+     * @param Request $request Request 对象
+     */
+    public function __construct(Request $request = null) {
+        $this->request = is_null($request) ? Request::instance() : $request;
+
+        // 控制器初始化
+        $this->_initialize();
+
+        // 前置操作方法
+        if ($this->beforeActionList) {
+            foreach ($this->beforeActionList as $method => $options) {
+                is_numeric($method) ? $this->beforeAction($options) : $this->beforeAction($method, $options);
+            }
+        }
+        $controllername = strtolower($this->request->controller());
+
+    }
+
+
+    /**
+     * 初始化操作
+     * @access protected
+     */
+    protected function _initialize() {
+        //跨域请求检测
+        check_cors_request();
+
+        //移除HTML标签
+        $this->request->filter('trim,strip_tags,htmlspecialchars');
+
+        $this->auth = StaffAuth::instance(['type'=>'Mysqlstaff']);
+
+        $modulename     = $this->request->module();
+        $controllername = Loader::parseName($this->request->controller());
+        $actionname     = strtolower($this->request->action());
+
+		// token
+		$token   = $this->request->server('HTTP_TOKEN', $this->request->request('token', \think\Cookie::get('token')));
+		$path           = str_replace('.', '/', $controllername) . '/' . $actionname;
+		// 设置当前请求的URI
+		$this->auth->setRequestUri($path);
+		// 检测是否需要验证登录
+		if (!$this->auth->match($this->noNeedLogin)) {
+
+            //初始化
+			$this->auth->init($token);
+            //检测是否登录
+			if (!$this->auth->isLogin()) {
+				$this->error(__('Please login first'), null, 401);
+			}
+			if (!$this->auth->match($this->noNeedRight)) {
+				//检测是否完善用户信息
+				if (!$this->auth->mobile || !$this->auth->name) {
+					$this->error('请先完善用户信息', null, 402);
+				}
+				//状态错误
+				if ($this->auth->status != 1) {
+					$this->error('等待管理员审核', null, 405);
+				}
+			}
+		} else {
+            // 如果有传递token才验证是否登录状态
+			if ($token) {
+				$this->auth->init($token);
+			}
+		}
+
+        $upload = \app\common\model\Config::upload();
+
+        // 上传信息配置后
+        Hook::listen("upload_config_init", $upload);
+
+        Config::set('upload', array_merge(Config::get('upload'), $upload));
+        // 加载当前控制器语言包
+        $this->loadlang($controllername);
+    }
+
+
+    /**
+     * 加载语言文件
+     * @param string $name
+     */
+    protected function loadlang($name) {
+        $name = Loader::parseName($name);
+        Lang::load(ADDON_PATH  . 'qingdong/lang/' . $this->request->langset() . '/' . str_replace('.', '/', $name) . '.php');
+    }
+
+
+    /**
+     * 操作成功返回的数据
+     * @param string $msg 提示信息
+     * @param mixed $data 要返回的数据
+     * @param int $code 错误码,默认为1
+     * @param string $type 输出类型
+     * @param array $header 发送的 Header 信息
+     */
+    protected function success($msg = '', $data = null, $code = 1, $type = null, array $header = []) {
+        $this->result($msg, $data, $code, $type, $header);
+    }
+
+
+    /**
+     * 操作失败返回的数据
+     * @param string $msg 提示信息
+     * @param mixed $data 要返回的数据
+     * @param int $code 错误码,默认为0
+     * @param string $type 输出类型
+     * @param array $header 发送的 Header 信息
+     */
+    protected function error($msg = '', $data = null, $code = 0, $type = null, array $header = []) {
+        $this->result($msg, $data, $code, $type, $header);
+    }
+
+
+    /**
+     * 返回封装后的 API 数据到客户端
+     * @access protected
+     * @param mixed $msg 提示信息
+     * @param mixed $data 要返回的数据
+     * @param int $code 错误码,默认为0
+     * @param string $type 输出类型,支持json/xml/jsonp
+     * @param array $header 发送的 Header 信息
+     * @return void
+     * @throws HttpResponseException
+     */
+    protected function result($msg, $data = null, $code = 0, $type = null, array $header = []) {
+        $result = [
+            'code' => $code,
+            'msg'  => $msg,
+            'time' => Request::instance()->server('REQUEST_TIME'),
+            'data' => $data,
+        ];
+        // 如果未设置类型则自动判断
+        $type = $type ? $type : ($this->request->param(config('var_jsonp_handler')) ? 'jsonp' : $this->responseType);
+
+        if (isset($header['statuscode'])) {
+            $code = $header['statuscode'];
+            unset($header['statuscode']);
+        } else {
+            //未设置状态码,根据code值判断
+            $code = $code >= 1000 || $code < 200 ? 200 : $code;
+        }
+        $response = Response::create($result, $type, $code)->header($header);
+        throw new HttpResponseException($response);
+    }
+
+
+    /**
+     * 前置操作
+     * @access protected
+     * @param string $method 前置操作方法名
+     * @param array $options 调用参数 ['only'=>[...]] 或者 ['except'=>[...]]
+     * @return void
+     */
+    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 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);
+
+            !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());
+            }
+
+            return $v->getError();
+        }
+
+        return true;
+    }
+
+
+    /**
+     * 刷新Token
+     */
+    protected function token() {
+        $token = $this->request->param('__token__');
+
+        //验证Token
+        if (!Validate::make()->check(['__token__' => $token], ['__token__' => 'require|token'])) {
+            $this->error(__('Token verification error'), ['__token__' => $this->request->token()]);
+        }
+
+		//刷新Token
+		$this->request->token();
+	}
+
+    protected function qingdongValidate($params, $class, $scene, $rules = []) {
+        $validate = validate(str_replace('controller', 'validate', $class));
+        if (!$validate->check($params, $rules, $scene)) {
+            return $validate->getError();
+        }
+        return true;
+    }
+}

+ 906 - 0
addons/qingdong/controller/Statistics.php

@@ -0,0 +1,906 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Achievement;
+use addons\qingdong\model\Achievement as AchievementModel;
+use addons\qingdong\model\ContractRatio;
+use addons\qingdong\model\Receivables;
+use addons\qingdong\model\Contract;
+use addons\qingdong\model\Leads;
+use addons\qingdong\model\Customer;
+use addons\qingdong\model\ReceivablesPlan;
+use addons\qingdong\model\Record;
+use addons\qingdong\model\Staff;
+
+
+/**
+ * 统计接口
+ */
+class Statistics extends StaffApi {
+	protected $noNeedLogin = [];
+	protected $noNeedRight = [];
+
+
+	/**
+	 *成交排行
+	 */
+	public function contractRanding() {
+//		$date = input('date', date('Y-m'));
+		$type = input('type', 0);//0 本人及下属 1 仅本人 2 仅下属 3公司
+        $status=input('status',1);//1 合同 2 回款
+        $times=input('times','');
+        $times=explode(',',$times);
+        if(empty($times)){
+            $this->error('参数不能为空');
+        }
+        $startDate=date("Y-m",strtotime($times[0]));
+        $endDate=date("Y-m",strtotime($times[1]));
+		$between=[$times[0],$times[1]];
+        if($status == 1){
+            $contracts = Contract::where([
+                'order_date'   => ['between', $between],
+                'check_status' => 2,
+            ])->group('owner_staff_id')->field('owner_staff_id,sum(money) as money')->order('money desc')->select();
+            $list      = [];
+            foreach ($contracts as $v) {
+                $list[$v['owner_staff_id']] = $v['money'];
+            }
+        }else{
+            $receivables = Receivables::where([
+                'return_time'   => ['between', $between],
+                'check_status' => 2,
+            ])->group('owner_staff_id')->field('owner_staff_id,sum(money) as money')->order('money desc')->select();
+            $list      = [];
+            foreach ($receivables as $v) {
+                $list[$v['owner_staff_id']] = $v['money'];
+            }
+        }
+
+		$data      = [];
+		$staffs    = Staff::getList();
+		foreach ($staffs as $v) {
+			if (isset($list[$v['id']])) {
+				$data[$v['id']] = $list[$v['id']];
+			} else {
+				$data[$v['id']] = 0;
+			}
+		}
+		arsort($data);
+		$staffs   = Staff::getKeyList();
+		$result   = [];
+		$i        = 1;
+		$oneMoney = 0;
+		if ($type == 1) {//本人
+			$showStaffIds = [$this->auth->id];
+		} elseif ($type == 2) {//下属
+			$showStaffIds = Staff::getLowerStaffId();
+		} elseif ($type == 3) {//公司
+			$showStaffIds = Staff::getLowerStaffId();
+		} else {//全部
+			$showStaffIds = Staff::getMyStaffIds();
+		}
+
+
+		foreach ($data as $id => $money) {
+			if ($i == 1) {
+				$oneMoney = $money;
+			}
+			$val          = $staffs[$id];
+			$val['money'] = $money;
+			$val['ratio'] = ($money && $oneMoney) ? sprintf("%.2f", $money / $oneMoney * 100) : 0;
+			$val['rank']  = $i;
+			$i++;
+			if(in_array($id,$showStaffIds)){
+				$result[]     = $val;
+			}
+		}
+
+		if (count($result) >= 10) {
+			$top    = array_slice($result, 0, 3);
+			$bottom = array_slice($result, -3, 3);
+			$middle = array_slice($result, 3, 4);
+			$result = array_merge($top, $bottom, $middle);
+		}
+
+		if ($type == 1) {//本人
+			$showStaffIds = [$this->auth->id];
+			//业绩目标完成情况
+            $data = Achievement::getStaffAchievement($startDate,$endDate,$status);
+		} elseif ($type == 2) {//下属
+			$showStaffIds = Staff::getLowerStaffId();
+			//业绩目标完成情况
+            $data = Achievement::getStaffAchievement($startDate,$endDate,$status);
+		} elseif ($type == 3) {//公司
+			$showStaffIds = Staff::getLowerStaffId();
+			//业绩目标完成情况
+			$data = Achievement::getCompanyAchievement($startDate,$endDate,$status);
+		} else {//全部
+			$showStaffIds = Staff::getMyStaffIds();
+			//业绩目标完成情况
+            $data = Achievement::getStaffAchievement($startDate,$endDate,$status);
+		}
+
+        $achievement=$data['achievement']??0;
+        if($status == 1){
+            $totalMoneys = Contract::where([
+                'order_date'     => ['between', $between],
+                'check_status'   => 2,
+                'owner_staff_id' => ['in',$showStaffIds],
+            ])->sum('money');
+        }else{
+            $totalMoneys = Receivables::where([
+                'return_time'     => ['between', $between],
+                'check_status'   => 2,
+                'owner_staff_id' => ['in',$showStaffIds],
+            ])->sum('money');
+        }
+
+        $ratio = ($totalMoneys && intval($achievement)) ? (intval($achievement) == 0) ? 100 : round($totalMoneys / $achievement * 100, 2) : 0;
+		$data  = [
+			'achievement'       => $achievement,
+			'contract_moneys'   => $totalMoneys,
+			'completion_status' => ($ratio >= 100) ? 1 : 0,//完成状态
+			'ratio'             => $ratio,
+			'ranking'           => $result
+		];
+
+		$this->success('请求成功', $data);
+	}
+
+
+    /**
+     * 合同排行 机型排行
+     */
+	public function contractRanking() {
+
+		$date = input('date', date('Y-m'));
+		$type = input('type', 0);//0 本人及下属 1 仅本人 2 仅下属
+		//月底
+		$endDate = date('Y-m-d', strtotime('+1 month', strtotime($date . '-1')) - 1);
+
+		$contracts = Contract::where([
+			'order_date'   => ['between', [$date . '-1', $endDate]],
+			'check_status' => 2,
+		])->group('owner_staff_id')->field('owner_staff_id,count(*) as contract_number')->order('contract_number desc')->select();
+		$list      = [];
+		foreach ($contracts as $v) {
+			$list[$v['owner_staff_id']] = $v['contract_number'];
+		}
+		$contracts = $list;
+
+		$data   = [];
+		$staffs = Staff::getList();
+		foreach ($staffs as $v) {
+			if (isset($contracts[$v['id']])) {
+				$data[$v['id']] = $contracts[$v['id']];
+			} else {
+				$data[$v['id']] = 0;
+			}
+		}
+		arsort($data);
+		$staffs    = Staff::getKeyList();
+		$result    = [];
+		$i         = 1;
+		$oneNumber = 0;
+		if ($type == 1) {//本人
+			$showStaffIds = [$this->auth->id];
+		} elseif ($type == 2) {//下属
+			$showStaffIds = Staff::getLowerStaffId();
+		} else {//全部
+			$showStaffIds = Staff::getMyStaffIds();
+		}
+		foreach ($data as $id => $number) {
+			if ($i == 1) {
+				$oneNumber = $number;
+			}
+			$val           = $staffs[$id];
+			$val['number'] = $number;
+			$val['ratio']  = $oneNumber ? sprintf("%.2f", $number / $oneNumber * 100) : 0;
+			$val['rank']   = $i;
+			$i++;
+			if(in_array($id,$showStaffIds)){
+				$result[]     = $val;
+			}
+		}
+		if (count($result) >= 10) {
+
+			$top    = array_slice($result, 0, 3);
+			$bottom = array_slice($result, -3, 3);
+			$middle = array_slice($result, 3, 4);
+			$result = array_merge($top, $bottom, $middle);
+		}
+
+		$this->success('请求成功', $result);
+	}
+
+
+    /**
+     * 回款统计
+     */
+	public function receivablesStatistics() {
+        $type = input('type',0); //0:全部 1:我负责的 2:下属负责的
+        switch($type){
+            case 1:
+                $wheres['owner_staff_id'] =  $this->auth->id;
+                break;
+            case 2:
+                $wheres['owner_staff_id'] =  array('in',Staff::getLowerStaffId());
+                break;
+            default:
+                $wheres['owner_staff_id'] =  array('in',Staff::getMyStaffIds());
+                break;
+
+        }
+		$contract_moneys    = Contract::where(['owner_staff_id' => $this->auth->id, 'check_status' => 2])->sum('money');
+		$receivables_moneys = Receivables::where($wheres)->where([
+			'check_status'   => 2,
+		])->sum('money');
+		$plan_moneys        = ReceivablesPlan::where($wheres)->where([
+			'status'         => 0,
+		])->sum('money');
+		$no_moneys          = $contract_moneys - $receivables_moneys;
+		$startDate          = date('Y-01');
+		$endDate            = date('Y-m');
+
+		$plans      = ReceivablesPlan::where($wheres)->group('dates')->field('sum(money) as money,FROM_UNIXTIME(UNIX_TIMESTAMP(return_date),"%Y-%m") as dates')->select();
+		$plans_list = [];
+		foreach ($plans as $item) {
+			$plans_list[$item['dates']] = $item['money'];
+		}
+		$receivables      = Receivables::where($wheres)->group('dates')->field('sum(money) as money,FROM_UNIXTIME(UNIX_TIMESTAMP(return_time),"%Y-%m") as dates')->select();
+		$receivables_list = [];
+		foreach ($receivables as $item) {
+			$receivables_list[$item['dates']] = $item['money'];
+		}
+		$data = [];
+		for ($startDate; strtotime($startDate) <= strtotime($endDate); $startDate = date('Y-m', strtotime($startDate . ' +1 month'))) {
+			$row       = [
+				'date'        => $startDate,
+				'plan'        => $plans_list[$startDate] ?? 0,
+				'receivables' => $receivables_list[$startDate] ?? 0,
+			];
+			$row['no'] = ($row['plan'] - $row['receivables']) > 0 ? $row['plan'] - $row['receivables'] : 0;
+			$data[]    = $row;
+		}
+
+		$this->success('请求成功', [
+			'contract_moneys'    => $contract_moneys,
+			'receivables_moneys' => $receivables_moneys,
+			'plan_moneys'        => $plan_moneys,
+			'no_moneys'          => $no_moneys,
+			'data'               => $data
+		]);
+	}
+
+    /**
+     * 所属员工回款统计
+     */
+	public function staffReceivablesStatistics() {
+		$ids = Staff::getMyStaffIds();
+
+
+		$contract_moneys    = Contract::where([
+			'owner_staff_id' => ['in', $ids],
+			'check_status'   => 2,
+		])->sum('money');
+		$receivables_moneys = Receivables::where([
+			'owner_staff_id' => ['in', $ids],
+			'check_status'   => 2,
+		])->sum('money');
+		$plan_moneys        = ReceivablesPlan::where([
+			'owner_staff_id' => ['in', $ids],
+			'status'         => 0,
+		])->sum('money');
+		$no_moneys          = $contract_moneys - $receivables_moneys;
+
+		$contracts      = Contract::where([
+			'owner_staff_id' => [
+				'in',
+				$ids
+			],
+			'check_status'   => 2,
+		])->group('owner_staff_id')->field('sum(money) as money,owner_staff_id')->select();
+		$contracts_list = [];
+		foreach ($contracts as $item) {
+			$contracts_list[$item['owner_staff_id']] = $item['money'];
+		}
+
+		$plans      = ReceivablesPlan::where([
+			'owner_staff_id' => [
+				'in',
+				$ids
+			],
+			'status'         => 0,
+		])->group('owner_staff_id')->field('sum(money) as money,owner_staff_id')->select();
+		$plans_list = [];
+		foreach ($plans as $item) {
+			$plans_list[$item['owner_staff_id']] = $item['money'];
+		}
+
+		$receivables      = Receivables::where([
+			'owner_staff_id' => [
+				'in',
+				$ids
+			],
+			'check_status'   => 2,
+		])->group('owner_staff_id')->field('sum(money) as money,owner_staff_id')->select();
+		$receivables_list = [];
+		foreach ($receivables as $item) {
+			$receivables_list[$item['owner_staff_id']] = $item['money'];
+		}
+		$data   = [];
+		$ids    = Staff::getMyStaffIds();
+		$staffs = Staff::where(['id' => ['in', $ids]])->field('id,name')->select();
+		foreach ($staffs as $v) {
+			$row       = [
+				'id'          => $v['id'],
+				'name'        => $v['name'],
+				'contracts'        => $contracts_list[$v['id']] ?? 0,
+				'plan'        => $plans_list[$v['id']] ?? 0,
+				'receivables' => $receivables_list[$v['id']] ?? 0,
+			];
+			$row['no'] = ($row['contracts'] - $row['receivables']) > 0 ? $row['contracts'] - $row['receivables'] : 0;
+			$data[]    = $row;
+		}
+		$this->success('请求成功', [
+			'contract_moneys'    => $contract_moneys,
+			'receivables_moneys' => $receivables_moneys,
+			'plan_moneys'        => $plan_moneys,
+			'no_moneys'          => $no_moneys,
+			'data'               => $data
+		]);
+	}
+
+    /**
+     * 我的业绩目标完成度
+     */
+	public function staffAchievementStatistics() {
+		$year = input('year', date('Y'));
+		$type = input('type', 0);
+		if ($type == 1) {//本人
+			$showStaffIds = [$this->auth->id];
+			$yearAchievement = Achievement::getStaffYearAchievement($year);
+		} elseif ($type == 2) {//下属
+			$showStaffIds = Staff::getLowerStaffId();
+			$yearAchievement = Achievement::getTeamYearAchievement($year);
+		} elseif ($type == 3) {//公司
+			$showStaffIds = Staff::getLowerStaffId();
+			$yearAchievement = Achievement::getCompanyYearAchievement($year);
+		} else {//全部
+			$showStaffIds = Staff::getMyStaffIds();
+			$yearAchievement = Achievement::getTeamYearAchievement($year);
+		}
+        $contracts=ContractRatio::where([
+            'contract.check_status'=>2, 'contract_ratio.staff_id' => ['in',$showStaffIds],
+            'contract.order_date'=>['like', $year . '%']
+        ])->with(['contract'])->select();
+        $contracts=collection($contracts)->toArray();
+        $contractData=[];
+        foreach ($contracts as $v) {
+            $order_date = $v['contract']['order_date'];
+            $month = date('Y-m', strtotime($order_date));
+            $contractData[$month]['money'][] = $v['ratio_money'];
+            $contractData[$month]['contract_id'][] = $v['contract_id'];
+        }
+
+        $contracts_list  = [];
+        foreach ($contractData as $month=>$v) {
+            $contracts_list[$month] = ['money'=>array_sum($v['money']),'count'=>count($v['contract_id'])];
+        }
+
+		$data = [];
+		foreach ($yearAchievement as $k => $v) {
+			if ($month = Achievement::getFieldMonth($k)) {
+				$month             = $year . '-' . $month;
+				$row               = [
+					'month'       => $month,
+					'achievement' => $v,
+					'money'       => isset($contracts_list[$month]) ? $contracts_list[$month]['money'] : 0,
+					'count'       => isset($contracts_list[$month]) ? $contracts_list[$month]['count'] : 0,
+				];
+				$row['ratio']      = ($row['money'] && intval($row['achievement'])) ? sprintf("%.2f", $row['money'] / $row['achievement'] * 100) : 0;
+				$row['unit_price'] = ($row['money'] && $row['count']) ? sprintf("%.2f", $row['money'] / $row['count']) : 0;
+
+				$data[] = $row;
+			}
+		}
+
+		$this->success('请求成功', $data);
+	}
+
+
+    /**
+     * 回款数据排行
+     */
+	public function receivablesRanking() {
+		$year = input('year', date('Y'));
+		$type = input('type', 0);
+		if ($type == 1) {//本人
+			$showStaffIds = [$this->auth->id];
+		} elseif ($type == 2) {//下属
+			$showStaffIds = Staff::getLowerStaffId();
+		} else {//全部
+			$showStaffIds = Staff::getMyStaffIds();
+		}
+
+		$receivables = Receivables::where([
+			'check_status' => 2,
+			'return_time'  => ['like', $year . '%'],
+		])->group('owner_staff_id')->with(['staff'])->order('money desc')->field('owner_staff_id,sum(money) as money,count(*) as count')->select();
+
+		$receivablesData = [];
+		$list            = [];
+		$i=1;
+		foreach ($receivables as $k => $v) {
+			$v['ranking']               = $i;
+			if(in_array($v['owner_staff_id'],$showStaffIds)){
+                $i++;
+				$receivablesData[]          = $v;
+			}
+			$list[$v['owner_staff_id']] = $v['money'];
+		}
+
+		$contracts = $list;
+
+		$data   = [];
+		$staffs = Staff::getList();
+		foreach ($staffs as $v) {
+			if (isset($contracts[$v['id']])) {
+				$data[$v['id']] = $contracts[$v['id']];
+			} else {
+				$data[$v['id']] = 0;
+			}
+		}
+		arsort($data);
+		$staffs    = Staff::getKeyList();
+		$result    = [];
+		$i         = 1;
+		$oneNumber = 0;
+		foreach ($data as $id => $number) {
+			if ($i == 1) {
+				$oneNumber = $number;
+			}
+			$val           = $staffs[$id];
+			$val['number'] = $number;
+			$val['ratio']  = $oneNumber ? sprintf("%.2f", $number / $oneNumber * 100) : 0;
+			$val['rank']   = $i;
+			if(in_array($id,$showStaffIds)){
+				$result[]     = $val;
+                $i++;
+			}
+		}
+
+		if (count($result) >= 10) {
+
+			$top    = array_slice($result, 0, 3);
+			$bottom = array_slice($result, -3, 3);
+			$middle = array_slice($result, 3, 4);
+			$result = array_merge($top, $bottom, $middle);
+		}
+
+
+		$this->success('请求成功', ['ranking' => $result, 'data' => $receivablesData]);
+	}
+
+
+    /**
+     * 成交数据排行
+     */
+	public function contractMoneyRanking() {
+		$date = input('year', date('Y'));
+		$type = input('type', 0);
+		if ($type == 1) {//本人
+			$showStaffIds = [$this->auth->id];
+		} elseif ($type == 2) {//下属
+			$showStaffIds = Staff::getLowerStaffId();
+		} else {//全部
+			$showStaffIds = Staff::getMyStaffIds();
+		}
+        $contracts=ContractRatio::where([
+            'contract.check_status'=>2, 'contract_ratio.staff_id' => ['in',$showStaffIds],
+            'contract.order_date'=>['like', $date . '%']
+        ])->with(['contract','staff'])->select();
+        $contracts=collection($contracts)->toArray();
+        $contractData=[];
+        foreach ($contracts as $v) {
+            $contractData[$v['staff_id']]['money'][] = $v['ratio_money'];
+            $contractData[$v['staff_id']]['contract_id'][] = $v['contract_id'];
+            $contractData[$v['staff_id']]['staff'] = $v['staff'];
+            $contractData[$v['staff_id']]['staff_id'] = $v['staff_id'];
+        }
+
+        $receivables  = [];
+        foreach ($contractData as $v) {
+            $receivables[] = [
+                'money'=>array_sum($v['money']),
+                'count'=>count($v['contract_id']),
+                'staff'=>$v['staff'],
+                'owner_staff_id'=>$v['staff_id'],
+            ];
+        }
+        $this->arraySortByOneField($receivables,'money',SORT_DESC);
+		$receivablesData = [];
+		$list            = [];
+		foreach ($receivables as $k => $v) {
+			$v['ranking']               = $k + 1;
+			$v['unit_price']            = ($v['money'] && $v['count']) ? sprintf("%.2f", $v['money'] / $v['count']) : 0;
+			if(in_array($v['owner_staff_id'],$showStaffIds)){
+				$receivablesData[]          = $v;
+			}
+			$list[$v['owner_staff_id']] = $v['money'];
+		}
+
+		$contracts = $list;
+
+		$data   = [];
+		$staffs = Staff::getList();
+		foreach ($staffs as $v) {
+			if (isset($contracts[$v['id']])) {
+				$data[$v['id']] = $contracts[$v['id']];
+			} else {
+				$data[$v['id']] = 0;
+			}
+		}
+		arsort($data);
+		$staffs    = Staff::getKeyList();
+		$result    = [];
+		$i         = 1;
+		$oneNumber = 0;
+		foreach ($data as $id => $number) {
+			if ($i == 1) {
+				$oneNumber = $number;
+			}
+			$val           = $staffs[$id];
+			$val['number'] = $number;
+			$val['ratio']  = $oneNumber ? sprintf("%.2f", $number / $oneNumber * 100) : 0;
+			$val['rank']   = $i;
+			$i++;
+			if(in_array($id,$showStaffIds)){
+				$result[]     = $val;
+			}
+		}
+
+		if (count($result) >= 10) {
+
+			$top    = array_slice($result, 0, 3);
+			$bottom = array_slice($result, -3, 3);
+			$middle = array_slice($result, 3, 4);
+			$result = array_merge($top, $bottom, $middle);
+		}
+
+
+		$this->success('请求成功', ['ranking' => $result, 'data' => $receivablesData]);
+	}
+
+    /**
+     * 新增排行
+     */
+	public function newRanking() {
+		$year      = input('date', date('Y'));
+		$between   = [strtotime($year . '-01-01'), strtotime($year.'-1-1 +1 year')];
+        $betweenC   = [date('Y-m-d 00:00:00',strtotime($year . '-01-01')), date('Y-m-d 23:59:59',strtotime($year.'-1-1 +1 year'))];
+		$customers = Customer::where([
+			'createtime' => [
+				'between',
+				$between
+			],
+			'owner_staff_id' => $this->auth->id
+		])->group('month')->field("FROM_UNIXTIME(createtime,'%Y-%m') as month,count(*) as count")->select();
+
+		$customers_list = [];
+		foreach ($customers as $v) {
+			$customers_list[$v['month']] = $v['count'];
+		}
+		$contracts      = Contract::where([
+			'order_date' => [
+				'between',
+                $betweenC
+			],
+			'owner_staff_id' => $this->auth->id,
+            'check_status'=>2
+		])->group('month')->field('FROM_UNIXTIME(createtime,"%Y-%m") as month,count(*) as count')->select();
+
+		$contracts_list = [];
+		foreach ($contracts as $v) {
+			$contracts_list[$v['month']] = $v['count'];
+		}
+		$leads      = Leads::where([
+			'createtime' => [
+				'between',
+				$between
+			],
+			'owner_staff_id' => $this->auth->id
+		])->group('month')->field('FROM_UNIXTIME(createtime,"%Y-%m") as month,count(*) as count')->select();
+		$leads_list = [];
+		foreach ($leads as $v) {
+			$leads_list[$v['month']] = $v['count'];
+		}
+		$data = [];
+		for ($i = 1; $i <= 12; $i++) {
+			$month  = date('Y-m', strtotime($year . '-' . $i));
+			$data[] = [
+				'month'     => $month,
+				'customers' => $customers_list[$month] ?? 0,
+				'contracts' => $contracts_list[$month] ?? 0,
+				'leads'     => $leads_list[$month] ?? 0,
+			];
+		}
+
+		$this->success('请求成功', $data);
+	}
+
+    /**
+     * 获取团队新增统计
+     */
+	public function addCustomerStatistics() {
+		$date = input('date', date('Y-m'));
+		if(strlen($date) == 4){
+			$between = [strtotime($date . '-01-01'), strtotime($date.'-1-1 +1 year') - 1];
+		}else{
+			$between = [strtotime($date), strtotime('+1 month', strtotime($date)) - 1];
+		}
+
+
+		$ids     = Staff::getMyStaffIds();
+		$staffs  = Staff::where(['id' => ['in', $ids]])->field('id,name,post,img')->select();
+
+		$c         = Customer::where([
+			'createtime'      => [
+				'between',
+				$between
+			],
+			'owner_staff_id' => ['in', $ids]
+		])->group('owner_staff_id')->order('count desc')->field("owner_staff_id,count(*) as count")->select();
+		$customers = [];
+		foreach ($c as $v) {
+			$customers[$v['owner_staff_id']] = $v['count'];
+		}
+		$l     = Leads::where([
+			'createtime'      => [
+				'between',
+				$between
+			],
+			'owner_staff_id' => ['in', $ids]
+		])->group('owner_staff_id')->field("owner_staff_id,count(*) as count")->select();
+		$leads = [];
+		foreach ($l as $v) {
+			$leads[$v['owner_staff_id']] = $v['count'];
+		}
+		$t         = Contract::where([
+			'createtime'      => [
+				'between',
+				$between
+			],
+			'owner_staff_id' => ['in', $ids]
+		])->group('owner_staff_id')->field("owner_staff_id,count(*) as count")->select();
+		$contracts = [];
+		foreach ($t as $v) {
+			$contracts[$v['owner_staff_id']] = $v['count'];
+		}
+		$total=[];
+		$total[0]=[
+			'name'=>'数据汇总',
+			'id'=>0,
+			'leads'=>0,
+			'customers'=>0,
+			'contracts'=>0,
+		];
+		$sort=[];
+		foreach ($staffs as $k => $v) {
+
+			$v['leads']     = $leads[$v['id']] ?? 0;
+			$v['customers'] = $customers[$v['id']] ?? 0;
+			$v['contracts'] = $contracts[$v['id']] ?? 0;
+			$sort[$v['id']] = $v['leads'] + $v['customers'] + $v['contracts'];
+			$total[0]['leads'] += $v['leads'];
+			$total[0]['customers'] += $v['customers'];
+			$total[0]['contracts'] += $v['contracts'];
+			$staffs[$v['id']]     = $v;
+		}
+		arsort($sort);
+		$result=[];
+		foreach ($sort as $id=>$v){
+			$result[]=$staffs[$id];
+		}
+		$staffs=array_merge($total,$result);
+		$this->success('请求成功',$staffs);
+	}
+
+
+    /**
+     * 客户新增排行
+     */
+    public function newCustomer() {
+        $date = input('date', date('Y-m'));
+        $type = input('type', 0);
+
+        if(strlen($date) == 4){
+            $between = [strtotime($date . '-01-01'), strtotime($date.'-1-1 +1 year') - 1];
+        }else{
+            $between = [strtotime($date), strtotime('+1 month', strtotime($date)) - 1];
+        }
+        if ($type == 1) {//本人
+            $ids = [$this->auth->id];
+        } elseif ($type == 2) {//下属
+            $ids = Staff::getLowerStaffId();
+        } else {//全部
+            $ids = Staff::getMyStaffIds();
+        }
+        $c         = Customer::where([
+            'createtime'      => [
+                'between',
+                $between
+            ],
+            'owner_staff_id' => ['in', $ids]
+        ])->group('owner_staff_id')->order('count desc')->field("owner_staff_id,count(*) as count")->select();
+        $customers = [];
+        foreach ($c as $v) {
+            $customers[$v['owner_staff_id']] = $v['count'];
+        }
+
+        arsort($customers);
+        $staffs    = Staff::getKeyList();
+        $result    = [];
+        $i         = 1;
+        $data=[];
+        foreach ($customers as $id => $number) {
+            $val           = $staffs[$id];
+            $val['number'] = $number;
+            $val['rank']   = $i;
+            $data[]=[
+                'name'=>$val['name'],
+                'number'=>$number
+            ];
+            $i++;
+            $result[]     = $val;
+        }
+
+        $this->success('请求成功',['ranking' => $result, 'data' => $data]);
+    }
+
+    /**
+     * 客户跟进排行
+     */
+    public function newRecord() {
+        $date = input('date', date('Y-m'));
+        $type = input('type', 0);
+
+        if(strlen($date) == 4){
+            $between = [strtotime($date . '-01-01'), strtotime($date.'-1-1 +1 year') - 1];
+        }else{
+            $between = [strtotime($date), strtotime('+1 month', strtotime($date)) - 1];
+        }
+        if ($type == 1) {//本人
+            $ids = [$this->auth->id];
+        } elseif ($type == 2) {//下属
+            $ids = Staff::getLowerStaffId();
+        } else {//全部
+            $ids = Staff::getMyStaffIds();
+        }
+        //跟进次数
+        $r= Record::where([
+            'create_staff_id' => ['in',$ids],
+            'relation_type' =>1,
+            'createtime' => [
+                'between',
+                $between
+            ]
+        ])->field("create_staff_id,count(*) as count")->group('create_staff_id')->select();
+
+        $records = [];
+        foreach ($r as $v) {
+            $records[$v['create_staff_id']] = $v['count'];
+        }
+
+        arsort($records);
+        $staffs    = Staff::getKeyList();
+        $result    = [];
+        $data    = [];
+        $i         = 1;
+        foreach ($records as $id => $number) {
+            $val           = $staffs[$id];
+            $val['number'] = $number;
+            $val['rank']   = $i;
+            $data[]=[
+                'name'=>$val['name'],
+                'number'=>$number
+            ];
+            $i++;
+            $result[]     = $val;
+        }
+
+        $this->success('请求成功',['ranking' => $result, 'data' => $data]);
+    }
+
+    /**
+     * 获取业绩详情
+     */
+    public function getAchievementDetail()
+    {
+        $year = input('year', date('Y'));
+        $status = input('status', 1);
+        $staff_id = input('staff_id', '');
+        if (empty($staff_id)) {
+            $this->error('员工不能为空');
+        }
+
+        $ids = $staff_id;
+
+        $achievements = AchievementModel::where(['type' => 3, 'obj_id' => ['in', $ids], 'year' => $year, 'status' => $status])
+            ->field('sum(january) as january,sum(february) as february,sum(march) as march,sum(april) as april,sum(may) as may,sum(june) as june,sum(july) as july,sum(august) as august,sum(september) as september,sum(october) as october,sum(november) as november,sum(december) as december,sum(yeartarget) as yeartarget')->find()->toArray();
+        if ($status == 1) {//合同金额
+            $contracts = ContractRatio::where([
+                'contract.check_status' => 2, 'contract_ratio.staff_id' => ['in', $ids],
+                'contract.order_date' => ['like', $year . '%']
+            ])->with(['contract'])->select();
+            $contracts = collection($contracts)->toArray();
+            $contractData = [];
+            foreach ($contracts as $v) {
+                $order_date = $v['contract']['order_date'];
+                $month = date('Y-m', strtotime($order_date));
+                $contractData[$month]['money'][] = $v['ratio_money'];
+                $contractData[$month]['contract_id'][] = $v['contract_id'];
+            }
+
+            $list = [];
+            foreach ($contractData as $month => $v) {
+                $list[$month] = ['money' => array_sum($v['money']), 'count' => count($v['contract_id'])];
+            }
+        } else {
+            $receivables = Receivables::where([
+                'owner_staff_id' => ['in', $ids],
+                'check_status' => 2,
+                'return_time' => ['like', $year . '%'],
+            ])->group('month')
+                ->field('sum(money) as money,FROM_UNIXTIME(UNIX_TIMESTAMP(return_time),"%Y-%m") as month,count(*) as count')->select();
+            $list = [];
+            foreach ($receivables as $v) {
+                $list[$v['month']] = $v;
+            }
+        }
+        $data = [];
+        $echartdata = [];
+        foreach ($achievements as $k => $v) {
+            if ($month = AchievementModel::getFieldMonth($k)) {
+                $month = $year . '-' . $month;
+                $row = [
+                    'month' => $month,
+                    'achievement' => $v ?? 0,
+                    'money' => isset($list[$month]) ? $list[$month]['money'] : 0,
+                    'count' => isset($list[$month]) ? $list[$month]['count'] : 0,
+                ];
+                $row['ratio'] = ($row['money'] && intval($row['achievement'])) ? sprintf("%.2f", $row['money'] / $row['achievement'] * 100) : 0;
+                $row['unit_price'] = ($row['money'] && $row['count']) ? sprintf("%.2f", $row['money'] / $row['count']) : 0;
+
+                $echartdata['month'][] = $row['month'];
+                $echartdata['achievement'][] = $row['achievement']??0;
+                $echartdata['money'][] = $row['money'];
+                $data[] = $row;
+            }
+        }
+        $money = isset($echartdata['money']) ? array_sum($echartdata['money']) : 0;
+        $ratio = ($money && intval($achievements['yeartarget'])) ? sprintf("%.2f", $money / $achievements['yeartarget'] * 100) : 0;
+        $yeartarget = [
+            'year' => $year,
+            'money' => $money,
+            'achievement' => $achievements['yeartarget'] ?? 0,
+            'ratio' => $ratio
+        ];
+        $this->success('请求成功', ['data' => $data, 'echartdata' => $echartdata, 'yeartarget' => $yeartarget]);
+    }
+
+    /**
+     * 排序
+     * @param $data
+     * @param $field
+     * @param int $sort
+     * @return mixed
+     */
+    public function arraySortByOneField($data, $field, $sort = SORT_ASC)
+    {
+        $field = array_column($data, $field);
+        array_multisort($field, $sort, $data);
+        return $data;
+    }
+}

+ 55 - 0
addons/qingdong/controller/Wx.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace addons\qingdong\controller;
+
+use addons\qingdong\model\Staff;
+use addons\qingdong\model\AdminConfig;
+use think\Log;
+use WeWork\Crypt\WXBizMsgCrypt;
+
+/**
+ *  * 操作文档:https://doc.fastadmin.net/qingdong
+ * 软件介绍:https://www.fastadmin.net/store/qingdong.html
+ * 售后微信:qingdong_crm
+ * 企业微信接口
+ */
+class Wx extends StaffApi
+{
+    protected $noNeedLogin = ['userid','template','token'];
+    protected $noNeedRight = [];
+
+
+    public function _initialize()
+    {
+        parent::_initialize();
+    }
+
+    //验证
+    public function token()
+    {
+        $corpId = AdminConfig::getConfigValue('wechat', 'corpid');
+        $token = '';
+        $encodingAesKey = '';
+        Log::write('a---' . json_encode($_GET));
+
+        $sVerifyMsgSig = input('msg_signature');
+        $sVerifyTimeStamp = input('timestamp');
+        $sVerifyNonce = input('nonce');
+        $sVerifyEchoStr = input('echostr');
+
+        if (empty($sVerifyMsgSig) || empty($sVerifyTimeStamp) || empty($sVerifyNonce) || empty($sVerifyEchoStr)) {
+            $this->error('参数不正确');
+        }
+
+        $sEchoStr = "";
+        $wxcpt = new WXBizMsgCrypt($token, $encodingAesKey, $corpId);
+        $errCode = $wxcpt->VerifyURL($sVerifyMsgSig, $sVerifyTimeStamp, $sVerifyNonce, $sVerifyEchoStr, $sEchoStr);
+        if ($errCode == 0) {
+            return $sEchoStr;
+        } else {
+            return false;
+        }
+    }
+
+
+}

+ 68 - 0
addons/qingdong/controller/Wxbizdatacrypt.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace addons\qingdong\controller;
+/**
+ * 对微信小程序用户加密数据的解密示例代码.
+ *
+ * @copyright Copyright (c) 1998-2014 Tencent Inc.
+ */
+
+
+
+class Wxbizdatacrypt
+{
+    private $appid;
+	private $sessionKey;
+
+	/**
+	 * 构造函数
+	 * @param $sessionKey string 用户在小程序登录后获取的会话密钥
+	 * @param $appid string 小程序的appid
+	 */
+	public function __construct( $appid, $sessionKey)
+	{
+		$this->sessionKey = $sessionKey;
+		$this->appid = $appid;
+	}
+
+
+	/**
+	 * 检验数据的真实性,并且获取解密后的明文.
+	 * @param $encryptedData string 加密的用户数据
+	 * @param $iv string 与用户数据一同返回的初始向量
+	 * @param $data string 解密后的原文
+     *
+	 * @return int 成功0,失败返回对应的错误码
+	 */
+	public function decryptData( $encryptedData, $iv, &$data )
+	{
+		if (strlen($this->sessionKey) != 24) {
+			return ErrorCode::$IllegalAesKey;
+		}
+		$aesKey=base64_decode($this->sessionKey);
+
+        
+		if (strlen($iv) != 24) {
+			return ErrorCode::$IllegalIv;
+		}
+		$aesIV=base64_decode($iv);
+
+		$aesCipher=base64_decode($encryptedData);
+
+		$result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
+
+		$dataObj=json_decode( $result );
+		if( $dataObj  == NULL )
+		{
+			return ErrorCode::$IllegalBuffer;
+		}
+		if( $dataObj->watermark->appid != $this->appid )
+		{
+			return ErrorCode::$IllegalBuffer;
+		}
+		$data = $result;
+		return ErrorCode::$OK;
+	}
+
+}
+

+ 532 - 0
addons/qingdong/helper.php

@@ -0,0 +1,532 @@
+<?php
+
+
+// 公共助手函数
+
+use Symfony\Component\VarExporter\VarExporter;
+
+/**
+ * 求两个已知经纬度之间的距离,单位为米
+ * @param lng1 $ ,lng2 经度
+ * @param lat1 $ ,lat2 纬度
+ * @return float 距离,单位米
+ * @author www.Alixixi.com
+ */
+function getdistance($lng1, $lat1, $lng2, $lat2)
+{
+    // 将角度转为狐度
+    $radLat1 = deg2rad($lat1); //deg2rad()函数将角度转换为弧度
+    $radLat2 = deg2rad($lat2);
+    $radLng1 = deg2rad($lng1);
+    $radLng2 = deg2rad($lng2);
+    $a = $radLat1 - $radLat2;
+    $b = $radLng1 - $radLng2;
+    $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))) * 6378.137 * 1000;
+
+    return $s;
+}
+
+function float_number($number)
+{
+    $number = intval($number);
+    $length = strlen(intval($number));  //数字长度
+    if ($length > 3) { //万单位
+        //截取前俩为
+        $str = substr_replace(strstr($number, substr($number, -2), ' '), '.', -1, 0) . "公里";
+    } else {
+        return $number . '米';
+    }
+
+    return $str . '米';
+}
+
+function build_field_option($name = null, $selected = null,$type = null)
+{
+    //获取选项列表
+    $fields = \addons\qingdong\model\Field::getField($name,$type);
+    $html = '<option value="">请选择'.$name.'</option>';
+    foreach ($fields as $v) {
+        if ($selected == $v) {
+            $html .= "<option value='{$v}' selected='selected'>{$v}</option>";
+        } else {
+            $html .= "<option value='{$v}'>{$v}</option>";
+        }
+    }
+
+    return $html;
+}
+
+//修改多维数组为一位数组
+function modify_array($arr, $field1, $field2)
+{
+    $data = [];
+    foreach ($arr as $v) {
+        $data[$v[$field1] ?? ''] = $v[$field2] ?? '';
+    }
+
+    return $data;
+}
+
+//显示文件夹
+function showdir($path)
+{
+    $dh = opendir($path);//打开目录
+    $arr = [];
+    while (($d = readdir($dh)) != false) {
+        //逐个文件读取,添加!=false条件,是为避免有文件或目录的名称为0
+        if ($d == '.' || $d == '..') {//判断是否为.或..,默认都会有
+            continue;
+        }
+        if (is_dir($path . '/' . $d)) {//如果为目录
+            $lowers = showdir($path . '/' . $d);//继续读取该目录下的目录或文件
+            if ($lowers) {
+                $arr = array_merge($arr, $lowers);
+            }
+        } else {
+            $arr[] = $path . '/' . $d;
+        }
+    }
+
+    return $arr;
+}
+//获取年度列表
+function getYears(){
+
+    $start=2020;
+    $years=[];
+    $toYear=date('Y');
+    $end=date('Y')+1;
+    for ($start;$start<=$end;$start++){
+        if($start == $toYear){
+            $years[]=[
+                'id'=>$start,
+                'name'=>$start.'年',
+                'selected'=>'selected'
+            ];
+        }else{
+            $years[]=[
+                'id'=>$start,
+                'name'=>$start.'年',
+            ];
+        }
+    }
+    return $years;
+}
+
+///随机字符串,字母+数字
+function genRandomString($len,$t=0)
+{
+    $chars = array(
+        "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
+        "l", "m", "n", "p", "q", "r", "s", "t", "u", "v",
+        "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G",
+        "H", "I", "J", "K", "L", "M", "N", "P", "Q", "R",
+        "S", "T", "U", "V", "W", "X", "Y", "Z"
+    );
+
+    $chars1= array(
+        "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
+        "l", "m", "n", "p", "q", "r", "s", "t", "u", "v",
+        "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G",
+        "H", "I", "J", "K", "L", "M", "N", "P", "Q", "R",
+        "S", "T", "U", "V", "W", "X", "Y", "Z"
+    );
+
+    $chars2 = array(
+        "1", "2",
+        "3", "4", "5", "6", "7", "8", "9"
+    );
+    $chars3 = array(
+        "A", "B", "C", "D", "E", "F", "G", "O" ,
+        "H", "I", "J", "K", "L", "M", "N", "P", "Q", "R",
+        "S", "T", "U", "V", "W", "X", "Y", "Z"
+    );
+    $chars4 = array(
+        "A", "B", "C", "D", "E", "F", "G",
+        "H", "I", "J", "K", "L", "M", "N", "P", "Q", "R",
+        "S", "T", "U", "V", "W", "X", "Y", "Z", "1","2",
+        "3", "4", "5", "6", "7", "8", "9"
+    );
+
+    if($t==1){
+
+        $charsLen = count($chars1) - 1;
+
+        shuffle($chars1);    // 将数组打乱
+
+        $output = "";
+        for ($i=0; $i<$len; $i++)
+        {
+            $output .= $chars1[mt_rand(0, $charsLen)];
+        }
+
+    }elseif($t==2){
+
+        $charsLen = count($chars2) - 1;
+
+        shuffle($chars2);    // 将数组打乱
+
+        $output = "";
+        for ($i=0; $i<$len; $i++)
+        {
+            $output .= $chars2[mt_rand(0, $charsLen)];
+        }
+
+    }elseif($t==3){
+
+        $charsLen = count($chars3) - 1;
+
+        shuffle($chars3);    // 将数组打乱
+
+        $output = "";
+        for ($i=0; $i<$len; $i++)
+        {
+            $output .= $chars3[mt_rand(0, $charsLen)];
+        }
+
+    }elseif($t==4){
+
+        $charsLen = count($chars4) - 1;
+
+        shuffle($chars4);    // 将数组打乱
+
+        $output = "";
+        for ($i=0; $i<$len; $i++)
+        {
+            $output .= $chars4[mt_rand(0, $charsLen)];
+        }
+    }else{
+
+        $charsLen = count($chars) - 1;
+
+        shuffle($chars);    // 将数组打乱
+
+        $output = "";
+        for ($i=0; $i<$len; $i++)
+        {
+            $output .= $chars[mt_rand(0, $charsLen)];
+        }
+    }
+
+    return $output;
+
+}
+
+//将表情进行转义  用于存储的时候
+function emoji_encode($str){
+    if(!is_string($str)) return $str;
+
+    if(!$str || $str=='undefined') return '';
+
+
+
+    $text = json_encode($str); //暴露出unicode
+
+    $text = preg_replace_callback("/(\\\u[2def][0-9a-f]{3})/i",function($str){
+
+        return addslashes($str[0]);
+
+    },$text); //将emoji的unicode留下,其他不动,这里的正则比原答案增加了d,因为我发现我很多emoji实际上是\ud开头的,反而暂时没发现有\ue开头。
+
+    return json_decode($text);
+}
+//将表情进行反转义  用于读取的时候
+function emoji_decode($str){
+    $text = json_encode($str); //暴露出unicode
+
+    $text = preg_replace_callback('/\\\\\\\\/i',function($str){
+
+        return '\\';
+
+    },$text); //将两条斜杠变成一条,其他不动
+
+    return json_decode($text);
+}
+//过滤emoji
+function filter_Emoji($str)
+{
+    $str = preg_replace_callback(    //执行一个正则表达式搜索并且使用一个回调进行替换
+        '/./u',
+        function (array $match) {
+            return strlen($match[0]) >= 4 ? '' : $match[0];
+        },
+        $str);
+
+    return $str;
+}
+//获取编号
+function get_num($type)
+{
+    return 'R' . date('Ymd') . rand(10000, 99999);
+}
+
+
+if (!function_exists('setTimes')) {
+
+    /**
+     * @param $times
+     * @param string $type date|datetime|time
+     * @return array|string
+     */
+    function setTimes($times, $type = 'date')
+    {
+        switch ($times) {
+            case 'today':
+                $today = date('Y-m-d');
+                $todayend = date('Y-m-d');
+                $result = [$today, $todayend];
+                break;
+            case 'yesterday':
+                $yesterday = date('Y-m-d', strtotime('-1 day'));
+                $result = [$yesterday, $yesterday];
+                break;
+            case 'tomorrow':
+                $tomorrow = date('Y-m-d', strtotime('+1 day'));
+                $result = [$tomorrow, $tomorrow];
+                break;
+            case 'thisweek':
+                $thisweek_start = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d") - date("w") + 1, date("Y")));
+                $thisweek_end = date("Y-m-d", mktime(23, 59, 59, date("m"), date("d") - date("w") + 7, date("Y")));
+                $result = [$thisweek_start, $thisweek_end];
+                break;
+            case 'lastweek':
+                $lastweek_start = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d") - date("w") + 1 - 7, date("Y")));
+                $lastweek_end = date("Y-m-d", mktime(23, 59, 59, date("m"), date("d") - date("w") + 7 - 7, date("Y")));
+                $result = [$lastweek_start, $lastweek_end];
+                break;
+            case 'nextweek':
+                $lastweek_start = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d") - date("w") + 1 + 7, date("Y")));
+                $lastweek_end = date("Y-m-d", mktime(23, 59, 59, date("m"), date("d") - date("w") + 7 + 7, date("Y")));
+                $result = [$lastweek_start, $lastweek_end];
+                break;
+            case 'thismonth':
+                $thismonth_start = date("Y-m-d", mktime(0, 0, 0, date("m"), 1, date("Y")));
+                $thismonth_end = date("Y-m-d", mktime(23, 59, 59, date("m"), date("t"), date("Y")));
+                $result = [$thismonth_start, $thismonth_end];
+                break;
+            case 'lastmonth':
+                $lastmonth_start = date("Y-m-d", mktime(0, 0, 0, date("m") - 1, 1, date("Y")));
+                $lastmonth_end = date("Y-m-d", mktime(23, 59, 59, date("m"), 0, date("Y")));
+                $result = [$lastmonth_start, $lastmonth_end];
+                break;
+            case 'nextmonth':
+                $nextmonth_start = date("Y-m-d", mktime(0, 0, 0, date("m") + 1, 1, date("Y")));
+                $nextmonth_end = date("Y-m-d", mktime(23, 59, 59, date("m") + 1, date("t"), date("Y")));
+                $result = [$nextmonth_start, $nextmonth_end];
+                break;
+            case 'thisquarter':
+                //本季度未最后一月天数
+                $getMonthDays = date("t", mktime(0, 0, 0, date('n') + (date('n') - 1) % 3, 1, date("Y")));
+                //本季度/
+                $thisquarter_start = date('Y-m-d', mktime(0, 0, 0, date('n') - (date('n') - 1) % 3, 1, date('Y')));
+                $thisquarter_end = date('Y-m-d', mktime(23, 59, 59, date('n') + (date('n') - 1) % 3, $getMonthDays, date('Y')));
+
+                $result = [$thisquarter_start, $thisquarter_end];
+                break;
+            case 'lastquarter':
+                //上季度未最后一月天数
+                $getMonthDays = date("t", mktime(0, 0, 0, date('n') + (date('n') - 1) % 3 - 3, 1, date("Y")));
+                $thisquarter_start = date('Y-m-d', mktime(0, 0, 0, date('n') - (date('n') - 1) % 3 - 3, 1, date('Y')));
+                $thisquarter_end = date('Y-m-d', mktime(23, 59, 59, date('n') + (date('n') - 1) % 3 - 3, $getMonthDays, date('Y')));
+
+                $result = [$thisquarter_start, $thisquarter_end];
+                break;
+            case 'nextquarter':
+                //下季度未最后一月天数
+                $getMonthDays = date("t", mktime(0, 0, 0, date('n') + (date('n') - 1) % 3 + 3, 1, date("Y")));
+                $thisquarter_start = date('Y-m-d', mktime(0, 0, 0, date('n') - (date('n') - 1) % 3 + 3, 1, date('Y')));
+                $thisquarter_end = date('Y-m-d', mktime(23, 59, 59, date('n') + (date('n') - 1) % 3 + 3, $getMonthDays, date('Y')));
+
+                $result = [$thisquarter_start, $thisquarter_end];
+                break;
+            case 'thisyear':
+                //今年
+                $thisyear_start = date('Y') . '-1-1';
+                $thisquarter_end = date('Y') . '-12-31';
+
+                $result = [$thisyear_start, $thisquarter_end];
+                break;
+            case 'lastyear':
+                //去年
+                $lastyear_start = date('Y') . '-1-1';
+                $lastyear_end = date('Y') . '-12-31';
+
+                $result = [$lastyear_start, $lastyear_end];
+                break;
+            case 'nextyear':
+                //下一年
+                $nextyear_start = date('Y') . '-1-1';
+                $nextyear_end = date('Y') . '-12-31';
+
+                $result = [$nextyear_start, $nextyear_end];
+                break;
+            default:
+                $times = explode(',', $times);
+                $result = [$times[0] ?? date('Y-m-d'), $times[1] ?? date('Y-m-d')];
+                break;
+
+        }
+        if ($type == 'date') {
+            return $result;
+        } elseif ($type == 'datetime') {
+            $result[0] = date('Y-m-d H:i:s', strtotime($result[0]));
+            $result[1] = date('Y-m-d H:i:s', strtotime($result[1]) + 86400 - 1);
+            return $result;
+        } elseif ($type == 'time') {
+            $result[0] =strtotime($result[0]);
+            $result[1] =strtotime($result[1]) + 86400 - 1;
+            return $result;
+        } else {
+            return $result;
+        }
+    }
+
+}
+
+if (!function_exists('export_excel')){
+
+    //导出excel
+    function export_excel($title, $expTableData, $excel = 'export')
+    {
+
+        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
+        header('Content-Disposition: attachment;filename=' . $excel . '.xlsx');
+        header('Cache-Control: max-age=0');
+
+        $obj = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
+        // 以下内容是excel文件的信息描述信息
+        $obj->getProperties()->setTitle('导出文件'); //设置标题
+        $obj->setActiveSheetIndex(0);
+        $obj->getActiveSheet()->setTitle('导出文件');
+        /* 循环读取每个单元格的数据 */
+        $a = 'A';
+        $currentSheet = $obj->getActiveSheet();
+        foreach ($title as $key => $value) {
+            //读取工作表1
+
+            // 设置第一行加粗
+            $obj->getActiveSheet()->getStyle($a . '1')->getFont()->setBold(true);
+            //这里是设置单元格的内容
+            $currentSheet->getCell($a . '1')->setValue($value);
+            $a++;
+        }
+
+        //行数循环
+        $b = 2;
+        foreach ($expTableData as $k => $row) {
+            $a = 'A';
+            foreach ($row as $key => $value) {
+                //这里是设置单元格的内容
+                $currentSheet->getCell($a . $b)->setValue($value);
+                $a++;
+            }
+            $b++;
+        }
+
+        $PHPWriter = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($obj);
+        $fileName = $excel . date('YmdHis') . '.xlsx';
+
+        $file_path = ROOT_PATH . 'public' . '/export/' . date('Y-m-d') . '/' . $fileName;
+        // 创建文件夹
+        $path_info = pathinfo($file_path);
+        if ($path_info['dirname'] && !is_dir($path_info['dirname'])) {
+            $result = create_dir($path_info['dirname']);
+            if (false === $result) {
+                return false;
+            }
+        }
+        $PHPWriter->save($file_path);
+        $datas['filePath'] = '/' . 'export/' . date('Y-m-d') . '/' . $fileName;
+        $datas['fileName'] = $fileName;
+        $datas['size'] = filesize('./' . 'export/' . date('Y-m-d') . '/' . $fileName);
+        return $datas;
+    }
+}
+if (!function_exists('create_dir')){
+    /**
+     * 创建文件夹,可以多级创建
+     * @param string $filename 需要创建的文件夹路径
+     * @return boolean
+     */
+    function create_dir($filename) {
+        if (!is_dir($filename)) {
+            create_dir(dirname($filename));
+
+            return mkdir($filename, 0777);
+        }
+
+        return true;
+    }
+
+}
+
+if (!function_exists('convertAmountToCn')){
+
+    /**
+     * 将数值金额转换为中文大写金额
+     * @param $amount float 金额(支持到分)
+     * @param $type   int   补整类型,0:到角补整;1:到元补整
+     * @return mixed 中文大写金额
+     */
+    function convertAmountToCn($amount, $type = 1)
+    {
+
+        // 判断输出的金额是否为数字或数字字符串
+        if (!is_numeric($amount)) {
+            return "要转换的金额只能为数字!";
+        }
+        // 金额为0,则直接输出"零元整"
+
+        if ($amount == 0) {
+            return "人民币零元整";
+        }
+        // 金额不能为负数
+        if ($amount < 0) {
+            return "要转换的金额不能为负数!";
+        }
+        // 金额不能超过万亿,即12位
+        if (strlen($amount) > 12) {
+            return "要转换的金额不能为万亿及更高金额!";
+        }
+        // 预定义中文转换的数组
+        $digital = array('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖');
+        // 预定义单位转换的数组
+        $position = array('仟', '佰', '拾', '亿', '仟', '佰', '拾', '万', '仟', '佰', '拾', '元');
+        // 将金额的数值字符串拆分成数组
+        $amountArr = explode('.', $amount);
+        // 将整数位的数值字符串拆分成数组
+        $integerArr = str_split($amountArr[0], 1);
+        // 将整数部分替换成大写汉字
+        $result = '';
+        $integerArrLength = count($integerArr);     // 整数位数组的长度
+        $positionLength = count($position);         // 单位数组的长度
+        for ($i = 0; $i < $integerArrLength; $i++) {
+            // 如果数值不为0,则正常转换
+            if ($integerArr[$i] != 0) {
+                $result = $result . $digital[$integerArr[$i]] . $position[$positionLength - $integerArrLength + $i];
+            } else {
+                // 如果数值为0, 且单位是亿,万,元这三个的时候,则直接显示单位
+                if (($positionLength - $integerArrLength + $i + 1) % 4 == 0) {
+                    $result = $result . $position[$positionLength - $integerArrLength + $i];
+                }
+            }
+        }
+        // 如果小数位也要转换
+        if ($type == 0) {
+            // 将小数位的数值字符串拆分成数组
+            $decimalArr = str_split($amountArr[1], 1);
+            // 将角替换成大写汉字. 如果为0,则不替换
+            if ($decimalArr[0] != 0) {
+                $result = $result . $digital[$decimalArr[0]] . '角';
+            }
+            // 将分替换成大写汉字. 如果为0,则不替换
+            if ($decimalArr[1] != 0) {
+                $result = $result . $digital[$decimalArr[1]] . '分';
+            }
+        } else {
+            $result = $result . '整';
+        }
+        return $result;
+    }
+
+}

+ 10 - 0
addons/qingdong/info.ini

@@ -0,0 +1,10 @@
+name = qingdong
+title = 青动CRM
+intro = 青动CRM客户关系管理系统
+author = qingdong
+website = www.qdsd.vip
+version = 3.2.2
+state = 1
+url = /addons/qingdong
+license = extended
+licenseto = 81266

文件差異過大導致無法顯示
+ 1268 - 0
addons/qingdong/install.sql


+ 3 - 0
addons/qingdong/lang/zh-cn.php

@@ -0,0 +1,3 @@
+<?php
+
+return [];

+ 38 - 0
addons/qingdong/lang/zh-cn/staff.php

@@ -0,0 +1,38 @@
+<?php
+
+return [
+    'User center'                           => '会员中心',
+    'Register'                              => '注册',
+    'Login'                                 => '登录',
+    'Sign up successful'                    => '注册成功',
+    'Username can not be empty'             => '用户名不能为空',
+    'Username must be 6 to 30 characters'   => '用户名必须6-30个字符',
+    'Password can not be empty'             => '密码不能为空',
+    'Password must be 6 to 30 characters'   => '密码必须6-30个字符',
+    'Mobile is incorrect'                   => '手机格式不正确',
+    'Username already exist'                => '用户名已经存在',
+    'Nickname already exist'                => '昵称已经存在',
+    'Email already exist'                   => '邮箱已经存在',
+    'Mobile already exist'                  => '手机号已经存在',
+    'Username is incorrect'                 => '用户名不正确',
+    'Email is incorrect'                    => '邮箱不正确',
+    'Account is locked'                     => '账户已经被锁定',
+    'Password is incorrect'                 => '密码不正确',
+    'Account is incorrect'                  => '账户不正确',
+    'Account not exist'                     => '账户不存在',
+    'Account can not be empty'              => '账户不能为空',
+    'Username or password is incorrect'     => '用户名或密码不正确',
+    'You are not logged in'                 => '你当前还未登录',
+    'You\'ve logged in, do not login again' => '你已经存在,请不要重复登录',
+    'Profile'                               => '个人资料',
+    'Verify email'                          => '邮箱验证',
+    'Change password'                       => '修改密码',
+    'Captcha is incorrect'                  => '验证码不正确',
+    'Logged in successful'                  => '登录成功',
+    'Logout successful'                     => '退出成功',
+    'Operation failed'                      => '操作失败',
+    'Invalid parameters'                    => '参数不正确',
+    'Change password failure'               => '修改密码失败',
+    'Change password successful'            => '修改密码成功',
+    'Reset password successful'             => '重置密码成功',
+];

+ 100 - 0
addons/qingdong/library/Ding.php

@@ -0,0 +1,100 @@
+<?php
+
+namespace  addons\qingdong\library;
+
+use dingding\TopSdk;
+use think\Cache;
+use think\Log;
+use think\Model;
+use addons\qingdong\model\AdminConfig;
+
+/**
+ *
+ */
+class Ding extends Model
+{
+    public $config;
+    protected $app;
+
+
+    public function __construct()
+    {
+        $this->config = [
+        ];
+        $sdk=new TopSdk();
+        return parent::__construct();
+    }
+
+    //获取accessToken
+    public function getAccessToken()
+    {
+        $config = AdminConfig::where(array('type'=>'dingding'))->find();
+        $tokenRequest = new \OapiGettokenRequest();
+        $this->app = new \DingTalkClient(\DingTalkConstant::$CALL_TYPE_OAPI, \DingTalkConstant::$METHOD_GET, \DingTalkConstant::$FORMAT_JSON);
+        $accessKey = AdminConfig::where(array('type'=>'dingding','field'=>'ding_key'))->value('value');
+        $accessSecret = AdminConfig::where(array('type'=>'dingding','field'=>'ding_secret'))->value('value');
+        $tokenRequest->setAppkey($accessKey);
+        $tokenRequest->setAppsecret($accessSecret);
+       $token= $this->app->execute($tokenRequest, null, "https://oapi.dingtalk.com/gettoken");
+        return $token;
+    }
+    //获取部门
+    public function departmentInfo($access_token=null,$dept_id=null){
+        $this->app = new \DingTalkClient(\DingTalkConstant::$CALL_TYPE_OAPI, \DingTalkConstant::$METHOD_POST , \DingTalkConstant::$FORMAT_JSON);
+        $req = new \OapiV2DepartmentListsubRequest();
+        if($dept_id){
+            $req->setDeptId($dept_id);
+        }
+        $resp = $this->app->execute($req, $access_token, "https://oapi.dingtalk.com/topapi/v2/department/listsub");
+        return $resp;
+    }
+    //获取员工
+    public function staffInfo($access_token=null,$dept_id=null){
+        $this->app = new \DingTalkClient(\DingTalkConstant::$CALL_TYPE_OAPI, \DingTalkConstant::$METHOD_POST , \DingTalkConstant::$FORMAT_JSON);
+        $req = new \OapiUserListsimpleRequest();
+        $req->setDeptId($dept_id);
+        $req->setCursor("0");
+        $req->setSize("80");
+        $resp = $this->app->execute($req, $access_token, "https://oapi.dingtalk.com/topapi/user/listsimple");
+        return $resp;
+    }
+    //获取员工详情
+    public function staffInfoDetail($access_token=null,$user_id=null){
+        $this->app = new \DingTalkClient(\DingTalkConstant::$CALL_TYPE_OAPI, \DingTalkConstant::$METHOD_POST , \DingTalkConstant::$FORMAT_JSON);
+        $req = new \OapiV2UserGetRequest();
+        $req->setUserid($user_id);
+        $resp = $this->app->execute($req, $access_token, "https://oapi.dingtalk.com/topapi/v2/user/get");
+        return $resp;
+    }
+    //批量获取客户
+    public function customerBatch($access_token=null,$user_id=null,$staft =0,$end=300){
+        $this->app = new \DingTalkClient(\DingTalkConstant::$CALL_TYPE_OAPI, \DingTalkConstant::$METHOD_POST , \DingTalkConstant::$FORMAT_JSON);
+        $req = new \OapiCrmObjectdataCustomerQueryRequest();
+        $req->setCurrentOperatorUserid($user_id);
+        $req->setCursor($staft);
+        $req->setPageSize($end);
+        $resp = $this->app->execute($req, $access_token, "https://oapi.dingtalk.com/topapi/crm/objectdata/customer/query");
+        return $resp;
+    }
+    //批量获取联系人
+    public function contactsBatch($access_token=null,$user_id=null,$staft =0,$end=300){
+        $this->app = new \DingTalkClient(\DingTalkConstant::$CALL_TYPE_OAPI, \DingTalkConstant::$METHOD_POST , \DingTalkConstant::$FORMAT_JSON);
+        $req = new \OapiCrmObjectdataCustomerQueryRequest();
+        $req->setCurrentOperatorUserid($user_id);
+        $req->setCursor($staft);
+        $req->setPageSize($end);
+        $resp = $this->app->execute($req, $access_token, "https://oapi.dingtalk.com/topapi/crm/objectdata/contact/query");
+        return $resp;
+    }
+    //批量获取跟进记录
+    public function recordBatch($access_token=null,$user_id=null,$staft =0,$end=300){
+        $this->app = new \DingTalkClient(\DingTalkConstant::$CALL_TYPE_OAPI, \DingTalkConstant::$METHOD_POST , \DingTalkConstant::$FORMAT_JSON);
+        $req = new \OapiCrmObjectdataCustomerQueryRequest();
+        $req->setCurrentOperatorUserid($user_id);
+        $req->setCursor($staft);
+        $req->setPageSize($end);
+        $resp = $this->app->execute($req, $access_token, "https://oapi.dingtalk.com/topapi/crm/objectdata/followrecord/query");
+        return $resp;
+    }
+}
+

+ 113 - 0
addons/qingdong/library/Ku.php

@@ -0,0 +1,113 @@
+<?php
+
+namespace  addons\qingdong\library;
+
+use addons\qingdong\model\AdminConfig;
+use addons\qingdong\model\Contacts;
+use addons\qingdong\model\Customer;
+use addons\qingdong\model\KuCustomer;
+use think\Model;
+use fast\Http;
+
+/**
+ *
+ */
+class Ku extends Model
+{
+
+    //客户增加
+    public function addCustomer($params=null){
+        $ku = AdminConfig::where(['type'=>AdminConfig::TYPE_KU])->column('field,value');
+        if(isset($ku) && $ku && $params){
+            if($ku['status'] == 1 && $ku['account'] && $ku['key']){
+                $info = KuCustomer::where(array('customer_id'=>$params['customer_id']))->find();
+                if($info){
+                    return true;
+                }
+                $customer = Customer::where(array('id'=>$params['customer_id']))->find();
+                $url =$ku['url'].'api/kuerp/third/customers/joinCustomers';
+                $sign = md5('account='.$ku['account'].'&mobile='.$params['mobile'].'&name='.$customer['name'].'key='.$ku['key']);
+                $data = array(
+                    'account'=>$ku['account'],
+                    'sign'=>$sign,
+                    'request_time'=>time(),
+                    'name'=>$customer['name'],
+                    'mobile'=>$params['mobile'],
+                    'address'=>$customer['address'],
+                    'note'=>$customer['remarks'],
+                );
+                $result = $this->http_post($url,$data);
+                $result = json_decode($result,true);
+                if($result['code'] == 1){
+                    $ress = array(
+                        'customer_id'=>$params['customer_id'],
+                        'contacts_id'=>$params['contacts_id'],
+                        'ku_id'=>$result['data']['id'],
+                        'code'=>$result['data']['customer_code'],
+                        'createtime'=>time()
+                    );
+                    KuCustomer::create($ress);
+                }
+            }
+        }
+        return true;
+    }
+    //客户修改
+    public function editCustomer($params=null){
+
+        $ku = AdminConfig::where(['type'=>AdminConfig::TYPE_KU])->column('field,value');
+        if(isset($ku) && $ku && $params){
+            if($ku['status'] == 1 && $ku['account'] && $ku['key']){
+                $info = KuCustomer::where(array('customer_id'=>$params['id']))->find();
+                if(!$info){
+                    return true;
+                }
+                $contacts = Contacts::where(array('id'=>$info['contacts_id']))->value('mobile');
+                $url =$ku['url'].'api/kuerp/third/customers/editCustomers';
+                $sign = md5('account='.$ku['account'].'&code='.$info['code'].'&mobile='.$contacts.'&name='.$params['name'].'key='.$ku['key']);
+                $data = array(
+                    'account'=>$ku['account'],
+                    'sign'=>$sign,
+                    'request_time'=>time(),
+                    'code'=>$info['code'],
+                    'name'=>$params['name'],
+                    'mobile'=>$contacts,
+                    'address'=>$params['address'],
+                );
+                $result = $this->http_post($url,$data);
+                $result = json_decode($result,true);
+            }
+        }
+        return true;
+    }
+    public function http_post($url,$param,$post_file=false){
+        $oCurl = curl_init();
+        if(stripos($url,"https://")!==FALSE){
+            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
+            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
+            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
+        }
+        if (is_string($param) || $post_file) {
+            $strPOST = $param;
+        } else {
+            $aPOST = array();
+            foreach($param as $key=>$val){
+                $aPOST[] = $key."=".urlencode($val);
+            }
+            $strPOST =  join("&", $aPOST);
+        }
+        curl_setopt($oCurl, CURLOPT_URL, $url);
+        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
+        curl_setopt($oCurl, CURLOPT_POST,true);
+        curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST);
+        $sContent = curl_exec($oCurl);
+        $aStatus = curl_getinfo($oCurl);
+        curl_close($oCurl);
+        if(intval($aStatus["http_code"])==200){
+            return $sContent;
+        }else{
+            return false;
+        }
+    }
+
+}

+ 95 - 0
addons/qingdong/library/PhpWord/Collection/AbstractCollection.php

@@ -0,0 +1,95 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Collection;
+
+/**
+ * Collection abstract class
+ *
+ * @since 0.10.0
+ */
+abstract class AbstractCollection
+{
+    /**
+     * Items
+     *
+     * @var \PhpOffice\PhpWord\Element\AbstractContainer[]
+     */
+    private $items = array();
+
+    /**
+     * Get items
+     *
+     * @return \PhpOffice\PhpWord\Element\AbstractContainer[]
+     */
+    public function getItems()
+    {
+        return $this->items;
+    }
+
+    /**
+     * Get item by index
+     *
+     * @param int $index
+     * @return \PhpOffice\PhpWord\Element\AbstractContainer
+     */
+    public function getItem($index)
+    {
+        if (array_key_exists($index, $this->items)) {
+            return $this->items[$index];
+        }
+
+        return null;
+    }
+
+    /**
+     * Set item.
+     *
+     * @param int $index
+     * @param \PhpOffice\PhpWord\Element\AbstractContainer $item
+     */
+    public function setItem($index, $item)
+    {
+        if (array_key_exists($index, $this->items)) {
+            $this->items[$index] = $item;
+        }
+    }
+
+    /**
+     * Add new item
+     *
+     * @param \PhpOffice\PhpWord\Element\AbstractContainer $item
+     * @return int
+     */
+    public function addItem($item)
+    {
+        $index = $this->countItems() + 1;
+        $this->items[$index] = $item;
+
+        return $index;
+    }
+
+    /**
+     * Get item count
+     *
+     * @return int
+     */
+    public function countItems()
+    {
+        return count($this->items);
+    }
+}

+ 27 - 0
addons/qingdong/library/PhpWord/Collection/Bookmarks.php

@@ -0,0 +1,27 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Collection;
+
+/**
+ * Bookmarks collection
+ *
+ * @since 0.12.0
+ */
+class Bookmarks extends AbstractCollection
+{
+}

+ 27 - 0
addons/qingdong/library/PhpWord/Collection/Charts.php

@@ -0,0 +1,27 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Collection;
+
+/**
+ * Charts collection
+ *
+ * @since 0.12.0
+ */
+class Charts extends AbstractCollection
+{
+}

+ 27 - 0
addons/qingdong/library/PhpWord/Collection/Comments.php

@@ -0,0 +1,27 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Collection;
+
+/**
+ * Comments collection
+ *
+ * @since 0.12.0
+ */
+class Comments extends AbstractCollection
+{
+}

+ 27 - 0
addons/qingdong/library/PhpWord/Collection/Endnotes.php

@@ -0,0 +1,27 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Collection;
+
+/**
+ * Endnotes collection
+ *
+ * @since 0.10.0
+ */
+class Endnotes extends AbstractCollection
+{
+}

+ 27 - 0
addons/qingdong/library/PhpWord/Collection/Footnotes.php

@@ -0,0 +1,27 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Collection;
+
+/**
+ * Footnotes collection
+ *
+ * @since 0.10.0
+ */
+class Footnotes extends AbstractCollection
+{
+}

+ 27 - 0
addons/qingdong/library/PhpWord/Collection/Titles.php

@@ -0,0 +1,27 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Collection;
+
+/**
+ * Titles collection
+ *
+ * @since 0.10.0
+ */
+class Titles extends AbstractCollection
+{
+}

+ 181 - 0
addons/qingdong/library/PhpWord/ComplexType/FootnoteProperties.php

@@ -0,0 +1,181 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\ComplexType;
+
+use PhpOffice\PhpWord\SimpleType\NumberFormat;
+
+/**
+ * Footnote properties
+ *
+ * @see http://www.datypic.com/sc/ooxml/e-w_footnotePr-1.html
+ */
+final class FootnoteProperties
+{
+    const RESTART_NUMBER_CONTINUOUS = 'continuous';
+    const RESTART_NUMBER_EACH_SECTION = 'eachSect';
+    const RESTART_NUMBER_EACH_PAGE = 'eachPage';
+
+    const POSITION_PAGE_BOTTOM = 'pageBottom';
+    const POSITION_BENEATH_TEXT = 'beneathText';
+    const POSITION_SECTION_END = 'sectEnd';
+    const POSITION_DOC_END = 'docEnd';
+
+    /**
+     * Footnote Positioning Location
+     *
+     * @var string
+     */
+    private $pos;
+
+    /**
+     * Footnote Numbering Format w:numFmt, one of PhpOffice\PhpWord\SimpleType\NumberFormat
+     *
+     * @var string
+     */
+    private $numFmt;
+
+    /**
+     * Footnote and Endnote Numbering Starting Value
+     *
+     * @var float
+     */
+    private $numStart;
+
+    /**
+     * Footnote and Endnote Numbering Restart Location
+     *
+     * @var string
+     */
+    private $numRestart;
+
+    /**
+     * Get the Footnote Positioning Location
+     *
+     * @return string
+     */
+    public function getPos()
+    {
+        return $this->pos;
+    }
+
+    /**
+     * Set the Footnote Positioning Location (pageBottom, beneathText, sectEnd, docEnd)
+     *
+     * @param string $pos
+     * @throws \InvalidArgumentException
+     * @return self
+     */
+    public function setPos($pos)
+    {
+        $position = array(
+            self::POSITION_PAGE_BOTTOM,
+            self::POSITION_BENEATH_TEXT,
+            self::POSITION_SECTION_END,
+            self::POSITION_DOC_END,
+        );
+
+        if (in_array($pos, $position)) {
+            $this->pos = $pos;
+        } else {
+            throw new \InvalidArgumentException('Invalid value, on of ' . implode(', ', $position) . ' possible');
+        }
+
+        return $this;
+    }
+
+    /**
+     * Get the Footnote Numbering Format
+     *
+     * @return string
+     */
+    public function getNumFmt()
+    {
+        return $this->numFmt;
+    }
+
+    /**
+     * Set the Footnote Numbering Format
+     *
+     * @param string $numFmt One of NumberFormat
+     * @return self
+     */
+    public function setNumFmt($numFmt)
+    {
+        NumberFormat::validate($numFmt);
+        $this->numFmt = $numFmt;
+
+        return $this;
+    }
+
+    /**
+     * Get the Footnote Numbering Format
+     *
+     * @return float
+     */
+    public function getNumStart()
+    {
+        return $this->numStart;
+    }
+
+    /**
+     * Set the Footnote Numbering Format
+     *
+     * @param float $numStart
+     * @return self
+     */
+    public function setNumStart($numStart)
+    {
+        $this->numStart = $numStart;
+
+        return $this;
+    }
+
+    /**
+     * Get the Footnote and Endnote Numbering Starting Value
+     *
+     * @return string
+     */
+    public function getNumRestart()
+    {
+        return $this->numRestart;
+    }
+
+    /**
+     * Set the Footnote and Endnote Numbering Starting Value (continuous, eachSect, eachPage)
+     *
+     * @param  string $numRestart
+     * @throws \InvalidArgumentException
+     * @return self
+     */
+    public function setNumRestart($numRestart)
+    {
+        $restartNumbers = array(
+            self::RESTART_NUMBER_CONTINUOUS,
+            self::RESTART_NUMBER_EACH_SECTION,
+            self::RESTART_NUMBER_EACH_PAGE,
+        );
+
+        if (in_array($numRestart, $restartNumbers)) {
+            $this->numRestart = $numRestart;
+        } else {
+            throw new \InvalidArgumentException('Invalid value, on of ' . implode(', ', $restartNumbers) . ' possible');
+        }
+
+        return $this;
+    }
+}

+ 106 - 0
addons/qingdong/library/PhpWord/ComplexType/ProofState.php

@@ -0,0 +1,106 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\ComplexType;
+
+/**
+ * Spelling and Grammatical Checking State
+ *
+ * @see http://www.datypic.com/sc/ooxml/e-w_proofState-1.html
+ */
+final class ProofState
+{
+    /**
+     * Check Completed
+     */
+    const CLEAN = 'clean';
+
+    /**
+     * Check Not Completed
+     */
+    const DIRTY = 'dirty';
+
+    /**
+     * Spell Checking State
+     *
+     * @var string
+     */
+    private $spelling;
+
+    /**
+     * Grammatical Checking State
+     *
+     * @var string
+     */
+    private $grammar;
+
+    /**
+     * Set the Spell Checking State (dirty or clean)
+     *
+     * @param string $spelling
+     * @throws \InvalidArgumentException
+     * @return self
+     */
+    public function setSpelling($spelling)
+    {
+        if ($spelling == self::CLEAN || $spelling == self::DIRTY) {
+            $this->spelling = $spelling;
+        } else {
+            throw new \InvalidArgumentException('Invalid value, dirty or clean possible');
+        }
+
+        return $this;
+    }
+
+    /**
+     * Get the Spell Checking State
+     *
+     * @return string
+     */
+    public function getSpelling()
+    {
+        return $this->spelling;
+    }
+
+    /**
+     * Set the Grammatical Checking State (dirty or clean)
+     *
+     * @param string $grammar
+     * @throws \InvalidArgumentException
+     * @return self
+     */
+    public function setGrammar($grammar)
+    {
+        if ($grammar == self::CLEAN || $grammar == self::DIRTY) {
+            $this->grammar = $grammar;
+        } else {
+            throw new \InvalidArgumentException('Invalid value, dirty or clean possible');
+        }
+
+        return $this;
+    }
+
+    /**
+     * Get the Grammatical Checking State
+     *
+     * @return string
+     */
+    public function getGrammar()
+    {
+        return $this->grammar;
+    }
+}

+ 59 - 0
addons/qingdong/library/PhpWord/ComplexType/TblWidth.php

@@ -0,0 +1,59 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\ComplexType;
+
+use PhpOffice\PhpWord\SimpleType\TblWidth as TblWidthSimpleType;
+
+/**
+ * @see http://www.datypic.com/sc/ooxml/t-w_CT_TblWidth.html
+ */
+final class TblWidth
+{
+    /** @var string */
+    private $type;
+
+    /** @var int */
+    private $value;
+
+    /**
+     * @param int $value If omitted, then its value shall be assumed to be 0
+     * @param string $type If omitted, then its value shall be assumed to be dxa
+     */
+    public function __construct($value = 0, $type = TblWidthSimpleType::TWIP)
+    {
+        $this->value = $value;
+        TblWidthSimpleType::validate($type);
+        $this->type = $type;
+    }
+
+    /**
+     * @return string
+     */
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    /**
+     * @return int
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+}

+ 166 - 0
addons/qingdong/library/PhpWord/ComplexType/TrackChangesView.php

@@ -0,0 +1,166 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\ComplexType;
+
+/**
+ * Visibility of Annotation Types
+ *
+ * @see http://www.datypic.com/sc/ooxml/e-w_revisionView-1.html
+ */
+final class TrackChangesView
+{
+    /**
+     * Display Visual Indicator Of Markup Area
+     *
+     * @var bool
+     */
+    private $markup;
+
+    /**
+     * Display Comments
+     *
+     * @var bool
+     */
+    private $comments;
+
+    /**
+     * Display Content Revisions
+     *
+     * @var bool
+     */
+    private $insDel;
+
+    /**
+     * Display Formatting Revisions
+     *
+     * @var bool
+     */
+    private $formatting;
+
+    /**
+     * Display Ink Annotations
+     *
+     * @var bool
+     */
+    private $inkAnnotations;
+
+    /**
+     * Get Display Visual Indicator Of Markup Area
+     *
+     * @return bool True if markup is shown
+     */
+    public function hasMarkup()
+    {
+        return $this->markup;
+    }
+
+    /**
+     * Set Display Visual Indicator Of Markup Area
+     *
+     * @param bool $markup
+     *            Set to true to show markup
+     */
+    public function setMarkup($markup)
+    {
+        $this->markup = $markup === null ? true : $markup;
+    }
+
+    /**
+     * Get Display Comments
+     *
+     * @return bool True if comments are shown
+     */
+    public function hasComments()
+    {
+        return $this->comments;
+    }
+
+    /**
+     * Set Display Comments
+     *
+     * @param bool $comments
+     *            Set to true to show comments
+     */
+    public function setComments($comments)
+    {
+        $this->comments = $comments === null ? true : $comments;
+    }
+
+    /**
+     * Get Display Content Revisions
+     *
+     * @return bool True if content revisions are shown
+     */
+    public function hasInsDel()
+    {
+        return $this->insDel;
+    }
+
+    /**
+     * Set Display Content Revisions
+     *
+     * @param bool $insDel
+     *            Set to true to show content revisions
+     */
+    public function setInsDel($insDel)
+    {
+        $this->insDel = $insDel === null ? true : $insDel;
+    }
+
+    /**
+     * Get Display Formatting Revisions
+     *
+     * @return bool True if formatting revisions are shown
+     */
+    public function hasFormatting()
+    {
+        return $this->formatting;
+    }
+
+    /**
+     * Set Display Formatting Revisions
+     *
+     * @param bool|null $formatting
+     *            Set to true to show formatting revisions
+     */
+    public function setFormatting($formatting = null)
+    {
+        $this->formatting = $formatting === null ? true : $formatting;
+    }
+
+    /**
+     * Get Display Ink Annotations
+     *
+     * @return bool True if ink annotations are shown
+     */
+    public function hasInkAnnotations()
+    {
+        return $this->inkAnnotations;
+    }
+
+    /**
+     * Set Display Ink Annotations
+     *
+     * @param bool $inkAnnotations
+     *            Set to true to show ink annotations
+     */
+    public function setInkAnnotations($inkAnnotations)
+    {
+        $this->inkAnnotations = $inkAnnotations === null ? true : $inkAnnotations;
+    }
+}

+ 316 - 0
addons/qingdong/library/PhpWord/Element/AbstractContainer.php

@@ -0,0 +1,316 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+/**
+ * Container abstract class
+ *
+ * @method Text addText(string $text, mixed $fStyle = null, mixed $pStyle = null)
+ * @method TextRun addTextRun(mixed $pStyle = null)
+ * @method Bookmark addBookmark(string $name)
+ * @method Link addLink(string $target, string $text = null, mixed $fStyle = null, mixed $pStyle = null, boolean $internal = false)
+ * @method PreserveText addPreserveText(string $text, mixed $fStyle = null, mixed $pStyle = null)
+ * @method void addTextBreak(int $count = 1, mixed $fStyle = null, mixed $pStyle = null)
+ * @method ListItem addListItem(string $txt, int $depth = 0, mixed $font = null, mixed $list = null, mixed $para = null)
+ * @method ListItemRun addListItemRun(int $depth = 0, mixed $listStyle = null, mixed $pStyle = null)
+ * @method Footnote addFootnote(mixed $pStyle = null)
+ * @method Endnote addEndnote(mixed $pStyle = null)
+ * @method CheckBox addCheckBox(string $name, $text, mixed $fStyle = null, mixed $pStyle = null)
+ * @method Title addTitle(mixed $text, int $depth = 1)
+ * @method TOC addTOC(mixed $fontStyle = null, mixed $tocStyle = null, int $minDepth = 1, int $maxDepth = 9)
+ * @method PageBreak addPageBreak()
+ * @method Table addTable(mixed $style = null)
+ * @method Image addImage(string $source, mixed $style = null, bool $isWatermark = false, $name = null)
+ * @method OLEObject addOLEObject(string $source, mixed $style = null)
+ * @method TextBox addTextBox(mixed $style = null)
+ * @method Field addField(string $type = null, array $properties = array(), array $options = array(), mixed $text = null)
+ * @method Line addLine(mixed $lineStyle = null)
+ * @method Shape addShape(string $type, mixed $style = null)
+ * @method Chart addChart(string $type, array $categories, array $values, array $style = null, $seriesName = null)
+ * @method FormField addFormField(string $type, mixed $fStyle = null, mixed $pStyle = null)
+ * @method SDT addSDT(string $type)
+ *
+ * @method \PhpOffice\PhpWord\Element\OLEObject addObject(string $source, mixed $style = null) deprecated, use addOLEObject instead
+ *
+ * @since 0.10.0
+ */
+abstract class AbstractContainer extends AbstractElement
+{
+    /**
+     * Elements collection
+     *
+     * @var \PhpOffice\PhpWord\Element\AbstractElement[]
+     */
+    protected $elements = array();
+
+    /**
+     * Container type Section|Header|Footer|Footnote|Endnote|Cell|TextRun|TextBox|ListItemRun|TrackChange
+     *
+     * @var string
+     */
+    protected $container;
+
+    /**
+     * Magic method to catch all 'addElement' variation
+     *
+     * This removes addText, addTextRun, etc. When adding new element, we have to
+     * add the model in the class docblock with `@method`.
+     *
+     * Warning: This makes capitalization matters, e.g. addCheckbox or addcheckbox won't work.
+     *
+     * @param mixed $function
+     * @param mixed $args
+     * @return \PhpOffice\PhpWord\Element\AbstractElement
+     */
+    public function __call($function, $args)
+    {
+        $elements = array(
+            'Text', 'TextRun', 'Bookmark', 'Link', 'PreserveText', 'TextBreak',
+            'ListItem', 'ListItemRun', 'Table', 'Image', 'Object', 'OLEObject',
+            'Footnote', 'Endnote', 'CheckBox', 'TextBox', 'Field',
+            'Line', 'Shape', 'Title', 'TOC', 'PageBreak',
+            'Chart', 'FormField', 'SDT', 'Comment',
+        );
+        $functions = array();
+        foreach ($elements as $element) {
+            $functions['add' . strtolower($element)] = $element == 'Object' ? 'OLEObject' : $element;
+        }
+
+        // Run valid `add` command
+        $function = strtolower($function);
+        if (isset($functions[$function])) {
+            $element = $functions[$function];
+
+            // Special case for TextBreak
+            // @todo Remove the `$count` parameter in 1.0.0 to make this element similiar to other elements?
+            if ($element == 'TextBreak') {
+                list($count, $fontStyle, $paragraphStyle) = array_pad($args, 3, null);
+                if ($count === null) {
+                    $count = 1;
+                }
+                for ($i = 1; $i <= $count; $i++) {
+                    $this->addElement($element, $fontStyle, $paragraphStyle);
+                }
+            } else {
+                // All other elements
+                array_unshift($args, $element); // Prepend element name to the beginning of args array
+
+                return call_user_func_array(array($this, 'addElement'), $args);
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Add element
+     *
+     * Each element has different number of parameters passed
+     *
+     * @param string $elementName
+     * @return \PhpOffice\PhpWord\Element\AbstractElement
+     */
+    protected function addElement($elementName)
+    {
+        $elementClass = __NAMESPACE__ . '\\' . $elementName;
+        $this->checkValidity($elementName);
+
+        // Get arguments
+        $args = func_get_args();
+        $withoutP = in_array($this->container, array('TextRun', 'Footnote', 'Endnote', 'ListItemRun', 'Field'));
+        if ($withoutP && ($elementName == 'Text' || $elementName == 'PreserveText')) {
+            $args[3] = null; // Remove paragraph style for texts in textrun
+        }
+
+        // Create element using reflection
+        $reflection = new \ReflectionClass($elementClass);
+        $elementArgs = $args;
+        array_shift($elementArgs); // Shift the $elementName off the beginning of array
+
+        /** @var \PhpOffice\PhpWord\Element\AbstractElement $element Type hint */
+        $element = $reflection->newInstanceArgs($elementArgs);
+
+        // Set parent container
+        $element->setParentContainer($this);
+        $element->setElementIndex($this->countElements() + 1);
+        $element->setElementId();
+
+        $this->elements[] = $element;
+
+        return $element;
+    }
+
+    /**
+     * Get all elements
+     *
+     * @return \PhpOffice\PhpWord\Element\AbstractElement[]
+     */
+    public function getElements()
+    {
+        return $this->elements;
+    }
+
+    /**
+     * Returns the element at the requested position
+     *
+     * @param int $index
+     * @return \PhpOffice\PhpWord\Element\AbstractElement|null
+     */
+    public function getElement($index)
+    {
+        if (array_key_exists($index, $this->elements)) {
+            return $this->elements[$index];
+        }
+
+        return null;
+    }
+
+    /**
+     * Removes the element at requested index
+     *
+     * @param int|\PhpOffice\PhpWord\Element\AbstractElement $toRemove
+     */
+    public function removeElement($toRemove)
+    {
+        if (is_int($toRemove) && array_key_exists($toRemove, $this->elements)) {
+            unset($this->elements[$toRemove]);
+        } elseif ($toRemove instanceof \PhpOffice\PhpWord\Element\AbstractElement) {
+            foreach ($this->elements as $key => $element) {
+                if ($element->getElementId() === $toRemove->getElementId()) {
+                    unset($this->elements[$key]);
+
+                    return;
+                }
+            }
+        }
+    }
+
+    /**
+     * Count elements
+     *
+     * @return int
+     */
+    public function countElements()
+    {
+        return count($this->elements);
+    }
+
+    /**
+     * Check if a method is allowed for the current container
+     *
+     * @param string $method
+     *
+     * @throws \BadMethodCallException
+     * @return bool
+     */
+    private function checkValidity($method)
+    {
+        $generalContainers = array(
+            'Section', 'Header', 'Footer', 'Footnote', 'Endnote', 'Cell', 'TextRun', 'TextBox', 'ListItemRun', 'TrackChange',
+        );
+
+        $validContainers = array(
+            'Text'          => $generalContainers,
+            'Bookmark'      => $generalContainers,
+            'Link'          => $generalContainers,
+            'TextBreak'     => $generalContainers,
+            'Image'         => $generalContainers,
+            'OLEObject'     => $generalContainers,
+            'Field'         => $generalContainers,
+            'Line'          => $generalContainers,
+            'Shape'         => $generalContainers,
+            'FormField'     => $generalContainers,
+            'SDT'           => $generalContainers,
+            'TrackChange'   => $generalContainers,
+            'TextRun'       => array('Section', 'Header', 'Footer', 'Cell', 'TextBox', 'TrackChange', 'ListItemRun'),
+            'ListItem'      => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'),
+            'ListItemRun'   => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'),
+            'Table'         => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'),
+            'CheckBox'      => array('Section', 'Header', 'Footer', 'Cell', 'TextRun'),
+            'TextBox'       => array('Section', 'Header', 'Footer', 'Cell'),
+            'Footnote'      => array('Section', 'TextRun', 'Cell', 'ListItemRun'),
+            'Endnote'       => array('Section', 'TextRun', 'Cell'),
+            'PreserveText'  => array('Section', 'Header', 'Footer', 'Cell'),
+            'Title'         => array('Section', 'Cell'),
+            'TOC'           => array('Section'),
+            'PageBreak'     => array('Section'),
+            'Chart'         => array('Section', 'Cell'),
+        );
+
+        // Special condition, e.g. preservetext can only exists in cell when
+        // the cell is located in header or footer
+        $validSubcontainers = array(
+            'PreserveText'  => array(array('Cell'), array('Header', 'Footer', 'Section')),
+            'Footnote'      => array(array('Cell', 'TextRun'), array('Section')),
+            'Endnote'       => array(array('Cell', 'TextRun'), array('Section')),
+        );
+
+        // Check if a method is valid for current container
+        if (isset($validContainers[$method])) {
+            if (!in_array($this->container, $validContainers[$method])) {
+                throw new \BadMethodCallException("Cannot add {$method} in {$this->container}.");
+            }
+        }
+
+        // Check if a method is valid for current container, located in other container
+        if (isset($validSubcontainers[$method])) {
+            $rules = $validSubcontainers[$method];
+            $containers = $rules[0];
+            $allowedDocParts = $rules[1];
+            foreach ($containers as $container) {
+                if ($this->container == $container && !in_array($this->getDocPart(), $allowedDocParts)) {
+                    throw new \BadMethodCallException("Cannot add {$method} in {$this->container}.");
+                }
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Create textrun element
+     *
+     * @deprecated 0.10.0
+     *
+     * @param mixed $paragraphStyle
+     *
+     * @return \PhpOffice\PhpWord\Element\TextRun
+     *
+     * @codeCoverageIgnore
+     */
+    public function createTextRun($paragraphStyle = null)
+    {
+        return $this->addTextRun($paragraphStyle);
+    }
+
+    /**
+     * Create footnote element
+     *
+     * @deprecated 0.10.0
+     *
+     * @param mixed $paragraphStyle
+     *
+     * @return \PhpOffice\PhpWord\Element\Footnote
+     *
+     * @codeCoverageIgnore
+     */
+    public function createFootnote($paragraphStyle = null)
+    {
+        return $this->addFootnote($paragraphStyle);
+    }
+}

+ 507 - 0
addons/qingdong/library/PhpWord/Element/AbstractElement.php

@@ -0,0 +1,507 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Media;
+use PhpOffice\PhpWord\PhpWord;
+
+/**
+ * Element abstract class
+ *
+ * @since 0.10.0
+ */
+abstract class AbstractElement
+{
+    /**
+     * PhpWord object
+     *
+     * @var \PhpOffice\PhpWord\PhpWord
+     */
+    protected $phpWord;
+
+    /**
+     * Section Id
+     *
+     * @var int
+     */
+    protected $sectionId;
+
+    /**
+     * Document part type: Section|Header|Footer|Footnote|Endnote
+     *
+     * Used by textrun and cell container to determine where the element is
+     * located because it will affect the availability of other element,
+     * e.g. footnote will not be available when $docPart is header or footer.
+     *
+     * @var string
+     */
+    protected $docPart = 'Section';
+
+    /**
+     * Document part Id
+     *
+     * For header and footer, this will be = ($sectionId - 1) * 3 + $index
+     * because the max number of header/footer in every page is 3, i.e.
+     * AUTO, FIRST, and EVEN (AUTO = ODD)
+     *
+     * @var int
+     */
+    protected $docPartId = 1;
+
+    /**
+     * Index of element in the elements collection (start with 1)
+     *
+     * @var int
+     */
+    protected $elementIndex = 1;
+
+    /**
+     * Unique Id for element
+     *
+     * @var string
+     */
+    protected $elementId;
+
+    /**
+     * Relation Id
+     *
+     * @var int
+     */
+    protected $relationId;
+
+    /**
+     * Depth of table container nested level; Primarily used for RTF writer/reader
+     *
+     * 0 = Not in a table; 1 = in a table; 2 = in a table inside another table, etc.
+     *
+     * @var int
+     */
+    private $nestedLevel = 0;
+
+    /**
+     * A reference to the parent
+     *
+     * @var AbstractElement|null
+     */
+    private $parent;
+
+    /**
+     * changed element info
+     *
+     * @var TrackChange
+     */
+    private $trackChange;
+
+    /**
+     * Parent container type
+     *
+     * @var string
+     */
+    private $parentContainer;
+
+    /**
+     * Has media relation flag; true for Link, Image, and Object
+     *
+     * @var bool
+     */
+    protected $mediaRelation = false;
+
+    /**
+     * Is part of collection; true for Title, Footnote, Endnote, Chart, and Comment
+     *
+     * @var bool
+     */
+    protected $collectionRelation = false;
+
+    /**
+     * The start position for the linked comment
+     *
+     * @var Comment
+     */
+    protected $commentRangeStart;
+
+    /**
+     * The end position for the linked comment
+     *
+     * @var Comment
+     */
+    protected $commentRangeEnd;
+
+    /**
+     * Get PhpWord
+     *
+     * @return \PhpOffice\PhpWord\PhpWord
+     */
+    public function getPhpWord()
+    {
+        return $this->phpWord;
+    }
+
+    /**
+     * Set PhpWord as reference.
+     *
+     * @param \PhpOffice\PhpWord\PhpWord $phpWord
+     */
+    public function setPhpWord(PhpWord $phpWord = null)
+    {
+        $this->phpWord = $phpWord;
+    }
+
+    /**
+     * Get section number
+     *
+     * @return int
+     */
+    public function getSectionId()
+    {
+        return $this->sectionId;
+    }
+
+    /**
+     * Set doc part.
+     *
+     * @param string $docPart
+     * @param int $docPartId
+     */
+    public function setDocPart($docPart, $docPartId = 1)
+    {
+        $this->docPart = $docPart;
+        $this->docPartId = $docPartId;
+    }
+
+    /**
+     * Get doc part
+     *
+     * @return string
+     */
+    public function getDocPart()
+    {
+        return $this->docPart;
+    }
+
+    /**
+     * Get doc part Id
+     *
+     * @return int
+     */
+    public function getDocPartId()
+    {
+        return $this->docPartId;
+    }
+
+    /**
+     * Return media element (image, object, link) container name
+     *
+     * @return string section|headerx|footerx|footnote|endnote
+     */
+    private function getMediaPart()
+    {
+        $mediaPart = $this->docPart;
+        if ($mediaPart == 'Header' || $mediaPart == 'Footer') {
+            $mediaPart .= $this->docPartId;
+        }
+
+        return strtolower($mediaPart);
+    }
+
+    /**
+     * Get element index
+     *
+     * @return int
+     */
+    public function getElementIndex()
+    {
+        return $this->elementIndex;
+    }
+
+    /**
+     * Set element index.
+     *
+     * @param int $value
+     */
+    public function setElementIndex($value)
+    {
+        $this->elementIndex = $value;
+    }
+
+    /**
+     * Get element unique ID
+     *
+     * @return string
+     */
+    public function getElementId()
+    {
+        return $this->elementId;
+    }
+
+    /**
+     * Set element unique ID from 6 first digit of md5.
+     */
+    public function setElementId()
+    {
+        $this->elementId = substr(md5(rand()), 0, 6);
+    }
+
+    /**
+     * Get relation Id
+     *
+     * @return int
+     */
+    public function getRelationId()
+    {
+        return $this->relationId;
+    }
+
+    /**
+     * Set relation Id.
+     *
+     * @param int $value
+     */
+    public function setRelationId($value)
+    {
+        $this->relationId = $value;
+    }
+
+    /**
+     * Get nested level
+     *
+     * @return int
+     */
+    public function getNestedLevel()
+    {
+        return $this->nestedLevel;
+    }
+
+    /**
+     * Get comment start
+     *
+     * @return Comment
+     */
+    public function getCommentRangeStart()
+    {
+        return $this->commentRangeStart;
+    }
+
+    /**
+     * Set comment start
+     *
+     * @param Comment $value
+     */
+    public function setCommentRangeStart(Comment $value)
+    {
+        if ($this instanceof Comment) {
+            throw new \InvalidArgumentException('Cannot set a Comment on a Comment');
+        }
+        $this->commentRangeStart = $value;
+        $this->commentRangeStart->setStartElement($this);
+    }
+
+    /**
+     * Get comment end
+     *
+     * @return Comment
+     */
+    public function getCommentRangeEnd()
+    {
+        return $this->commentRangeEnd;
+    }
+
+    /**
+     * Set comment end
+     *
+     * @param Comment $value
+     */
+    public function setCommentRangeEnd(Comment $value)
+    {
+        if ($this instanceof Comment) {
+            throw new \InvalidArgumentException('Cannot set a Comment on a Comment');
+        }
+        $this->commentRangeEnd = $value;
+        $this->commentRangeEnd->setEndElement($this);
+    }
+
+    /**
+     * Get parent element
+     *
+     * @return AbstractElement|null
+     */
+    public function getParent()
+    {
+        return $this->parent;
+    }
+
+    /**
+     * Set parent container
+     *
+     * Passed parameter should be a container, except for Table (contain Row) and Row (contain Cell)
+     *
+     * @param \PhpOffice\PhpWord\Element\AbstractElement $container
+     */
+    public function setParentContainer(self $container)
+    {
+        $this->parentContainer = substr(get_class($container), strrpos(get_class($container), '\\') + 1);
+        $this->parent = $container;
+
+        // Set nested level
+        $this->nestedLevel = $container->getNestedLevel();
+        if ($this->parentContainer == 'Cell') {
+            $this->nestedLevel++;
+        }
+
+        // Set phpword
+        $this->setPhpWord($container->getPhpWord());
+
+        // Set doc part
+        if (!$this instanceof Footnote) {
+            $this->setDocPart($container->getDocPart(), $container->getDocPartId());
+        }
+
+        $this->setMediaRelation();
+        $this->setCollectionRelation();
+    }
+
+    /**
+     * Set relation Id for media elements (link, image, object; legacy of OOXML)
+     *
+     * - Image element needs to be passed to Media object
+     * - Icon needs to be set for Object element
+     */
+    private function setMediaRelation()
+    {
+        if (!$this instanceof Link && !$this instanceof Image && !$this instanceof OLEObject) {
+            return;
+        }
+
+        $elementName = substr(get_class($this), strrpos(get_class($this), '\\') + 1);
+        if ($elementName == 'OLEObject') {
+            $elementName = 'Object';
+        }
+        $mediaPart = $this->getMediaPart();
+        $source = $this->getSource();
+        $image = null;
+        if ($this instanceof Image) {
+            $image = $this;
+        }
+        $rId = Media::addElement($mediaPart, strtolower($elementName), $source, $image);
+        $this->setRelationId($rId);
+
+        if ($this instanceof OLEObject) {
+            $icon = $this->getIcon();
+            $rId = Media::addElement($mediaPart, 'image', $icon, new Image($icon));
+            $this->setImageRelationId($rId);
+        }
+    }
+
+    /**
+     * Set relation Id for elements that will be registered in the Collection subnamespaces.
+     */
+    private function setCollectionRelation()
+    {
+        if ($this->collectionRelation === true && $this->phpWord instanceof PhpWord) {
+            $elementName = substr(get_class($this), strrpos(get_class($this), '\\') + 1);
+            $addMethod = "add{$elementName}";
+            $rId = $this->phpWord->$addMethod($this);
+            $this->setRelationId($rId);
+        }
+    }
+
+    /**
+     * Check if element is located in Section doc part (as opposed to Header/Footer)
+     *
+     * @return bool
+     */
+    public function isInSection()
+    {
+        return $this->docPart == 'Section';
+    }
+
+    /**
+     * Set new style value
+     *
+     * @param mixed $styleObject Style object
+     * @param mixed $styleValue Style value
+     * @param bool $returnObject Always return object
+     * @return mixed
+     */
+    protected function setNewStyle($styleObject, $styleValue = null, $returnObject = false)
+    {
+        if (!is_null($styleValue) && is_array($styleValue)) {
+            $styleObject->setStyleByArray($styleValue);
+            $style = $styleObject;
+        } else {
+            $style = $returnObject ? $styleObject : $styleValue;
+        }
+
+        return $style;
+    }
+
+    /**
+     * Sets the trackChange information
+     *
+     * @param TrackChange $trackChange
+     */
+    public function setTrackChange(TrackChange $trackChange)
+    {
+        $this->trackChange = $trackChange;
+    }
+
+    /**
+     * Gets the trackChange information
+     *
+     * @return TrackChange
+     */
+    public function getTrackChange()
+    {
+        return $this->trackChange;
+    }
+
+    /**
+     * Set changed
+     *
+     * @param string $type INSERTED|DELETED
+     * @param string $author
+     * @param null|int|\DateTime $date allways in UTC
+     */
+    public function setChangeInfo($type, $author, $date = null)
+    {
+        $this->trackChange = new TrackChange($type, $author, $date);
+    }
+
+    /**
+     * Set enum value
+     *
+     * @param string|null $value
+     * @param string[] $enum
+     * @param string|null $default
+     *
+     * @throws \InvalidArgumentException
+     * @return string|null
+     *
+     * @todo Merge with the same method in AbstractStyle
+     */
+    protected function setEnumVal($value = null, $enum = array(), $default = null)
+    {
+        if ($value !== null && trim($value) != '' && !empty($enum) && !in_array($value, $enum)) {
+            throw new \InvalidArgumentException("Invalid style value: {$value}");
+        } elseif ($value === null || trim($value) == '') {
+            $value = $default;
+        }
+
+        return $value;
+    }
+}

+ 60 - 0
addons/qingdong/library/PhpWord/Element/Bookmark.php

@@ -0,0 +1,60 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Shared\Text as SharedText;
+
+/**
+ * Bookmark element
+ */
+class Bookmark extends AbstractElement
+{
+    /**
+     * Bookmark Name
+     *
+     * @var string
+     */
+    private $name;
+
+    /**
+     * Is part of collection
+     *
+     * @var bool
+     */
+    protected $collectionRelation = true;
+
+    /**
+     * Create a new Bookmark Element
+     *
+     * @param string $name
+     */
+    public function __construct($name = '')
+    {
+        $this->name = SharedText::toUTF8($name);
+    }
+
+    /**
+     * Get Bookmark name
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+}

+ 77 - 0
addons/qingdong/library/PhpWord/Element/Cell.php

@@ -0,0 +1,77 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Style\Cell as CellStyle;
+
+/**
+ * Table cell element
+ */
+class Cell extends AbstractContainer
+{
+    /**
+     * @var string Container type
+     */
+    protected $container = 'Cell';
+
+    /**
+     * Cell width
+     *
+     * @var int
+     */
+    private $width = null;
+
+    /**
+     * Cell style
+     *
+     * @var \PhpOffice\PhpWord\Style\Cell
+     */
+    private $style;
+
+    /**
+     * Create new instance
+     *
+     * @param int $width
+     * @param array|\PhpOffice\PhpWord\Style\Cell $style
+     */
+    public function __construct($width = null, $style = null)
+    {
+        $this->width = $width;
+        $this->style = $this->setNewStyle(new CellStyle(), $style, true);
+    }
+
+    /**
+     * Get cell style
+     *
+     * @return \PhpOffice\PhpWord\Style\Cell
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+
+    /**
+     * Get cell width
+     *
+     * @return int
+     */
+    public function getWidth()
+    {
+        return $this->width;
+    }
+}

+ 129 - 0
addons/qingdong/library/PhpWord/Element/Chart.php

@@ -0,0 +1,129 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Style\Chart as ChartStyle;
+
+/**
+ * Chart element
+ *
+ * @since 0.12.0
+ */
+class Chart extends AbstractElement
+{
+    /**
+     * Is part of collection
+     *
+     * @var bool
+     */
+    protected $collectionRelation = true;
+
+    /**
+     * Type
+     *
+     * @var string
+     */
+    private $type = 'pie';
+
+    /**
+     * Series
+     *
+     * @var array
+     */
+    private $series = array();
+
+    /**
+     * Chart style
+     *
+     * @var \PhpOffice\PhpWord\Style\Chart
+     */
+    private $style;
+
+    /**
+     * Create new instance
+     *
+     * @param string $type
+     * @param array $categories
+     * @param array $values
+     * @param array $style
+     * @param null|mixed $seriesName
+     */
+    public function __construct($type, $categories, $values, $style = null, $seriesName = null)
+    {
+        $this->setType($type);
+        $this->addSeries($categories, $values, $seriesName);
+        $this->style = $this->setNewStyle(new ChartStyle(), $style, true);
+    }
+
+    /**
+     * Get type
+     *
+     * @return string
+     */
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    /**
+     * Set type.
+     *
+     * @param string $value
+     */
+    public function setType($value)
+    {
+        $enum = array('pie', 'doughnut', 'line', 'bar', 'stacked_bar', 'percent_stacked_bar', 'column', 'stacked_column', 'percent_stacked_column', 'area', 'radar', 'scatter');
+        $this->type = $this->setEnumVal($value, $enum, 'pie');
+    }
+
+    /**
+     * Add series
+     *
+     * @param array $categories
+     * @param array $values
+     * @param null|mixed $name
+     */
+    public function addSeries($categories, $values, $name = null)
+    {
+        $this->series[] = array(
+            'categories' => $categories,
+            'values'     => $values,
+            'name'       => $name,
+        );
+    }
+
+    /**
+     * Get series
+     *
+     * @return array
+     */
+    public function getSeries()
+    {
+        return $this->series;
+    }
+
+    /**
+     * Get chart style
+     *
+     * @return \PhpOffice\PhpWord\Style\Chart
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+}

+ 72 - 0
addons/qingdong/library/PhpWord/Element/CheckBox.php

@@ -0,0 +1,72 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Shared\Text as SharedText;
+
+/**
+ * Check box element
+ *
+ * @since 0.10.0
+ */
+class CheckBox extends Text
+{
+    /**
+     * Name content
+     *
+     * @var string
+     */
+    private $name;
+
+    /**
+     * Create new instance
+     *
+     * @param string $name
+     * @param string $text
+     * @param mixed $fontStyle
+     * @param mixed $paragraphStyle
+     */
+    public function __construct($name = null, $text = null, $fontStyle = null, $paragraphStyle = null)
+    {
+        $this->setName($name);
+        parent::__construct($text, $fontStyle, $paragraphStyle);
+    }
+
+    /**
+     * Set name content
+     *
+     * @param string $name
+     * @return self
+     */
+    public function setName($name)
+    {
+        $this->name = SharedText::toUTF8($name);
+
+        return $this;
+    }
+
+    /**
+     * Get name content
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+}

+ 122 - 0
addons/qingdong/library/PhpWord/Element/Comment.php

@@ -0,0 +1,122 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+/**
+ * Comment element
+ * @see http://datypic.com/sc/ooxml/t-w_CT_Comment.html
+ */
+class Comment extends TrackChange
+{
+    /**
+     * Initials
+     *
+     * @var string
+     */
+    private $initials;
+
+    /**
+     * The Element where this comment starts
+     *
+     * @var AbstractElement
+     */
+    private $startElement;
+
+    /**
+     * The Element where this comment ends
+     *
+     * @var AbstractElement
+     */
+    private $endElement;
+
+    /**
+     * Is part of collection
+     *
+     * @var bool
+     */
+    protected $collectionRelation = true;
+
+    /**
+     * Create a new Comment Element
+     *
+     * @param string $author
+     * @param null|\DateTime $date
+     * @param string $initials
+     */
+    public function __construct($author, $date = null, $initials = null)
+    {
+        parent::__construct(null, $author, $date);
+        $this->initials = $initials;
+    }
+
+    /**
+     * Get Initials
+     *
+     * @return string
+     */
+    public function getInitials()
+    {
+        return $this->initials;
+    }
+
+    /**
+     * Sets the element where this comment starts
+     *
+     * @param \PhpOffice\PhpWord\Element\AbstractElement $value
+     */
+    public function setStartElement(AbstractElement $value)
+    {
+        $this->startElement = $value;
+        if ($value->getCommentRangeStart() == null) {
+            $value->setCommentRangeStart($this);
+        }
+    }
+
+    /**
+     * Get the element where this comment starts
+     *
+     * @return \PhpOffice\PhpWord\Element\AbstractElement
+     */
+    public function getStartElement()
+    {
+        return $this->startElement;
+    }
+
+    /**
+     * Sets the element where this comment ends
+     *
+     * @param \PhpOffice\PhpWord\Element\AbstractElement $value
+     */
+    public function setEndElement(AbstractElement $value)
+    {
+        $this->endElement = $value;
+        if ($value->getCommentRangeEnd() == null) {
+            $value->setCommentRangeEnd($this);
+        }
+    }
+
+    /**
+     * Get the element where this comment ends
+     *
+     * @return \PhpOffice\PhpWord\Element\AbstractElement
+     */
+    public function getEndElement()
+    {
+        return $this->endElement;
+    }
+}

+ 41 - 0
addons/qingdong/library/PhpWord/Element/Endnote.php

@@ -0,0 +1,41 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+/**
+ * Endnote element
+ *
+ * @since 0.10.0
+ */
+class Endnote extends Footnote
+{
+    /**
+     * @var string Container type
+     */
+    protected $container = 'Endnote';
+
+    /**
+     * Create new instance
+     *
+     * @param string|array|\PhpOffice\PhpWord\Style\Paragraph $paragraphStyle
+     */
+    public function __construct($paragraphStyle = null)
+    {
+        parent::__construct($paragraphStyle);
+    }
+}

+ 299 - 0
addons/qingdong/library/PhpWord/Element/Field.php

@@ -0,0 +1,299 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Style\Font;
+
+/**
+ * Field element
+ *
+ * @since 0.11.0
+ * @see  http://www.schemacentral.com/sc/ooxml/t-w_CT_SimpleField.html
+ */
+class Field extends AbstractElement
+{
+    /**
+     * Field properties and options. Depending on type, a field can have different properties
+     * and options
+     *
+     * @var array
+     */
+    protected $fieldsArray = array(
+        'PAGE' => array(
+           'properties' => array(
+               'format' => array('Arabic', 'ArabicDash', 'alphabetic', 'ALPHABETIC', 'roman', 'ROMAN'),
+           ),
+           'options' => array('PreserveFormat'),
+        ),
+        'NUMPAGES' => array(
+           'properties' => array(
+               'format' => array('Arabic', 'ArabicDash', 'CardText', 'DollarText', 'Ordinal', 'OrdText',
+                   'alphabetic', 'ALPHABETIC', 'roman', 'ROMAN', 'Caps', 'FirstCap', 'Lower', 'Upper', ),
+               'numformat' => array('0', '0,00', '#.##0', '#.##0,00', '€ #.##0,00(€ #.##0,00)', '0%', '0,00%'),
+           ),
+           'options' => array('PreserveFormat'),
+        ),
+        'DATE' => array(
+            'properties' => array(
+                'dateformat' => array(
+                    /* Generic formats */
+                    'yyyy-MM-dd', 'yyyy-MM', 'MMM-yy', 'MMM-yyyy', 'h:mm am/pm', 'h:mm:ss am/pm', 'HH:mm', 'HH:mm:ss',
+                    /* Day-Month-Year formats */
+                    'dddd d MMMM yyyy', 'd MMMM yyyy', 'd-MMM-yy', 'd MMM. yy',
+                    'd-M-yy', 'd-M-yy h:mm', 'd-M-yy h:mm:ss', 'd-M-yy h:mm am/pm', 'd-M-yy h:mm:ss am/pm', 'd-M-yy HH:mm', 'd-M-yy HH:mm:ss',
+                    'd/M/yy', 'd/M/yy h:mm', 'd/M/yy h:mm:ss', 'd/M/yy h:mm am/pm', 'd/M/yy h:mm:ss am/pm', 'd/M/yy HH:mm', 'd/M/yy HH:mm:ss',
+                    'd-M-yyyy', 'd-M-yyyy h:mm', 'd-M-yyyy h:mm:ss', 'd-M-yyyy h:mm am/pm', 'd-M-yyyy h:mm:ss am/pm', 'd-M-yyyy HH:mm', 'd-M-yyyy HH:mm:ss',
+                    'd/M/yyyy', 'd/M/yyyy h:mm', 'd/M/yyyy h:mm:ss', 'd/M/yyyy h:mm am/pm', 'd/M/yyyy h:mm:ss am/pm', 'd/M/yyyy HH:mm', 'd/M/yyyy HH:mm:ss',
+                    /* Month-Day-Year formats */
+                    'dddd, MMMM d yyyy', 'MMMM d yyyy', 'MMM-d-yy', 'MMM. d yy',
+                    'M-d-yy', 'M-d-yy h:mm', 'M-d-yy h:mm:ss', 'M-d-yy h:mm am/pm', 'M-d-yy h:mm:ss am/pm', 'M-d-yy HH:mm', 'M-d-yy HH:mm:ss',
+                    'M/d/yy', 'M/d/yy h:mm', 'M/d/yy h:mm:ss', 'M/d/yy h:mm am/pm', 'M/d/yy h:mm:ss am/pm', 'M/d/yy HH:mm', 'M/d/yy HH:mm:ss',
+                    'M-d-yyyy', 'M-d-yyyy h:mm', 'M-d-yyyy h:mm:ss', 'M-d-yyyy h:mm am/pm', 'M-d-yyyy h:mm:ss am/pm', 'M-d-yyyy HH:mm', 'M-d-yyyy HH:mm:ss',
+                    'M/d/yyyy', 'M/d/yyyy h:mm', 'M/d/yyyy h:mm:ss', 'M/d/yyyy h:mm am/pm', 'M/d/yyyy h:mm:ss am/pm', 'M/d/yyyy HH:mm', 'M/d/yyyy HH:mm:ss',
+                ),
+            ),
+            'options' => array('PreserveFormat', 'LunarCalendar', 'SakaEraCalendar', 'LastUsedFormat'),
+        ),
+        'MACROBUTTON' => array(
+            'properties' => array('macroname' => ''),
+        ),
+        'XE' => array(
+            'properties' => array(),
+            'options'    => array('Bold', 'Italic'),
+        ),
+        'INDEX' => array(
+            'properties' => array(),
+            'options'    => array('PreserveFormat'),
+        ),
+        'STYLEREF' => array(
+            'properties' => array('StyleIdentifier' => ''),
+            'options'    => array('PreserveFormat'),
+        ),
+    );
+
+    /**
+     * Field type
+     *
+     * @var string
+     */
+    protected $type;
+
+    /**
+     * Field text
+     *
+     * @var TextRun|string
+     */
+    protected $text;
+
+    /**
+     * Field properties
+     *
+     * @var array
+     */
+    protected $properties = array();
+
+    /**
+     * Field options
+     *
+     * @var array
+     */
+    protected $options = array();
+
+    /**
+     * Font style
+     *
+     * @var string|\PhpOffice\PhpWord\Style\Font
+     */
+    protected $fontStyle;
+
+    /**
+     * Set Font style
+     *
+     * @param string|array|\PhpOffice\PhpWord\Style\Font $style
+     * @return string|\PhpOffice\PhpWord\Style\Font
+     */
+    public function setFontStyle($style = null)
+    {
+        if ($style instanceof Font) {
+            $this->fontStyle = $style;
+        } elseif (is_array($style)) {
+            $this->fontStyle = new Font('text');
+            $this->fontStyle->setStyleByArray($style);
+        } elseif (null === $style) {
+            $this->fontStyle = null;
+        } else {
+            $this->fontStyle = $style;
+        }
+
+        return $this->fontStyle;
+    }
+
+    /**
+     * Get Font style
+     *
+     * @return string|\PhpOffice\PhpWord\Style\Font
+     */
+    public function getFontStyle()
+    {
+        return $this->fontStyle;
+    }
+
+    /**
+     * Create a new Field Element
+     *
+     * @param string $type
+     * @param array $properties
+     * @param array $options
+     * @param TextRun|string|null $text
+     * @param string|array|\PhpOffice\PhpWord\Style\Font $fontStyle
+     */
+    public function __construct($type = null, $properties = array(), $options = array(), $text = null, $fontStyle = null)
+    {
+        $this->setType($type);
+        $this->setProperties($properties);
+        $this->setOptions($options);
+        $this->setText($text);
+        $this->setFontStyle($fontStyle);
+    }
+
+    /**
+     * Set Field type
+     *
+     * @param string $type
+     *
+     * @throws \InvalidArgumentException
+     * @return string
+     */
+    public function setType($type = null)
+    {
+        if (isset($type)) {
+            if (isset($this->fieldsArray[$type])) {
+                $this->type = $type;
+            } else {
+                throw new \InvalidArgumentException("Invalid type '$type'");
+            }
+        }
+
+        return $this->type;
+    }
+
+    /**
+     * Get Field type
+     *
+     * @return string
+     */
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    /**
+     * Set Field properties
+     *
+     * @param array $properties
+     *
+     * @throws \InvalidArgumentException
+     * @return self
+     */
+    public function setProperties($properties = array())
+    {
+        if (is_array($properties)) {
+            foreach (array_keys($properties) as $propkey) {
+                if (!(isset($this->fieldsArray[$this->type]['properties'][$propkey]))) {
+                    throw new \InvalidArgumentException("Invalid property '$propkey'");
+                }
+            }
+            $this->properties = array_merge($this->properties, $properties);
+        }
+
+        return $this->properties;
+    }
+
+    /**
+     * Get Field properties
+     *
+     * @return array
+     */
+    public function getProperties()
+    {
+        return $this->properties;
+    }
+
+    /**
+     * Set Field options
+     *
+     * @param array $options
+     *
+     * @throws \InvalidArgumentException
+     * @return self
+     */
+    public function setOptions($options = array())
+    {
+        if (is_array($options)) {
+            foreach (array_keys($options) as $optionkey) {
+                if (!(isset($this->fieldsArray[$this->type]['options'][$optionkey])) && substr($optionkey, 0, 1) !== '\\') {
+                    throw new \InvalidArgumentException("Invalid option '$optionkey', possible values are " . implode(', ', $this->fieldsArray[$this->type]['options']));
+                }
+            }
+            $this->options = array_merge($this->options, $options);
+        }
+
+        return $this->options;
+    }
+
+    /**
+     * Get Field properties
+     *
+     * @return array
+     */
+    public function getOptions()
+    {
+        return $this->options;
+    }
+
+    /**
+     * Set Field text
+     *
+     * @param string|TextRun $text
+     *
+     * @throws \InvalidArgumentException
+     * @return null|string|TextRun
+     */
+    public function setText($text = null)
+    {
+        if (isset($text)) {
+            if (is_string($text) || $text instanceof TextRun) {
+                $this->text = $text;
+            } else {
+                throw new \InvalidArgumentException('Invalid text');
+            }
+        }
+
+        return $this->text;
+    }
+
+    /**
+     * Get Field text
+     *
+     * @return string|TextRun
+     */
+    public function getText()
+    {
+        return $this->text;
+    }
+}

+ 116 - 0
addons/qingdong/library/PhpWord/Element/Footer.php

@@ -0,0 +1,116 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+/**
+ * Footer element
+ */
+class Footer extends AbstractContainer
+{
+    /**
+     * Header/footer types constants
+     *
+     * @var string
+     * @see  http://www.datypic.com/sc/ooxml/t-w_ST_HdrFtr.html Header or Footer Type
+     */
+    const AUTO = 'default';  // default and odd pages
+    const FIRST = 'first';
+    const EVEN = 'even';
+
+    /**
+     * @var string Container type
+     */
+    protected $container = 'Footer';
+
+    /**
+     * Header type
+     *
+     * @var string
+     */
+    protected $type = self::AUTO;
+
+    /**
+     * Create new instance
+     *
+     * @param int $sectionId
+     * @param int $containerId
+     * @param string $type
+     */
+    public function __construct($sectionId, $containerId = 1, $type = self::AUTO)
+    {
+        $this->sectionId = $sectionId;
+        $this->setType($type);
+        $this->setDocPart($this->container, ($sectionId - 1) * 3 + $containerId);
+    }
+
+    /**
+     * Set type.
+     *
+     * @since 0.10.0
+     *
+     * @param string $value
+     */
+    public function setType($value = self::AUTO)
+    {
+        if (!in_array($value, array(self::AUTO, self::FIRST, self::EVEN))) {
+            $value = self::AUTO;
+        }
+        $this->type = $value;
+    }
+
+    /**
+     * Get type
+     *
+     * @return string
+     * @since 0.10.0
+     */
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    /**
+     * Reset type to default
+     *
+     * @return string
+     */
+    public function resetType()
+    {
+        return $this->type = self::AUTO;
+    }
+
+    /**
+     * First page only header
+     *
+     * @return string
+     */
+    public function firstPage()
+    {
+        return $this->type = self::FIRST;
+    }
+
+    /**
+     * Even numbered pages only
+     *
+     * @return string
+     */
+    public function evenPage()
+    {
+        return $this->type = self::EVEN;
+    }
+}

+ 89 - 0
addons/qingdong/library/PhpWord/Element/Footnote.php

@@ -0,0 +1,89 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Style\Paragraph;
+
+class Footnote extends AbstractContainer
+{
+    /**
+     * @var string Container type
+     */
+    protected $container = 'Footnote';
+
+    /**
+     * Paragraph style
+     *
+     * @var string|\PhpOffice\PhpWord\Style\Paragraph
+     */
+    protected $paragraphStyle;
+
+    /**
+     * Is part of collection
+     *
+     * @var bool
+     */
+    protected $collectionRelation = true;
+
+    /**
+     * Create new instance
+     *
+     * @param string|array|\PhpOffice\PhpWord\Style\Paragraph $paragraphStyle
+     */
+    public function __construct($paragraphStyle = null)
+    {
+        $this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle);
+        $this->setDocPart($this->container);
+    }
+
+    /**
+     * Get paragraph style
+     *
+     * @return string|\PhpOffice\PhpWord\Style\Paragraph
+     */
+    public function getParagraphStyle()
+    {
+        return $this->paragraphStyle;
+    }
+
+    /**
+     * Get Footnote Reference ID
+     *
+     * @deprecated 0.10.0
+     * @codeCoverageIgnore
+     *
+     * @return int
+     */
+    public function getReferenceId()
+    {
+        return $this->getRelationId();
+    }
+
+    /**
+     * Set Footnote Reference ID
+     *
+     * @deprecated 0.10.0
+     * @codeCoverageIgnore
+     *
+     * @param int $rId
+     */
+    public function setReferenceId($rId)
+    {
+        $this->setRelationId($rId);
+    }
+}

+ 195 - 0
addons/qingdong/library/PhpWord/Element/FormField.php

@@ -0,0 +1,195 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+/**
+ * Form field element
+ *
+ * @since 0.12.0
+ * @see  http://www.datypic.com/sc/ooxml/t-w_CT_FFData.html
+ */
+class FormField extends Text
+{
+    /**
+     * Form field type: textinput|checkbox|dropdown
+     *
+     * @var string
+     */
+    private $type = 'textinput';
+
+    /**
+     * Form field name
+     *
+     * @var string|bool|int
+     */
+    private $name;
+
+    /**
+     * Default value
+     *
+     * - TextInput: string
+     * - CheckBox: bool
+     * - DropDown: int Index of entries (zero based)
+     *
+     * @var string|bool|int
+     */
+    private $default;
+
+    /**
+     * Value
+     *
+     * @var string|bool|int
+     */
+    private $value;
+
+    /**
+     * Dropdown entries
+     *
+     * @var array
+     */
+    private $entries = array();
+
+    /**
+     * Create new instance
+     *
+     * @param string $type
+     * @param mixed $fontStyle
+     * @param mixed $paragraphStyle
+     */
+    public function __construct($type, $fontStyle = null, $paragraphStyle = null)
+    {
+        parent::__construct(null, $fontStyle, $paragraphStyle);
+        $this->setType($type);
+    }
+
+    /**
+     * Get type
+     *
+     * @return string
+     */
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    /**
+     * Set type
+     *
+     * @param string $value
+     * @return self
+     */
+    public function setType($value)
+    {
+        $enum = array('textinput', 'checkbox', 'dropdown');
+        $this->type = $this->setEnumVal($value, $enum, $this->type);
+
+        return $this;
+    }
+
+    /**
+     * Get name
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Set name
+     *
+     * @param string|bool|int $value
+     * @return self
+     */
+    public function setName($value)
+    {
+        $this->name = $value;
+
+        return $this;
+    }
+
+    /**
+     * Get default
+     *
+     * @return string|bool|int
+     */
+    public function getDefault()
+    {
+        return $this->default;
+    }
+
+    /**
+     * Set default
+     *
+     * @param string|bool|int $value
+     * @return self
+     */
+    public function setDefault($value)
+    {
+        $this->default = $value;
+
+        return $this;
+    }
+
+    /**
+     * Get value
+     *
+     * @return string|bool|int
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+
+    /**
+     * Set value
+     *
+     * @param string|bool|int $value
+     * @return self
+     */
+    public function setValue($value)
+    {
+        $this->value = $value;
+
+        return $this;
+    }
+
+    /**
+     * Get entries
+     *
+     * @return array
+     */
+    public function getEntries()
+    {
+        return $this->entries;
+    }
+
+    /**
+     * Set entries
+     *
+     * @param array $value
+     * @return self
+     */
+    public function setEntries($value)
+    {
+        $this->entries = $value;
+
+        return $this;
+    }
+}

+ 41 - 0
addons/qingdong/library/PhpWord/Element/Header.php

@@ -0,0 +1,41 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+/**
+ * Header element
+ */
+class Header extends Footer
+{
+    /**
+     * @var string Container type
+     */
+    protected $container = 'Header';
+
+    /**
+     * Add a Watermark Element
+     *
+     * @param string $src
+     * @param mixed $style
+     * @return Image
+     */
+    public function addWatermark($src, $style = null)
+    {
+        return $this->addImage($src, $style, true);
+    }
+}

+ 602 - 0
addons/qingdong/library/PhpWord/Element/Image.php

@@ -0,0 +1,602 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Exception\CreateTemporaryFileException;
+use PhpOffice\PhpWord\Exception\InvalidImageException;
+use PhpOffice\PhpWord\Exception\UnsupportedImageTypeException;
+use PhpOffice\PhpWord\Settings;
+use PhpOffice\PhpWord\Shared\ZipArchive;
+use PhpOffice\PhpWord\Style\Image as ImageStyle;
+
+/**
+ * Image element
+ */
+class Image extends AbstractElement
+{
+    /**
+     * Image source type constants
+     */
+    const SOURCE_LOCAL = 'local'; // Local images
+    const SOURCE_GD = 'gd'; // Generated using GD
+    const SOURCE_ARCHIVE = 'archive'; // Image in archives zip://$archive#$image
+    const SOURCE_STRING = 'string'; // Image from string
+
+    /**
+     * Image source
+     *
+     * @var string
+     */
+    private $source;
+
+    /**
+     * Source type: local|gd|archive
+     *
+     * @var string
+     */
+    private $sourceType;
+
+    /**
+     * Image style
+     *
+     * @var ImageStyle
+     */
+    private $style;
+
+    /**
+     * Is watermark
+     *
+     * @var bool
+     */
+    private $watermark;
+
+    /**
+     * Name of image
+     *
+     * @var string
+     */
+    private $name;
+
+    /**
+     * Image type
+     *
+     * @var string
+     */
+    private $imageType;
+
+    /**
+     * Image create function
+     *
+     * @var string
+     */
+    private $imageCreateFunc;
+
+    /**
+     * Image function
+     *
+     * @var string
+     */
+    private $imageFunc;
+
+    /**
+     * Image extension
+     *
+     * @var string
+     */
+    private $imageExtension;
+
+    /**
+     * Is memory image
+     *
+     * @var bool
+     */
+    private $memoryImage;
+
+    /**
+     * Image target file name
+     *
+     * @var string
+     */
+    private $target;
+
+    /**
+     * Image media index
+     *
+     * @var int
+     */
+    private $mediaIndex;
+
+    /**
+     * Has media relation flag; true for Link, Image, and Object
+     *
+     * @var bool
+     */
+    protected $mediaRelation = true;
+
+    /**
+     * Create new image element
+     *
+     * @param string $source
+     * @param mixed $style
+     * @param bool $watermark
+     * @param string $name
+     *
+     * @throws \PhpOffice\PhpWord\Exception\InvalidImageException
+     * @throws \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException
+     */
+    public function __construct($source, $style = null, $watermark = false, $name = null)
+    {
+        $this->source = $source;
+        $this->style = $this->setNewStyle(new ImageStyle(), $style, true);
+        $this->setIsWatermark($watermark);
+        $this->setName($name);
+
+        $this->checkImage();
+    }
+
+    /**
+     * Get Image style
+     *
+     * @return ImageStyle
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+
+    /**
+     * Get image source
+     *
+     * @return string
+     */
+    public function getSource()
+    {
+        return $this->source;
+    }
+
+    /**
+     * Get image source type
+     *
+     * @return string
+     */
+    public function getSourceType()
+    {
+        return $this->sourceType;
+    }
+
+    /**
+     * Sets the image name
+     *
+     * @param string $value
+     */
+    public function setName($value)
+    {
+        $this->name = $value;
+    }
+
+    /**
+     * Get image name
+     *
+     * @return null|string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Get image media ID
+     *
+     * @return string
+     */
+    public function getMediaId()
+    {
+        return md5($this->source);
+    }
+
+    /**
+     * Get is watermark
+     *
+     * @return bool
+     */
+    public function isWatermark()
+    {
+        return $this->watermark;
+    }
+
+    /**
+     * Set is watermark
+     *
+     * @param bool $value
+     */
+    public function setIsWatermark($value)
+    {
+        $this->watermark = $value;
+    }
+
+    /**
+     * Get image type
+     *
+     * @return string
+     */
+    public function getImageType()
+    {
+        return $this->imageType;
+    }
+
+    /**
+     * Get image create function
+     *
+     * @return string
+     */
+    public function getImageCreateFunction()
+    {
+        return $this->imageCreateFunc;
+    }
+
+    /**
+     * Get image function
+     *
+     * @return string
+     */
+    public function getImageFunction()
+    {
+        return $this->imageFunc;
+    }
+
+    /**
+     * Get image extension
+     *
+     * @return string
+     */
+    public function getImageExtension()
+    {
+        return $this->imageExtension;
+    }
+
+    /**
+     * Get is memory image
+     *
+     * @return bool
+     */
+    public function isMemImage()
+    {
+        return $this->memoryImage;
+    }
+
+    /**
+     * Get target file name
+     *
+     * @return string
+     */
+    public function getTarget()
+    {
+        return $this->target;
+    }
+
+    /**
+     * Set target file name.
+     *
+     * @param string $value
+     */
+    public function setTarget($value)
+    {
+        $this->target = $value;
+    }
+
+    /**
+     * Get media index
+     *
+     * @return int
+     */
+    public function getMediaIndex()
+    {
+        return $this->mediaIndex;
+    }
+
+    /**
+     * Set media index.
+     *
+     * @param int $value
+     */
+    public function setMediaIndex($value)
+    {
+        $this->mediaIndex = $value;
+    }
+
+    /**
+     * Get image string data
+     *
+     * @param bool $base64
+     * @return string|null
+     * @since 0.11.0
+     */
+    public function getImageStringData($base64 = false)
+    {
+        $source = $this->source;
+        $actualSource = null;
+        $imageBinary = null;
+        $imageData = null;
+        $isTemp = false;
+
+        // Get actual source from archive image or other source
+        // Return null if not found
+        if ($this->sourceType == self::SOURCE_ARCHIVE) {
+            $source = substr($source, 6);
+            list($zipFilename, $imageFilename) = explode('#', $source);
+
+            $zip = new ZipArchive();
+            if ($zip->open($zipFilename) !== false) {
+                if ($zip->locateName($imageFilename) !== false) {
+                    $isTemp = true;
+                    $zip->extractTo(Settings::getTempDir(), $imageFilename);
+                    $actualSource = Settings::getTempDir() . DIRECTORY_SEPARATOR . $imageFilename;
+                }
+            }
+            $zip->close();
+        } else {
+            $actualSource = $source;
+        }
+
+        // Can't find any case where $actualSource = null hasn't captured by
+        // preceding exceptions. Please uncomment when you find the case and
+        // put the case into Element\ImageTest.
+        // if ($actualSource === null) {
+        //     return null;
+        // }
+
+        // Read image binary data and convert to hex/base64 string
+        if ($this->sourceType == self::SOURCE_GD) {
+            $imageResource = call_user_func($this->imageCreateFunc, $actualSource);
+            if ($this->imageType === 'image/png') {
+                // PNG images need to preserve alpha channel information
+                imagesavealpha($imageResource, true);
+            }
+            ob_start();
+            call_user_func($this->imageFunc, $imageResource);
+            $imageBinary = ob_get_contents();
+            ob_end_clean();
+        } elseif ($this->sourceType == self::SOURCE_STRING) {
+            $imageBinary = $this->source;
+        } else {
+            $fileHandle = fopen($actualSource, 'rb', false);
+            if ($fileHandle !== false) {
+                $imageBinary = fread($fileHandle, filesize($actualSource));
+                fclose($fileHandle);
+            }
+        }
+        if ($imageBinary !== null) {
+            if ($base64) {
+                $imageData = chunk_split(base64_encode($imageBinary));
+            } else {
+                $imageData = chunk_split(bin2hex($imageBinary));
+            }
+        }
+
+        // Delete temporary file if necessary
+        if ($isTemp === true) {
+            @unlink($actualSource);
+        }
+
+        return $imageData;
+    }
+
+    /**
+     * Check memory image, supported type, image functions, and proportional width/height.
+     *
+     * @throws \PhpOffice\PhpWord\Exception\InvalidImageException
+     * @throws \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException
+     */
+    private function checkImage()
+    {
+        $this->setSourceType();
+
+        // Check image data
+        if ($this->sourceType == self::SOURCE_ARCHIVE) {
+            $imageData = $this->getArchiveImageSize($this->source);
+        } elseif ($this->sourceType == self::SOURCE_STRING) {
+            $imageData = $this->getStringImageSize($this->source);
+        } else {
+            $imageData = @getimagesize($this->source);
+        }
+        if (!is_array($imageData)) {
+            throw new InvalidImageException(sprintf('Invalid image: %s', $this->source));
+        }
+        list($actualWidth, $actualHeight, $imageType) = $imageData;
+
+        // Check image type support
+        $supportedTypes = array(IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_PNG);
+        if ($this->sourceType != self::SOURCE_GD && $this->sourceType != self::SOURCE_STRING) {
+            $supportedTypes = array_merge($supportedTypes, array(IMAGETYPE_BMP, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM));
+        }
+        if (!in_array($imageType, $supportedTypes)) {
+            throw new UnsupportedImageTypeException();
+        }
+
+        // Define image functions
+        $this->imageType = image_type_to_mime_type($imageType);
+        $this->setFunctions();
+        $this->setProportionalSize($actualWidth, $actualHeight);
+    }
+
+    /**
+     * Set source type.
+     */
+    private function setSourceType()
+    {
+        if (stripos(strrev($this->source), strrev('.php')) === 0) {
+            $this->memoryImage = true;
+            $this->sourceType = self::SOURCE_GD;
+        } elseif (strpos($this->source, 'zip://') !== false) {
+            $this->memoryImage = false;
+            $this->sourceType = self::SOURCE_ARCHIVE;
+        } elseif (filter_var($this->source, FILTER_VALIDATE_URL) !== false) {
+            $this->memoryImage = true;
+            if (strpos($this->source, 'https') === 0) {
+                $fileContent = file_get_contents($this->source);
+                $this->source = $fileContent;
+                $this->sourceType = self::SOURCE_STRING;
+            } else {
+                $this->sourceType = self::SOURCE_GD;
+            }
+        } elseif ((strpos($this->source, chr(0)) === false) && @file_exists($this->source)) {
+            $this->memoryImage = false;
+            $this->sourceType = self::SOURCE_LOCAL;
+        } else {
+            $this->memoryImage = true;
+            $this->sourceType = self::SOURCE_STRING;
+        }
+    }
+
+    /**
+     * Get image size from archive
+     *
+     * @since 0.12.0 Throws CreateTemporaryFileException.
+     *
+     * @param string $source
+     *
+     * @throws \PhpOffice\PhpWord\Exception\CreateTemporaryFileException
+     *
+     * @return array|null
+     */
+    private function getArchiveImageSize($source)
+    {
+        $imageData = null;
+        $source = substr($source, 6);
+        list($zipFilename, $imageFilename) = explode('#', $source);
+
+        $tempFilename = tempnam(Settings::getTempDir(), 'PHPWordImage');
+        if (false === $tempFilename) {
+            throw new CreateTemporaryFileException(); // @codeCoverageIgnore
+        }
+
+        $zip = new ZipArchive();
+        if ($zip->open($zipFilename) !== false) {
+            if ($zip->locateName($imageFilename) !== false) {
+                $imageContent = $zip->getFromName($imageFilename);
+                if ($imageContent !== false) {
+                    file_put_contents($tempFilename, $imageContent);
+                    $imageData = getimagesize($tempFilename);
+                    unlink($tempFilename);
+                }
+            }
+            $zip->close();
+        }
+
+        return $imageData;
+    }
+
+    /**
+     * get image size from string
+     *
+     * @param string $source
+     *
+     * @codeCoverageIgnore this method is just a replacement for getimagesizefromstring which exists only as of PHP 5.4
+     */
+    private function getStringImageSize($source)
+    {
+        $result = false;
+        if (!function_exists('getimagesizefromstring')) {
+            $uri = 'data://application/octet-stream;base64,' . base64_encode($source);
+            $result = @getimagesize($uri);
+        } else {
+            $result = @getimagesizefromstring($source);
+        }
+
+        return $result;
+    }
+
+    /**
+     * Set image functions and extensions.
+     */
+    private function setFunctions()
+    {
+        switch ($this->imageType) {
+            case 'image/png':
+                $this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefrompng';
+                $this->imageFunc = 'imagepng';
+                $this->imageExtension = 'png';
+                break;
+            case 'image/gif':
+                $this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefromgif';
+                $this->imageFunc = 'imagegif';
+                $this->imageExtension = 'gif';
+                break;
+            case 'image/jpeg':
+            case 'image/jpg':
+                $this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefromjpeg';
+                $this->imageFunc = 'imagejpeg';
+                $this->imageExtension = 'jpg';
+                break;
+            case 'image/bmp':
+            case 'image/x-ms-bmp':
+                $this->imageType = 'image/bmp';
+                $this->imageExtension = 'bmp';
+                break;
+            case 'image/tiff':
+                $this->imageExtension = 'tif';
+                break;
+        }
+    }
+
+    /**
+     * Set proportional width/height if one dimension not available.
+     *
+     * @param int $actualWidth
+     * @param int $actualHeight
+     */
+    private function setProportionalSize($actualWidth, $actualHeight)
+    {
+        $styleWidth = $this->style->getWidth();
+        $styleHeight = $this->style->getHeight();
+        if (!($styleWidth && $styleHeight)) {
+            if ($styleWidth == null && $styleHeight == null) {
+                $this->style->setWidth($actualWidth);
+                $this->style->setHeight($actualHeight);
+            } elseif ($styleWidth) {
+                $this->style->setHeight($actualHeight * ($styleWidth / $actualWidth));
+            } else {
+                $this->style->setWidth($actualWidth * ($styleHeight / $actualHeight));
+            }
+        }
+    }
+
+    /**
+     * Get is watermark
+     *
+     * @deprecated 0.10.0
+     *
+     * @codeCoverageIgnore
+     */
+    public function getIsWatermark()
+    {
+        return $this->isWatermark();
+    }
+
+    /**
+     * Get is memory image
+     *
+     * @deprecated 0.10.0
+     *
+     * @codeCoverageIgnore
+     */
+    public function getIsMemImage()
+    {
+        return $this->isMemImage();
+    }
+}

+ 53 - 0
addons/qingdong/library/PhpWord/Element/Line.php

@@ -0,0 +1,53 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Style\Line as LineStyle;
+
+/**
+ * Line element
+ */
+class Line extends AbstractElement
+{
+    /**
+     * Line style
+     *
+     * @var \PhpOffice\PhpWord\Style\Line
+     */
+    private $style;
+
+    /**
+     * Create new line element
+     *
+     * @param mixed $style
+     */
+    public function __construct($style = null)
+    {
+        $this->style = $this->setNewStyle(new LineStyle(), $style);
+    }
+
+    /**
+     * Get line style
+     *
+     * @return \PhpOffice\PhpWord\Style\Line
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+}

+ 180 - 0
addons/qingdong/library/PhpWord/Element/Link.php

@@ -0,0 +1,180 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Shared\Text as SharedText;
+use PhpOffice\PhpWord\Style\Font;
+use PhpOffice\PhpWord\Style\Paragraph;
+
+/**
+ * Link element
+ */
+class Link extends AbstractElement
+{
+    /**
+     * Link source
+     *
+     * @var string
+     */
+    private $source;
+
+    /**
+     * Link text
+     *
+     * @var string
+     */
+    private $text;
+
+    /**
+     * Font style
+     *
+     * @var string|\PhpOffice\PhpWord\Style\Font
+     */
+    private $fontStyle;
+
+    /**
+     * Paragraph style
+     *
+     * @var string|\PhpOffice\PhpWord\Style\Paragraph
+     */
+    private $paragraphStyle;
+
+    /**
+     * Has media relation flag; true for Link, Image, and Object
+     *
+     * @var bool
+     */
+    protected $mediaRelation = true;
+
+    /**
+     * Has internal flag - anchor to internal bookmark
+     *
+     * @var bool
+     */
+    protected $internal = false;
+
+    /**
+     * Create a new Link Element
+     *
+     * @param string $source
+     * @param string $text
+     * @param mixed $fontStyle
+     * @param mixed $paragraphStyle
+     * @param bool $internal
+     */
+    public function __construct($source, $text = null, $fontStyle = null, $paragraphStyle = null, $internal = false)
+    {
+        $this->source = SharedText::toUTF8($source);
+        $this->text = is_null($text) ? $this->source : SharedText::toUTF8($text);
+        $this->fontStyle = $this->setNewStyle(new Font('text'), $fontStyle);
+        $this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle);
+        $this->internal = $internal;
+    }
+
+    /**
+     * Get link source
+     *
+     * @return string
+     */
+    public function getSource()
+    {
+        return $this->source;
+    }
+
+    /**
+     * Get link text
+     *
+     * @return string
+     */
+    public function getText()
+    {
+        return $this->text;
+    }
+
+    /**
+     * Get Text style
+     *
+     * @return string|\PhpOffice\PhpWord\Style\Font
+     */
+    public function getFontStyle()
+    {
+        return $this->fontStyle;
+    }
+
+    /**
+     * Get Paragraph style
+     *
+     * @return string|\PhpOffice\PhpWord\Style\Paragraph
+     */
+    public function getParagraphStyle()
+    {
+        return $this->paragraphStyle;
+    }
+
+    /**
+     * Get link target
+     *
+     * @deprecated 0.12.0
+     *
+     * @return string
+     *
+     * @codeCoverageIgnore
+     */
+    public function getTarget()
+    {
+        return $this->source;
+    }
+
+    /**
+     * Get Link source
+     *
+     * @deprecated 0.10.0
+     *
+     * @return string
+     *
+     * @codeCoverageIgnore
+     */
+    public function getLinkSrc()
+    {
+        return $this->getSource();
+    }
+
+    /**
+     * Get Link name
+     *
+     * @deprecated 0.10.0
+     *
+     * @return string
+     *
+     * @codeCoverageIgnore
+     */
+    public function getLinkName()
+    {
+        return $this->getText();
+    }
+
+    /**
+     * is internal
+     *
+     * @return bool
+     */
+    public function isInternal()
+    {
+        return $this->internal;
+    }
+}

+ 111 - 0
addons/qingdong/library/PhpWord/Element/ListItem.php

@@ -0,0 +1,111 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Shared\Text as SharedText;
+use PhpOffice\PhpWord\Style\ListItem as ListItemStyle;
+
+/**
+ * List item element
+ */
+class ListItem extends AbstractElement
+{
+    /**
+     * Element style
+     *
+     * @var \PhpOffice\PhpWord\Style\ListItem
+     */
+    private $style;
+
+    /**
+     * Text object
+     *
+     * @var \PhpOffice\PhpWord\Element\Text
+     */
+    private $textObject;
+
+    /**
+     * Depth
+     *
+     * @var int
+     */
+    private $depth;
+
+    /**
+     * Create a new ListItem
+     *
+     * @param string $text
+     * @param int $depth
+     * @param mixed $fontStyle
+     * @param array|string|null $listStyle
+     * @param mixed $paragraphStyle
+     */
+    public function __construct($text, $depth = 0, $fontStyle = null, $listStyle = null, $paragraphStyle = null)
+    {
+        $this->textObject = new Text(SharedText::toUTF8($text), $fontStyle, $paragraphStyle);
+        $this->depth = $depth;
+
+        // Version >= 0.10.0 will pass numbering style name. Older version will use old method
+        if (!is_null($listStyle) && is_string($listStyle)) {
+            $this->style = new ListItemStyle($listStyle); // @codeCoverageIgnore
+        } else {
+            $this->style = $this->setNewStyle(new ListItemStyle(), $listStyle, true);
+        }
+    }
+
+    /**
+     * Get style
+     *
+     * @return \PhpOffice\PhpWord\Style\ListItem
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+
+    /**
+     * Get Text object
+     *
+     * @return \PhpOffice\PhpWord\Element\Text
+     */
+    public function getTextObject()
+    {
+        return $this->textObject;
+    }
+
+    /**
+     * Get depth
+     *
+     * @return int
+     */
+    public function getDepth()
+    {
+        return $this->depth;
+    }
+
+    /**
+     * Get text
+     *
+     * @return string
+     * @since 0.11.0
+     */
+    public function getText()
+    {
+        return $this->textObject->getText();
+    }
+}

+ 85 - 0
addons/qingdong/library/PhpWord/Element/ListItemRun.php

@@ -0,0 +1,85 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+* word processing documents.
+*
+* PHPWord is free software distributed under the terms of the GNU Lesser
+* General Public License version 3 as published by the Free Software Foundation.
+*
+* For the full copyright and license information, please read the LICENSE
+* file that was distributed with this source code. For the full list of
+* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+*
+* @see         https://github.com/PHPOffice/PHPWord
+* @copyright   2010-2018 PHPWord contributors
+* @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+*/
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Style\ListItem as ListItemStyle;
+
+/**
+ * List item element
+ */
+class ListItemRun extends TextRun
+{
+    /**
+     * @var string Container type
+     */
+    protected $container = 'ListItemRun';
+
+    /**
+     * ListItem Style
+     *
+     * @var \PhpOffice\PhpWord\Style\ListItem
+     */
+    private $style;
+
+    /**
+     * ListItem Depth
+     *
+     * @var int
+     */
+    private $depth;
+
+    /**
+     * Create a new ListItem
+     *
+     * @param int $depth
+     * @param array|string|null $listStyle
+     * @param mixed $paragraphStyle
+     */
+    public function __construct($depth = 0, $listStyle = null, $paragraphStyle = null)
+    {
+        $this->depth = $depth;
+
+        // Version >= 0.10.0 will pass numbering style name. Older version will use old method
+        if (!is_null($listStyle) && is_string($listStyle)) {
+            $this->style = new ListItemStyle($listStyle);
+        } else {
+            $this->style = $this->setNewStyle(new ListItemStyle(), $listStyle, true);
+        }
+        parent::__construct($paragraphStyle);
+    }
+
+    /**
+     * Get ListItem style.
+     *
+     * @return \PhpOffice\PhpWord\Style\ListItem
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+
+    /**
+     * Get ListItem depth.
+     *
+     * @return int
+     */
+    public function getDepth()
+    {
+        return $this->depth;
+    }
+}

+ 169 - 0
addons/qingdong/library/PhpWord/Element/OLEObject.php

@@ -0,0 +1,169 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Exception\InvalidObjectException;
+use PhpOffice\PhpWord\Style\Image as ImageStyle;
+
+/**
+ * OLEObject element
+ */
+class OLEObject extends AbstractElement
+{
+    /**
+     * Ole-Object Src
+     *
+     * @var string
+     */
+    private $source;
+
+    /**
+     * Image Style
+     *
+     * @var \PhpOffice\PhpWord\Style\Image
+     */
+    private $style;
+
+    /**
+     * Icon
+     *
+     * @var string
+     */
+    private $icon;
+
+    /**
+     * Image Relation ID
+     *
+     * @var int
+     */
+    private $imageRelationId;
+
+    /**
+     * Has media relation flag; true for Link, Image, and Object
+     *
+     * @var bool
+     */
+    protected $mediaRelation = true;
+
+    /**
+     * Create a new Ole-Object Element
+     *
+     * @param string $source
+     * @param mixed $style
+     *
+     * @throws \PhpOffice\PhpWord\Exception\InvalidObjectException
+     */
+    public function __construct($source, $style = null)
+    {
+        $supportedTypes = array('xls', 'doc', 'ppt', 'xlsx', 'docx', 'pptx');
+        $pathInfo = pathinfo($source);
+
+        if (file_exists($source) && in_array($pathInfo['extension'], $supportedTypes)) {
+            $ext = $pathInfo['extension'];
+            if (strlen($ext) == 4 && strtolower(substr($ext, -1)) == 'x') {
+                $ext = substr($ext, 0, -1);
+            }
+
+            $this->source = $source;
+            $this->style = $this->setNewStyle(new ImageStyle(), $style, true);
+            $this->icon = realpath(__DIR__ . "/../resources/{$ext}.png");
+
+            return;
+        }
+
+        throw new InvalidObjectException();
+    }
+
+    /**
+     * Get object source
+     *
+     * @return string
+     */
+    public function getSource()
+    {
+        return $this->source;
+    }
+
+    /**
+     * Get object style
+     *
+     * @return \PhpOffice\PhpWord\Style\Image
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+
+    /**
+     * Get object icon
+     *
+     * @return string
+     */
+    public function getIcon()
+    {
+        return $this->icon;
+    }
+
+    /**
+     * Get image relation ID
+     *
+     * @return int
+     */
+    public function getImageRelationId()
+    {
+        return $this->imageRelationId;
+    }
+
+    /**
+     * Set Image Relation ID.
+     *
+     * @param int $rId
+     */
+    public function setImageRelationId($rId)
+    {
+        $this->imageRelationId = $rId;
+    }
+
+    /**
+     * Get Object ID
+     *
+     * @deprecated 0.10.0
+     *
+     * @return int
+     *
+     * @codeCoverageIgnore
+     */
+    public function getObjectId()
+    {
+        return $this->relationId + 1325353440;
+    }
+
+    /**
+     * Set Object ID
+     *
+     * @deprecated 0.10.0
+     *
+     * @param int $objId
+     *
+     * @codeCoverageIgnore
+     */
+    public function setObjectId($objId)
+    {
+        $this->relationId = $objId;
+    }
+}

+ 31 - 0
addons/qingdong/library/PhpWord/Element/PageBreak.php

@@ -0,0 +1,31 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+/**
+ * Page break element
+ */
+class PageBreak extends AbstractElement
+{
+    /**
+     * Create new page break
+     */
+    public function __construct()
+    {
+    }
+}

+ 98 - 0
addons/qingdong/library/PhpWord/Element/PreserveText.php

@@ -0,0 +1,98 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Shared\Text as SharedText;
+use PhpOffice\PhpWord\Style\Font;
+use PhpOffice\PhpWord\Style\Paragraph;
+
+/**
+ * Preserve text/field element
+ */
+class PreserveText extends AbstractElement
+{
+    /**
+     * Text content
+     *
+     * @var string|array
+     */
+    private $text;
+
+    /**
+     * Text style
+     *
+     * @var string|\PhpOffice\PhpWord\Style\Font
+     */
+    private $fontStyle;
+
+    /**
+     * Paragraph style
+     *
+     * @var string|\PhpOffice\PhpWord\Style\Paragraph
+     */
+    private $paragraphStyle;
+
+    /**
+     * Create a new Preserve Text Element
+     *
+     * @param string $text
+     * @param mixed $fontStyle
+     * @param mixed $paragraphStyle
+     */
+    public function __construct($text = null, $fontStyle = null, $paragraphStyle = null)
+    {
+        $this->fontStyle = $this->setNewStyle(new Font('text'), $fontStyle);
+        $this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle);
+
+        $this->text = SharedText::toUTF8($text);
+        $matches = preg_split('/({.*?})/', $this->text, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
+        if (isset($matches[0])) {
+            $this->text = $matches;
+        }
+    }
+
+    /**
+     * Get Text style
+     *
+     * @return string|\PhpOffice\PhpWord\Style\Font
+     */
+    public function getFontStyle()
+    {
+        return $this->fontStyle;
+    }
+
+    /**
+     * Get Paragraph style
+     *
+     * @return string|\PhpOffice\PhpWord\Style\Paragraph
+     */
+    public function getParagraphStyle()
+    {
+        return $this->paragraphStyle;
+    }
+
+    /**
+     * Get Text content
+     *
+     * @return string|array
+     */
+    public function getText()
+    {
+        return $this->text;
+    }
+}

+ 107 - 0
addons/qingdong/library/PhpWord/Element/Row.php

@@ -0,0 +1,107 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Style\Row as RowStyle;
+
+/**
+ * Table row element
+ *
+ * @since 0.8.0
+ */
+class Row extends AbstractElement
+{
+    /**
+     * Row height
+     *
+     * @var int
+     */
+    private $height = null;
+
+    /**
+     * Row style
+     *
+     * @var \PhpOffice\PhpWord\Style\Row
+     */
+    private $style;
+
+    /**
+     * Row cells
+     *
+     * @var \PhpOffice\PhpWord\Element\Cell[]
+     */
+    private $cells = array();
+
+    /**
+     * Create a new table row
+     *
+     * @param int $height
+     * @param mixed $style
+     */
+    public function __construct($height = null, $style = null)
+    {
+        $this->height = $height;
+        $this->style = $this->setNewStyle(new RowStyle(), $style, true);
+    }
+
+    /**
+     * Add a cell
+     *
+     * @param int $width
+     * @param mixed $style
+     * @return \PhpOffice\PhpWord\Element\Cell
+     */
+    public function addCell($width = null, $style = null)
+    {
+        $cell = new Cell($width, $style);
+        $cell->setParentContainer($this);
+        $this->cells[] = $cell;
+
+        return $cell;
+    }
+
+    /**
+     * Get all cells
+     *
+     * @return \PhpOffice\PhpWord\Element\Cell[]
+     */
+    public function getCells()
+    {
+        return $this->cells;
+    }
+
+    /**
+     * Get row style
+     *
+     * @return \PhpOffice\PhpWord\Style\Row
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+
+    /**
+     * Get row height
+     *
+     * @return int
+     */
+    public function getHeight()
+    {
+        return $this->height;
+    }
+}

+ 190 - 0
addons/qingdong/library/PhpWord/Element/SDT.php

@@ -0,0 +1,190 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+/**
+ * Structured document tag (SDT) element
+ *
+ * @since 0.12.0
+ */
+class SDT extends Text
+{
+    /**
+     * Form field type: comboBox|dropDownList|date
+     *
+     * @var string
+     */
+    private $type;
+
+    /**
+     * Value
+     *
+     * @var string|bool|int
+     */
+    private $value;
+
+    /**
+     * CheckBox/DropDown list entries
+     *
+     * @var array
+     */
+    private $listItems = array();
+
+    /**
+     * Alias
+     *
+     * @var string
+     */
+    private $alias;
+
+    /**
+     * Tag
+     *
+     * @var string
+     */
+    private $tag;
+
+    /**
+     * Create new instance
+     *
+     * @param string $type
+     * @param mixed $fontStyle
+     * @param mixed $paragraphStyle
+     */
+    public function __construct($type, $fontStyle = null, $paragraphStyle = null)
+    {
+        parent::__construct(null, $fontStyle, $paragraphStyle);
+        $this->setType($type);
+    }
+
+    /**
+     * Get type
+     *
+     * @return string
+     */
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    /**
+     * Set type
+     *
+     * @param string $value
+     * @return self
+     */
+    public function setType($value)
+    {
+        $enum = array('plainText', 'comboBox', 'dropDownList', 'date');
+        $this->type = $this->setEnumVal($value, $enum, 'comboBox');
+
+        return $this;
+    }
+
+    /**
+     * Get value
+     *
+     * @return string|bool|int
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+
+    /**
+     * Set value
+     *
+     * @param string|bool|int $value
+     * @return self
+     */
+    public function setValue($value)
+    {
+        $this->value = $value;
+
+        return $this;
+    }
+
+    /**
+     * Get listItems
+     *
+     * @return array
+     */
+    public function getListItems()
+    {
+        return $this->listItems;
+    }
+
+    /**
+     * Set listItems
+     *
+     * @param array $value
+     * @return self
+     */
+    public function setListItems($value)
+    {
+        $this->listItems = $value;
+
+        return $this;
+    }
+
+    /**
+     * Get tag
+     *
+     * @return string
+     */
+    public function getTag()
+    {
+        return $this->tag;
+    }
+
+    /**
+     * Set tag
+     *
+     * @param string $tag
+     * @return self
+     */
+    public function setTag($tag)
+    {
+        $this->tag = $tag;
+
+        return $this;
+    }
+
+    /**
+     * Get alias
+     *
+     * @return string
+     */
+    public function getAlias()
+    {
+        return $this->alias;
+    }
+
+    /**
+     * Set alias
+     *
+     * @param string $alias
+     * @return self
+     */
+    public function setAlias($alias)
+    {
+        $this->alias = $alias;
+
+        return $this;
+    }
+}

+ 307 - 0
addons/qingdong/library/PhpWord/Element/Section.php

@@ -0,0 +1,307 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\ComplexType\FootnoteProperties;
+use PhpOffice\PhpWord\Style\Section as SectionStyle;
+
+class Section extends AbstractContainer
+{
+    /**
+     * @var string Container type
+     */
+    protected $container = 'Section';
+
+    /**
+     * Section style
+     *
+     * @var \PhpOffice\PhpWord\Style\Section
+     */
+    private $style;
+
+    /**
+     * Section headers, indexed from 1, not zero
+     *
+     * @var Header[]
+     */
+    private $headers = array();
+
+    /**
+     * Section footers, indexed from 1, not zero
+     *
+     * @var Footer[]
+     */
+    private $footers = array();
+
+    /**
+     * The properties for the footnote of this section
+     *
+     * @var FootnoteProperties
+     */
+    private $footnoteProperties;
+
+    /**
+     * Create new instance
+     *
+     * @param int $sectionCount
+     * @param null|array|\PhpOffice\PhpWord\Style $style
+     */
+    public function __construct($sectionCount, $style = null)
+    {
+        $this->sectionId = $sectionCount;
+        $this->setDocPart($this->container, $this->sectionId);
+        if (null === $style) {
+            $style = new SectionStyle();
+        }
+        $this->style = $this->setNewStyle(new SectionStyle(), $style);
+    }
+
+    /**
+     * Set section style.
+     *
+     * @param array $style
+     */
+    public function setStyle($style = null)
+    {
+        if (!is_null($style) && is_array($style)) {
+            $this->style->setStyleByArray($style);
+        }
+    }
+
+    /**
+     * Get section style
+     *
+     * @return \PhpOffice\PhpWord\Style\Section
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+
+    /**
+     * Add header
+     *
+     * @since 0.10.0
+     *
+     * @param string $type
+     *
+     * @return Header
+     */
+    public function addHeader($type = Header::AUTO)
+    {
+        return $this->addHeaderFooter($type, true);
+    }
+
+    /**
+     * Add footer
+     *
+     * @since 0.10.0
+     *
+     * @param string $type
+     *
+     * @return Footer
+     */
+    public function addFooter($type = Header::AUTO)
+    {
+        return $this->addHeaderFooter($type, false);
+    }
+
+    /**
+     * Get header elements
+     *
+     * @return Header[]
+     */
+    public function getHeaders()
+    {
+        return $this->headers;
+    }
+
+    /**
+     * Get footer elements
+     *
+     * @return Footer[]
+     */
+    public function getFooters()
+    {
+        return $this->footers;
+    }
+
+    /**
+     * Get the footnote properties
+     *
+     * @return FootnoteProperties
+     */
+    public function getFootnoteProperties()
+    {
+        return $this->footnoteProperties;
+    }
+
+    /**
+     * Get the footnote properties
+     *
+     * @deprecated Use the `getFootnoteProperties` method instead
+     *
+     * @return FootnoteProperties
+     *
+     * @codeCoverageIgnore
+     */
+    public function getFootnotePropoperties()
+    {
+        return $this->footnoteProperties;
+    }
+
+    /**
+     * Set the footnote properties
+     *
+     * @param FootnoteProperties $footnoteProperties
+     */
+    public function setFootnoteProperties(FootnoteProperties $footnoteProperties = null)
+    {
+        $this->footnoteProperties = $footnoteProperties;
+    }
+
+    /**
+     * Is there a header for this section that is for the first page only?
+     *
+     * If any of the Header instances have a type of Header::FIRST then this method returns true.
+     * False otherwise.
+     *
+     * @return bool
+     */
+    public function hasDifferentFirstPage()
+    {
+        foreach ($this->headers as $header) {
+            if ($header->getType() == Header::FIRST) {
+                return true;
+            }
+        }
+        foreach ($this->footers as $footer) {
+            if ($footer->getType() == Header::FIRST) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Add header/footer
+     *
+     * @since 0.10.0
+     *
+     * @param string $type
+     * @param bool $header
+     *
+     * @throws \Exception
+     *
+     * @return Header|Footer
+     */
+    private function addHeaderFooter($type = Header::AUTO, $header = true)
+    {
+        $containerClass = substr(get_class($this), 0, strrpos(get_class($this), '\\')) . '\\' .
+            ($header ? 'Header' : 'Footer');
+        $collectionArray = $header ? 'headers' : 'footers';
+        $collection = &$this->$collectionArray;
+
+        if (in_array($type, array(Header::AUTO, Header::FIRST, Header::EVEN))) {
+            $index = count($collection);
+            /** @var \PhpOffice\PhpWord\Element\AbstractContainer $container Type hint */
+            $container = new $containerClass($this->sectionId, ++$index, $type);
+            $container->setPhpWord($this->phpWord);
+
+            $collection[$index] = $container;
+
+            return $container;
+        }
+        throw new \Exception('Invalid header/footer type.');
+    }
+
+    /**
+     * Set section style
+     *
+     * @deprecated 0.12.0
+     *
+     * @param array $settings
+     *
+     * @codeCoverageIgnore
+     */
+    public function setSettings($settings = null)
+    {
+        $this->setStyle($settings);
+    }
+
+    /**
+     * Get section style
+     *
+     * @deprecated 0.12.0
+     *
+     * @return \PhpOffice\PhpWord\Style\Section
+     *
+     * @codeCoverageIgnore
+     */
+    public function getSettings()
+    {
+        return $this->getStyle();
+    }
+
+    /**
+     * Create header
+     *
+     * @deprecated 0.10.0
+     *
+     * @return Header
+     *
+     * @codeCoverageIgnore
+     */
+    public function createHeader()
+    {
+        return $this->addHeader();
+    }
+
+    /**
+     * Create footer
+     *
+     * @deprecated 0.10.0
+     *
+     * @return Footer
+     *
+     * @codeCoverageIgnore
+     */
+    public function createFooter()
+    {
+        return $this->addFooter();
+    }
+
+    /**
+     * Get footer
+     *
+     * @deprecated 0.10.0
+     *
+     * @return Footer
+     *
+     * @codeCoverageIgnore
+     */
+    public function getFooter()
+    {
+        if (empty($this->footers)) {
+            return null;
+        }
+
+        return $this->footers[1];
+    }
+}

+ 88 - 0
addons/qingdong/library/PhpWord/Element/Shape.php

@@ -0,0 +1,88 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Style\Shape as ShapeStyle;
+
+/**
+ * Shape element
+ *
+ * @since 0.12.0
+ */
+class Shape extends AbstractElement
+{
+    /**
+     * Shape type arc|curve|line|polyline|rect|oval
+     *
+     * @var string
+     */
+    private $type;
+
+    /**
+     * Shape style
+     *
+     * @var \PhpOffice\PhpWord\Style\Shape
+     */
+    private $style;
+
+    /**
+     * Create new instance
+     *
+     * @param string $type
+     * @param mixed $style
+     */
+    public function __construct($type, $style = null)
+    {
+        $this->setType($type);
+        $this->style = $this->setNewStyle(new ShapeStyle(), $style);
+    }
+
+    /**
+     * Get type
+     *
+     * @return string
+     */
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    /**
+     * Set pattern
+     *
+     * @param string $value
+     * @return self
+     */
+    public function setType($value = null)
+    {
+        $enum = array('arc', 'curve', 'line', 'polyline', 'rect', 'oval');
+        $this->type = $this->setEnumVal($value, $enum, null);
+
+        return $this;
+    }
+
+    /**
+     * Get shape style
+     *
+     * @return \PhpOffice\PhpWord\Style\Shape
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+}

+ 169 - 0
addons/qingdong/library/PhpWord/Element/TOC.php

@@ -0,0 +1,169 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\PhpWord;
+use PhpOffice\PhpWord\Style\Font;
+use PhpOffice\PhpWord\Style\TOC as TOCStyle;
+
+/**
+ * Table of contents
+ */
+class TOC extends AbstractElement
+{
+    /**
+     * TOC style
+     *
+     * @var \PhpOffice\PhpWord\Style\TOC
+     */
+    private $TOCStyle;
+
+    /**
+     * Font style
+     *
+     * @var \PhpOffice\PhpWord\Style\Font|string
+     */
+    private $fontStyle;
+
+    /**
+     * Min title depth to show
+     *
+     * @var int
+     */
+    private $minDepth = 1;
+
+    /**
+     * Max title depth to show
+     *
+     * @var int
+     */
+    private $maxDepth = 9;
+
+    /**
+     * Create a new Table-of-Contents Element
+     *
+     * @param mixed $fontStyle
+     * @param array $tocStyle
+     * @param int $minDepth
+     * @param int $maxDepth
+     */
+    public function __construct($fontStyle = null, $tocStyle = null, $minDepth = 1, $maxDepth = 9)
+    {
+        $this->TOCStyle = new TOCStyle();
+
+        if (!is_null($tocStyle) && is_array($tocStyle)) {
+            $this->TOCStyle->setStyleByArray($tocStyle);
+        }
+
+        if (!is_null($fontStyle) && is_array($fontStyle)) {
+            $this->fontStyle = new Font();
+            $this->fontStyle->setStyleByArray($fontStyle);
+        } else {
+            $this->fontStyle = $fontStyle;
+        }
+
+        $this->minDepth = $minDepth;
+        $this->maxDepth = $maxDepth;
+    }
+
+    /**
+     * Get all titles
+     *
+     * @return array
+     */
+    public function getTitles()
+    {
+        if (!$this->phpWord instanceof PhpWord) {
+            return array();
+        }
+
+        $titles = $this->phpWord->getTitles()->getItems();
+        foreach ($titles as $i => $title) {
+            /** @var \PhpOffice\PhpWord\Element\Title $title Type hint */
+            $depth = $title->getDepth();
+            if ($this->minDepth > $depth) {
+                unset($titles[$i]);
+            }
+            if (($this->maxDepth != 0) && ($this->maxDepth < $depth)) {
+                unset($titles[$i]);
+            }
+        }
+
+        return $titles;
+    }
+
+    /**
+     * Get TOC Style
+     *
+     * @return \PhpOffice\PhpWord\Style\TOC
+     */
+    public function getStyleTOC()
+    {
+        return $this->TOCStyle;
+    }
+
+    /**
+     * Get Font Style
+     *
+     * @return \PhpOffice\PhpWord\Style\Font|string
+     */
+    public function getStyleFont()
+    {
+        return $this->fontStyle;
+    }
+
+    /**
+     * Set max depth.
+     *
+     * @param int $value
+     */
+    public function setMaxDepth($value)
+    {
+        $this->maxDepth = $value;
+    }
+
+    /**
+     * Get Max Depth
+     *
+     * @return int Max depth of titles
+     */
+    public function getMaxDepth()
+    {
+        return $this->maxDepth;
+    }
+
+    /**
+     * Set min depth.
+     *
+     * @param int $value
+     */
+    public function setMinDepth($value)
+    {
+        $this->minDepth = $value;
+    }
+
+    /**
+     * Get Min Depth
+     *
+     * @return int Min depth of titles
+     */
+    public function getMinDepth()
+    {
+        return $this->minDepth;
+    }
+}

+ 174 - 0
addons/qingdong/library/PhpWord/Element/Table.php

@@ -0,0 +1,174 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Style\Table as TableStyle;
+
+/**
+ * Table element
+ */
+class Table extends AbstractElement
+{
+    /**
+     * Table style
+     *
+     * @var \PhpOffice\PhpWord\Style\Table
+     */
+    private $style;
+
+    /**
+     * Table rows
+     *
+     * @var \PhpOffice\PhpWord\Element\Row[]
+     */
+    private $rows = array();
+
+    /**
+     * Table width
+     *
+     * @var int
+     */
+    private $width = null;
+
+    /**
+     * Create a new table
+     *
+     * @param mixed $style
+     */
+    public function __construct($style = null)
+    {
+        $this->style = $this->setNewStyle(new TableStyle(), $style);
+    }
+
+    /**
+     * Add a row
+     *
+     * @param int $height
+     * @param mixed $style
+     * @return \PhpOffice\PhpWord\Element\Row
+     */
+    public function addRow($height = null, $style = null)
+    {
+        $row = new Row($height, $style);
+        $row->setParentContainer($this);
+        $this->rows[] = $row;
+
+        return $row;
+    }
+
+    /**
+     * Add a cell
+     *
+     * @param int $width
+     * @param mixed $style
+     * @return \PhpOffice\PhpWord\Element\Cell
+     */
+    public function addCell($width = null, $style = null)
+    {
+        $index = count($this->rows) - 1;
+        $row = $this->rows[$index];
+        $cell = $row->addCell($width, $style);
+
+        return $cell;
+    }
+
+    /**
+     * Get all rows
+     *
+     * @return \PhpOffice\PhpWord\Element\Row[]
+     */
+    public function getRows()
+    {
+        return $this->rows;
+    }
+
+    /**
+     * Get table style
+     *
+     * @return \PhpOffice\PhpWord\Style\Table
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+
+    /**
+     * Get table width
+     *
+     * @return int
+     */
+    public function getWidth()
+    {
+        return $this->width;
+    }
+
+    /**
+     * Set table width.
+     *
+     * @param int $width
+     */
+    public function setWidth($width)
+    {
+        $this->width = $width;
+    }
+
+    /**
+     * Get column count
+     *
+     * @return int
+     */
+    public function countColumns()
+    {
+        $columnCount = 0;
+
+        $rowCount = count($this->rows);
+        for ($i = 0; $i < $rowCount; $i++) {
+            /** @var \PhpOffice\PhpWord\Element\Row $row Type hint */
+            $row = $this->rows[$i];
+            $cellCount = count($row->getCells());
+            if ($columnCount < $cellCount) {
+                $columnCount = $cellCount;
+            }
+        }
+
+        return $columnCount;
+    }
+
+    /**
+     * The first declared cell width for each column
+     *
+     * @return int[]
+     */
+    public function findFirstDefinedCellWidths()
+    {
+        $cellWidths = array();
+
+        foreach ($this->rows as $row) {
+            $cells = $row->getCells();
+            if (count($cells) <= count($cellWidths)) {
+                continue;
+            }
+            $cellWidths = array();
+            foreach ($cells as $cell) {
+                $cellWidths[] = $cell->getWidth();
+            }
+        }
+
+        return $cellWidths;
+    }
+}

+ 153 - 0
addons/qingdong/library/PhpWord/Element/Text.php

@@ -0,0 +1,153 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Shared\Text as SharedText;
+use PhpOffice\PhpWord\Style\Font;
+use PhpOffice\PhpWord\Style\Paragraph;
+
+/**
+ * Text element
+ */
+class Text extends AbstractElement
+{
+    /**
+     * Text content
+     *
+     * @var string
+     */
+    protected $text;
+
+    /**
+     * Text style
+     *
+     * @var string|\PhpOffice\PhpWord\Style\Font
+     */
+    protected $fontStyle;
+
+    /**
+     * Paragraph style
+     *
+     * @var string|\PhpOffice\PhpWord\Style\Paragraph
+     */
+    protected $paragraphStyle;
+
+    /**
+     * Create a new Text Element
+     *
+     * @param string $text
+     * @param mixed $fontStyle
+     * @param mixed $paragraphStyle
+     */
+    public function __construct($text = null, $fontStyle = null, $paragraphStyle = null)
+    {
+        $this->setText($text);
+        $paragraphStyle = $this->setParagraphStyle($paragraphStyle);
+        $this->setFontStyle($fontStyle, $paragraphStyle);
+    }
+
+    /**
+     * Set Text style
+     *
+     * @param string|array|\PhpOffice\PhpWord\Style\Font $style
+     * @param string|array|\PhpOffice\PhpWord\Style\Paragraph $paragraphStyle
+     * @return string|\PhpOffice\PhpWord\Style\Font
+     */
+    public function setFontStyle($style = null, $paragraphStyle = null)
+    {
+        if ($style instanceof Font) {
+            $this->fontStyle = $style;
+            $this->setParagraphStyle($paragraphStyle);
+        } elseif (is_array($style)) {
+            $this->fontStyle = new Font('text', $paragraphStyle);
+            $this->fontStyle->setStyleByArray($style);
+        } elseif (null === $style) {
+            $this->fontStyle = new Font('text', $paragraphStyle);
+        } else {
+            $this->fontStyle = $style;
+            $this->setParagraphStyle($paragraphStyle);
+        }
+
+        return $this->fontStyle;
+    }
+
+    /**
+     * Get Text style
+     *
+     * @return string|\PhpOffice\PhpWord\Style\Font
+     */
+    public function getFontStyle()
+    {
+        return $this->fontStyle;
+    }
+
+    /**
+     * Set Paragraph style
+     *
+     * @param string|array|\PhpOffice\PhpWord\Style\Paragraph $style
+     * @return string|\PhpOffice\PhpWord\Style\Paragraph
+     */
+    public function setParagraphStyle($style = null)
+    {
+        if (is_array($style)) {
+            $this->paragraphStyle = new Paragraph();
+            $this->paragraphStyle->setStyleByArray($style);
+        } elseif ($style instanceof Paragraph) {
+            $this->paragraphStyle = $style;
+        } elseif (null === $style) {
+            $this->paragraphStyle = new Paragraph();
+        } else {
+            $this->paragraphStyle = $style;
+        }
+
+        return $this->paragraphStyle;
+    }
+
+    /**
+     * Get Paragraph style
+     *
+     * @return string|\PhpOffice\PhpWord\Style\Paragraph
+     */
+    public function getParagraphStyle()
+    {
+        return $this->paragraphStyle;
+    }
+
+    /**
+     * Set text content
+     *
+     * @param string $text
+     * @return self
+     */
+    public function setText($text)
+    {
+        $this->text = SharedText::toUTF8($text);
+
+        return $this;
+    }
+
+    /**
+     * Get Text content
+     *
+     * @return string
+     */
+    public function getText()
+    {
+        return $this->text;
+    }
+}

+ 60 - 0
addons/qingdong/library/PhpWord/Element/TextBox.php

@@ -0,0 +1,60 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Style\TextBox as TextBoxStyle;
+
+/**
+ * TextBox element
+ *
+ * @since 0.11.0
+ */
+class TextBox extends AbstractContainer
+{
+    /**
+     * @var string Container type
+     */
+    protected $container = 'TextBox';
+
+    /**
+     * TextBox style
+     *
+     * @var \PhpOffice\PhpWord\Style\TextBox
+     */
+    private $style;
+
+    /**
+     * Create a new textbox
+     *
+     * @param mixed $style
+     */
+    public function __construct($style = null)
+    {
+        $this->style = $this->setNewStyle(new TextBoxStyle(), $style);
+    }
+
+    /**
+     * Get textbox style
+     *
+     * @return \PhpOffice\PhpWord\Style\TextBox
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+}

+ 130 - 0
addons/qingdong/library/PhpWord/Element/TextBreak.php

@@ -0,0 +1,130 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Style\Font;
+use PhpOffice\PhpWord\Style\Paragraph;
+
+/**
+ * Text break element
+ */
+class TextBreak extends AbstractElement
+{
+    /**
+     * Paragraph style
+     *
+     * @var string|\PhpOffice\PhpWord\Style\Paragraph
+     */
+    private $paragraphStyle = null;
+
+    /**
+     * Text style
+     *
+     * @var string|\PhpOffice\PhpWord\Style\Font
+     */
+    private $fontStyle = null;
+
+    /**
+     * Create a new TextBreak Element
+     *
+     * @param mixed $fontStyle
+     * @param mixed $paragraphStyle
+     */
+    public function __construct($fontStyle = null, $paragraphStyle = null)
+    {
+        if (!is_null($paragraphStyle)) {
+            $paragraphStyle = $this->setParagraphStyle($paragraphStyle);
+        }
+        if (!is_null($fontStyle)) {
+            $this->setFontStyle($fontStyle, $paragraphStyle);
+        }
+    }
+
+    /**
+     * Set Text style
+     *
+     * @param mixed $style
+     * @param mixed $paragraphStyle
+     * @return string|\PhpOffice\PhpWord\Style\Font
+     */
+    public function setFontStyle($style = null, $paragraphStyle = null)
+    {
+        if ($style instanceof Font) {
+            $this->fontStyle = $style;
+            $this->setParagraphStyle($paragraphStyle);
+        } elseif (is_array($style)) {
+            $this->fontStyle = new Font('text', $paragraphStyle);
+            $this->fontStyle->setStyleByArray($style);
+        } else {
+            $this->fontStyle = $style;
+            $this->setParagraphStyle($paragraphStyle);
+        }
+
+        return $this->fontStyle;
+    }
+
+    /**
+     * Get Text style
+     *
+     * @return string|\PhpOffice\PhpWord\Style\Font
+     */
+    public function getFontStyle()
+    {
+        return $this->fontStyle;
+    }
+
+    /**
+     * Set Paragraph style
+     *
+     * @param   string|array|\PhpOffice\PhpWord\Style\Paragraph $style
+     * @return  string|\PhpOffice\PhpWord\Style\Paragraph
+     */
+    public function setParagraphStyle($style = null)
+    {
+        if (is_array($style)) {
+            $this->paragraphStyle = new Paragraph();
+            $this->paragraphStyle->setStyleByArray($style);
+        } elseif ($style instanceof Paragraph) {
+            $this->paragraphStyle = $style;
+        } else {
+            $this->paragraphStyle = $style;
+        }
+
+        return $this->paragraphStyle;
+    }
+
+    /**
+     * Get Paragraph style
+     *
+     * @return string|\PhpOffice\PhpWord\Style\Paragraph
+     */
+    public function getParagraphStyle()
+    {
+        return $this->paragraphStyle;
+    }
+
+    /**
+     * Has font/paragraph style defined
+     *
+     * @return bool
+     */
+    public function hasStyle()
+    {
+        return !is_null($this->fontStyle) || !is_null($this->paragraphStyle);
+    }
+}

+ 80 - 0
addons/qingdong/library/PhpWord/Element/TextRun.php

@@ -0,0 +1,80 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Style\Paragraph;
+
+/**
+ * Textrun/paragraph element
+ */
+class TextRun extends AbstractContainer
+{
+    /**
+     * @var string Container type
+     */
+    protected $container = 'TextRun';
+
+    /**
+     * Paragraph style
+     *
+     * @var string|\PhpOffice\PhpWord\Style\Paragraph
+     */
+    protected $paragraphStyle;
+
+    /**
+     * Create new instance
+     *
+     * @param string|array|\PhpOffice\PhpWord\Style\Paragraph $paragraphStyle
+     */
+    public function __construct($paragraphStyle = null)
+    {
+        $this->paragraphStyle = $this->setParagraphStyle($paragraphStyle);
+    }
+
+    /**
+     * Get Paragraph style
+     *
+     * @return string|\PhpOffice\PhpWord\Style\Paragraph
+     */
+    public function getParagraphStyle()
+    {
+        return $this->paragraphStyle;
+    }
+
+    /**
+     * Set Paragraph style
+     *
+     * @param string|array|\PhpOffice\PhpWord\Style\Paragraph $style
+     * @return string|\PhpOffice\PhpWord\Style\Paragraph
+     */
+    public function setParagraphStyle($style = null)
+    {
+        if (is_array($style)) {
+            $this->paragraphStyle = new Paragraph();
+            $this->paragraphStyle->setStyleByArray($style);
+        } elseif ($style instanceof Paragraph) {
+            $this->paragraphStyle = $style;
+        } elseif (null === $style) {
+            $this->paragraphStyle = new Paragraph();
+        } else {
+            $this->paragraphStyle = $style;
+        }
+
+        return $this->paragraphStyle;
+    }
+}

+ 108 - 0
addons/qingdong/library/PhpWord/Element/Title.php

@@ -0,0 +1,108 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+use PhpOffice\PhpWord\Shared\Text as SharedText;
+use PhpOffice\PhpWord\Style;
+
+/**
+ * Title element
+ */
+class Title extends AbstractElement
+{
+    /**
+     * Title Text content
+     *
+     * @var string|TextRun
+     */
+    private $text;
+
+    /**
+     * Title depth
+     *
+     * @var int
+     */
+    private $depth = 1;
+
+    /**
+     * Name of the heading style, e.g. 'Heading1'
+     *
+     * @var string
+     */
+    private $style;
+
+    /**
+     * Is part of collection
+     *
+     * @var bool
+     */
+    protected $collectionRelation = true;
+
+    /**
+     * Create a new Title Element
+     *
+     * @param string|TextRun $text
+     * @param int $depth
+     */
+    public function __construct($text, $depth = 1)
+    {
+        if (is_string($text)) {
+            $this->text = SharedText::toUTF8($text);
+        } elseif ($text instanceof TextRun) {
+            $this->text = $text;
+        } else {
+            throw new \InvalidArgumentException('Invalid text, should be a string or a TextRun');
+        }
+
+        $this->depth = $depth;
+        $styleName = $depth === 0 ? 'Title' : "Heading_{$this->depth}";
+        if (array_key_exists($styleName, Style::getStyles())) {
+            $this->style = str_replace('_', '', $styleName);
+        }
+    }
+
+    /**
+     * Get Title Text content
+     *
+     * @return string
+     */
+    public function getText()
+    {
+        return $this->text;
+    }
+
+    /**
+     * Get depth
+     *
+     * @return int
+     */
+    public function getDepth()
+    {
+        return $this->depth;
+    }
+
+    /**
+     * Get Title style
+     *
+     * @return string
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+}

+ 101 - 0
addons/qingdong/library/PhpWord/Element/TrackChange.php

@@ -0,0 +1,101 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Element;
+
+/**
+ * TrackChange element
+ * @see http://datypic.com/sc/ooxml/t-w_CT_TrackChange.html
+ * @see http://datypic.com/sc/ooxml/t-w_CT_RunTrackChange.html
+ */
+class TrackChange extends AbstractContainer
+{
+    const INSERTED = 'INSERTED';
+    const DELETED = 'DELETED';
+
+    /**
+     * @var string Container type
+     */
+    protected $container = 'TrackChange';
+
+    /**
+     * The type of change, (insert or delete), not applicable for PhpOffice\PhpWord\Element\Comment
+     *
+     * @var string
+     */
+    private $changeType;
+
+    /**
+     * Author
+     *
+     * @var string
+     */
+    private $author;
+
+    /**
+     * Date
+     *
+     * @var \DateTime
+     */
+    private $date;
+
+    /**
+     * Create a new TrackChange Element
+     *
+     * @param string $changeType
+     * @param string $author
+     * @param null|int|bool|\DateTime $date
+     */
+    public function __construct($changeType = null, $author = null, $date = null)
+    {
+        $this->changeType = $changeType;
+        $this->author = $author;
+        if ($date !== null && $date !== false) {
+            $this->date = ($date instanceof \DateTime) ? $date : new \DateTime('@' . $date);
+        }
+    }
+
+    /**
+     * Get TrackChange Author
+     *
+     * @return string
+     */
+    public function getAuthor()
+    {
+        return $this->author;
+    }
+
+    /**
+     * Get TrackChange Date
+     *
+     * @return \DateTime
+     */
+    public function getDate()
+    {
+        return $this->date;
+    }
+
+    /**
+     * Get the Change type
+     *
+     * @return string
+     */
+    public function getChangeType()
+    {
+        return $this->changeType;
+    }
+}

+ 46 - 0
addons/qingdong/library/PhpWord/Escaper/AbstractEscaper.php

@@ -0,0 +1,46 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Escaper;
+
+/**
+ * @since 0.13.0
+ *
+ * @codeCoverageIgnore
+ */
+abstract class AbstractEscaper implements EscaperInterface
+{
+    /**
+     * @param string $input
+     *
+     * @return string
+     */
+    abstract protected function escapeSingleValue($input);
+
+    public function escape($input)
+    {
+        if (is_array($input)) {
+            foreach ($input as &$item) {
+                $item = $this->escapeSingleValue($item);
+            }
+        } else {
+            $input = $this->escapeSingleValue($input);
+        }
+
+        return $input;
+    }
+}

+ 33 - 0
addons/qingdong/library/PhpWord/Escaper/EscaperInterface.php

@@ -0,0 +1,33 @@
+<?php
+/**
+ * This file is part of PHPWord - A pure PHP library for reading and writing
+ * word processing documents.
+ *
+ * PHPWord is free software distributed under the terms of the GNU Lesser
+ * General Public License version 3 as published by the Free Software Foundation.
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code. For the full list of
+ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
+ *
+ * @see         https://github.com/PHPOffice/PHPWord
+ * @copyright   2010-2018 PHPWord contributors
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
+ */
+
+namespace PhpOffice\PhpWord\Escaper;
+
+/**
+ * @since 0.13.0
+ *
+ * @codeCoverageIgnore
+ */
+interface EscaperInterface
+{
+    /**
+     * @param mixed $input
+     *
+     * @return mixed
+     */
+    public function escape($input);
+}

部分文件因文件數量過多而無法顯示