旭晓耿 преди 5 години
родител
ревизия
a20e5ab784
променени са 100 файла, в които са добавени 22747 реда и са изтрити 30 реда
  1. 8
    0
      .htaccess
  2. 51
    0
      LICENSE.txt
  3. 27
    30
      README.md
  4. 1
    0
      application/.htaccess
  5. 172
    0
      application/admin/common.php
  6. 14
    0
      application/admin/config.php
  7. 55
    0
      application/admin/controller/ApiCommon.php
  8. 76
    0
      application/admin/controller/Base.php
  9. 78
    0
      application/admin/controller/Comment.php
  10. 68
    0
      application/admin/controller/ConfigSet.php
  11. 152
    0
      application/admin/controller/DailyRule.php
  12. 369
    0
      application/admin/controller/ExamineFlow.php
  13. 673
    0
      application/admin/controller/Field.php
  14. 74
    0
      application/admin/controller/FieldGrant.php
  15. 230
    0
      application/admin/controller/File.php
  16. 217
    0
      application/admin/controller/Groups.php
  17. 154
    0
      application/admin/controller/Index.php
  18. 96
    0
      application/admin/controller/Initialize.php
  19. 382
    0
      application/admin/controller/Install.php
  20. 86
    0
      application/admin/controller/Log.php
  21. 87
    0
      application/admin/controller/Menus.php
  22. 205
    0
      application/admin/controller/Message.php
  23. 88
    0
      application/admin/controller/Posts.php
  24. 169
    0
      application/admin/controller/Printing.php
  25. 131
    0
      application/admin/controller/Record.php
  26. 79
    0
      application/admin/controller/Rules.php
  27. 169
    0
      application/admin/controller/Scene.php
  28. 43
    0
      application/admin/controller/Setting.php
  29. 243
    0
      application/admin/controller/Structures.php
  30. 55
    0
      application/admin/controller/System.php
  31. 723
    0
      application/admin/controller/Users.php
  32. 149
    0
      application/admin/controller/Work.php
  33. 0
    0
      application/admin/lang/en-us.php
  34. 4
    0
      application/admin/lang/zh-cn.php
  35. 309
    0
      application/admin/logic/DailyRuleLogic.php
  36. 572
    0
      application/admin/logic/FieldGrantLogic.php
  37. 996
    0
      application/admin/logic/InitializeLogic.php
  38. 218
    0
      application/admin/logic/LogLogic.php
  39. 282
    0
      application/admin/logic/MessageLogic.php
  40. 377
    0
      application/admin/logic/PrintingLogic.php
  41. 114
    0
      application/admin/logic/WorkLogic.php
  42. 52
    0
      application/admin/model/Access.php
  43. 111
    0
      application/admin/model/ActionRecord.php
  44. 91
    0
      application/admin/model/Admin.php
  45. 173
    0
      application/admin/model/Comment.php
  46. 336
    0
      application/admin/model/Common.php
  47. 46
    0
      application/admin/model/Config.php
  48. 269
    0
      application/admin/model/ExamineFlow.php
  49. 113
    0
      application/admin/model/ExamineRecord.php
  50. 495
    0
      application/admin/model/ExamineStep.php
  51. 2332
    0
      application/admin/model/Excel.php
  52. 1714
    0
      application/admin/model/Field.php
  53. 570
    0
      application/admin/model/File.php
  54. 192
    0
      application/admin/model/Group.php
  55. 55
    0
      application/admin/model/ImportRecord.php
  56. 133
    0
      application/admin/model/LoginRecord.php
  57. 94
    0
      application/admin/model/Menu.php
  58. 470
    0
      application/admin/model/Message.php
  59. 12
    0
      application/admin/model/OaSchedule.php
  60. 28
    0
      application/admin/model/OperationLog.php
  61. 44
    0
      application/admin/model/Post.php
  62. 652
    0
      application/admin/model/Record.php
  63. 131
    0
      application/admin/model/Rule.php
  64. 529
    0
      application/admin/model/Scene.php
  65. 118
    0
      application/admin/model/Structure.php
  66. 18
    0
      application/admin/model/Sync.php
  67. 41
    0
      application/admin/model/System.php
  68. 28
    0
      application/admin/model/SystemLog.php
  69. 1346
    0
      application/admin/model/User.php
  70. 198
    0
      application/admin/model/UserField.php
  71. 22
    0
      application/admin/validate/AdminField.php
  72. 21
    0
      application/admin/validate/AdminGroup.php
  73. 16
    0
      application/admin/validate/AdminPost.php
  74. 21
    0
      application/admin/validate/AdminRecord.php
  75. 20
    0
      application/admin/validate/AdminRule.php
  76. 16
    0
      application/admin/validate/AdminStructure.php
  77. 25
    0
      application/admin/validate/AdminUser.php
  78. 77
    0
      application/admin/view/install/index.html
  79. 101
    0
      application/admin/view/install/step1.html
  80. 97
    0
      application/admin/view/install/step2.html
  81. 55
    0
      application/admin/view/install/step3.html
  82. 6
    0
      application/admin/view/public/footer.html
  83. 14
    0
      application/admin/view/public/header.html
  84. 18
    0
      application/bi/common.php
  85. 14
    0
      application/bi/config.php
  86. 419
    0
      application/bi/controller/Achievement.php
  87. 287
    0
      application/bi/controller/Business.php
  88. 359
    0
      application/bi/controller/Contract.php
  89. 1215
    0
      application/bi/controller/Customer.php
  90. 173
    0
      application/bi/controller/Examine.php
  91. 93
    0
      application/bi/controller/Log.php
  92. 150
    0
      application/bi/controller/Product.php
  93. 565
    0
      application/bi/controller/Ranking.php
  94. 90
    0
      application/bi/controller/Receivables.php
  95. 5
    0
      application/bi/lang/en-us.php
  96. 4
    0
      application/bi/lang/zh-cn.php
  97. 145
    0
      application/bi/logic/BiCustomerLogic.php
  98. 300
    0
      application/bi/logic/ExcelLogic.php
  99. 32
    0
      application/bi/model/ActionRecord.php
  100. 0
    0
      application/bi/model/Business.php

+ 8
- 0
.htaccess Целия файл

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

+ 51
- 0
LICENSE.txt Целия файл

@@ -0,0 +1,51 @@
1
+用户须知:
2
+
3
+悟空CRM管理软件(以下简称该软件)由 郑州卡卡罗特软件科技有限公司(www.5kcrm.com)开发(以下简称卡卡罗特)。卡卡罗特依法拥有该软件的所有版权。本着共享开放的角度,卡卡罗特以开放源代码的形式发布该软件。您可以在遵守该协议的前提下使用该软件。
4
+
5
+官方地址:www.5kcrm.com
6
+官方电话:400-0812-558
7
+官方邮箱:service@5kcrm.com
8
+官方社区:bbs.72crm.com
9
+官方社群:悟空CRM交流10群(486745026)
10
+
11
+自您安装该软件开始,您和卡卡罗特之间的合同关系自动成立。除非您停止使用该软件或与卡卡罗特有签署额外合同,您须认真遵循该授权协议约定的每一条款。
12
+
13
+约定:
14
+
15
+下述条款中所指该软件的标志包括如下方面:
16
+
17
+该软件源代码及文档中关于该软件的版权提示、文字、图片和链接。
18
+该软件运行时界面上呈现出来的有关该软件的文字、图片和链接。
19
+
20
+不包括如下方面:
21
+
22
+该软件提供的演示数据中关于该软件的文字、图片和链接。
23
+
24
+一、免责
25
+
26
+该软件是以开放源代码的方式发行,您使用该软件无需任何费用,因此在使用该软件前,您须知晓:
27
+
28
+1.1 卡卡罗特没有对该软件提供任何技术支持的义务,您可联系卡卡罗特购买商业的技术支持。  
29
+1.2 卡卡罗特对因使用该软件而产生直接或间接的任何问题不负任何责任。  
30
+1.3 开源不等于免费,开源不等于无版权,开源软件的发展需要您和卡卡罗特共同的努力。
31
+
32
+二、自用该软件
33
+
34
+2.1 您个人可自由使用或学习该软件,卡卡罗特不对您做任何限制。
35
+2.2 您可以在您个人任意数量的电脑上运行该软件,卡卡罗特不对电脑的数量做任何限制。
36
+2.3 您可以对该软件源代码进行修改以适应您个人学习研究的要求,您做的改动无需对外发布。
37
+2.4 您个人使用该软件时,必须保留该软件的所有标志,不得以任何方式隐藏或遮掩任一标志。
38
+
39
+三、企业用户
40
+
41
+3.1未获商业授权之前,不得将本软件用于商业用途(包括但不限于企业内部使用、二次开发后进行销售、以营利为目的或实现盈利等形式)。
42
+3.2未经官方许可,禁止在该软件的整体或任何部分基础上发展任何派生版本、修改版本或第三方版本用于重新分发,包括但不限于基于悟空CRM开发SAAS平台等相关服务。
43
+3.3如果您未能遵守本协议的条款,您的授权将被终止,所被许可的权利将被收回,并承担相应法律责任。
44
+
45
+四、授权例外
46
+
47
+如果上述条款无法满足您使用该软件的要求,可联系卡卡罗特签署额外的合同以获得更灵活的授权许可。
48
+
49
+五、合同约束
50
+
51
+如果您违反了该协议的任一条款,该授权协议将自动终止,卡卡罗特保留通过法律手段追究责任的权利。

+ 27
- 30
README.md Целия файл

@@ -1,7 +1,4 @@
1
-# 72CRM-11.0-PHP
2
-
3
-## 悟空CRM介绍
4
-
1
+### 悟空CRM(9.0版本)
5 2
 悟空软件长期为企业提供企业管理软件(CRM/HRM/OA/ERP等)的研发、实施、营销、咨询、培训、服务于一体的信息化服务。悟空软件以高科技为起点,以技术为核心、以完善的售后服务为后盾,秉承稳固与发展、求实与创新的精神,已为国内外上千家企业提供服务。
6 3
 
7 4
 悟空的发展受益于开源,也会回馈于开源。2019年,悟空CRM会继续秉承“拥抱开放、合作共赢、创造价值”的理念,在开源的道路上继续砥砺前行,和更多的社区开发者一起为国内外开源做出积极贡献。
@@ -12,27 +9,21 @@
12 9
 
13 10
 论坛:[http://bbs.72crm.net](http://bbs.72crm.net/)
14 11
 
15
-演示地址:[demo11.5kcrm.net](http://demo11.5kcrm.net/)(帐号:18888888888   密码:123456)
12
+演示地址:[demo9.5kcrm.net](http://demo9.5kcrm.net/)(帐号:18888888888   密码:123456)
16 13
 
17 14
 QQ群交流群⑩群:[486745026](https:////shang.qq.com/wpa/qunwpa?idkey=f4687b809bf63f08f707aa1c56dee8dbcb9526237c429c4532222021d65bf83c)
18 15
 
19
-JAVA版下载地址:[https://gitee.com/wukongcrm/72crm-java](https://gitee.com/wukongcrm/72crm-java)
20
-
21
-
22
-扫码添加小悟官方客服微信,邀您加入千人微信交流群:
23
-
24
-<img src="https://images.gitee.com/uploads/images/2019/1231/115927_f9c580c8_345098.png" width="200">
25
-
26
-关注悟空CRM公众号,了解更多悟空资讯
16
+赞赏一下吧~~
27 17
 
28
-<img src="https://images.gitee.com/uploads/images/2019/1202/135713_d3566c6a_345098.jpeg" width="200">
18
+![](https://github.com/72crm/72crm/blob/master/ux/intro_img/g11.png)
29 19
 
20
+悟空CRM采用全新的前后端分离模式,本仓库代码中已集成前端vue打包后文件,可免去打包操作
30 21
 
31
- :boom:  :boom:  :boom: 注:悟空CRM采用全新的前后端分离模式,本仓库代码中已集成前端vue打包后文件,  **可免去打包操作,无需运行前端** 。如需调整前端代码,请单独下载前端代码,前端代码在根目录的ux文件夹中
22
+如需调整前端代码,请单独下载前端代码,前端代码在根目录的ux文件夹中
32 23
 
33 24
 ## 主要技术栈
34 25
 
35
-后端框架:ThinkPHP 5.0.24
26
+后端框架:ThinkPHP 5.0.2
36 27
 
37 28
 前端MVVM框架:Vue.JS 2.5.x 
38 29
 
@@ -49,11 +40,13 @@ UI框架:Element-UI 2.6.3
49 40
 
50 41
 代码中已集成前端vue打包后文件,可免去打包操作:
51 42
 以本地(phpstudy集成环境)搭建举例:
52
-下载悟空CRM11.0开源版,在服务器根目录(www目录)下创建72crm文件夹,并放置代码; 浏览器访问
43
+下载悟空CRM9.0开源版,在服务器根目录(www目录)下创建72crm文件夹,并放置代码; 浏览器访问
53 44
 
54 45
 `http://localhost/72crm/index.php/admin/install/index.html `
55 46
 
56
-根据安装提示步骤,完成悟空CRM11.0 的部署安装
47
+根据安装提示步骤,完成悟空CRM9.0 的部署安装
48
+
49
+
57 50
 
58 51
 
59 52
 
@@ -65,7 +58,7 @@ UI框架:Element-UI 2.6.3
65 58
 值得注意的一点是:跨域的情况下,会有预请求OPTION的情况
66 59
 
67 60
 ### Server搭建 
68
-服务端使用的框架为thinkphp5.0.24,搭建前请确保拥有lamp/lnmp/wamp环境。
61
+服务端使用的框架为thinkphp5.0.2,搭建前请确保拥有lamp/lnmp/wamp环境。
69 62
 
70 63
 这里所说的搭建其实就是把server框架放入WEB运行环境,并使用80端口。
71 64
 导入服务端根文件夹数据库文件public/sql/5kcrm.sql,并修改config/database.php配置文件。
@@ -91,20 +84,24 @@ PHP >= 5.6.0
91 84
 
92 85
 
93 86
 
87
+## 系统介绍
88
+
89
+以下为悟空CRM9.0 部分功能系统截图
90
+
91
+
94 92
 
93
+![](https://github.com/72crm/72crm/blob/master/ux/intro_img/g1.png)
94
+![](https://github.com/72crm/72crm/blob/master/ux/intro_img/g2.png)
95
+![](https://github.com/72crm/72crm/blob/master/ux/intro_img/g3.png)
96
+![](https://github.com/72crm/72crm/blob/master/ux/intro_img/g4.png)
97
+![](https://github.com/72crm/72crm/blob/master/ux/intro_img/g5.png)
98
+![](https://github.com/72crm/72crm/blob/master/ux/intro_img/g6.png)
99
+![](https://github.com/72crm/72crm/blob/master/ux/intro_img/g7.png)
100
+![](https://github.com/72crm/72crm/blob/master/ux/intro_img/g8.png)
101
+![](https://github.com/72crm/72crm/blob/master/ux/intro_img/g9.png)
102
+![](https://github.com/72crm/72crm/blob/master/ux/intro_img/g10.png)
95 103
 
96
-## 悟空CRM功能模块预览
97 104
 
98
-以下为悟空CRM11.0.0 部分功能系统截图
99 105
 
100
-![仪表盘](https://images.gitee.com/uploads/images/2021/0206/112721_6e50397d_345098.png "仪表盘.png")
101
-![客户列表](https://images.gitee.com/uploads/images/2021/0206/112822_4ab4eb50_345098.png "客户列表.png")
102
-![客户详情](https://images.gitee.com/uploads/images/2021/0206/112842_d69aff0f_345098.png "客户详情.png")
103
-![商机详情](https://images.gitee.com/uploads/images/2021/0206/112902_c38751fe_345098.png "商机详情.png")
104
-![任务详情](https://images.gitee.com/uploads/images/2021/0206/112924_175278e2_345098.png "任务详情.png")
105
-![商业智能](https://images.gitee.com/uploads/images/2021/0206/112938_0cbc95b7_345098.png "商业智能.png")
106
-![审批](https://images.gitee.com/uploads/images/2021/0206/113001_bfcbee0a_345098.png "审批.png")
107
-![自定义字段](https://images.gitee.com/uploads/images/2021/0206/113019_7894e7ed_345098.png "自定义字段.png")
108
-![字段授权](https://images.gitee.com/uploads/images/2021/0206/113030_cefa8932_345098.png "字段授权.png")
109 106
 
110 107
 

+ 1
- 0
application/.htaccess Целия файл

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

+ 172
- 0
application/admin/common.php Целия файл

@@ -0,0 +1,172 @@
1
+<?php
2
+//权限控制
3
+\think\Hook::add('check_auth','app\\common\\behavior\\AuthenticateBehavior');
4
+use think\Db;
5
+
6
+function structureList($structid,$str){
7
+    $str .= $structid.',';
8
+    if(Db::name('AdminStructure')->where('pid ='.$structid)->find() ){
9
+        $list = Db::name('AdminStructure')->field('id,name,pid')->where('pid ='.$structid)->select();
10
+        foreach($list as $value){
11
+            $str = structureList($value['id'],$str);
12
+        }
13
+    }
14
+    return $str;
15
+}
16
+
17
+/**
18
+ * cookies加密函数
19
+ * @param string 加密后字符串
20
+ */
21
+function encrypt($data, $key = '5k-72crm') 
22
+{ 
23
+    $cryptdes = new com\Cryptdes($key);
24
+    return $cryptdes->encrypt($data);
25
+    // $prep_code = serialize($data); 
26
+    // $block = mcrypt_get_block_size('des', 'ecb'); 
27
+    // if (($pad = $block - (strlen($prep_code) % $block)) < $block) { 
28
+    //     $prep_code .= str_repeat(chr($pad), $pad); 
29
+    // } 
30
+    // $encrypt = mcrypt_encrypt(MCRYPT_DES, $key, trim($prep_code), MCRYPT_MODE_ECB); 
31
+    // return base64_encode($encrypt); 
32
+} 
33
+
34
+/**
35
+ * cookies 解密密函数
36
+ * @param array 解密后数组
37
+ */
38
+function decrypt($data, $key = '5k-72crm') 
39
+{ 
40
+    $cryptdes = new com\Cryptdes($key);
41
+    return $cryptdes->decrypt($data);
42
+    // $str = base64_decode($str); 
43
+    // $str = mcrypt_decrypt(MCRYPT_DES, $key, $str, MCRYPT_MODE_ECB); 
44
+    // $block = mcrypt_get_block_size('des', 'ecb'); 
45
+    // $pad = ord($str[($len = strlen($str)) - 1]); 
46
+    // if ($pad && $pad < $block && preg_match('/' . chr($pad) . '{' . $pad . '}$/', $str)) { 
47
+    //     $str = substr($str, 0, strlen($str) - $pad); 
48
+    // } 
49
+    // return unserialize($str); 
50
+}
51
+
52
+/**
53
+ * 部门树形数组
54
+ * @param type 0 下属数组, 1包含自己
55
+ */
56
+function getSubObj($id, $objList, $separate, $is_first = 0) {
57
+    $array = array(); 
58
+    foreach ($objList as $key => $value) {
59
+        if ($key == 0 && $is_first == 1) {
60
+            if ($value['id'] == 1) {
61
+                $id = 0;
62
+            } else {
63
+                $id = $value['pid'];
64
+            }
65
+        }
66
+        if ($id == $value['pid']) {
67
+            $array[] = array('id' => $value['id'], 'name' => $separate.$value['name']);
68
+            $array = array_merge($array, getSubObj($value['id'], $objList, $separate.'--'));
69
+        }
70
+    }
71
+    return $array;
72
+}
73
+
74
+/**
75
+ * 解析sql语句
76
+ * @param  string $content sql内容
77
+ * @param  int $limit  如果为1,则只返回一条sql语句,默认返回所有
78
+ * @param  array $prefix 替换表前缀
79
+ * @return array|string 除去注释之后的sql语句数组或一条语句
80
+ */
81
+function parse_sql($sql = '', $limit = 0, $prefix = []) {
82
+    // 被替换的前缀
83
+    $from = '';
84
+    // 要替换的前缀
85
+    $to = '';
86
+    // 替换表前缀
87
+    if (!empty($prefix)) {
88
+        $to   = current($prefix);
89
+        $from = current(array_flip($prefix));
90
+    }
91
+    if ($sql != '') {
92
+        // 纯sql内容
93
+        $pure_sql = [];
94
+        // 多行注释标记
95
+        $comment = false;
96
+        // 按行分割,兼容多个平台
97
+        $sql = str_replace(["\r\n", "\r"], "\n", $sql);
98
+        $sql = explode("\n", trim($sql));
99
+        // 循环处理每一行
100
+        foreach ($sql as $key => $line) {
101
+            // 跳过空行
102
+            if ($line == '') {
103
+                continue;
104
+            }
105
+            // 跳过以#或者--开头的单行注释
106
+            if (preg_match("/^(#|--)/", $line)) {
107
+                continue;
108
+            }
109
+            // 跳过以/**/包裹起来的单行注释
110
+            if (preg_match("/^\/\*(.*?)\*\//", $line)) {
111
+                continue;
112
+            }
113
+            // 多行注释开始
114
+            if (substr($line, 0, 2) == '/*') {
115
+                $comment = true;
116
+                continue;
117
+            }
118
+            // 多行注释结束
119
+            if (substr($line, -2) == '*/') {
120
+                $comment = false;
121
+                continue;
122
+            }
123
+            // 多行注释没有结束,继续跳过
124
+            if ($comment) {
125
+                continue;
126
+            }
127
+            // 替换表前缀
128
+            if ($from != '') {
129
+                $line = str_replace('`'.$from, '`'.$to, $line);
130
+            }
131
+            if ($line == 'BEGIN;' || $line =='COMMIT;') {
132
+                continue;
133
+            }
134
+            // sql语句
135
+            array_push($pure_sql, $line);
136
+        }
137
+        // 只返回一条语句
138
+        if ($limit == 1) {
139
+            return implode($pure_sql, "");
140
+        }
141
+        // 以数组形式返回sql语句
142
+        $pure_sql = implode($pure_sql, "\n");
143
+        $pure_sql = explode(";\n", $pure_sql);
144
+        return $pure_sql;
145
+    } else {
146
+        return $limit == 1 ? '' : [];
147
+    }
148
+}
149
+
150
+function sendRequest($url, $params = array() , $headers = array()) {
151
+    $ch = curl_init();
152
+    curl_setopt($ch, CURLOPT_URL, $url);
153
+    if (!empty($params)) {
154
+        curl_setopt($ch, CURLOPT_POST, true);
155
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
156
+    }
157
+    if (!empty($headers)) {
158
+        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
159
+    }
160
+    $res = curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
161
+    $value = curl_exec($ch);
162
+    if (curl_errno($ch)) {
163
+        $return = array(0, '连接服务器出错', -1);
164
+    } else {
165
+        if (!$value) {
166
+            $return = array(0, '服务器返回数据异常', -1);
167
+        }
168
+        $return = $value;
169
+    }
170
+    curl_close($ch);
171
+    return $return;
172
+}

+ 14
- 0
application/admin/config.php Целия файл

@@ -0,0 +1,14 @@
1
+<?php
2
+// 基础模块配置文件
3
+
4
+return [
5
+	//'配置项'=>'配置值'
6
+    'LANG_SWITCH_ON'     =>     true,    //开启语言包功能        
7
+    'LANG_AUTO_DETECT'     =>     true, // 自动侦测语言
8
+    'DEFAULT_LANG'         =>     'zh-cn', // 默认语言        
9
+    'LANG_LIST'            =>    'en-us,zh-cn,zh-tw', //必须写可允许的语言列表
10
+    'VAR_LANGUAGE'     => 'l', // 默认语言切换变量
11
+];
12
+
13
+
14
+

+ 55
- 0
application/admin/controller/ApiCommon.php Целия файл

@@ -0,0 +1,55 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: Api基础类,验证权限
4
+// +----------------------------------------------------------------------
5
+// | Author:  
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use think\Request;
11
+use think\Db;
12
+use app\common\adapter\AuthAdapter;
13
+use app\common\controller\Common;
14
+
15
+
16
+class ApiCommon extends Common
17
+{
18
+    public function _initialize()
19
+    {
20
+        parent::_initialize();
21
+        /*获取头部信息*/ 
22
+        $header = Request::instance()->header();
23
+        $request = Request::instance();
24
+        
25
+        $authKey = $header['authkey'];
26
+        $sessionId = $header['sessionid'];
27
+        $paramArr = $request->param();
28
+        $platform = $paramArr['platform'] ? '_'.$paramArr['platform'] : ''; //请求平台(mobile,ding)
29
+        $cache = cache('Auth_'.$authKey.$platform);         
30
+
31
+        // 校验sessionid和authKey
32
+        if (empty($sessionId) || empty($authKey) || empty($cache) || ($cache['sessionId'] !== $sessionId)) {
33
+            header('Content-Type:application/json; charset=utf-8');
34
+            $dataTime=date('H:i',time());
35
+            exit(json_encode(['code' => 302, 'data' => ['extra' => 1, 'extraTime' => $dataTime], 'msg' => '请先登录!']));
36
+        }
37
+        //登录有效时间
38
+        $cacheConfig = config('cache');
39
+        $loginExpire = $cacheConfig['expire'] ? : 86400*3;
40
+
41
+        // 检查账号有效性
42
+        $userInfo = $cache['userInfo'];
43
+        $map['id'] = $userInfo['id'];
44
+        $map['status'] = array('in',['1','2']);
45
+        $userData = Db::name('admin_user')->where($map)->find();
46
+        if (!$userData) {
47
+            header('Content-Type:application/json; charset=utf-8');
48
+            exit(json_encode(['code'=>103, 'data' => [], 'msg'=>'账号已被删除或禁用']));   
49
+        }
50
+        session('user_id', $userInfo['id']);
51
+        // 更新缓存
52
+        cache('Auth_'.$authKey, $cache, $loginExpire);           
53
+        // $GLOBALS['userInfo'] = $userInfo;
54
+    }
55
+}

+ 76
- 0
application/admin/controller/Base.php Целия файл

@@ -0,0 +1,76 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 基础类,无需验证权限。
4
+// +----------------------------------------------------------------------
5
+// | Author:  
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use com\verify\HonrayVerify;
11
+use app\common\controller\Common;
12
+use think\Request;
13
+use think\Session;
14
+
15
+class Base extends Common
16
+{
17
+    public function login()
18
+    {
19
+        $request = Request::instance();
20
+        $paramArr = $request->param();        
21
+        $userModel = model('User');
22
+        $param = $this->param;
23
+        $username = $param['username'];
24
+        $password = $param['password'];
25
+        $verifyCode = !empty($param['verifyCode']) ? $param['verifyCode']: '';
26
+        $isRemember = !empty($param['isRemember']) ? $param['isRemember']: '';
27
+        $data = $userModel->login($username, $password, $verifyCode, $isRemember, $type, $authKey, $paramArr);
28
+        
29
+        Session::set('user_id', $data['userInfo']['id']);
30
+        if (!$data) {
31
+            return resultArray(['error' => $userModel->getError()]);
32
+        }
33
+        return resultArray(['data' => $data]);
34
+    }     
35
+
36
+    //退出登录
37
+    public function logout()
38
+    {
39
+        $param = $this->param;
40
+        $header = Request::instance()->header();
41
+        $request = Request::instance();
42
+        $paramArr = $request->param();
43
+        $platform = $paramArr['platform'] ? '_'.$paramArr['platform'] : ''; //请求平台(mobile,ding)
44
+        $cache = cache('Auth_'.$authKey.$platform,null);
45
+        cookie(null, '72crm_');
46
+        cookie(null, '5kcrm_');
47
+        session('user_id','null');
48
+        return resultArray(['data'=>'退出成功']);
49
+    }
50
+
51
+    //获取图片验证码
52
+    public function getVerify()
53
+    {
54
+        $captcha = new HonrayVerify(config('captcha'));
55
+        return $captcha->entry();
56
+    }
57
+
58
+	//网站信息
59
+    public function index()
60
+    {   
61
+        $systemModel = model('System');
62
+        $data = $systemModel->getDataList();
63
+        return  resultArray(['data' => $data]);
64
+    }    
65
+	
66
+    // miss 路由:处理没有匹配到的路由规则
67
+    public function miss()
68
+    {
69
+        if (Request::instance()->isOptions()) {
70
+            return ;
71
+        } else {
72
+            echo '悟空软件';
73
+        }
74
+    }
75
+}
76
+ 

+ 78
- 0
application/admin/controller/Comment.php Целия файл

@@ -0,0 +1,78 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 评论
4
+// +----------------------------------------------------------------------
5
+// | Author:  yykun
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use think\Request;
11
+use think\Session;
12
+use think\Hook;
13
+use app\common\controller\Common;
14
+
15
+class Comment extends Common
16
+{
17
+    /**
18
+     * 用于判断权限
19
+     * @permission 无限制
20
+     * @allow 登录用户可访问
21
+     * @other 其他根据系统设置
22
+    **/    
23
+    public function _initialize()
24
+    {
25
+        $action = [
26
+            'permission'=>[''],  //不登录可访问
27
+            'allow'=>['save','delete']  //需要登录才能访问          
28
+        ];
29
+        Hook::listen('check_auth',$action);
30
+        $request = Request::instance();
31
+        $a = strtolower($request->action());  
32
+		$c = strtolower($request->controller()); 
33
+		$m = strtolower($request->module()); 		
34
+        if (!in_array($a, $action['permission'])) {
35
+            parent::_initialize();
36
+        }
37
+    }
38
+
39
+    //添加评论
40
+    public function save()
41
+    {
42
+        $param = $this->param;
43
+        $model = model('Comment');
44
+        if ($param['task_id']) {
45
+            $userInfo = $this->userInfo;
46
+			$param['create_user_id'] = $userInfo['id']; 
47
+            $flag = $model->createData($param);
48
+            if ($flag) {
49
+                return resultArray(['data'=>$flag]);
50
+            } else {
51
+                return resultArray(['error'=>$workModel->getError()]);
52
+            }
53
+        } else {
54
+            return resultArray(['error'=>'参数错误']);
55
+        }
56
+
57
+    }
58
+
59
+    //删除评论
60
+    public function delete()
61
+    {
62
+        $param = $this->param;
63
+        $commentModel = model('Comment');
64
+        if ($param['comment_id']) {
65
+            $userInfo   			 = $this->userInfo;
66
+			$param['create_user_id'] = $userInfo['id']; 
67
+            $flag = $commentModel->delDataById($param);
68
+            if ($flag) {
69
+                return resultArray(['data'=>'删除成功']);
70
+            } else {
71
+                return resultArray(['error'=>$commentModel->getError()]);
72
+            }
73
+        } else {
74
+            return resultArray(['error'=>'参数错误']);
75
+        }
76
+    }   
77
+}
78
+ 

+ 68
- 0
application/admin/controller/ConfigSet.php Целия файл

@@ -0,0 +1,68 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 应用状态
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use think\Hook;
11
+use think\Request;
12
+
13
+class ConfigSet extends ApiCommon
14
+{
15
+    /**
16
+     * 用于判断权限
17
+     * @permission 无限制
18
+     * @allow 登录用户可访问
19
+     * @other 其他根据系统设置
20
+    **/  
21
+    
22
+    public function _initialize()
23
+    {
24
+        $action = [
25
+            'permission'=>[''],
26
+            'allow'=>['']
27
+        ];
28
+        Hook::listen('check_auth',$action);
29
+        $request = Request::instance();
30
+        $a = strtolower($request->action());        
31
+        if (!in_array($a, $action['permission'])) {
32
+            parent::_initialize();
33
+        }               
34
+    }        
35
+
36
+    /**
37
+     * 应用状态列表
38
+     * @author Michael_xu
39
+     * @return
40
+     */
41
+    public function index()
42
+    {   
43
+        $configModel = model('Config');
44
+        $data = $configModel->getDataList();
45
+        return resultArray(['data' => $data]);
46
+    }
47
+	
48
+    /**
49
+     * 状态编辑
50
+     * @author Michael_xu
51
+     * @return
52
+     */    
53
+    public function update()
54
+    {
55
+        $configModel = model('Config');
56
+        $param = $this->param;
57
+		if (!$param['id']) {
58
+			return resultArray(['error' => '参数错误']);
59
+		}
60
+        if ($configModel->updateDataById($param, $param['id'])) {
61
+            return resultArray(['data' => '编辑成功']);
62
+        }
63
+        return resultArray(['error' => $configModel->getError()]);        
64
+    }
65
+
66
+    
67
+}
68
+ 

+ 152
- 0
application/admin/controller/DailyRule.php Целия файл

@@ -0,0 +1,152 @@
1
+<?php
2
+/**
3
+ * 日志规则控制器
4
+ *
5
+ * @author qifan
6
+ * @date 2020-12-03
7
+ */
8
+
9
+namespace app\admin\controller;
10
+
11
+use app\admin\logic\DailyRuleLogic;
12
+use think\Hook;
13
+use think\Request;
14
+
15
+class DailyRule extends ApiCommon
16
+{
17
+    /**
18
+     * 用于判断权限
19
+     * @permission 无限制
20
+     * @allow 登录用户可访问
21
+     * @other 其他根据系统设置
22
+     **/
23
+    public function _initialize()
24
+    {
25
+        $action = [
26
+            'permission'=>[''],
27
+            'allow'=>['welcome', 'setwelcome', 'worklogrule', 'setworklogrule','scheduleList','addschedule','setschedule','delschedule']
28
+        ];
29
+        Hook::listen('check_auth',$action);
30
+        $request = Request::instance();
31
+        $a = strtolower($request->action());
32
+        if (!in_array($a, $action['permission'])) {
33
+            parent::_initialize();
34
+        }
35
+    }
36
+
37
+    /**
38
+     * 获取欢迎语
39
+     *
40
+     * @param DailyRuleLogic $dailyRuleLogic
41
+     * @return \think\response\Json
42
+     */
43
+    public function welcome(DailyRuleLogic $dailyRuleLogic)
44
+    {
45
+        $data = $dailyRuleLogic->welcome();
46
+
47
+        return resultArray(['data' => $data]);
48
+    }
49
+
50
+    /**
51
+     * 添加欢迎语
52
+     *
53
+     * @param DailyRuleLogic $dailyRuleLogic
54
+     * @return \think\response\Json
55
+     * @throws \think\Exception
56
+     * @throws \think\exception\PDOException
57
+     */
58
+    public function setWelcome(DailyRuleLogic $dailyRuleLogic)
59
+    {
60
+        $mark = $this->param['welcome'];
61
+
62
+        if (empty($mark)) return resultArray(['error' => '缺少日志欢迎语!']);
63
+
64
+        if (!$dailyRuleLogic->setWelcome($mark)) return resultArray(['error' => '添加失败!']);
65
+
66
+        return resultArray(['data' => '添加成功!']);
67
+    }
68
+
69
+    /**
70
+     * 获取日志规则
71
+     *
72
+     * @param DailyRuleLogic $dailyRuleLogic
73
+     * @return \think\response\Json
74
+     * @throws \think\db\exception\DataNotFoundException
75
+     * @throws \think\db\exception\ModelNotFoundException
76
+     * @throws \think\exception\DbException
77
+     */
78
+    public function workLogRule(DailyRuleLogic $dailyRuleLogic)
79
+    {
80
+        $data = $dailyRuleLogic->workLogRule();
81
+
82
+        return resultArray(['data' => $data]);
83
+    }
84
+
85
+    /**
86
+     * 设置日志规则
87
+     *
88
+     * @param DailyRuleLogic $dailyRuleLogic
89
+     * @return \think\response\Json
90
+     * @throws \think\Exception
91
+     * @throws \think\exception\PDOException
92
+     */
93
+    public function setWorkLogRule(DailyRuleLogic $dailyRuleLogic)
94
+    {
95
+        if (empty($this->param['rule'])) return resultArray(['error' => '缺少规则参数!']);
96
+
97
+        $dailyRuleLogic->setWorkLogRule($this->param['rule']);
98
+
99
+        return resultArray(['data' => '设置成功!']);
100
+    }
101
+
102
+    /**
103
+     * 获取日程规则
104
+     * @param DailyRuleLogic $dailyRuleLogic
105
+     * @return \think\response\Json
106
+     * @throws \think\db\exception\DataNotFoundException
107
+     * @throws \think\db\exception\ModelNotFoundException
108
+     * @throws \think\exception\DbException
109
+     */
110
+    public function scheduleList(DailyRuleLogic $dailyRuleLogic){
111
+        $data = $dailyRuleLogic->schedule();
112
+        return resultArray(['data' => $data]);
113
+    }
114
+
115
+    /**
116
+     * 设置日程自定义规则
117
+     * @param DailyRuleLogic $dailyRuleLogic
118
+     * @return \think\response\Json
119
+     * @throws \think\Exception
120
+     * @throws \think\exception\PDOException
121
+     */
122
+    public function  setSchedule(DailyRuleLogic $dailyRuleLogic){
123
+        if(empty($this->param['id'])) return resultArray(['error'=>'缺少参数']);
124
+          $dailyRuleLogic->setSchedule($this->param);
125
+        return resultArray(['data' => '设置成功!']);
126
+
127
+    }
128
+
129
+    /**
130
+     * 添加日程自定义规则
131
+     * @param DailyRuleLogic $dailyRuleLogic
132
+     * @return \think\response\Json
133
+     */
134
+    public function addSchedule(DailyRuleLogic $dailyRuleLogic){
135
+        if(empty($this->param['name'])) return resultArray(['error'=>'缺少参数']);
136
+        $dailyRuleLogic->addSchedule($this->param);
137
+        return resultArray(['data' => '添加成功!']);
138
+
139
+    }
140
+
141
+    /**
142
+     * 删除日程自定义规则
143
+     * @param DailyRuleLogic $dailyRuleLogic
144
+     * @return \think\response\Json
145
+     */
146
+    public function delSchedule(DailyRuleLogic $dailyRuleLogic){
147
+        if(empty($this->param['id'])) return resultArray(['error'=>'缺少参数']);
148
+        $dailyRuleLogic->delSchedule($this->param['id']);
149
+        return resultArray(['data' => '删除成功!']);
150
+    }
151
+
152
+}

+ 369
- 0
application/admin/controller/ExamineFlow.php Целия файл

@@ -0,0 +1,369 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 审批流程
4
+// +----------------------------------------------------------------------
5
+// | Author: Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use think\Hook;
11
+use think\Request;
12
+use think\Db;
13
+
14
+class ExamineFlow extends ApiCommon
15
+{
16
+    /**
17
+     * 用于判断权限
18
+     * @permission 无限制
19
+     * @allow 登录用户可访问
20
+     * @other 其他根据系统设置
21
+    **/    
22
+    public function _initialize()
23
+    {
24
+        $action = [
25
+            'permission'=>[],
26
+            'allow'=>['index','save','update','read','delete','enables','steplist','userlist','recordlist']            
27
+        ];
28
+        Hook::listen('check_auth',$action);
29
+        $request = Request::instance();
30
+        $a = strtolower($request->action());        
31
+        if (!in_array($a, $action['permission'])) {
32
+            parent::_initialize();
33
+        }
34
+        //权限判断
35
+        $unAction = ['steplist','userlist','recordlist'];
36
+        if (!in_array($a, $unAction) && !checkPerByAction('admin', 'examine_flow', 'index')) {
37
+            header('Content-Type:application/json; charset=utf-8');
38
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
39
+        }        
40
+    } 
41
+
42
+    /**
43
+     * 审批流程列表
44
+     * @author Michael_xu
45
+     * @return 
46
+     */
47
+    public function index()
48
+    {
49
+        $examineFlowModel = model('ExamineFlow');
50
+        $param = $this->param;
51
+        //过滤审批类型中关联的审批流
52
+        $param['types'] = ['neq','oa_examine'];
53
+        $data = $examineFlowModel->getDataList($param);
54
+        return resultArray(['data' => $data]);
55
+    }
56
+
57
+    /**
58
+     * 添加审批流程
59
+     *
60
+     * @return \think\response\Json
61
+     * @throws \think\Exception
62
+     * @throws \think\exception\PDOException
63
+     */
64
+    public function save()
65
+    {
66
+        if (empty($this->param['types'])) return resultArray(['error' => '请选择关联对象!']);
67
+
68
+        $examineFlowModel = model('ExamineFlow');
69
+        $examineStepModel = model('ExamineStep');
70
+        $param = $this->param;
71
+        $userInfo = $this->userInfo;
72
+        $param['update_user_id'] = $userInfo['id'];
73
+
74
+        # 验证名称是否重复
75
+        $repeatWhere['name'] = $param['name'];
76
+        $repeatWhere['is_deleted'] = 0;
77
+        $repeatWhere['types'] = ['neq', 'oa_examine'];
78
+        if (db('admin_examine_flow')->where($repeatWhere)->value('flow_id')) return resultArray(['error' => '审批流名称重复!']);
79
+
80
+        //处理
81
+        $param['user_ids'] = arrayToString($param['user_ids']);
82
+        $param['structure_ids'] = arrayToString($param['structure_ids']);
83
+        $res = $examineFlowModel->createData($param);
84
+        $param['config'] = $param['config'] ? 1 : 0;
85
+        if ($res) {
86
+            $config = $param['config'];
87
+            if ((int)$config == 1) {
88
+                //固定审批流
89
+                $resStep = $examineStepModel->createStepData($param['step'], $res['flow_id']);
90
+                if ($resStep) {
91
+                    return resultArray(['data' => '添加成功']);
92
+                } else {
93
+                    db('admin_examine_flow')->where(['flow_id' => $res['flow_id']])->delete();
94
+                    return resultArray(['error' => $examineStepModel->getError()]);
95
+                }               
96
+            }
97
+            return resultArray(['data' => '添加成功']);
98
+        } else {
99
+        	return resultArray(['error' => $examineFlowModel->getError()]);
100
+        }
101
+    }
102
+
103
+    /**
104
+     * 编辑审批流程
105
+     *
106
+     * @return \think\response\Json
107
+     * @throws \think\Exception
108
+     * @throws \think\db\exception\DataNotFoundException
109
+     * @throws \think\db\exception\ModelNotFoundException
110
+     * @throws \think\exception\DbException
111
+     * @throws \think\exception\PDOException
112
+     */
113
+    public function update()
114
+    {
115
+        if (empty($this->param['types'])) return resultArray(['error' => '请选择关联对象!']);
116
+
117
+        $examineFlowModel = model('ExamineFlow');
118
+        $examineStepModel = model('ExamineStep');
119
+        $param = $this->param;
120
+        $userInfo = $this->userInfo;
121
+        $param['update_user_id'] = $userInfo['id'];
122
+        $param['create_time'] = time();
123
+        $param['update_time'] = time();
124
+        $flowId = $param['flow_id'];
125
+        unset($param['flow_id']);
126
+
127
+        # 验证名称是否重复
128
+        $repeatWhere['name'] = $param['name'];
129
+        $repeatWhere['is_deleted'] = 0;
130
+        $repeatWhere['types'] = ['neq', 'oa_examine'];
131
+        $repeatWhere['flow_id'] = ['neq', $flowId];
132
+        if (db('admin_examine_flow')->where($repeatWhere)->value('flow_id')) return resultArray(['error' => '审批流名称重复!']);
133
+
134
+        //处理
135
+        $param['user_ids'] = arrayToString($param['user_ids']);
136
+        $param['structure_ids'] = arrayToString($param['structure_ids']);
137
+        $res = $examineFlowModel->createData($param);
138
+        $param['config'] = $param['config'] ? 1 : 0;
139
+        if ($res) {
140
+            //将当前审批流标记为已删除,重新创建审批流(目的:保留审批流程记录)
141
+            $upData = [];
142
+            $upData['is_deleted'] = 1;
143
+            $upData['delete_time'] = time();
144
+            $upData['delete_user_id'] = $userInfo['id'];
145
+            $upData['status'] = 0;
146
+            db('admin_examine_flow')->where(['flow_id' => $flowId])->update($upData);
147
+
148
+            $config = $param['config'];
149
+            if ((int)$config == 1) {
150
+                //固定审批流
151
+                $resStep = $examineStepModel->createStepData($param['step'], $res['flow_id']);
152
+                if ($resStep) {
153
+                    return resultArray(['data' => '添加成功']);
154
+                } else {
155
+                    db('admin_examine_flow')->where(['flow_id' => $res['flow_id']])->delete();
156
+                    return resultArray(['error' => $examineStepModel->getError()]);
157
+                }
158
+            }
159
+            return resultArray(['data' => '添加成功']);
160
+        } else {
161
+            return resultArray(['error' => $examineFlowModel->getError()]);
162
+        }
163
+
164
+
165
+//        $newData = db('admin_examine_flow')->where(['flow_id' => $param['flow_id']])->find();
166
+//        $newData['user_ids'] = arrayToString($param['user_ids']);
167
+//        $param['structure_ids'] = arrayToString($param['structure_ids']);
168
+//        $param['update_user_id'] = $userInfo['id'];
169
+//        $param['create_time'] = time();
170
+//        $param['update_time'] = time();
171
+//        $param['status'] = 1;
172
+//        $resUpdate = $examineFlowModel->updateDataById($param, $param['flow_id']);
173
+//
174
+//        if ($resUpdate) {
175
+//            if ($param['config'] == 1) {
176
+//                $resStep = $examineStepModel->createStepData($param['step'], $resUpdate['flow_id']);
177
+//                if (!$resStep) {
178
+//                    return resultArray(['error' => $examineStepModel->getError()]);
179
+//                }
180
+//            }
181
+//
182
+//            $upData = [];
183
+//            $upData['is_deleted'] = 1;
184
+//            $upData['delete_time'] = time();
185
+//            $upData['delete_user_id'] = $userInfo['id'];
186
+//            $upData['status'] = 0;
187
+//            $resFlow = db('admin_examine_flow')->where(['flow_id' => $param['flow_id']])->update($upData);
188
+//            if (!$resFlow) {
189
+//                return resultArray(['error' => '编辑失败1']);
190
+//            }
191
+//            return resultArray(['data' => '编辑成功']);
192
+//        } else {
193
+//            return resultArray(['error' => '编辑失败2']);
194
+//        }
195
+    }
196
+
197
+    /**
198
+     * 审批流程详情
199
+     * @author Michael_xu
200
+     * @param 
201
+     * @return
202
+     */
203
+    public function read()
204
+    {
205
+        $examineFlowModel = model('ExamineFlow');
206
+        $param = $this->param;        
207
+        $res = $examineFlowModel->getDataById($param['id']);
208
+        if (!$res) {
209
+            return resultArray(['error' => $examineFlowModel->getError()]);
210
+        }
211
+        return resultArray(['data' => $res]); 
212
+    }    
213
+
214
+    /**
215
+     * 删除审批流程(逻辑删)
216
+     * @author Michael_xu
217
+     * @param 
218
+     * @return
219
+     */
220
+    public function delete()
221
+    {
222
+        $examineFlowModel = model('ExamineFlow');
223
+        $param = $this->param;       
224
+        $data = $examineFlowModel->signDelById($param['flow_id']);
225
+        if (!$data) {
226
+            return resultArray(['error' => $examineFlowModel->getError()]);
227
+        }
228
+        return resultArray(['data' => '删除成功']);
229
+    }
230
+
231
+    /**
232
+     * 审批流程状态
233
+     * @author Michael_xu
234
+     * @param ids array
235
+     * @param status 1启用,0禁用
236
+     * @return
237
+     */    
238
+    public function enables()
239
+    {
240
+        $examineFlowModel = model('ExamineFlow');
241
+        $param = $this->param;        
242
+        $id = [$param['flow_id']];
243
+        $data = $examineFlowModel->enableDatas($id, $param['status']);  
244
+        if (!$data) {
245
+            return resultArray(['error' => $examineFlowModel->getError()]);
246
+        } 
247
+        return resultArray(['data' => '操作成功']);         
248
+    }
249
+
250
+    /**
251
+     * 完整审批步骤(固定审批流)
252
+     * @author Michael_xu
253
+     * @param  flow_id 审批流ID
254
+     * @param  user_id 审批对象创建人ID
255
+     * @return
256
+     */
257
+    public function stepList()
258
+    {
259
+        $param = $this->param;
260
+        $userInfo = $this->userInfo;
261
+        $examineStepModel = model('ExamineStep');
262
+        $examineFlowModel = model('ExamineFlow');
263
+
264
+        $check_user_id = $userInfo['id'];
265
+        $flow_id = $param['flow_id'];
266
+        $types = $param['types'];
267
+        $types_id = $param['types_id'];
268
+        $typesArr = ['crm_contract', 'crm_receivables', 'crm_invoice', 'oa_examine'];
269
+        if (!$types || !in_array($types, $typesArr)) {
270
+            return resultArray(['error' => '参数错误']);
271
+        }
272
+        
273
+        if ($flow_id) {
274
+            $examineFlowData = $examineFlowModel->getDataById($param['flow_id']);
275
+            if (!$examineFlowData) {
276
+                return resultArray(['error' => '参数错误']);
277
+            }
278
+            $typesInfo = $examineStepModel->getDataByTypes($types, $types_id);
279
+            $user_id = $typesInfo['dataInfo']['owner_user_id'];
280
+            if ($types == 'oa_examine') {
281
+                $user_id = $typesInfo['dataInfo']['create_user_id'];
282
+            }
283
+            if (!$user_id) {
284
+                return resultArray(['error' => '参数错误']);    
285
+            }      
286
+        } else {
287
+            $user_id = $check_user_id;
288
+            // 获取符合条件的审批流
289
+            $examineFlowData = $examineFlowModel->getFlowByTypes($user_id, $types, $types_id);
290
+            if (!$examineFlowData) {
291
+                # 合同、回款、发票模块审批流停用
292
+                if (in_array($types, ['crm_contract', 'crm_receivables', 'crm_invoice'])) {
293
+                    return resultArray(['data' => ['examineStatus' => false]]);
294
+                }
295
+
296
+                return resultArray(['error' => '无可用审批流,请联系管理员']);
297
+            } 
298
+            $flow_id = $examineFlowData['flow_id'];         
299
+        }
300
+        if ($types == 'oa_examine') {
301
+            $category_id = db('oa_examine')->where(['examine_id' => $types_id])->value('category_id');
302
+        }
303
+        $list=[];
304
+        //自选还是流程(1固定,0自选)
305
+        if ($examineFlowData['config'] == 1) {
306
+            //获取审批流程
307
+            $stepInfo = $examineStepModel->getStepList($flow_id, $user_id, $types, $types_id, $check_user_id, $param['action'], $category_id);
308
+            $stepList = $stepInfo['steplist'];
309
+            $list=$stepInfo['steplist'][0]['user_id_info'];
310
+//            foreach ($stepInfo['steplist'] as $k=>$v){
311
+//                $data['user_id_info'][]=$v['user_id_info'];
312
+//            }
313
+        } else {
314
+            $stepInfo = $examineStepModel->getPerStepList($types, $types_id, $user_id, $check_user_id, $param['action']);
315
+            $stepList = $stepInfo['steplist'];
316
+            $list=$stepInfo['steplist'][0]['user_id_info'];
317
+//            foreach ($stepInfo['steplist'] as $k=>$v){
318
+//                $data['user_id_info'][]=$stepInfo['steplist']['user_id_info'];
319
+//            }
320
+        }
321
+        $data = [];
322
+        $data['config'] = (int) $examineFlowData['config']; //1固定,0自选
323
+        $data['stepList'] = $stepList ? : []; 
324
+        $data['examine_user'] = $list ? : [];
325
+        $data['is_check'] = $stepInfo['is_check'] ? : 0;
326
+        $data['is_recheck'] = $stepInfo['is_recheck'] ? : 0;
327
+        $data['examineStatus'] = true;
328
+        return resultArray(['data' => $data]);
329
+    }
330
+
331
+    /**
332
+     * 自选审批人列表(授权审批类型)
333
+     * @author Michael_xu
334
+     * @param  types 类型
335
+     * @return
336
+     */
337
+    public function userList()
338
+    {
339
+        $param = $this->param;
340
+        $userInfo = $this->userInfo;
341
+        $types = $param['types'];
342
+        $examineStepModel = model('ExamineStep');
343
+        $userModel = model('User');
344
+        // $examine_user_ids = $examineStepModel->getUserByPer($types);
345
+        //暂定返回全部
346
+        $examine_user_ids = getSubUserId(true, 1);
347
+        $where = [];
348
+        $where['user.id'] = array('in',$examine_user_ids);
349
+        $where['status'] = ['gt',0];
350
+        $where['pageType'] = 'all';
351
+        $userList = $userModel->getDataList($where);
352
+        return resultArray(['data' => $userList['list']]);
353
+    } 
354
+
355
+    /**
356
+     * 审批记录
357
+     * @author Michael_xu
358
+     * @param  types 类型
359
+     * @return
360
+     */
361
+    public function recordList()
362
+    {
363
+        $param = $this->param;
364
+        $userInfo = $this->userInfo;
365
+        $examineRecordModel = model('ExamineRecord');
366
+        $list = $examineRecordModel->getDataList($param) ? : [];
367
+        return resultArray(['data' => $list]);
368
+    }        
369
+}

+ 673
- 0
application/admin/controller/Field.php Целия файл

@@ -0,0 +1,673 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 自定义字段
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use app\admin\logic\FieldGrantLogic;
11
+use app\crm\logic\VisitLogic;
12
+use app\crm\model\Business;
13
+use app\crm\model\Contacts;
14
+use app\crm\model\Contract;
15
+use app\crm\model\Customer;
16
+use app\crm\model\InvoiceInfoLogic;
17
+use app\crm\model\Leads;
18
+use app\crm\model\Product;
19
+use app\crm\model\Receivables;
20
+use think\Hook;
21
+use think\Request;
22
+use think\Db;
23
+use app\admin\model\User as UserModel;
24
+
25
+class Field extends ApiCommon
26
+{
27
+    /**
28
+     * 用于判断权限
29
+     * @permission 无限制
30
+     * @allow 登录用户可访问
31
+     * @other 其他根据系统设置
32
+    **/    
33
+    public function _initialize()
34
+    {
35
+        $action = [
36
+            'permission'=>[''],
37
+            'allow'=>['index','getfield','update','read','config','validates','configindex','columnwidth','uniquefield']
38
+        ];
39
+        Hook::listen('check_auth',$action);
40
+        $request = Request::instance();
41
+        $a = strtolower($request->action());        
42
+        if (!in_array($a, $action['permission'])) {
43
+            parent::_initialize();
44
+        }        
45
+    }
46
+    
47
+    /**
48
+     * 自定义字段列表
49
+     */
50
+    public function index()
51
+    {  
52
+        //权限判断
53
+        if (!checkPerByAction('admin', 'crm', 'field')) {
54
+            header('Content-Type:application/json; charset=utf-8');
55
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
56
+        }         
57
+        $param = $this->param;
58
+        $types_arr = [
59
+            ['types' => 'crm_leads','name' => '线索管理'],
60
+            ['types' => 'crm_customer','name' => '客户管理'],
61
+            ['types' => 'crm_contacts','name' => '联系人管理'],
62
+            ['types' => 'crm_product','name' => '产品管理'],
63
+            ['types' => 'crm_business','name' => '商机管理'],
64
+            ['types' => 'crm_contract','name' => '合同管理'],
65
+            ['types' => 'crm_receivables','name' => '回款管理'],
66
+            ['types' => 'crm_visit','name' => '客户回访管理'],
67
+        ];
68
+        $examine_types_arr = [];    
69
+        switch ($param['type']) {
70
+            case 'crm' : $typesArr = $types_arr; break;
71
+            case 'examine' : $typesArr = $examine_types_arr; break;
72
+            default : $typesArr = $types_arr; break;
73
+        }
74
+
75
+        foreach ($typesArr as $k=>$v) {
76
+            $updateTime = db('admin_field')->where(['types' => $v['types']])->max('update_time');
77
+
78
+            $typesArr[$k]['update_time'] = !empty($updateTime) ? date('Y-m-d H:i:s', $updateTime) : '';
79
+        }  
80
+        return resultArray(['data' => $typesArr]);
81
+    }    
82
+
83
+    /**
84
+     * 自定义字段数据
85
+     */
86
+    public function read()
87
+    {        
88
+        $fieldModel = model('Field');
89
+        $param = $this->param;
90
+        $data = $fieldModel->getDataList($param);    
91
+        if ($data === false) {
92
+            return resultArray(['error' => $fieldModel->getError()]);
93
+        }  
94
+        return resultArray(['data' => $data]);
95
+    }
96
+
97
+    /**
98
+     * 自定义字段创建
99
+     */
100
+    public function update()
101
+    {
102
+        # 权限判断 todo 允许有相应权限的普通员工操作,暂时注释代码,后期修改权限验证。
103
+//        if (!checkPerByAction('admin', 'crm', 'field')) {
104
+//            header('Content-Type:application/json; charset=utf-8');
105
+//            exit(json_encode(['code'=>102,'error'=>'无权操作']));
106
+//        }
107
+        # 系统审批类型暂不支持编辑
108
+        if ($this->param['types'] == 'oa_examine' && $this->param['types_id'] < 7) {
109
+            return resultArray(['error' => '系统审批类型暂不支持编辑']);
110
+        }
111
+
112
+        $fieldModel = model('Field');
113
+
114
+        $param      = $this->param;
115
+        $types      = $param['types'];
116
+        $types_id   = $param['types_id'] ? : 0;
117
+//        $data['types'] = $param['types'];
118
+
119
+        $data        = $param['data'];
120
+        $saveParam   = []; # 新增数据
121
+        $updateParam = []; # 编辑数据
122
+        $delParam    = []; # 删除数据
123
+        $fieldIds    = []; # 删除数据(兼容前端11.*.*版本)
124
+        $i = 0;
125
+        foreach ($data AS $k => $v) {
126
+            $i++;
127
+            if ($v['field_id']) {
128
+                if (isset($v['is_deleted']) && $v['is_deleted'] == '1') {
129
+                    # 删除
130
+                    $delParam[] = $v['field_id']; //删除
131
+                } else {
132
+                    # 编辑
133
+                    $updateParam[$k] = $v;
134
+                    $updateParam[$k]['order_id'] = $i;
135
+                    # 用来删除自定义字段(兼容前端11.*.*版本):记录存在的自定义字段ID,取出差集,就是要删的数。
136
+                    $fieldIds[] = $v['field_id'];
137
+                }
138
+            } else {
139
+                # 新增
140
+                $saveParam[$k] = $v;
141
+                $saveParam[$k]['order_id'] = $i;
142
+                $saveParam[$k]['types_id'] = $types_id;
143
+            }
144
+        }
145
+
146
+        # 错误数据
147
+        $errorMessage = [];
148
+
149
+        # 兼容前端11.*.*版本的删除条件处理,通过比较差异,来确定谁被前端给删除了 todo 这段代码需要写在新增上面,不然会把新增的给删除掉
150
+        $oldFieldIds = Db::name('admin_field')->where('types', $types)->column('field_id');
151
+        $deleteIds   = array_diff($oldFieldIds, $fieldIds);
152
+        foreach ($deleteIds AS $key => $value) {
153
+            if (!in_array($value, $delParam)) $delParam[] = $value;
154
+        }
155
+
156
+        # 新增
157
+        if (!empty($saveParam)) {
158
+            if (!$data = $fieldModel->createData($types, $saveParam)) {
159
+                $errorMessage[] = $fieldModel->getError();
160
+            }            
161
+        }
162
+
163
+        # 编辑
164
+        if (!empty($updateParam)) {
165
+            if (!$data = $fieldModel->updateDataById($updateParam)) {
166
+                $errorMessage[] = $fieldModel->getError();
167
+            }
168
+        }
169
+
170
+        # 删除
171
+        if (!empty($delParam)) {
172
+            if (!$data = $fieldModel->delDataById($delParam)) {
173
+                $errorMessage[] = $fieldModel->getError();
174
+            }
175
+        }
176
+
177
+        # 自定义字段变更后,同步更新字段授权表
178
+        (new FieldGrantLogic())->fieldGrantDiyHandle($types);
179
+        
180
+        if ($errorMessage) {
181
+            return resultArray(['error' => $errorMessage]);
182
+        } else {
183
+            return resultArray(['data' => '修改成功']);
184
+        }
185
+    }
186
+
187
+    /**
188
+     * 自定义字段数据获取
189
+     *
190
+     * @return \think\response\Json
191
+     * @throws \think\db\exception\DataNotFoundException
192
+     * @throws \think\db\exception\ModelNotFoundException
193
+     * @throws \think\exception\DbException
194
+     */
195
+    public function getField()
196
+    {
197
+        $fieldModel = model('Field');
198
+        $userModel = model('User');
199
+        $param = $this->param;
200
+        $module = trim($param['module']);
201
+        $controller = trim($param['controller']);
202
+        $action = trim($param['action']);
203
+        $system = !empty($param['system']) ? $param['system'] : 0;
204
+        unset($param['system']);
205
+        
206
+        if (!$module || !$controller || !$action) {
207
+            return resultArray(['error' => '参数错误']);
208
+        }
209
+        //判断权限
210
+        $userInfo = $this->userInfo;
211
+        $user_id = $userInfo['id'];
212
+        $types = $param['types'];
213
+        $types_id = $param['types_id'] ? : '';
214
+        $dataInfo = [];
215
+        if ($action == 'read' || $action == 'update') {
216
+            //获取详情数据
217
+            if (($param['action'] == 'update' || $param['action'] == 'read') && $param['action_id']) {
218
+                switch ($param['types']) {
219
+                    case 'crm_customer' : 
220
+                        $customerModel = new \app\crm\model\Customer();
221
+                        $dataInfo = $customerModel->getDataById(intval($param['action_id']));
222
+                        //判断权限
223
+                        $auth_user_ids = $userModel->getUserByPer('crm', 'customer', $param['action']);
224
+                        //读写权限
225
+                        $roPre = $userModel->rwPre($user_id, $dataInfo['ro_user_id'], $dataInfo['rw_user_id'], 'read');
226
+                        $rwPre = $userModel->rwPre($user_id, $dataInfo['ro_user_id'], $dataInfo['rw_user_id'], 'update');
227
+                        //判断是否客户池数据
228
+                        $wherePool = $customerModel->getWhereByPool();
229
+                        $resPool = db('crm_customer')->alias('customer')->where(['customer_id' => $param['action_id']])->where($wherePool)->find();
230
+                        if (!$resPool && !in_array($dataInfo['owner_user_id'],$auth_user_ids) && !$roPre && !$rwPre) {
231
+                            header('Content-Type:application/json; charset=utf-8');
232
+                            exit(json_encode(['code'=>102,'error'=>'无权操作']));
233
+                        }
234
+                        break;
235
+                    case 'crm_leads' : 
236
+                        $leadsModel = new \app\crm\model\Leads();
237
+                        $dataInfo = $leadsModel->getDataById(intval($param['action_id']));
238
+                        //判断权限
239
+                        $auth_user_ids = $userModel->getUserByPer('crm', 'leads', $param['action']);
240
+                        if (!in_array($dataInfo['owner_user_id'],$auth_user_ids)) {
241
+                            header('Content-Type:application/json; charset=utf-8');
242
+                            exit(json_encode(['code'=>102,'error'=>'无权操作']));
243
+                        }                        
244
+                        break;  
245
+                    case 'crm_contacts' : 
246
+                        $contactsModel = new \app\crm\model\Contacts();
247
+                        $dataInfo = $contactsModel->getDataById(intval($param['action_id']));
248
+                        //判断权限
249
+                        $auth_user_ids = $userModel->getUserByPer('crm', 'contacts', $param['action']);
250
+                        if (!in_array($dataInfo['owner_user_id'],$auth_user_ids)) {
251
+                            header('Content-Type:application/json; charset=utf-8');
252
+                            exit(json_encode(['code'=>102,'error'=>'无权操作']));
253
+                        }                          
254
+                        break;
255
+                    case 'crm_business' :
256
+                        $businessModel = new \app\crm\model\Business();
257
+                        $dataInfo = $businessModel->getDataById(intval($param['action_id']));
258
+                        //判断权限
259
+                        $auth_user_ids = $userModel->getUserByPer('crm', 'business', $param['action']);
260
+                        //读写权限
261
+                        $roPre = $userModel->rwPre($user_id, $dataInfo['ro_user_id'], $dataInfo['rw_user_id'], 'read');
262
+                        $rwPre = $userModel->rwPre($user_id, $dataInfo['ro_user_id'], $dataInfo['rw_user_id'], 'update');
263
+                        if (!in_array($dataInfo['owner_user_id'],$auth_user_ids) && !$roPre && !$rwPre) {
264
+                            header('Content-Type:application/json; charset=utf-8');
265
+                            exit(json_encode(['code'=>102,'error'=>'无权操作']));
266
+                        }
267
+                        break;
268
+                    case 'crm_contract' : 
269
+                        $contractModel = new \app\crm\model\Contract();
270
+                        $dataInfo = $contractModel->getDataById(intval($param['action_id']));
271
+                        //判断权限
272
+                        $auth_user_ids = $userModel->getUserByPer('crm', 'contract', $param['action']);
273
+                        //读写权限
274
+                        $roPre = $userModel->rwPre($user_id, $dataInfo['ro_user_id'], $dataInfo['rw_user_id'], 'read');
275
+                        $rwPre = $userModel->rwPre($user_id, $dataInfo['ro_user_id'], $dataInfo['rw_user_id'], 'update');
276
+                        if (!in_array($dataInfo['owner_user_id'],$auth_user_ids) && !$roPre && !$rwPre) {
277
+                            header('Content-Type:application/json; charset=utf-8');
278
+                            exit(json_encode(['code'=>102,'error'=>'无权操作']));
279
+                        }
280
+                        break;
281
+                    case 'crm_product' : 
282
+                        $productModel = new \app\crm\model\Product();
283
+                        $dataInfo = $productModel->getDataById(intval($param['action_id']));
284
+                        break;
285
+                    case 'crm_receivables' : 
286
+                        $receivablesModel = new \app\crm\model\Receivables();
287
+                        $dataInfo = $receivablesModel->getDataById(intval($param['action_id']));
288
+                        //判断权限
289
+                        $auth_user_ids = $userModel->getUserByPer('crm', 'receivables', $param['action']);
290
+                        if (!in_array($dataInfo['owner_user_id'],$auth_user_ids)) {
291
+                            header('Content-Type:application/json; charset=utf-8');
292
+                            exit(json_encode(['code'=>102,'error'=>'无权操作']));
293
+                        }
294
+                        break;
295
+                    case 'crm_receivables_plan' : 
296
+                        $receivablesPlanModel = new \app\crm\model\ReceivablesPlan();
297
+                        $dataInfo = $receivablesPlanModel->getDataById(intval($param['action_id']));
298
+                        break; 
299
+                    case 'oa_examine' :
300
+                        $examineModel = new \app\oa\model\Examine();  
301
+                        $examineFlowModel = new \app\admin\model\ExamineFlow();  
302
+                        $dataInfo = $examineModel->getDataById(intval($param['action_id']));
303
+                        # 前端没有传types_id,这里需要指定一下types_id
304
+                        if (!empty($dataInfo['category_id'])) $param['types_id'] = $dataInfo['category_id'];
305
+                        $adminIds = $userModel->getAdminId(); //管理员
306
+                        $checkUserIds = $examineFlowModel->getUserByFlow($dataInfo['flow_id'], $dataInfo['create_user_id'], $dataInfo['check_user_id']);
307
+                        if (((int)$dataInfo['create_user_id'] != $user_id && !in_array($user_id,$adminIds) && !in_array($user_id,$checkUserIds))) {
308
+                            header('Content-Type:application/json; charset=utf-8');
309
+                            exit(json_encode(['code'=>102,'error'=>'无权操作']));
310
+                        }                        
311
+                        break;
312
+                    case 'crm_visit' :
313
+                        $visit = new \app\crm\model\Visit();
314
+                        $dataInfo = $visit->getDataById(intval($param['action_id']));
315
+                        //判断权限
316
+                        $auth_user_ids = $userModel->getUserByPer('crm', 'visit', $param['action']);
317
+                        //读写权限
318
+                        $roPre = $userModel->rwPre($user_id, $dataInfo['ro_user_id'], $dataInfo['rw_user_id'], 'read');
319
+                        $rwPre = $userModel->rwPre($user_id, $dataInfo['ro_user_id'], $dataInfo['rw_user_id'], 'update');
320
+                        if (!in_array($dataInfo['owner_user_id'],$auth_user_ids) && !$roPre && !$rwPre) {
321
+                            header('Content-Type:application/json; charset=utf-8');
322
+                            exit(json_encode(['code'=>102,'error'=>'无权操作']));
323
+                        }
324
+                        break;
325
+                } 
326
+            }
327
+        }
328
+        $param['user_id'] = $user_id;
329
+        $action_id = $param['action_id'] ? : '';
330
+        $data = $fieldModel->field($param, $dataInfo) ? : [];
331
+
332
+        # 去掉客户模块下的成交信息
333
+        if ($param['types'] == 'crm_customer' && $param['action'] == 'read') {
334
+            foreach ($data AS $key => $value) {
335
+                if ($value['field'] == 'deal_status') {
336
+                    unset($data[(int)$key]);
337
+                    break;
338
+                }
339
+            }
340
+        }
341
+
342
+        if ($param['types'] == 'crm_customer' && $param['action'] == 'index') {
343
+            $data[] = [
344
+                'field'       => 'pool_day',
345
+                'name'        => '距进入公海天数',
346
+                'form_type'   => 'text',
347
+                'writeStatus' => 0,
348
+                'fieldName'   => 'pool_day'
349
+            ];
350
+        }
351
+
352
+        # 客户锁定状态
353
+        if ($param['types'] == 'crm_customer' && $param['action'] == 'index') {
354
+            $data[] = [
355
+                'field'     => "is_lock",
356
+                'fieldName' => "is_lock",
357
+                'form_type' => "text",
358
+                'name'      => "锁定状态",
359
+                'width'     => ""
360
+            ];
361
+        }
362
+
363
+        # 合同自动编号设置
364
+        if ($param['types'] == 'crm_contract') {
365
+            foreach ($data AS $key => $value) {
366
+                if ($value['field'] == 'num') {
367
+                    if ($this->getAutoNumberStatus(1)) {
368
+                        $data[$key]['is_null']   = 0;
369
+                        $data[$key]['is_unique'] = 0;
370
+                    }
371
+                    $data[$key]['autoGeneNumber'] = $this->getAutoNumberStatus(1) ? 1 : 0;
372
+                }
373
+            }
374
+        }
375
+        # 回款自动编号设置
376
+        if ($param['types'] == 'crm_receivables') {
377
+            foreach ($data AS $key => $value) {
378
+                if ($value['field'] == 'number') {
379
+                    if ($this->getAutoNumberStatus(2)) {
380
+                        $data[$key]['is_null']   = 0;
381
+                        $data[$key]['is_unique'] = 0;
382
+                    }
383
+                    $data[$key]['autoGeneNumber'] = $this->getAutoNumberStatus(2) ? 1 : 0;
384
+                }
385
+            }
386
+        }
387
+        # 回访自动编号设置
388
+        if ($param['types'] == 'crm_visit') {
389
+            foreach ($data AS $key => $value) {
390
+                if ($value['field'] == 'number') {
391
+                    if ($this->getAutoNumberStatus(3)) {
392
+                        $data[$key]['is_null']   = 0;
393
+                        $data[$key]['is_unique'] = 0;
394
+                    }
395
+                    $data[$key]['autoGeneNumber'] = $this->getAutoNumberStatus(3) ? 1 : 0;
396
+                }
397
+            }
398
+        }
399
+
400
+        # 隐藏回款计划中的附件
401
+        if ($param['types'] == 'crm_receivables_plan') {
402
+            foreach ($data AS $key => $value) {
403
+                if ($value['field'] == 'file') {
404
+                    unset($data[(int)$key]);
405
+                }
406
+            }
407
+        }
408
+        
409
+        if (!empty($system) && $system == 1) {
410
+            # 商机和合同排除产品字段
411
+            if (in_array($param['types'], ['crm_business', 'crm_contract'])) {
412
+                foreach ($data AS $key => $value) {
413
+                    if ($value['field'] == 'product' && $value['name'] == '产品') {
414
+                        unset($data[(int)$key]);
415
+                        break;
416
+                    }
417
+                }
418
+            }
419
+            $data = array_values($data);
420
+
421
+            # 系统信息
422
+            switch ($types) {
423
+                case 'crm_leads' :
424
+                    $leadsModel = new Leads();
425
+                    $leadsData  = $leadsModel->getSystemInfo($action_id);
426
+                    $leadsArray = ['create_user_name' => '创建人', 'create_time' => '创建时间', 'update_time' => '更新时间', 'follow_time' => '最后跟进时间'];
427
+
428
+                    foreach ($leadsData AS $key => $value) {
429
+                        if (empty($leadsArray[$key])) continue;
430
+
431
+                        $data[] = [
432
+                            'field'     => $key,
433
+                            'name'      => $leadsArray[$key],
434
+                            'form_type' => strpos($key, 'time') ? 'datetime' : 'text',
435
+                            'value'     => $value,
436
+                            'system'    => 1
437
+                        ];
438
+                    }
439
+                    break;
440
+                case 'crm_customer' :
441
+                    $customerModel = new Customer();
442
+                    $customerData  = $customerModel->getSystemInfo($action_id);
443
+                    $customerArray = ['obtain_time' => '负责人获取客户时间', 'create_time' => '创建时间', 'update_time' => '更新时间', 'follow_time' => '最后跟进时间', 'follow_record' => '最后跟进记录', 'deal_status' => '成交状态'];
444
+
445
+                    foreach ($customerData AS $key => $value) {
446
+                        if (empty($customerArray[$key])) continue;
447
+
448
+                        $data[] = [
449
+                            'field'     => $key,
450
+                            'name'      => $customerArray[$key],
451
+                            'form_type' => strpos($key, 'time') ? 'datetime' : 'text',
452
+                            'value'     => $value,
453
+                            'system'    => 1
454
+                        ];
455
+                    }
456
+                    break;
457
+                case 'crm_contacts' :
458
+                    $contactsModel = new Contacts();
459
+                    $contactsData  = $contactsModel->getSystemInfo($action_id);
460
+                    $contactsArray = ['create_user_name' => '创建人', 'create_time' => '创建时间', 'update_time' => '更新时间', 'follow_time' => '最后跟进时间'];
461
+
462
+                    foreach ($contactsData AS $key => $value) {
463
+                        if (empty($contactsArray[$key])) continue;
464
+
465
+                        $data[] = [
466
+                            'field'     => $key,
467
+                            'name'      => $contactsArray[$key],
468
+                            'form_type' => strpos($key, 'time') ? 'datetime' : 'text',
469
+                            'value'     => $value,
470
+                            'system'    => 1
471
+                        ];
472
+                    }
473
+                    break;
474
+                case 'crm_business' :
475
+                    $businessModel = new Business();
476
+                    $businessData  = $businessModel->getSystemInfo($action_id);
477
+                    $businessArray = ['create_user_name' => '创建人', 'create_time' => '创建时间', 'update_time' => '更新时间', 'follow_time' => '最后跟进时间'];
478
+
479
+                    foreach ($businessData AS $key => $value) {
480
+                        if (empty($businessArray[$key])) continue;
481
+
482
+                        $data[] = [
483
+                            'field'     => $key,
484
+                            'name'      => $businessArray[$key],
485
+                            'form_type' => strpos($key, 'time') ? 'datetime' : 'text',
486
+                            'value'     => $value,
487
+                            'system'    => 1
488
+                        ];
489
+                    }
490
+                    break;
491
+                case 'crm_contract' :
492
+                    $contractModel = new Contract();
493
+                    $contractData  = $contractModel->getSystemInfo($action_id);
494
+                    $contractArray = ['create_user_name' => '创建人', 'create_time' => '创建时间', 'update_time' => '更新时间', 'follow_time' => '最后跟进时间', 'done_money' => '已收款金额', 'un_money' => '未收款金额'];
495
+
496
+                    foreach ($contractData AS $key => $value) {
497
+                        if (empty($contractArray[$key])) continue;
498
+
499
+                        $data[] = [
500
+                            'field'     => $key,
501
+                            'name'      => $contractArray[$key],
502
+                            'form_type' => strpos($key, 'time') ? 'datetime' : 'text',
503
+                            'value'     => $value,
504
+                            'system'    => 1
505
+                        ];
506
+                    }
507
+                    break;
508
+                case 'crm_receivables' :
509
+                    $receivablesModel = new Receivables();
510
+                    $receivablesData  = $receivablesModel->getSystemInfo($action_id);
511
+                    $receivablesArray = ['create_user_name' => '创建人', 'create_time' => '创建时间', 'update_time' => '更新时间'];
512
+
513
+                    foreach ($receivablesData AS $key => $value) {
514
+                        if (empty($receivablesArray[$key])) continue;
515
+
516
+                        $data[] = [
517
+                            'field'     => $key,
518
+                            'name'      => $receivablesArray[$key],
519
+                            'form_type' => strpos($key, 'time') ? 'datetime' : 'text',
520
+                            'value'     => $value,
521
+                            'system'    => 1
522
+                        ];
523
+                    }
524
+                    break;
525
+                case 'crm_product' :
526
+                    $productModel = new Product();
527
+                    $productData  = $productModel->getSystemInfo($action_id);
528
+                    $productArray = ['create_user_name' => '创建人', 'create_time' => '创建时间', 'update_time' => '更新时间'];
529
+
530
+                    foreach ($productData AS $key => $value) {
531
+                        if (empty($productArray[$key])) continue;
532
+
533
+                        $data[] = [
534
+                            'field'     => $key,
535
+                            'name'      => $productArray[$key],
536
+                            'form_type' => strpos($key, 'time') ? 'datetime' : 'text',
537
+                            'value'     => $value,
538
+                            'system'    => 1
539
+                        ];
540
+                    }
541
+                    break;
542
+                case 'crm_visit' :
543
+                    $visitLogic = new VisitLogic();
544
+                    $visitData  = $visitLogic->getSystemInfo($action_id);
545
+                    $visitArray = ['create_user_name' => '创建人', 'create_time' => '创建时间', 'update_time' => '更新时间'];
546
+
547
+                    foreach ($visitData AS $key => $value) {
548
+                        if (empty($visitArray[$key])) continue;
549
+
550
+                        $data[] = [
551
+                            'field'     => $key,
552
+                            'name'      => $visitArray[$key],
553
+                            'form_type' => strpos($key, 'time') ? 'datetime' : 'text',
554
+                            'value'     => $value,
555
+                            'system'    => 1
556
+                        ];
557
+                    }
558
+                    break;
559
+            }
560
+        }
561
+
562
+        $data = $fieldModel->resetField($param['types'], $data);
563
+        return resultArray(['data' => array_values($data)]);
564
+    }
565
+
566
+    /**
567
+     * 自定义字段数据验重
568
+     *
569
+     * @return \think\response\Json
570
+     */
571
+    public function validates()
572
+    {
573
+        $param = $this->param;
574
+        $fieldModel = model('Field');
575
+        if (is_array($param['val'])) {
576
+            //多选类型暂不验证
577
+            return resultArray(['data' => '验证通过']);
578
+        }
579
+        $res = $fieldModel->getValidate(trim($param['field']), trim($param['val']), intval($param['id']), trim($param['types']));
580
+        if (!$res) {
581
+            return resultArray(['error' => $fieldModel->getError()]);
582
+        }
583
+        return resultArray(['data' => '验证通过']);
584
+    }
585
+
586
+    /**
587
+     * 自定义字段列表设置(排序、展示、列宽度)
588
+     * @param types 分类
589
+     * @param value 值
590
+     */
591
+    public function config()
592
+    {
593
+        $param = $this->param;
594
+        $userInfo = $this->userInfo;
595
+        $param['user_id'] = $userInfo['id'];
596
+        $userFieldModel = model('UserField');
597
+        $res = $userFieldModel->updateConfig($param['types'], $param);
598
+        if (!$res) {
599
+            return resultArray(['error' => $userFieldModel->getError()]);
600
+        }
601
+        return resultArray(['data' => '设置成功']);
602
+    } 
603
+
604
+    /**
605
+     * 自定义字段列宽度设置
606
+     * @param types 分类
607
+     * @param field 字段名
608
+     * @param width 列宽度
609
+     */
610
+    public function columnWidth()
611
+    {
612
+        $param = $this->param;
613
+        $userInfo = $this->userInfo;
614
+        $userFieldModel = model('UserField');
615
+        $width = $param['width'] > 10 ? $param['width'] : '';
616
+        $unField = array('pool_day','owner_user_name','is_lock','create_user_name');
617
+        if (!in_array($param['field'],$unField)) {
618
+            $res = $userFieldModel->setColumnWidth($param['types'], $param['field'], $width, $userInfo['id']);
619
+            if (!$res) {
620
+                return resultArray(['error' => $userFieldModel->getError()]);
621
+            }            
622
+        }
623
+        return resultArray(['data' => '设置成功']);
624
+    }
625
+
626
+    /**
627
+     * 自定义字段列表设置数据
628
+     * @param types 分类
629
+     * @param value 值
630
+     */
631
+    public function configIndex()
632
+    {
633
+        $param = $this->param;
634
+        $userInfo = $this->userInfo;
635
+        $userFieldModel = model('UserField');
636
+        $res = $userFieldModel->getDataList($param['types'], $userInfo['id']);
637
+        if (!$res) {
638
+            return resultArray(['error' => $userFieldModel->getError()]);
639
+        }
640
+        return resultArray(['data' => $res]);
641
+    }
642
+
643
+    /**
644
+     * 自定义验重字段
645
+     * @param types 分类
646
+     * @param
647
+     */
648
+    public function uniqueField()
649
+    {
650
+        $param = $this->param;
651
+        if ($param['types'] == 'crm_user') {
652
+            $list = array_filter(UserModel::$import_field_list, function ($val) {
653
+                return $val['is_unique'] == 1;
654
+            });
655
+            $list = array_column($list, 'name');
656
+        } else {
657
+            $list = db('admin_field')->where(['types' => $param['types'],'is_unique' => 1])->column('name');
658
+        }
659
+        $list = $list ? implode(',',$list) : '无';
660
+        return resultArray(['data' => $list]);
661
+    }
662
+
663
+    /**
664
+     * 获取自动编号状态
665
+     *
666
+     * @param $type
667
+     * @return int|mixed|string|null
668
+     */
669
+    private function getAutoNumberStatus($type)
670
+    {
671
+        return Db::name('crm_number_sequence')->where('number_type', $type)->where('status', 0)->value('number_sequence_id');
672
+    }
673
+}

+ 74
- 0
application/admin/controller/FieldGrant.php Целия файл

@@ -0,0 +1,74 @@
1
+<?php
2
+/**
3
+ * 字段授权控制器
4
+ *
5
+ * @author qifan
6
+ * @date 2020-12-02
7
+ */
8
+
9
+namespace app\admin\controller;
10
+
11
+use app\admin\logic\FieldGrantLogic;
12
+use think\Hook;
13
+use think\Request;
14
+
15
+class FieldGrant extends ApiCommon
16
+{
17
+    /**
18
+     * 用于判断权限
19
+     * @permission 无限制
20
+     * @allow 登录用户可访问
21
+     * @other 其他根据系统设置
22
+     **/
23
+    public function _initialize()
24
+    {
25
+        $action = [
26
+            'permission'=>[''],
27
+            'allow'=>['index', 'update']
28
+        ];
29
+        Hook::listen('check_auth',$action);
30
+        $request = Request::instance();
31
+        $a = strtolower($request->action());
32
+        if (!in_array($a, $action['permission'])) {
33
+            parent::_initialize();
34
+        }
35
+    }
36
+
37
+    /**
38
+     * 字段授权列表
39
+     *
40
+     * @param FieldGrantLogic $fieldGrantLogic
41
+     * @return \think\response\Json
42
+     * @throws \think\db\exception\DataNotFoundException
43
+     * @throws \think\db\exception\ModelNotFoundException
44
+     * @throws \think\exception\DbException
45
+     */
46
+    public function index(FieldGrantLogic $fieldGrantLogic)
47
+    {
48
+        $data = $fieldGrantLogic->index($this->param);
49
+
50
+        return resultArray(['data' => $data]);
51
+    }
52
+
53
+    /**
54
+     * 更新授权信息
55
+     *
56
+     * @param FieldGrantLogic $fieldGrantLogic
57
+     * @return \think\response\Json
58
+     * @throws \think\Exception
59
+     * @throws \think\exception\PDOException
60
+     */
61
+    public function update(FieldGrantLogic $fieldGrantLogic)
62
+    {
63
+        if (empty($this->param['grant_id'])) return resultArray(['error' => '缺少授权ID!']);
64
+        if (empty($this->param['content']))  return resultArray(['error' => '缺少授权数据!']);
65
+
66
+        $status = $fieldGrantLogic->update($this->param['grant_id'], $this->param['content']);
67
+
68
+        if ($status === false) {
69
+            return resultArray(['error' => '更新授权信息失败!']);
70
+        }
71
+
72
+        return resultArray(['data' => '更新授权信息成功!']);
73
+    }
74
+}

+ 230
- 0
application/admin/controller/File.php Целия файл

@@ -0,0 +1,230 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 附件
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+namespace app\admin\controller;
8
+
9
+use app\work\traits\WorkAuthTrait;
10
+use think\Hook;
11
+use think\Request;
12
+
13
+class File extends ApiCommon
14
+{
15
+    use WorkAuthTrait;
16
+
17
+	/**
18
+     * 用于判断权限
19
+     * @permission 无限制
20
+     * @allow 登录用户可访问
21
+     * @other 其他根据系统设置
22
+    **/    
23
+    public function _initialize()
24
+    {
25
+        $action = [
26
+            'permission'=>[''],
27
+            'allow'=>['index', 'save', 'delete', 'update', 'read', 'download', 'deleteall', 'downloadimage']
28
+        ];
29
+        Hook::listen('check_auth',$action);
30
+        $request = Request::instance();
31
+        $a = strtolower($request->action());        
32
+        if (!in_array($a, $action['permission'])) {
33
+            parent::_initialize();
34
+        }         
35
+    }
36
+
37
+    /**
38
+     * 附件列表
39
+     * @author Michael_xu
40
+     * @param 
41
+     * @return                            
42
+     */
43
+    public function index()
44
+    {
45
+        $fileModel = model('File');
46
+        $param = $this->param;
47
+        $data = $fileModel->getDataList($param, $param['by']);
48
+        return resultArray(['data' => $data]);
49
+    }
50
+
51
+	/**
52
+     * 附件上传
53
+     * @author Michael_xu
54
+     * @return                            
55
+     */
56
+    public function save()
57
+    {
58
+        header('Access-Control-Allow-Origin: *');
59
+        header('Access-Control-Allow-Methods: POST');
60
+        header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
61
+        $type     = $this->param['type'];
62
+        $files    = request()->file('file');
63
+        $imgs     = request()->file('img');
64
+        $i        = 0;
65
+        $newFiles = [];
66
+
67
+        # 项目上传附件权限
68
+        if (!empty($this->param['module']) && $this->param['module'] == 'work_task' && !empty($this->param['work_id'])) {
69
+            if (!$this->checkWorkOperationAuth('uploadTaskFile', $this->param['work_id'], $this->userInfo['id'])) {
70
+                header('Content-Type:application/json; charset=utf-8');
71
+                exit(json_encode(['code' => 102, 'error' => '无权操作!']));
72
+            }
73
+        }
74
+
75
+        if (!empty($type) && in_array($type, ['img', 'file'])) {
76
+            # todo 兼容11.0前端
77
+            if ($type == 'img') {
78
+                $newFiles[0]['obj']   = $files;
79
+                $newFiles[0]['types'] = 'img';
80
+            }
81
+            if ($type == 'file') {
82
+                $newFiles[0]['obj']   = $files;
83
+                $newFiles[0]['types'] = 'file';
84
+            }
85
+        } else {
86
+            # todo 兼容9.0前端
87
+            if (!empty($files)) {
88
+                foreach ($files as $v) {
89
+                    $newFiles[$i]['obj']   = $v;
90
+                    $newFiles[$i]['types'] = 'file';
91
+                    $i++;
92
+                }
93
+            }
94
+            if (!empty($imgs)) {
95
+                foreach ($imgs as $v) {
96
+                    $newFiles[$i]['obj']   = $v;
97
+                    $newFiles[$i]['types'] = 'img';
98
+                    $i++;
99
+                }
100
+            }
101
+        }
102
+
103
+
104
+        $fileModel = model('File');
105
+        $param = $this->param;
106
+        $param['create_user_id'] = $this->userInfo['id'];
107
+        $res = $fileModel->createData($newFiles, $param);
108
+		if($res){
109
+			return resultArray(['data' => $res]);
110
+		} else {
111
+			return resultArray(['error' => $fileModel->getError()]);
112
+		}
113
+        
114
+    }
115
+
116
+	/**
117
+     * 附件删除
118
+     * @author Michael_xu
119
+     * @param 通过 save_name 作为条件 来删除附件
120
+     * @return                            
121
+     */ 
122
+    public function delete()
123
+    {
124
+        $fileModel = model('File');
125
+        $param = $this->param;
126
+
127
+        # 项目删除附件权限
128
+        if (!empty($this->param['module']) && $this->param['module'] == 'work_task' && !empty($this->param['work_id'])) {
129
+            if (!$this->checkWorkOperationAuth('deleteTaskFile', $this->param['work_id'], $this->userInfo['id'])) {
130
+                header('Content-Type:application/json; charset=utf-8');
131
+                exit(json_encode(['code' => 102, 'error' => '无权操作!']));
132
+            }
133
+        }
134
+
135
+        $res = $fileModel->delFileBySaveName($param['save_name'], $param);
136
+        if (!$res) {
137
+            return resultArray(['error' => $fileModel->getError()]);
138
+        }
139
+        return resultArray(['data' => '删除成功']);        
140
+    }
141
+
142
+    /**
143
+     * 全部删除(活动、产品)
144
+     *
145
+     * @return \think\response\Json
146
+     * @throws \think\Exception
147
+     * @throws \think\exception\PDOException
148
+     */
149
+    public function deleteAll()
150
+    {
151
+        if ((empty($this->param['module']) && empty($this->param['module_id'])) || empty($this->param['file_id'])) {
152
+            return resultArray(['error' => '参数错误!']);
153
+        }
154
+
155
+        $fileModel = new \app\admin\model\File();
156
+
157
+        if (!$fileModel->deleteAll($this->param)) return resultArray(['error' => '操作失败!']);
158
+
159
+        return resultArray(['data' => '操作成功!']);
160
+    }
161
+
162
+    /**
163
+     * 附件编辑
164
+     */
165
+    public function update()
166
+    {
167
+        $fileModel = model('File');
168
+        $param = $this->param;
169
+        if ( $param['save_name'] && $param['name'] ) {
170
+            $ret = $fileModel->updateNameBySaveName($param['save_name'],$param['name']);
171
+            if ($ret) {
172
+                return resultArray(['data'=>'操作成功']);
173
+            } else {
174
+                return resultArray(['error'=>'操作失败']);
175
+            } 
176
+        } else {
177
+            return resultArray(['error'=>'参数错误']);
178
+        }
179
+    }
180
+
181
+	/**
182
+     * 附件查看(下载)
183
+     * @author Michael_xu
184
+     * @return                            
185
+     */  
186
+    public function read()
187
+    {
188
+        $fileModel = model('File');
189
+        $param = $this->param;
190
+        $data = $fileModel->getDataBySaveName($param['save_name']);
191
+        if (!$data) {
192
+            return resultArray(['error' => $this->getError()]);
193
+        }
194
+        return resultArray(['data' => $data]);        
195
+    }   
196
+    
197
+    /**
198
+     * 静态资源文件下载
199
+     */
200
+    public function download()
201
+    {
202
+        if(isset($this->param['path'])){
203
+            $path = $this->param['path'];
204
+            $name = $this->param['name'] ?: '';
205
+            if (empty($path)) return resultArray(['error' => '参数错误!']);
206
+            return download(realpath('./public/' . $path), $name);
207
+        }else{
208
+            $path = $this->param['save_name'];
209
+            $name = $this->param['name'] ?: '';
210
+            if (empty($path)) return resultArray(['error' => '参数错误!']);
211
+            if (!strstr($path, 'uploads')) $path = 'uploads/' . $path;
212
+            return download(realpath('./public/' . $path), $name);
213
+        }
214
+    }
215
+
216
+    /**
217
+     * 下载图片(头像),前端要求重写一个。
218
+     *
219
+     * @return \think\response\Json|void
220
+     */
221
+    public function downloadImage()
222
+    {
223
+        $path = $this->param['path'];
224
+        $file = explode('public/', $path);
225
+
226
+        if (empty($path) || empty($file[1])) return resultArray(['error' => '参数错误!']);
227
+
228
+        return download(realpath('./public/'.$file[1]));
229
+    }
230
+}

+ 217
- 0
application/admin/controller/Groups.php Целия файл

@@ -0,0 +1,217 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 用户组
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use app\admin\logic\FieldGrantLogic;
11
+use think\Hook;
12
+use think\Request;
13
+
14
+class Groups extends ApiCommon
15
+{
16
+    /**
17
+     * 用于判断权限
18
+     * @permission 无限制
19
+     * @allow 登录用户可访问
20
+     * @other 其他根据系统设置
21
+    **/    
22
+    public function _initialize()
23
+    {
24
+        $action = [
25
+            'permission'=>[''],
26
+            'allow'=>['index','enables','copy','typelist','save','update','delete']
27
+        ];
28
+        Hook::listen('check_auth',$action);
29
+        $request = Request::instance();
30
+        $a = strtolower($request->action());        
31
+        if (!in_array($a, $action['permission'])) {
32
+            parent::_initialize();
33
+        } 
34
+        //权限判断
35
+        $unAction = ['index','typelist'];
36
+        if (!in_array($a, $unAction) && !checkPerByAction('admin', 'groups', 'update')) {
37
+            header('Content-Type:application/json; charset=utf-8');
38
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
39
+        }                        
40
+    }        
41
+
42
+    /**
43
+     * 角色列表
44
+     * @author Michael_xu
45
+     * @param 
46
+     * @return                            
47
+     */     
48
+    public function index()
49
+    {         
50
+        $groupModel = model('Group');
51
+        $param = $this->param;
52
+        $data = $groupModel->getDataList($param);
53
+        return resultArray(['data' => $data]);
54
+    }
55
+
56
+    /**
57
+     * 角色详情
58
+     * @author Michael_xu
59
+     * @param 
60
+     * @return                            
61
+     */    
62
+    public function read()
63
+    {   
64
+        $groupModel = model('Group');
65
+        $param = $this->param;
66
+        $data = $groupModel->getDataById($param['id']);
67
+        if (!$data) {
68
+            return resultArray(['error' => $groupModel->getError()]);
69
+        } 
70
+        return resultArray(['data' => $data]);
71
+    }
72
+
73
+    /**
74
+     * 角色添加
75
+     * @author Michael_xu
76
+     * @param 
77
+     * @return                            
78
+     */    
79
+    public function save(FieldGrantLogic $fieldGrantLogic)
80
+    {
81
+        $groupModel = model('Group');
82
+        $param = $this->param;
83
+		$param['rules'] = arrayToString($param['rules']);
84
+        $lastInsId = $groupModel->createData($param);
85
+        if (!$lastInsId) {
86
+            return resultArray(['error' => $groupModel->getError()]);
87
+        }
88
+
89
+        # 新增客户管理角色的字段授权数据
90
+        if (isset($param['pid']) && $param['pid'] == 2) {
91
+            $fieldGrantLogic->createCrmFieldGrant($lastInsId);
92
+        }
93
+
94
+        return resultArray(['data' => 1]);
95
+    }
96
+
97
+    /**
98
+     * 角色编辑
99
+     * @author Michael_xu
100
+     * @param 
101
+     * @return                            
102
+     */     
103
+    public function update()
104
+    {        
105
+        $groupModel = model('Group');
106
+        $param = $this->param;
107
+        $dataInfo = $groupModel->getDataById($param['id']);
108
+        if (!$dataInfo) {
109
+            return resultArray(['error' => '参数错误']);
110
+        }
111
+
112
+        # 处理前端传来的type是work的错误
113
+        if (!empty($param['type']) && $param['type'] == 'work') $param['type'] = 1;
114
+
115
+        $param['rules'] = arrayToString($param['rules']);
116
+        $data = $groupModel->updateDataById($param, $param['id']);
117
+        return resultArray(['data' => '编辑成功']);
118
+    }
119
+
120
+    /**
121
+     * 角色删除
122
+     * @author Michael_xu
123
+     * @param 
124
+     * @return                            
125
+     */     
126
+    public function delete(FieldGrantLogic $fieldGrantLogic)
127
+    {            
128
+        $groupModel = model('Group');
129
+        $param = $this->param;
130
+        $dataInfo = $groupModel->getDataById($param['id']);
131
+        if (!$dataInfo) {
132
+            return resultArray(['error' => '参数错误']);
133
+        }
134
+        if ($dataInfo['types']) {
135
+            return resultArray(['error' => '系统角色,不能删除']);
136
+        }        
137
+        $data = $groupModel->delGroupById($param['id']);      
138
+        if (!$data) {
139
+            return resultArray(['error' => $groupModel->getError()]);
140
+        }
141
+
142
+        # 删除字段授权数据
143
+        $fieldGrantLogic->deleteCrmFieldGrant($param['id']);
144
+
145
+        return resultArray(['data' => '删除成功']);    
146
+    }
147
+
148
+    /**
149
+     * 角色启用、禁用
150
+     * @author Michael_xu
151
+     * @param 
152
+     * @return                            
153
+     */   
154
+    public function enables()
155
+    {        
156
+        $groupModel = model('Group');
157
+        $param = $this->param;
158
+        $dataInfo = $groupModel->getDataById($param['id']);
159
+        if (!$dataInfo) {
160
+            return resultArray(['error' => '参数错误']);
161
+        }
162
+        if ($dataInfo['types']) {
163
+            return resultArray(['error' => '系统角色,不能删除']);
164
+        }         
165
+        $data = $groupModel->enableDatas($param['id'], $param['status'], true);  
166
+        if (!$data) {
167
+            return resultArray(['error' => $groupModel->getError()]);
168
+        } 
169
+        return resultArray(['data' => '操作成功']);         
170
+    }
171
+
172
+    /**
173
+     * 角色复制
174
+     * @author Michael_xu
175
+     * @param 
176
+     * @return                            
177
+     */   
178
+    public function copy(FieldGrantLogic $fieldGrantLogic)
179
+    {        
180
+        $groupModel = model('Group');
181
+        $param = $this->param;
182
+        $dataInfo = $groupModel->getDataById($param['id']);
183
+        if (!$dataInfo) {
184
+            return resultArray(['error' => '参数错误']);
185
+        }
186
+        $dataInfo = json_decode($dataInfo, true);
187
+        unset($dataInfo['id']);
188
+        $titleCount = db('admin_group')->where(['title' => $dataInfo['title']])->count();
189
+        $dataInfo['title'] = $dataInfo['title'].'('.$titleCount.')';
190
+        $data = $groupModel->createData($dataInfo);
191
+        if (!$data) {
192
+            return resultArray(['error' => $groupModel->getError()]);
193
+        }
194
+
195
+        # 复制客户管理角色的字段授权数据
196
+        if (!empty($dataInfo['pid']) && $dataInfo['pid'] == 2) {
197
+            $fieldGrantLogic->copyCrmFieldGrant($param['id'], $data);
198
+        }
199
+
200
+        return resultArray(['data' => '操作成功']);         
201
+    }
202
+
203
+    /**
204
+     * 角色分类列表
205
+     * @author Michael_xu
206
+     * @param 
207
+     * @return                            
208
+     */     
209
+    public function typeList()
210
+    {         
211
+        $groupModel = model('Group');
212
+        $param = $this->param;
213
+        $data = $groupModel->getTypeList($param);
214
+        return resultArray(['data' => $data]);
215
+    }        
216
+}
217
+ 

+ 154
- 0
application/admin/controller/Index.php Целия файл

@@ -0,0 +1,154 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 工作台及基础
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use think\Hook;
11
+use think\Request;
12
+
13
+class Index extends ApiCommon
14
+{
15
+    /**
16
+     * 用于判断权限
17
+     * @permission 无限制
18
+     * @allow 登录用户可访问
19
+     * @other 其他根据系统设置
20
+     */
21
+    public function _initialize()
22
+    {
23
+        parent::_initialize();
24
+        $action = [
25
+            'permission' => [],
26
+            'allow' => ['fields', 'fieldrecord', 'authlist','sort','updatesort',
27
+            'importnum','importinfo','importlist'],
28
+        ];
29
+        Hook::listen('check_auth', $action);
30
+        $request = Request::instance();
31
+        $a = strtolower($request->action());
32
+        if (!in_array($a, $action['permission'])) {
33
+            parent::_initialize();
34
+        }
35
+    }
36
+
37
+    /**
38
+     * 获取字段属性,用于筛选或其他操作
39
+     * @param
40
+     * @return
41
+     */
42
+    public function fields()
43
+    {
44
+        $param = $this->param;
45
+        $userInfo = $this->userInfo;
46
+        $param['user_id'] = $userInfo['id'];
47
+        $fieldModel = model('Field');
48
+        $field_arr = $fieldModel->getField($param);
49
+
50
+        # 转form_type类型,用于场景筛选和创建自定义场景
51
+        foreach ($field_arr AS $key => $value) {
52
+            if ($value['field'] == 'address')      $field_arr[$key]['form_type'] = 'map_address';
53
+            if ($value['field'] == 'deal_status')  $field_arr[$key]['form_type'] = 'deal_status';
54
+            if ($value['field'] == 'check_status') $field_arr[$key]['form_type'] = 'check_status';
55
+        }
56
+
57
+        return resultArray(['data' => $field_arr]);
58
+    }
59
+
60
+    /**
61
+     * 获取字段修改记录
62
+     * @param
63
+     * @return
64
+     */
65
+    public function fieldRecord()
66
+    {
67
+        $param = $this->param;
68
+        $userInfo = $this->userInfo;
69
+        $param['user_id'] = $userInfo['id'];
70
+        $actionRecordModel = model('ActionRecord');
71
+        $data = $actionRecordModel->getDataList($param);
72
+        if (!$data) {
73
+            return resultArray(['data' => '暂无数据']);
74
+        }
75
+        return resultArray(['data' => $data]);
76
+    }
77
+
78
+    /**
79
+     * 权限数据返回
80
+     * @param
81
+     * @return
82
+     */
83
+    public function authList()
84
+    {
85
+        $userInfo = $this->userInfo;
86
+        $userModel = model('User');
87
+        $dataList = $userModel->getMenuAndRule($userInfo['id']);
88
+        return resultArray(['data' => $dataList['authList']]);
89
+    }
90
+
91
+    /**
92
+     * todo
93
+     * 顶部菜单栏展示
94
+     * @return mixed
95
+     */
96
+    //todo admin_sort 表数据未完善
97
+    public function sort(){
98
+        $param = $this->param;
99
+        $userModel = model('User');
100
+        $userInfo = $this->userInfo;
101
+        $param['user_id']= $param['user_id']?:$userInfo['id'];
102
+        $dataList = $userModel->sortList($param);
103
+        return resultArray(['data' => $dataList]);
104
+    }
105
+
106
+    /**
107
+     *顶部菜单栏编辑
108
+     */
109
+    public function updateSort(){
110
+        $param = $this->param;
111
+        $userInfo = $this->userInfo;
112
+        $userModel = model('User');
113
+        $param['value']=$param;
114
+        $param['user_id']= $param['user_id']?:$userInfo['id'];
115
+        $dataList = $userModel->updateSort($param);
116
+        if (!$dataList) {
117
+            return resultArray(['data' => '编辑失败']);
118
+        }
119
+        return resultArray(['data' => '编辑成功']);
120
+    }
121
+    /**
122
+     * 导入中
123
+     * @return \think\response\Json
124
+     */
125
+    public function importNum(){
126
+        $excelModel = model('Excel');
127
+        $data = $excelModel->importNum();
128
+        return resultArray(['data'=>$data]);
129
+
130
+    }
131
+
132
+    /**
133
+     * 导入成功返回值
134
+     * @return \think\response\Json
135
+     */
136
+    public function importInfo(){
137
+        $excelModel = model('Excel');
138
+        $data = $excelModel->importInfo();
139
+        return resultArray(['data'=>$data]);
140
+    }
141
+
142
+    /**
143
+     * 导入历史
144
+     * @return \think\response\Json
145
+     */
146
+    public function importList(){
147
+        $param = $this->param;
148
+        $userInfo = $this->userInfo;
149
+        $param['user_id'] = $userInfo['id'];
150
+        $excelModel = model('Excel');
151
+        $data = $excelModel->importList($param);
152
+        return resultArray(['data'=>$data]);
153
+    }
154
+}

+ 96
- 0
application/admin/controller/Initialize.php Целия файл

@@ -0,0 +1,96 @@
1
+<?php
2
+/**
3
+ * 初始化控制器
4
+ *
5
+ * @author qifan
6
+ * @date 2020-01-05
7
+ */
8
+
9
+namespace app\admin\controller;
10
+
11
+use app\admin\logic\InitializeLogic;
12
+use think\Hook;
13
+use think\Request;
14
+
15
+class Initialize extends ApiCommon
16
+{
17
+    /**
18
+     * 用于判断权限
19
+     * @permission 无限制
20
+     * @allow 登录用户可访问
21
+     * @other 其他根据系统设置
22
+     **/
23
+    public function _initialize()
24
+    {
25
+        $action = [
26
+            'permission' => [],
27
+            'allow' => ['verification']
28
+        ];
29
+        Hook::listen('check_auth',$action);
30
+        $request = Request::instance();
31
+        $a = strtolower($request->action());
32
+        if (!in_array($a, $action['permission'])) {
33
+            parent::_initialize();
34
+        }
35
+    }
36
+
37
+    /**
38
+     * 列表
39
+     *
40
+     * @return \think\response\Json
41
+     */
42
+    public function index()
43
+    {
44
+        $data = [
45
+            ['type' => 1, 'name' => '全部应用'],
46
+            ['type' => 2, 'name' => '客户管理'],
47
+            ['type' => 3, 'name' => '任务/审批'],
48
+            ['type' => 4, 'name' => '日志'],
49
+            ['type' => 5, 'name' => '项目管理'],
50
+            ['type' => 6, 'name' => '日历'],
51
+//            ['type' => 7, 'name' => '知识库'],
52
+        ];
53
+
54
+        return resultArray(['data' => $data]);
55
+    }
56
+
57
+    /**
58
+     * 初始化数据
59
+     *
60
+     * @param InitializeLogic $initializeLogic
61
+     * @return \think\response\Json
62
+     * @throws \think\db\exception\DataNotFoundException
63
+     * @throws \think\db\exception\ModelNotFoundException
64
+     * @throws \think\exception\DbException
65
+     */
66
+    public function update(InitializeLogic $initializeLogic)
67
+    {
68
+        if (empty($this->param['type']) || !is_array($this->param['type'])) return resultArray(['error' => '模块类型错误!']);
69
+
70
+        if (!empty($this->param['password']) && !$initializeLogic->verification($this->userInfo['id'], $this->param['password'])) {
71
+            return resultArray(['error' => '密码错误!']);
72
+        }
73
+
74
+        $initializeLogic->update($this->param['type']);
75
+
76
+        return resultArray(['data' => $initializeLogic->log]);
77
+    }
78
+
79
+    /**
80
+     * 验证密码
81
+     *
82
+     * @param InitializeLogic $initializeLogic
83
+     * @return \think\response\Json
84
+     * @throws \think\db\exception\DataNotFoundException
85
+     * @throws \think\db\exception\ModelNotFoundException
86
+     * @throws \think\exception\DbException
87
+     */
88
+    public function verification(InitializeLogic $initializeLogic)
89
+    {
90
+        if (empty($this->param['password'])) return resultArray(['error' => '参数错误!']);
91
+
92
+        if (!$initializeLogic->verification($this->userInfo['id'], $this->param['password'])) return resultArray(['error' => '密码错误!']);
93
+
94
+        return resultArray(['data' => '密码正确!']);
95
+    }
96
+}

+ 382
- 0
application/admin/controller/Install.php Целия файл

@@ -0,0 +1,382 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 安装
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use think\Controller;
11
+use think\Request;
12
+use think\Db;
13
+use Env;
14
+
15
+class Install extends Controller
16
+{
17
+    // private $count = 100;
18
+    // private $now = 0; 
19
+
20
+    public function _initialize()
21
+    {
22
+        /*防止跨域*/      
23
+        header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']);
24
+        header('Access-Control-Allow-Credentials: true');
25
+        header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
26
+        header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, authKey, sessionId");
27
+        $param = Request::instance()->param();          
28
+        $this->param = $param;
29
+
30
+        $request = request();
31
+        $m = strtolower($request->module());
32
+        $c = strtolower($request->controller());
33
+        $a = strtolower($request->action());     
34
+	
35
+        if (!in_array($a, array('upgrade','upgradeprocess','checkversion')) && file_exists(CONF_PATH . "install.lock")) {
36
+            echo "<meta http-equiv='content-type' content='text/html; charset=UTF-8'> <script>alert('请勿重复安装!');location.href='".$_SERVER["HTTP_HOST"]."';</script>";
37
+            die();       
38
+        }    
39
+    }
40
+
41
+    private $upgrade_site = "http://message.72crm.com/";
42
+
43
+    /**
44
+     * [index 安装步骤]
45
+     * @author Michael_xu 
46
+     * @param  
47
+     */    
48
+    public function index()
49
+    {
50
+        if (file_exists(CONF_PATH . "install.lock")) {
51
+            echo "<meta http-equiv='content-type' content='text/html; charset=UTF-8'> <script>alert('请勿重复安装!');location.href='".$_SERVER["HTTP_HOST"]."';</script>";
52
+            die();     
53
+        }
54
+        if (!file_exists(getcwd() . "/public/sql/5kcrm.sql")) {
55
+            echo "<meta http-equiv='content-type' content='text/html; charset=UTF-8'> <script>alert('缺少必要的数据库文件!');location.href='".$_SERVER["HTTP_HOST"]."';</script>";
56
+            die();     
57
+        }         
58
+        return $this->fetch('index');      
59
+    }
60
+
61
+    public function step1()
62
+    {
63
+		session('install_error',null);
64
+        $data           = [];
65
+        $data['env']    = self::checkNnv();
66
+        $data['dir']    = self::checkDir();
67
+        $data['version'] = $this->version();
68
+        $this->assign('data',$data);
69
+        return $this->fetch('step1');
70
+    }
71
+
72
+    //版本
73
+    public function version()
74
+    {
75
+        $res = include(CONF_PATH.'version.php'); 
76
+        return $res ? : array('VERSION' => '9.0.0','RELEASE' => '20190330'); 
77
+    }    
78
+
79
+    public function step2(){
80
+		if (session('install_error')){
81
+            echo "<meta http-equiv='content-type' content='text/html; charset=UTF-8'> <script>alert('环境检测未通过,不能进行下一步操作!');location.href='".$_SERVER["HTTP_REFERER"]."';</script>";
82
+            die(); 
83
+        }
84
+        $data['os'] = PHP_OS;
85
+        $data['php'] = phpversion();
86
+        $data['version'] = $this->version();
87
+        $this->assign('envir_data',$data);
88
+        return $this->fetch();
89
+    }
90
+	
91
+    public function step3(){
92
+        return $this->fetch();
93
+    }
94
+
95
+    public function step4(){
96
+        if (session('install_error')){
97
+            return resultArray(['error' => '环境检测未通过,不能进行下一步操作!']);    
98
+        } 
99
+        if (file_exists(CONF_PATH . "install.lock")) {
100
+            return resultArray(['error' => '请勿重复安装!']);       
101
+        } 
102
+        if (!file_exists(getcwd() . "/public/sql/5kcrm.sql")) {
103
+            return resultArray(['error' => '缺少必要的数据库文件!']);      
104
+        } 
105
+        $temp = $this->param;
106
+        $param = $temp['form'];
107
+        $db_config['type'] = 'mysql';
108
+        $db_config['hostname'] = $param['databaseUrl'];
109
+        $db_config['hostport'] = $param['databasePort'];
110
+        $db_config['database'] = $param['databaseName'];
111
+        $db_config['username'] = $param['databaseUser'];
112
+        $db_config['password'] = $param['databasePwd'];        
113
+        $db_config['prefix'] = $param['databaseTable'];
114
+        
115
+        $username = $param['root'];
116
+        $password = $param['pwd'];
117
+        if (empty($db_config['hostname'])) {
118
+            return resultArray(['error' => '请填写数据库主机!']);
119
+        }           
120
+        if (empty($db_config['hostport'])) {
121
+            return resultArray(['error' => '请填写数据库端口!']);
122
+        }
123
+        if (preg_match('/[^0-9]/', $db_config['hostport'])) {
124
+            return resultArray(['error' => '数据库端口只能是数字!']);
125
+        }
126
+        if (empty($db_config['database'])) {
127
+            return resultArray(['error' => '请填写数据库名!']);
128
+        }
129
+        if (empty($db_config['username'])) {
130
+            return resultArray(['error' => '请填写数据库用户名!']);
131
+        }
132
+        if (empty($db_config['password'])) {
133
+            return resultArray(['error' => '请填写数据库密码!']);
134
+        }        
135
+        if (empty($db_config['prefix'])) {
136
+            return resultArray(['error' => '请填写表前缀!']);
137
+        }
138
+        if (preg_match('/[^a-z0-9_]/i', $db_config['prefix'])) {
139
+            return resultArray(['error' => '表前缀只能包含数字、字母和下划线!']);
140
+        }
141
+        if (empty($username)) {
142
+            return resultArray(['error' => '请填写管理员用户名!']);
143
+        }
144
+        if (empty($password)) {
145
+            return resultArray(['error' => '请填写管理员密码!']);
146
+        }
147
+        session('install_count','');
148
+        session('install_now','');
149
+        $database = $db_config['database'];
150
+		unset($db_config['database']);
151
+        $connect = Db::connect($db_config);
152
+        // 检测数据库连接
153
+        try{
154
+            $ret = $connect->execute('select version()');
155
+        }catch(\Exception $e){
156
+            return resultArray(['error' => '数据库连接失败,请检查数据库配置!']);
157
+        }
158
+        $check = $connect->execute("SELECT * FROM information_schema.schemata WHERE schema_name='".$database."'");
159
+        if (!$check && !$connect->execute("CREATE DATABASE IF NOT EXISTS `".$database."` default collate utf8_general_ci ")) {
160
+            return resultArray(['error' => '没有找到您填写的数据库名且无法创建!请检查连接账号是否有创建数据库的权限!']);
161
+        }
162
+		$db_config['database'] = $database;
163
+        self::mkDatabase($db_config);
164
+        $C_Patch = substr($_SERVER['SCRIPT_FILENAME'],0,-10);
165
+        $sql = file_get_contents( $C_Patch.'/public/sql/5kcrm.sql');
166
+        $sqlList = parse_sql($sql, 0, ['5kcrm_' => $db_config['prefix']]);
167
+        if ($sqlList) {
168
+            $sqlList = array_filter($sqlList);
169
+            $install_count = count($sqlList);
170
+            session('install_count',$install_count);
171
+            foreach ($sqlList as $k=>$v) {
172
+                $install_now = $k+1;
173
+                session('install_now',$install_now);
174
+                try {
175
+                    $temp_sql = $v.';';
176
+                    Db::connect($db_config)->query($temp_sql);
177
+                } catch(\Exception $e) {
178
+                    // return resultArray(['error' => '请启用InnoDB数据引擎,并检查数据库是否有DROP和CREATE权限']);
179
+                    return resultArray(['error' => '数据库sql安装出错,请操作数据库手动导入sql文件']);
180
+                }
181
+            }
182
+        } 
183
+        $salt = substr(md5(time()),0,4);
184
+        $password = user_md5(trim($password), $salt, $username);
185
+		//插入信息
186
+        Db::connect($db_config)->query("insert into ".$db_config['prefix']."admin_user (username, password, salt, img, thumb_img, realname, create_time, num, email, mobile, sex, status, structure_id, post, parent_id, type, authkey, authkey_time ) values ( '".$username."', '".$password."', '".$salt."', '', '', '管理员', ".time().", '', '', '".$username."', '', 1, 1, 'CEO', 0, 1, '', 0 )");
187
+        Db::connect($db_config)->query("insert into ".$db_config['prefix']."hrm_user_det (user_id, join_time, type, status, userstatus, create_time, update_time, mobile, sex, age, job_num, idtype, idnum, birth_time, nation, internship, done_time, parroll_id, email, political, location, leave_time ) values ( 1, ".time().", 1, 1, 2, ".time().", ".time().", '".$username."', '', 0, '', 0, '', '', 0, 0, 0, 0, '', '', '', 0 )");
188
+        touch(CONF_PATH . "install.lock"); 
189
+        return resultArray(['data'=>'安装成功']);
190
+    }
191
+	
192
+	//ajax 进度条
193
+    public function progress()
194
+    {
195
+        $data['length'] = session('install_count');
196
+        $data['now'] = session('install_now');
197
+        return resultArray(['data'=>$data]);
198
+    }
199
+
200
+    //添加database.php文件
201
+    private function mkDatabase(array $data)
202
+    {
203
+        $code = <<<INFO
204
+<?php
205
+return [
206
+    // 数据库类型
207
+    'type'            => 'mysql',
208
+    // 服务器地址
209
+    'hostname'        => '{$data['hostname']}',
210
+    // 数据库名
211
+    'database'        => '{$data['database']}',
212
+    // 用户名
213
+    'username'        => '{$data['username']}',
214
+    // 密码
215
+    'password'        => '{$data['password']}',
216
+    // 端口
217
+    'hostport'        => '{$data['hostport']}',
218
+    // 连接dsn
219
+    'dsn'             => '',
220
+    // 数据库连接参数
221
+    'params'          => [],
222
+    // 数据库编码默认采用utf8
223
+    'charset'         => 'utf8',
224
+    // 数据库表前缀
225
+    'prefix'          => '{$data['prefix']}',
226
+    // 数据库调试模式
227
+    'debug'           => true,
228
+    // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
229
+    'deploy'          => 0,
230
+    // 数据库读写是否分离 主从式有效
231
+    'rw_separate'     => false,
232
+    // 读写分离后 主服务器数量
233
+    'master_num'      => 1,
234
+    // 指定从服务器序号
235
+    'slave_no'        => '',
236
+    // 自动读取主库数据
237
+    'read_master'     => false,
238
+    // 是否严格检查字段是否存在
239
+    'fields_strict'   => true,
240
+    // 数据集返回类型
241
+    'resultset_type'  => 'array',
242
+];
243
+
244
+INFO;
245
+        file_put_contents( CONF_PATH.'database.php', $code);
246
+        // 判断写入是否成功
247
+        $config = include CONF_PATH.'database.php';
248
+        if (empty($config['database']) || $config['database'] != $data['database']) {
249
+            return resultArray(['error' => '[config/database.php]数据库配置写入失败!']);
250
+        }
251
+        return true;
252
+    }
253
+
254
+    //检查目录权限
255
+    public function check_dir_iswritable($dir_path){ 
256
+        $dir_path=str_replace( '\\','/',$dir_path); 
257
+        $is_writale=1; 
258
+        if (!is_dir($dir_path)) { 
259
+            $is_writale=0; 
260
+            return $is_writale; 
261
+        } else { 
262
+            $file_hd=@fopen($dir_path.'/test.txt','w'); 
263
+            if (!$file_hd) { 
264
+                @fclose($file_hd); 
265
+                @unlink($dir_path.'/test.txt'); 
266
+                $is_writale=0; 
267
+                return $is_writale; 
268
+            } 
269
+            $dir_hd = opendir($dir_path); 
270
+            while (false !== ($file=readdir($dir_hd))) { 
271
+                if ($file != "." && $file != "..") { 
272
+                    if (is_file($dir_path.'/'.$file)) { 
273
+                        //文件不可写,直接返回 
274
+                        if (!is_writable($dir_path.'/'.$file)) { 
275
+                            return 0; 
276
+                        }  
277
+                    } else { 
278
+                        $file_hd2=@fopen($dir_path.'/'.$file.'/test.txt','w'); 
279
+                        if (!$file_hd2) { 
280
+                            @fclose($file_hd2); 
281
+                            @unlink($dir_path.'/'.$file.'/test.txt'); 
282
+                            $is_writale=0; 
283
+                            return $is_writale; 
284
+                        } 
285
+                        //递归 
286
+                        $is_writale=check_dir_iswritable($dir_path.'/'.$file); 
287
+                    } 
288
+                } 
289
+            } 
290
+        } 
291
+        return $is_writale; 
292
+    } 
293
+
294
+    /**
295
+     * [checkVersion 检查升级]
296
+     * @author Michael_xu 
297
+     * @param  
298
+     */     
299
+    public function checkVersion(){
300
+        $version = Config::load('version');
301
+        $info = sendRequest($this->upgrade_site.'index.php?m=version&a=checkVersion', $version['VERSION']);
302
+        if ($info){
303
+            return resultArray(['data' => $info]);
304
+        } else {
305
+            return resultArray(['error' => '检查新版本出错!']);
306
+        }
307
+    }    
308
+
309
+    /**
310
+     * 环境检测
311
+     * @return array
312
+     */
313
+    private function checkNnv()
314
+    {
315
+        $items = [
316
+            'os'      => ['操作系统', PHP_OS, '类Unix', 'ok'],
317
+            'php'     => ['PHP版本', PHP_VERSION, '7.2 ( <em style="color: #888; font-size: 12px;">>= 5.6</em> )', 'ok','性能更佳'],
318
+            'gd'      => ['gd', '开启', '开启', 'ok'],
319
+            'openssl' => ['openssl', '开启', '开启', 'ok'],
320
+            'pdo' => ['pdo', '开启', '开启', 'ok'],
321
+        ];
322
+        session('install_error','');
323
+        if (substr($items['php'][1],0,3) < '5.6') {
324
+            $items['php'][3] = 'error';
325
+            session('install_error', true);
326
+        }
327
+        
328
+        if (!extension_loaded('gd')) {
329
+            $items['gd'][1] = '未开启';
330
+            $items['gd'][3] = 'error';
331
+            session('install_error', true);
332
+        }
333
+        if (!extension_loaded('openssl')) {
334
+            $items['openssl'][1] = '未开启';
335
+            $items['openssl'][3] = 'error';
336
+            session('install_error', true);
337
+        }
338
+        if (!extension_loaded('pdo')) {
339
+            $items['pdo'][1] = '未开启';
340
+            $items['pdo'][3] = 'error';
341
+            session('install_error', true);
342
+        }
343
+        // dump($items);die;
344
+        return $items;
345
+    }
346
+    
347
+    /**
348
+     * 目录权限检查
349
+     * @return array
350
+     */
351
+    private function checkDir()
352
+    {
353
+        $items = [
354
+            ['dir', $this->root_path.'application', 'application', '读写', '读写', 'ok'],
355
+            ['dir', $this->root_path.'extend', 'extend', '读写', '读写', 'ok'],
356
+            ['dir', $this->root_path.'runtime', './temp', '读写', '读写', 'ok'],
357
+            ['dir', $this->root_path.'public', './upload', '读写', '读写', 'ok'],
358
+            ['file', $this->root_path.'config', 'config', '读写', '读写', 'ok'],
359
+        ];
360
+        foreach ($items as &$v) {
361
+            if ($v[0] == 'dir') {// 文件夹
362
+                if (!is_writable($v[1])) {
363
+                    if (is_dir($v[1])) {
364
+                        $v[4] = '不可写';
365
+                        $v[5] = 'no';
366
+                    } else {
367
+                        $v[4] = '不存在';
368
+                        $v[5] = 'no';
369
+                    }
370
+                    session('install_error', true);
371
+                }
372
+            } else {// 文件
373
+                if (!is_writable($v[1])) {
374
+                    $v[4] = '不可写';
375
+                    $v[5] = 'no';
376
+                    session('install_error', true);
377
+                }
378
+            }
379
+        }
380
+        return $items;
381
+    }
382
+}

+ 86
- 0
application/admin/controller/Log.php Целия файл

@@ -0,0 +1,86 @@
1
+<?php
2
+/**
3
+ * 日志控制器
4
+ *
5
+ * @author qifan
6
+ * @date 2020-11-30
7
+ */
8
+
9
+namespace app\admin\controller;
10
+
11
+use app\admin\logic\LogLogic;
12
+use think\Hook;
13
+use think\Request;
14
+
15
+class Log extends ApiCommon
16
+{
17
+    /**
18
+     * 用于判断权限
19
+     * @permission 无限制
20
+     * @allow 登录用户可访问
21
+     * @other 其他根据系统设置
22
+     **/
23
+    public function _initialize()
24
+    {
25
+        $action = [
26
+            'permission' => [''],
27
+            'allow' => ['dataRecord', 'systemRecord', 'loginRecord']
28
+        ];
29
+        Hook::listen('check_auth',$action);
30
+        $request = Request::instance();
31
+        $a = strtolower($request->action());
32
+        if (!in_array($a, $action['permission'])) {
33
+            parent::_initialize();
34
+        }
35
+    }
36
+
37
+    /**
38
+     * 数据操作日志
39
+     *
40
+     * @param LogLogic $logLogic
41
+     * @return \think\response\Json
42
+     * @throws \think\db\exception\DataNotFoundException
43
+     * @throws \think\db\exception\ModelNotFoundException
44
+     * @throws \think\exception\DbException
45
+     */
46
+    public function dataRecord(LogLogic $logLogic)
47
+    {
48
+        $data['list']    = $logLogic->getRecordLogs($this->param);
49
+        $data['count']   = $logLogic->getRecordLogCount($this->param);
50
+        $data['modules'] = $logLogic->recordModules;
51
+
52
+        return resultArray(['data' => $data]);
53
+    }
54
+
55
+    /**
56
+     * 系统操作日志
57
+     *
58
+     * @param LogLogic $logLogic
59
+     * @return \think\response\Json
60
+     * @throws \think\db\exception\DataNotFoundException
61
+     * @throws \think\db\exception\ModelNotFoundException
62
+     * @throws \think\exception\DbException
63
+     */
64
+    public function systemRecord(LogLogic $logLogic)
65
+    {
66
+        $data['list']    = $logLogic->getSystemLogs($this->param);
67
+        $data['count']   = $logLogic->getSystemLogCount($this->param);
68
+        $data['modules'] = $logLogic->systemModules;
69
+
70
+        return resultArray(['data' => $data]);
71
+    }
72
+
73
+    /**
74
+     * 登录日志
75
+     *
76
+     * @param LogLogic $logLogic
77
+     * @return \think\response\Json
78
+     * @throws \think\exception\DbException
79
+     */
80
+    public function loginRecord(LogLogic $logLogic)
81
+    {
82
+        $data = $logLogic->getLoginRecord($this->param);
83
+
84
+        return resultArray(['data' => $data]);
85
+    }
86
+}

+ 87
- 0
application/admin/controller/Menus.php Целия файл

@@ -0,0 +1,87 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 菜单
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+class Menus extends ApiCommon
11
+{
12
+    
13
+    public function index()
14
+    {   
15
+        $menuModel = model('Menu');
16
+        $param = $this->param;
17
+        $data = $menuModel->getDataList();
18
+        return resultArray(['data' => $data]);
19
+    }
20
+
21
+    public function read()
22
+    {   
23
+        $menuModel = model('Menu');
24
+        $param = $this->param;
25
+        $data = $menuModel->getDataById($param['id']);
26
+        if (!$data) {
27
+            return resultArray(['error' => $menuModel->getError()]);
28
+        } 
29
+        return resultArray(['data' => $data]);
30
+    }
31
+
32
+    public function save()
33
+    {
34
+        $menuModel = model('Menu');
35
+        $param = $this->param;
36
+        $data = $menuModel->createData($param);
37
+        if (!$data) {
38
+            return resultArray(['error' => $menuModel->getError()]);
39
+        } 
40
+        return resultArray(['data' => '添加成功']);
41
+    }
42
+
43
+    public function update()
44
+    {
45
+        $menuModel = model('Menu');
46
+        $param = $this->param;
47
+        $data = $menuModel->updateDataById($param, $param['id']);
48
+        if (!$data) {
49
+            return resultArray(['error' => $menuModel->getError()]);
50
+        } 
51
+        return resultArray(['data' => '编辑成功']);
52
+    }
53
+
54
+    public function delete()
55
+    {
56
+        $menuModel = model('Menu');
57
+        $param = $this->param;
58
+        $data = $menuModel->delDataById($param['id'], true);       
59
+        if (!$data) {
60
+            return resultArray(['error' => $menuModel->getError()]);
61
+        } 
62
+        return resultArray(['data' => '删除成功']);    
63
+    }
64
+
65
+    public function deletes()
66
+    {
67
+        $menuModel = model('Menu');
68
+        $param = $this->param;
69
+        $data = $menuModel->delDatas($param['ids'], true);  
70
+        if (!$data) {
71
+            return resultArray(['error' => $menuModel->getError()]);
72
+        } 
73
+        return resultArray(['data' => '删除成功']); 
74
+    }
75
+
76
+    public function enables()
77
+    {
78
+        $menuModel = model('Menu');
79
+        $param = $this->param;
80
+        $data = $menuModel->enableDatas($param['ids'], $param['status'], true);  
81
+        if (!$data) {
82
+            return resultArray(['error' => $menuModel->getError()]);
83
+        } 
84
+        return resultArray(['data' => '操作成功']);         
85
+    }
86
+}
87
+ 

+ 205
- 0
application/admin/controller/Message.php Целия файл

@@ -0,0 +1,205 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 工作台及基础
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use app\admin\logic\MessageLogic;
11
+use think\Db;
12
+use think\Hook;
13
+use app\admin\model\Message as MessageModel;
14
+use think\Request;
15
+
16
+class Message extends ApiCommon
17
+{
18
+    /**
19
+     * 用于判断权限
20
+     * @permission 无限制
21
+     * @allow 登录用户可访问
22
+     * @other 其他根据系统设置
23
+     **/
24
+    public function _initialize()
25
+    {
26
+        parent::_initialize();
27
+        $action = [
28
+            'permission' => [],
29
+            'allow' => ['index', 'markedRead',  'messagelist', 'updatemessage','delete','readallmessage','clear','unreadcount'],
30
+        ];
31
+        Hook::listen('check_auth', $action);
32
+        $request = Request::instance();
33
+        $a = strtolower($request->action());
34
+        if (!in_array($a, $action['permission'])) {
35
+            parent::_initialize();
36
+        }
37
+    }
38
+
39
+    /**
40
+     * 系统信息
41
+     */
42
+    public function index()
43
+    {
44
+        $param = $this->param;
45
+        $userInfo = $this->userInfo;
46
+        $type = $param['type'] ?: 'all';
47
+
48
+        if ($type != 'all' && !isset(MessageModel::$typeGroup[$type])) {
49
+            return resultArray(['error' => '参数错误']);
50
+        }
51
+
52
+        $where = ['to_user_id' => $userInfo['id']];
53
+
54
+        if ($type != 'all') {
55
+            $where['type'] = ['IN', MessageModel::$typeGroup[$type]];
56
+        }
57
+
58
+        $order = [
59
+            'read_time' => 'ASC',
60
+            'send_time' => 'DESC',
61
+        ];
62
+
63
+        $page = $param['page'] ?: 1;
64
+        $limit = $param['limit'] ?: 15;
65
+
66
+        $data = MessageModel::where($where)
67
+            ->order($order)
68
+            ->paginate($limit)
69
+            ->each(function ($val) {
70
+                $val['relation_title'] = $val->relation_title;
71
+                $val['from_user_id_info'] = $val->from_user_id_info;
72
+            })
73
+            ->toArray();
74
+
75
+        return resultArray([
76
+            'data' => [
77
+                'list' => $data['data'],
78
+                'dataCount' => $data['total']
79
+            ]
80
+        ]);
81
+    }
82
+
83
+    /**
84
+     * 阅读系统通知,修改状态为已读
85
+     */
86
+    public function markedRead()
87
+    {
88
+        $userInfo = $this->userInfo;
89
+        $param = $this->param;
90
+
91
+        $where = [
92
+            'to_user_id' => $userInfo['id'],
93
+            'message_id' => ['IN', (array)$param['message_id']],
94
+            'read_time' => 0,
95
+        ];
96
+
97
+        $res = MessageModel::where($where)->update(['read_time' => time()]);
98
+        return resultArray(['data' => $res > 0]);
99
+    }
100
+
101
+    /**
102
+     * 未读数
103
+     */
104
+//    public function unReadCount()
105
+//    {
106
+//        $data = [];
107
+//        foreach (MessageModel::$typeGroup as $key => $val) {
108
+//            $data[$key] = MessageModel::where(['type' => ['IN', $val]])->count();
109
+//        }
110
+//        $data['all'] = array_sum($data);
111
+//        return resultArray(['data' => $data]);
112
+//    }
113
+
114
+    /**
115
+     * 未读消息列表
116
+     * @return \think\response\Json
117
+     */
118
+    public function messageList()
119
+    {
120
+        $param = $this->param;
121
+        $userInfo = $this->userInfo;
122
+        $param['user_id'] = $userInfo['id'];
123
+        $messageLogic = new MessageLogic();
124
+        $data = $messageLogic->getDataList($param);
125
+        return resultArray(['data' => $data]);
126
+    }
127
+
128
+    /**
129
+     *更新消息类型 已读未读
130
+     */
131
+    public function updateMessage()
132
+    {
133
+        $param = $this->param;
134
+        $userInfo = $this->userInfo;
135
+        $param['id']=$userInfo['id'];
136
+        $messageLogic = new MessageLogic();
137
+        $data = $messageLogic->endMessage($param);
138
+        if(!$data){
139
+            return resultArray(['data' => "操作失败!"]);
140
+        }
141
+        return resultArray(['data' => "操作成功!"]);
142
+    }
143
+
144
+    /**
145
+     * 删除消息
146
+     *
147
+     * @throws \think\Exception
148
+     * @throws \think\exception\PDOException
149
+     */
150
+    public function delete()
151
+    {
152
+        if (empty($this->param['message_id'])) return resultArray(['error' => '参数错误!']);
153
+        $userInfo = $this->userInfo;
154
+        $param = $this->param;
155
+        $data['message_id'] = $param['message_id'];
156
+        $data['user_id'] = $userInfo['id'];
157
+        $messageLogic = new MessageLogic();
158
+        if (!$messageLogic->delete($data)) return resultArray(['error' => '操作失败!']);
159
+
160
+        return resultArray(['data' => '操作成功!']);
161
+    }
162
+
163
+    /**
164
+     * 批量更新
165
+     * @throws \think\Exception
166
+     * @throws \think\exception\PDOException
167
+     */
168
+    public function readAllMessage(){
169
+        $param = $this->param;
170
+        $userInfo = $this->userInfo;
171
+        $param['user_id'] = $userInfo['id'];        
172
+        $messageLogic = new MessageLogic();
173
+        $data = $messageLogic->readAllMessage($param);
174
+        return resultArray(['data' => "操作成功!"]);
175
+    }
176
+
177
+    /**
178
+     * 批量删除
179
+     * @throws \think\Exception
180
+     * @throws \think\exception\PDOException
181
+     */
182
+    public function clear(){
183
+        $param = $this->param;
184
+        $userInfo = $this->userInfo;
185
+        $param['user_id'] = $userInfo['id'];        
186
+        $messageLogic = new MessageLogic();
187
+        $data = $messageLogic->clear($param);
188
+        return resultArray(['data' => "操作成功!"]);
189
+    }
190
+
191
+    /**
192
+     * 总数
193
+     * @return \think\response\Json
194
+     * @throws \think\Exception
195
+     * @throws \think\exception\PDOException
196
+     */
197
+    public function unreadCount(){
198
+        $param = $this->param;
199
+        $userInfo = $this->userInfo;
200
+        $param['user_id'] = $userInfo['id'];
201
+        $messageLogic = new MessageLogic();
202
+        $data = $messageLogic->unreadCount($param);
203
+        return resultArray(['data' => $data]);
204
+    }
205
+}

+ 88
- 0
application/admin/controller/Posts.php Целия файл

@@ -0,0 +1,88 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 岗位控制器
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+class Posts extends ApiCommon
11
+{
12
+    
13
+    public function index()
14
+    {   
15
+        $postModel = model('Post');
16
+        $param = $this->param;
17
+        $data = $postModel->getDataList($param);
18
+        return resultArray(['data' => $data]);
19
+    }
20
+
21
+    public function read()
22
+    {   
23
+        $postModel = model('Post');
24
+        $param = $this->param;
25
+        $data = $postModel->getDataById($param['id']);
26
+        if (!$data) {
27
+            return resultArray(['error' => $postModel->getError()]);
28
+        } 
29
+        return resultArray(['data' => $data]);
30
+    }
31
+
32
+    public function save()
33
+    {
34
+        $postModel = model('Post');
35
+        $param = $this->param;
36
+        $data = $postModel->createData($param);
37
+        if (!$data) {
38
+            return resultArray(['error' => $postModel->getError()]);
39
+        } 
40
+        return resultArray(['data' => '添加成功']);
41
+    }
42
+
43
+    public function update()
44
+    {
45
+        $postModel = model('Post');
46
+        $param = $this->param;
47
+        $data = $postModel->updateDataById($param, $param['id']);
48
+        if (!$data) {
49
+            return resultArray(['error' => $postModel->getError()]);
50
+        } 
51
+        return resultArray(['data' => '编辑成功']);
52
+    }
53
+
54
+    public function delete()
55
+    {
56
+        $postModel = model('Post');
57
+        $param = $this->param;
58
+        $data = $postModel->delDataById($param['id']);     
59
+        if (!$data) {
60
+            return resultArray(['error' => $postModel->getError()]);
61
+        } 
62
+        return resultArray(['data' => '删除成功']);    
63
+    }
64
+
65
+    public function deletes()
66
+    {
67
+        $postModel = model('Post');
68
+        $param = $this->param;
69
+        $data = $postModel->delDatas($param['ids']);  
70
+        if (!$data) {
71
+            return resultArray(['error' => $postModel->getError()]);
72
+        } 
73
+        return resultArray(['data' => '删除成功']); 
74
+    }
75
+
76
+    public function enables()
77
+    {
78
+        $postModel = model('Post');
79
+        $param = $this->param;
80
+        $data = $postModel->enableDatas($param['ids'], $param['status']);  
81
+        if (!$data) {
82
+            return resultArray(['error' => $postModel->getError()]);
83
+        } 
84
+        return resultArray(['data' => '操作成功']);         
85
+    }
86
+    
87
+}
88
+ 

+ 169
- 0
application/admin/controller/Printing.php Целия файл

@@ -0,0 +1,169 @@
1
+<?php
2
+/**
3
+ * 打印设置控制器
4
+ *
5
+ * @author qifan
6
+ * @date 2020-12-03
7
+ */
8
+
9
+namespace app\admin\controller;
10
+
11
+use app\admin\logic\PrintingLogic;
12
+use think\Hook;
13
+use think\Request;
14
+
15
+class Printing extends ApiCommon
16
+{
17
+    /**
18
+     * 用于判断权限
19
+     * @permission 无限制
20
+     * @allow 登录用户可访问
21
+     * @other 其他根据系统设置
22
+     **/
23
+    public function _initialize()
24
+    {
25
+        $action = [
26
+            'permission'=>[''],
27
+            'allow'=>['index', 'create', 'update', 'read', 'delete', 'field', 'copy']
28
+        ];
29
+        Hook::listen('check_auth',$action);
30
+        $request = Request::instance();
31
+        $a = strtolower($request->action());
32
+        if (!in_array($a, $action['permission'])) {
33
+            parent::_initialize();
34
+        }
35
+    }
36
+
37
+    /**
38
+     * 打印模板列表
39
+     *
40
+     * @param PrintingLogic $printingLogic
41
+     * @return \think\response\Json
42
+     * @throws \think\db\exception\DataNotFoundException
43
+     * @throws \think\db\exception\ModelNotFoundException
44
+     * @throws \think\exception\DbException
45
+     */
46
+    public function index(PrintingLogic $printingLogic)
47
+    {
48
+        $page  = !empty($this->param['page'])  ? $this->param['page']  : 1;
49
+        $limit = !empty($this->param['limit']) ? $this->param['limit'] : 15;
50
+
51
+        $data = $printingLogic->index($page, $limit);
52
+
53
+        return resultArray(['data' => $data]);
54
+    }
55
+
56
+    /**
57
+     * 创建打印模板
58
+     *
59
+     * @param PrintingLogic $printingLogic
60
+     * @return \think\response\Json
61
+     */
62
+    public function create(PrintingLogic $printingLogic)
63
+    {
64
+        $param = $this->param;
65
+
66
+        if (empty($param['name']))    return resultArray(['error' => '缺少模板名称!']);
67
+        if (empty($param['type']))    return resultArray(['error' => '缺少模板类型!']);
68
+        if (empty($param['content'])) return resultArray(['error' => '缺少模板详情!']);
69
+
70
+        if (!$printingLogic->create($param)) return resultArray(['error' => '添加失败!']);
71
+
72
+
73
+        return resultArray(['data' => '添加成功!']);
74
+    }
75
+
76
+    /**
77
+     * 获取模板详情
78
+     *
79
+     * @param PrintingLogic $printingLogic
80
+     * @return \think\response\Json
81
+     */
82
+    public function read(PrintingLogic $printingLogic)
83
+    {
84
+        $id = $this->param['id'];
85
+
86
+        if (empty($id)) return resultArray('缺少模板ID!');
87
+
88
+        $data = $printingLogic->read($id);
89
+
90
+        return resultArray(['data' => $data]);
91
+    }
92
+
93
+    /**
94
+     * 更新模板数据
95
+     *
96
+     * @param PrintingLogic $printingLogic
97
+     * @return \think\response\Json
98
+     * @throws \think\Exception
99
+     * @throws \think\exception\PDOException
100
+     */
101
+    public function update(PrintingLogic $printingLogic)
102
+    {
103
+        $param = $this->param;
104
+
105
+        if (empty($param['id'])) return resultArray(['error' => '缺少模板ID!']);
106
+
107
+        if (!$printingLogic->update($param)) return resultArray(['error' => '更新失败!']);
108
+
109
+        return resultArray(['data' => '更新成功!']);
110
+    }
111
+
112
+    /**
113
+     * 删除模板数据
114
+     *
115
+     * @param PrintingLogic $printingLogic
116
+     * @return \think\response\Json
117
+     * @throws \think\Exception
118
+     * @throws \think\exception\PDOException
119
+     */
120
+    public function delete(PrintingLogic $printingLogic)
121
+    {
122
+        $id = $this->param['id'];
123
+
124
+        if (empty($id)) return resultArray(['error' => '缺少模板ID!']);
125
+
126
+        if (!$printingLogic->delete($id)) return resultArray(['error' => '删除失败!']);
127
+
128
+        return resultArray(['data' => '删除成功!']);
129
+    }
130
+
131
+    /**
132
+     * 复制模板数据
133
+     *
134
+     * @param PrintingLogic $printingLogic
135
+     * @return \think\response\Json
136
+     * @throws \think\db\exception\DataNotFoundException
137
+     * @throws \think\db\exception\ModelNotFoundException
138
+     * @throws \think\exception\DbException
139
+     */
140
+    public function copy(PrintingLogic $printingLogic)
141
+    {
142
+        $id = $this->param['id'];
143
+
144
+        if (empty($id)) return resultArray(['error' => '缺少模板ID!']);
145
+
146
+        if (!$printingLogic->copy($id)) return resultArray(['error' => '复制失败!']);
147
+
148
+        return resultArray(['data' => '复制成功!']);
149
+    }
150
+
151
+    /**
152
+     * 获取打印字段
153
+     *
154
+     * @param PrintingLogic $printingLogic
155
+     * @return \think\response\Json
156
+     * @throws \think\db\exception\DataNotFoundException
157
+     * @throws \think\db\exception\ModelNotFoundException
158
+     * @throws \think\exception\DbException
159
+     */
160
+    public function field(PrintingLogic $printingLogic)
161
+    {
162
+        # 打印类型:1商机;2合同;3回款
163
+        $type = !empty($this->param['type']) ? $this->param['type'] : 5;
164
+
165
+        $data = $printingLogic->getFields($type);
166
+
167
+        return resultArray(['data' => $data]);
168
+    }
169
+}

+ 131
- 0
application/admin/controller/Record.php Целия файл

@@ -0,0 +1,131 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 跟进记录
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use think\Hook;
11
+use think\Request;
12
+use think\Db;
13
+
14
+class Record extends ApiCommon
15
+{
16
+    /**
17
+     * 用于判断权限
18
+     * @permission 无限制
19
+     * @allow 登录用户可访问
20
+     * @other 其他根据系统设置
21
+    **/    
22
+    public function _initialize()
23
+    {
24
+        $action = [
25
+            'permission'=>[''],
26
+            'allow'=>['index','save','update','delete']            
27
+        ];
28
+        Hook::listen('check_auth',$action);
29
+        $request = Request::instance();
30
+        $a = strtolower($request->action());        
31
+        if (!in_array($a, $action['permission'])) {
32
+            parent::_initialize();
33
+        }
34
+    }
35
+
36
+    /**
37
+     * 跟进记录列表
38
+     * @return
39
+     */
40
+    public function index()
41
+    {
42
+        $param = $this->param;
43
+        $by = $param['by'] ? : '';
44
+        unset($param['by']);
45
+        $recordModel = model('Record');
46
+        $data = $recordModel->getDataList($param, $by);
47
+        if (!$data) {
48
+            return resultArray(['error' => $recordModel->getError()]);
49
+        }
50
+        return resultArray(['data' => $data]);
51
+    }
52
+
53
+    /**
54
+     * 跟进记录创建
55
+     * @param
56
+     * @return
57
+     */
58
+    public function save()
59
+    {
60
+        $recordModel = model('Record');
61
+        $param = $this->param;
62
+        $userInfo = $this->userInfo;
63
+        $param['create_user_id'] = $userInfo['id'];
64
+        $resData = $recordModel->createData($param);
65
+        if (!$resData) {
66
+            return resultArray(['error' => $recordModel->getError()]);
67
+        }
68
+        //同时创建日程
69
+        if ($param['is_event']) {
70
+            $eventModel = new \app\oa\model\Event();
71
+            $data['title'] = trim($param['content']);
72
+            $data['content'] = trim($param['content']);
73
+            $data['start_time'] = $param['next_time'] ? : time();
74
+            $data['end_time'] = $param['next_time']+86399;
75
+            $data['create_user_id'] = $userInfo['id'];
76
+            if ($param['types'] == 'crm_customer') $data['customer_ids'] = $param['types_id'];
77
+            $data['business_ids'] = $param['business_ids'];
78
+            $data['contacts_ids'] = $param['contacts_ids'];            
79
+            $resEvent = $eventModel->createData($data);          
80
+        }
81
+        return resultArray(['data' => '添加成功']);
82
+    }
83
+
84
+    /**
85
+     * 跟进记录编辑
86
+     * @param 
87
+     * @return
88
+     */
89
+    public function update()
90
+    {
91
+        $recordModel = model('Record');
92
+        $param = $this->param;
93
+        $data = $recordModel->updateDataById($param, $param['id']);
94
+        if (!$data) {
95
+            return resultArray(['error' => $recordModel->getError()]);
96
+        } 
97
+        return resultArray(['data' => '编辑成功']);        
98
+    }
99
+
100
+    /**
101
+     * 跟进记录删除
102
+     * @param
103
+     * @return
104
+     */
105
+    public function delete()
106
+    {
107
+        $recordModel = model('Record');
108
+        $param = $this->param;
109
+        $userInfo = $this->userInfo;
110
+        //权限判断
111
+        $dataInfo = $recordModel->getDataById($param['id']);
112
+        if (!$dataInfo) {
113
+            return resultArray(['error' => '数据不存在或已删除']);
114
+        }
115
+        //自己(24小时)或者管理员
116
+        $adminTypes = adminGroupTypes($userInfo['id']);
117
+        if(!in_array(1,$adminTypes)){
118
+            if((time()-$dataInfo['create_time']) > 86400){
119
+                return resultArray(['error' => '超过24小时,不能删除']);
120
+            }
121
+            if ($dataInfo['create_user_id'] !== $userInfo['id']){
122
+                return resultArray(['error' => '无权操作']);
123
+            }
124
+        }
125
+        $resData = $recordModel->delDataById($param['id']);
126
+        if (!$resData) {
127
+            return resultArray(['error' => $recordModel->getError()]);
128
+        }
129
+        return resultArray(['data' => '删除成功']);
130
+    }   
131
+}

+ 79
- 0
application/admin/controller/Rules.php Целия файл

@@ -0,0 +1,79 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 规则
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use think\Hook;
11
+use think\Request;
12
+
13
+class Rules extends ApiCommon
14
+{
15
+    /**
16
+     * 用于判断权限
17
+     * @permission 无限制
18
+     * @allow 登录用户可访问
19
+     * @other 其他根据系统设置
20
+    **/    
21
+    public function _initialize()
22
+    {
23
+        $action = [
24
+            'permission'=>[''],
25
+            'allow'=>['index']            
26
+        ];
27
+        Hook::listen('check_auth',$action);
28
+        $request = Request::instance();
29
+        $a = strtolower($request->action());        
30
+        if (!in_array($a, $action['permission'])) {
31
+            parent::_initialize();
32
+        }  
33
+
34
+        $m = $this->m;
35
+        $c = $this->c;
36
+        $a = $this->a;
37
+    }    
38
+
39
+    public function index()
40
+    {   
41
+        $ruleModel = model('Rule');
42
+        $param = $this->param;
43
+        $data = $ruleModel->getDataList($param);
44
+        return resultArray(['data' => $data]);
45
+    }
46
+
47
+    /**
48
+     * 新建规则
49
+     * @param
50
+     * @return
51
+     */    
52
+    public function save()
53
+    {
54
+        $ruleModel = model('Rule');
55
+        $param = $this->param;
56
+        $data = $ruleModel->createData($param);
57
+        if (!$data) {
58
+            return resultArray(['error' => $ruleModel->getError()]);
59
+        } 
60
+        return resultArray(['data' => '添加成功']);
61
+    }
62
+
63
+    /**
64
+     * 编辑规则
65
+     * @param
66
+     * @return
67
+     */
68
+    public function update()
69
+    {
70
+        $ruleModel = model('Rule');
71
+        $param = $this->param;
72
+        $data = $ruleModel->updateDataById($param, $param['id']);
73
+        if (!$data) {
74
+            return resultArray(['error' => $ruleModel->getError()]);
75
+        } 
76
+        return resultArray(['data' => '编辑成功']);
77
+    }
78
+}
79
+ 

+ 169
- 0
application/admin/controller/Scene.php Целия файл

@@ -0,0 +1,169 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 场景
4
+// +----------------------------------------------------------------------
5
+// | Author:   Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use think\Hook;
11
+use think\Session;
12
+use think\Request;
13
+use think\Db;
14
+
15
+class Scene extends ApiCommon
16
+{
17
+    /**
18
+     * 用于判断权限
19
+     * @permission 无限制
20
+     * @allow 登录用户可访问
21
+     * @other 其他根据系统设置
22
+    **/    
23
+    public function _initialize()
24
+    {
25
+        $action = [
26
+            'permission'=>[''],
27
+            'allow'=>['index','save','read','update','delete','sort','defaults']            
28
+        ];
29
+        Hook::listen('check_auth',$action);
30
+        $request = Request::instance();
31
+        $a = strtolower($request->action());        
32
+        if (!in_array($a, $action['permission'])) {
33
+            parent::_initialize();
34
+        }
35
+    }
36
+
37
+    /**
38
+     * 场景列表
39
+     * @return
40
+     */
41
+    public function index()
42
+    {
43
+        $param = $this->param;
44
+        $userInfo = $this->userInfo;
45
+        $sceneModel = model('Scene');
46
+        $data = $sceneModel->getDataList($param['types'], $userInfo['id']);
47
+        if (!$data) {
48
+            return resultArray(['error' => $sceneModel->getError()]);
49
+        }
50
+        return resultArray(['data' => $data]);
51
+    }
52
+
53
+    /**
54
+     * 场景创建
55
+     * @param
56
+     * @return
57
+     */
58
+    public function save()
59
+    {
60
+        $sceneModel = model('Scene');
61
+        $param = $this->param;
62
+        $userInfo = $this->userInfo;
63
+        $param['user_id'] = $userInfo['id'];
64
+        $data = $sceneModel->createData($param, $param['types']);
65
+        if (!$data) {
66
+            return resultArray(['error' => $sceneModel->getError()]);
67
+        }
68
+        return resultArray(['data' => '添加成功']);
69
+    }
70
+
71
+    /**
72
+     * 场景详情
73
+     * @param  int  $id
74
+     * @return 
75
+     */
76
+    public function read()
77
+    {
78
+        $sceneModel = model('Scene');
79
+        $param = $this->param;
80
+        $userInfo = $this->userInfo;
81
+        $data = $sceneModel->getDataById($param['id'], $userInfo['id']);
82
+        if (!$data) {
83
+            return resultArray(['error' => $sceneModel->getError()]);
84
+        }
85
+        return resultArray(['data' => $data]);
86
+    }
87
+
88
+    /**
89
+     * 编辑场景
90
+     * @param  int  $id
91
+     * @return 
92
+     */
93
+    public function update()
94
+    {
95
+        $sceneModel = model('Scene');
96
+        $param = $this->param;
97
+        $userInfo = $this->userInfo;
98
+        $param['user_id'] = $userInfo['id'];
99
+        $data = $sceneModel->updateDataById($param, $param['id']);
100
+        if (!$data) {
101
+            return resultArray(['error' => $sceneModel->getError()]);
102
+        } 
103
+        return resultArray(['data' => '编辑成功']);        
104
+    }
105
+
106
+    /**
107
+     * 删除场景
108
+     * @param  int  $id
109
+     * @return 
110
+     */
111
+    public function delete($id)
112
+    {
113
+        $sceneModel = model('Scene');
114
+        $param = $this->param;
115
+        $userInfo = $this->userInfo;
116
+        //权限判断
117
+        if (!$sceneModel->getDataById($param['id'], $userInfo['id'])) {
118
+            return resultArray(['error' => '数据不存在或已删除']);
119
+        }
120
+        $dataInfo = db('admin_scene')->where(['scene_id' => $param['id']])->find();
121
+        $resData = $sceneModel->delDataById($param['id']);
122
+        if ($resData) {
123
+            //重新设置默认
124
+            $default = db('admin_scene')->where(['types' => $dataInfo['types'],'bydata' => 'all'])->find();
125
+            $sceneModel->defaultDataById(['types' => $dataInfo['types'],'user_id' => $userInfo['id']], $default['scene_id']);
126
+            return resultArray(['data' => '删除成功']);
127
+        } else {
128
+            return resultArray(['error' => $sceneModel->getError()]);
129
+        }
130
+    } 
131
+
132
+    /**
133
+     * 场景排序
134
+     * @param 
135
+     * @return 
136
+     */
137
+    public function sort()
138
+    {
139
+        $sceneModel = model('Scene');
140
+        $param = $this->param;
141
+        $userInfo = $this->userInfo;
142
+        $param['ids'] = $param['ids'] ? : [];
143
+        $param['hide_ids'] = $param['hide_ids'] ? : [];
144
+        $resData = $sceneModel->listOrder($param, $userInfo['id']);
145
+        if (!$resData) {
146
+            return resultArray(['error' => $sceneModel->getError()]);
147
+        }
148
+        return resultArray(['data' => '设置成功']);
149
+    } 
150
+
151
+    /**
152
+     * 场景默认
153
+     * @param scene_id 场景ID
154
+     * @return 
155
+     */
156
+    public function defaults() 
157
+    {
158
+        $sceneModel = model('Scene');
159
+        $param = $this->param;
160
+        $userInfo = $this->userInfo;
161
+        $scene_id = $param['id'];
162
+        $param['user_id'] = $userInfo['id'];
163
+        $resData = $sceneModel->defaultDataById($param, $scene_id);
164
+        if (!$resData) {
165
+            return resultArray(['error' => $sceneModel->getError()]);
166
+        }
167
+        return resultArray(['data' => '设置成功']);        
168
+    }     
169
+}

+ 43
- 0
application/admin/controller/Setting.php Целия файл

@@ -0,0 +1,43 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 系统设置
4
+// +----------------------------------------------------------------------
5
+// | Author: Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use app\admin\controller\ApiCommon;
11
+use think\Hook;
12
+use think\Request;
13
+
14
+class Setting extends ApiCommon
15
+{
16
+	/**
17
+     * 用于判断权限
18
+     * @permission 无限制
19
+     * @allow 登录用户可访问
20
+     * @other 其他根据系统设置
21
+    **/    
22
+    public function _initialize()
23
+    {
24
+        $action = [
25
+            'permission'=>[''],
26
+            'allow'=>['']            
27
+        ];
28
+        Hook::listen('check_auth',$action);
29
+        $request = Request::instance();
30
+        $a = strtolower($request->action());        
31
+        if (!in_array($a, $action['permission'])) {
32
+            parent::_initialize();
33
+        }
34
+        $userInfo = $this->userInfo;
35
+        //权限判断
36
+        $unAction = [''];
37
+        $adminTypes = adminGroupTypes($userInfo['id']);
38
+        if (!in_array(2,$adminTypes) && !in_array(1,$adminTypes) && !in_array($a, $unAction)) {
39
+            header('Content-Type:application/json; charset=utf-8');
40
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
41
+        }           
42
+    }
43
+}

+ 243
- 0
application/admin/controller/Structures.php Целия файл

@@ -0,0 +1,243 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 组织架构
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use think\Hook;
11
+use think\Request;
12
+use think\Db;
13
+
14
+class Structures extends ApiCommon
15
+{
16
+    /**
17
+     * 用于判断权限
18
+     * @permission 无限制
19
+     * @allow 登录用户可访问
20
+     * @other 其他根据系统设置
21
+    **/    
22
+    public function _initialize()
23
+    {
24
+        $action = [
25
+            'permission'=>[''],
26
+            'allow'=>['index','read','save','update','delete','deletes','enables','listdialog','subindex','getsubuserbystructrue']
27
+        ];
28
+        Hook::listen('check_auth',$action);
29
+        $request = Request::instance();
30
+        $a = strtolower($request->action());        
31
+        if (!in_array($a, $action['permission'])) {
32
+            parent::_initialize();
33
+        }
34
+    }    
35
+    
36
+    //获取权限范围内的部门
37
+    public function subIndex()
38
+    {
39
+        $param = $this->param;
40
+        $userInfo = $this->userInfo;
41
+        $userModel = model('User');
42
+        $m = $param['m'] ? : '';
43
+        $c = $param['c'] ? : '';
44
+        $a = $param['a'] ? : '';
45
+        $ret = $userModel->getUserByPer($m, $c, $a);
46
+        $where['au.id'] = ['in',$ret];
47
+        $structure_ids = Db::name('AdminUser')
48
+            ->alias('au')
49
+            ->join('AdminStructure ast','ast.id = au.structure_id','LEFT')
50
+            ->where($where)
51
+            ->group('structure_id')
52
+            ->order('structure_id asc')
53
+            ->column('ast.id');
54
+        $list = Db::name('AdminStructure')
55
+            ->group('id')
56
+            ->order('id asc')
57
+            ->select();
58
+        $result = getSubObj(0, $list, '', 1);
59
+        $adminTypes = adminGroupTypes($userInfo['id']);
60
+        if(!in_array(1,$adminTypes)){
61
+            foreach ($result as $key => $value) {
62
+                if(!in_array($value['id'],$structure_ids)){
63
+                    unset($result[$key]);
64
+                }
65
+            }
66
+        }
67
+        return resultArray(['data'=>$result]);
68
+    }
69
+
70
+    //获取部门下权限范围内员工
71
+    public function getSubUserByStructrue()
72
+    {
73
+        $param = $this->param;
74
+        $userModel = model('User');
75
+        $structureList = $userModel->getSubUserByStr($param['structure_id'],2);
76
+        if($param['structure_id']){
77
+            $where['id'] = ['in',$structureList];
78
+        }
79
+        $list =Db::name('AdminUser')->field('id,realname')->where($where)->select();
80
+        $list = $list?:array();
81
+        return resultArray(['data'=>$list]);
82
+    }
83
+
84
+    /**
85
+     * 部门列表
86
+     * @author Michael_xu
87
+     * @param 
88
+     * @return                            
89
+     */    
90
+    public function index()
91
+    {   
92
+        //权限判断
93
+        // if (!checkPerByAction('admin', 'users', 'index')) {
94
+        //     header('Content-Type:application/json; charset=utf-8');
95
+        //     exit(json_encode(['code'=>102,'error'=>'无权操作']));
96
+        // }        
97
+        $structureModel = model('Structure');
98
+		$param = $this->param;
99
+        $type = $param['type'] ? 'tree' : '';
100
+		$data = $structureModel->getDataList($type);
101
+        return resultArray(['data' => $data]);
102
+    }
103
+
104
+    /**
105
+     * 部门详情
106
+     * @author Michael_xu
107
+     * @param 
108
+     * @return                            
109
+     */    
110
+    public function read()
111
+    {           
112
+        $structureModel = model('Structure');
113
+        $param = $this->param;
114
+        $data = $structureModel->getDataById($param['id']);
115
+        if (!$data) {
116
+            return resultArray(['error' => $structureModel->getError()]);
117
+        } 
118
+        return resultArray(['data' => $data]);
119
+    }
120
+
121
+    /**
122
+     * 部门添加
123
+     * @author Michael_xu
124
+     * @param 
125
+     * @return                            
126
+     */    
127
+    public function save()
128
+    {
129
+        //权限判断
130
+        if (!checkPerByAction('admin', 'users', 'structures_save')) {
131
+            header('Content-Type:application/json; charset=utf-8');
132
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
133
+        }        
134
+        $structureModel = model('Structure');
135
+        $param = $this->param;
136
+		if(!$param['pid']){
137
+			resultArray(['error' => '请选择上级部门']);
138
+		}
139
+        $data = $structureModel->createData($param);
140
+        if (!$data) {
141
+            return resultArray(['error' => $structureModel->getError()]);
142
+        } 
143
+        return resultArray(['data' => '添加成功']);
144
+    }
145
+
146
+    /**
147
+     * 部门编辑
148
+     * @author Michael_xu
149
+     * @param 
150
+     * @return                            
151
+     */
152
+    public function update()
153
+    {
154
+        //权限判断
155
+        if (!checkPerByAction('admin', 'users', 'structures_update')) {
156
+            header('Content-Type:application/json; charset=utf-8');
157
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
158
+        }        
159
+        $structureModel = model('Structure');
160
+        $param = $this->param;
161
+        $dataInfo = $structureModel->getDataByID($param['id']);
162
+        if (empty($dataInfo['pid']) || $param['id'] == '1') {
163
+            unset($param['pid']);
164
+        }
165
+        $data = $structureModel->updateDataById($param, $param['id']);
166
+        if (!$data) {
167
+            return resultArray(['error' => $structureModel->getError()]);
168
+        } 
169
+        return resultArray(['data' => '编辑成功']);
170
+    }
171
+
172
+    /**
173
+     * 部门删除
174
+     * @author Michael_xu
175
+     * @param 
176
+     * @return                            
177
+     */  
178
+    public function delete()
179
+    {
180
+        //权限判断
181
+        if (!checkPerByAction('admin', 'users', 'structures_delete')) {
182
+            header('Content-Type:application/json; charset=utf-8');
183
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
184
+        }        
185
+        $structureModel = model('Structure');
186
+        $param = $this->param;
187
+        $data = $structureModel->delStrById($param['id']);       
188
+        if (!$data) {
189
+            return resultArray(['error' => $structureModel->getError()]);
190
+        } 
191
+        return resultArray(['data' => '删除成功']);    
192
+    }
193
+
194
+    /**
195
+     * 部门启用、停用
196
+     * @author Michael_xu
197
+     * @param 
198
+     * @return                            
199
+     */    
200
+    public function enables()
201
+    {
202
+        //权限判断
203
+        if (!checkPerByAction('admin', 'users', 'structures_update')) {
204
+            header('Content-Type:application/json; charset=utf-8');
205
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
206
+        }        
207
+        $structureModel = model('Structure');
208
+        $param = $this->param;
209
+        $data = $structureModel->enableDatas($param['ids'], $param['status'], true);  
210
+        if (!$data) {
211
+            return resultArray(['error' => $structureModel->getError()]);
212
+        } 
213
+        return resultArray(['data' => '操作成功']);         
214
+    }
215
+
216
+    /**
217
+     * 部门list
218
+     * @author Michael_xu
219
+     * @param 
220
+     * @return                            
221
+     */  
222
+    public function listDialog()
223
+    {   
224
+        $param = $this->param;
225
+        $structure_id = $param['id'];
226
+        $type = $param['type'];
227
+        if (!$structure_id) {
228
+            return resultArray(['error' => '参数错误']);
229
+        }
230
+        $structureList = db('admin_structure')->select();
231
+        if ($type == 'update') {
232
+            //去除自身及下属部门
233
+            foreach ($structureList as $k => $v) {
234
+                if (($v['id'] == $structure_id) || ($v['pid'] == $structure_id)) {
235
+                    unset($structureList[$k]);
236
+                }
237
+            }
238
+        }
239
+        $structureList = getSubObj(0, $structureList, '', 1);
240
+        return resultArray(['data' => $structureList]);   
241
+    }  
242
+}
243
+ 

+ 55
- 0
application/admin/controller/System.php Целия файл

@@ -0,0 +1,55 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 系统配置
4
+// +----------------------------------------------------------------------
5
+// | Author:  yykun
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use think\Hook;
11
+use think\Request;
12
+
13
+class System extends ApiCommon
14
+{
15
+    //用于判断权限
16
+    public function _initialize()
17
+    {
18
+        $action = [
19
+            'permission'=>['index'],
20
+            'allow'=>['']
21
+        ];
22
+        Hook::listen('check_auth',$action);
23
+        $request = Request::instance();
24
+        $a = strtolower($request->action());        
25
+        if (!in_array($a, $action['permission'])) {
26
+            parent::_initialize();
27
+        }            
28
+    }        
29
+
30
+    //信息列表
31
+    public function index()
32
+    {   
33
+        $systemModel = model('System');
34
+        $data = $systemModel->getDataList();
35
+        return resultArray(['data' => $data]);
36
+    }
37
+	
38
+    //编辑保存
39
+	public function save()
40
+	{
41
+        $param = $this->param;
42
+
43
+        if (isset($param['logo'])) {
44
+            $logo = !empty($param['logo']) ? './public/uploads/'.$param['logo'] : '';
45
+            db('admin_system')->where('name', 'logo')->update(['value' => $logo]);
46
+        }
47
+
48
+        if (isset($param['name'])) {
49
+            db('admin_system')->where('name', 'name')->update(['value' => $param['name']]);
50
+        }
51
+
52
+        return resultArray(['data' => '操作成功!']);
53
+	}
54
+}
55
+ 

+ 723
- 0
application/admin/controller/Users.php Целия файл

@@ -0,0 +1,723 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 系统员工
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\controller;
9
+
10
+use app\admin\model\User;
11
+use think\Request;
12
+use think\Session;
13
+use think\Hook;
14
+use think\Cache;
15
+use think\Db;
16
+use app\admin\model\LoginRecord;
17
+use app\admin\model\User as UserModel;
18
+use app\admin\logic\UserLogic;
19
+use app\admin\model\Admin as AdminModel;
20
+use app\crm\traits\StarTrait;
21
+class Users extends ApiCommon
22
+{
23
+    use StarTrait;
24
+    /**
25
+     * 用于判断权限
26
+     * @permission 无限制
27
+     * @allow 登录员工可访问
28
+     * @other 其他根据系统设置
29
+    **/    
30
+    public function _initialize()
31
+    {
32
+        $action = [
33
+            'permission' => ['exceldownload'],
34
+            'allow' => [
35
+                'index',
36
+                'update',
37
+                'updatepwd',
38
+                'read',
39
+                'updateimg',
40
+                'resetpassword',
41
+                'userlistbystructid',
42
+                'groups',
43
+                'groupsdel',
44
+                'tobeusers',
45
+                'structureuserlist',
46
+                'getuserlist',
47
+                'usernameedit',
48
+                'import',
49
+                'setparent',
50
+                'loginRecord',
51
+                'userstar',
52
+                'querylist',
53
+                'starlist',
54
+                'copyrole',
55
+                'subordinate'
56
+            ]
57
+        ];
58
+        Hook::listen('check_auth',$action);
59
+
60
+        $request = Request::instance();
61
+        $a = strtolower($request->action());        
62
+        if (!in_array($a, $action['permission'])) {
63
+            parent::_initialize();
64
+        }        
65
+    }
66
+
67
+    /**
68
+     * 员工列表
69
+     * @param 
70
+     * @return
71
+     */
72
+    public function index()
73
+    {   
74
+        $userModel = model('User');
75
+        $param = $this->param;  
76
+        $data = $userModel->getDataList($param);
77
+        return resultArray(['data' => $data]);
78
+    }
79
+
80
+    /**
81
+     * 员工详情
82
+     * @param 
83
+     * @return
84
+     */
85
+    public function read()
86
+    {   
87
+        $userModel = model('User');
88
+        $param = $this->param;
89
+        $userInfo = $this->userInfo;
90
+        if (!$param['id']) $param['id'] = $userInfo['id'];
91
+        $data = $userModel->getDataById($param['id']);
92
+        if (!$data) {
93
+            return resultArray(['error' => $userModel->getError()]);
94
+        } 
95
+        return resultArray(['data' => $data]);
96
+    }
97
+
98
+    /**
99
+     * 员工创建
100
+     * @param 
101
+     * @return
102
+     */    
103
+    public function save()
104
+    {
105
+        $userModel = model('User');
106
+        $param = $this->param;
107
+		$userInfo = $this->userInfo;
108
+        $data = $userModel->createData($param);
109
+        if (!$data) {
110
+            return resultArray(['error' => $userModel->getError()]);
111
+        }
112
+        return resultArray(['data' => '添加成功']);
113
+    }
114
+
115
+    /**
116
+     * 员工编辑
117
+     * @param 
118
+     * @return
119
+     */
120
+    public function update()
121
+    {
122
+        $userModel = model('User');
123
+        $param = $this->param;
124
+        $userInfo = $this->userInfo;
125
+        $userData = db('admin_user')->where(['id' => $param['id']])->find();
126
+        if (!$param['id']) {
127
+            //修改个人信息
128
+            $param['user_id'] = $userInfo['id'];
129
+        } else {
130
+            //权限判断
131
+            if (!checkPerByAction('admin', 'users', 'update')) {
132
+                header('Content-Type:application/json; charset=utf-8');
133
+                exit(json_encode(['code'=>102,'error'=>'无权操作']));
134
+            }             
135
+        }
136
+        unset($param['username']);
137
+        $data = $userModel->updateDataById($param, $param['id']);
138
+        if (!$data) {
139
+            return resultArray(['error' => $userModel->getError()]);
140
+        }
141
+        $param['userInfo'] = $userData;
142
+        $resSync = model('Sync')->syncData($param);
143
+        return resultArray(['data' => '编辑成功']);
144
+    }    
145
+
146
+	//批量设置密码
147
+	public function updatePwd()
148
+	{
149
+        //权限判断
150
+        if (!checkPerByAction('admin', 'users', 'update')) {
151
+            header('Content-Type:application/json; charset=utf-8');
152
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
153
+        }         
154
+		$param = $this->param;
155
+		if ($param['password'] && is_array($param['id'])) {
156
+			$userModel = model('User');
157
+			$ret = $userModel->updatePwdById($param);
158
+			if ($ret) {
159
+				return resultArray(['data'=>true]);
160
+			} else {
161
+				return resultArray(['error'=>$userModel->getError()]);
162
+			}
163
+		} else {
164
+			return resultArray(['error'=>'参数错误']);
165
+		}
166
+	}
167
+	
168
+    /**
169
+     * 员工状态
170
+     * @param status   0禁用,1启用,2禁止登陆,3未激活
171
+     * @return
172
+     */
173
+    public function enables()
174
+    {
175
+        $userModel = model('User');
176
+        $param = $this->param;
177
+        if (!is_array($param['id'])) {
178
+            $ids[] = $param['id'];
179
+        } else {
180
+            $ids = $param['id'];
181
+        }
182
+        //顶级管理员不能修改
183
+        foreach ($ids as $k=>$v) {
184
+            if ((int)$v == 1 && $param['status'] == '0') {
185
+                unset($ids[$k]);
186
+            }
187
+        }
188
+        $data = $userModel->enableDatas($ids, $param['status']);  
189
+        if (!$data) {
190
+            return resultArray(['error' => $userModel->getError()]);
191
+        } 
192
+        return resultArray(['data' => '操作成功']);         
193
+    }
194
+
195
+    /**
196
+     * 获取权限范围内的员工数组
197
+     * @param  
198
+     * @return
199
+     */
200
+    public function getUserList()
201
+    {
202
+        $userModel = model('User');
203
+        $param = $this->param;
204
+        $by = $param['by'] ? : '';
205
+        $user_id = $param['user_id'] ? : '';
206
+        $where = [];
207
+        $belowIds = [];
208
+        if ($param['m'] && $param['c'] && $param['a']) {
209
+            if ($param['m'] == 'oa' && $param['c'] == 'task') {
210
+               $belowIds = getSubUserId(true, 1); 
211
+            } else {
212
+                $belowIds = $userModel->getUserByPer($param['m'], $param['c'], $param['a']);
213
+            }
214
+            $where['user.id'] = ['in',$belowIds];
215
+        } else {
216
+            if ($by == 'sub') {
217
+                $userInfo = $this->userInfo;
218
+                $adminIds = $userModel->getAdminId();
219
+                if (in_array($userInfo['id'],$adminIds)) {
220
+                    $belowIds = getSubUserId(true, 1);
221
+                } else {
222
+                    //下属id
223
+                    $belowIds = getSubUserId();
224
+                } 
225
+                $where['user.id'] = ['in',$belowIds];
226
+            } elseif ($by == 'parent') {
227
+                if ($user_id == 1) {
228
+                    $where['user.id'] = 0;
229
+                } else {
230
+                    $unUserId[] = $user_id;
231
+                    $subUserId = getSubUser($user_id);
232
+                    $unUserId = $subUserId ? array_merge($subUserId,$unUserId) : $unUserId;
233
+                }
234
+                $where['user.id'] = ['not in',$unUserId];  
235
+            } else {
236
+                $belowIds = getSubUserId(true, 1);
237
+                $where['user.id'] = ['in',$belowIds];     
238
+            }
239
+        }
240
+        $userList = db('admin_user')
241
+                    ->alias('user')
242
+                    ->where($where)
243
+                    ->where('user.status>0 and user.type=1')
244
+                    ->join('__ADMIN_STRUCTURE__ structure', 'structure.id = user.structure_id', 'LEFT')
245
+                    ->field('user.id,user.realname,user.thumb_img,structure.name as s_name')
246
+                    ->select();
247
+
248
+        # 角色数据
249
+        $groupList = db('admin_access')->alias('access')
250
+                    ->join('__ADMIN_GROUP__ group', 'group.id = access.group_id', 'LEFT')
251
+                    ->field('group.id, group.title, access.user_id')->select();
252
+        $groupArray = [];
253
+        foreach ($groupList AS $key => $value) {
254
+            $groupArray[$value['user_id']]['roleId'][] = $value['id'];
255
+            $groupArray[$value['user_id']]['roleName'][] = $value['title'];
256
+        }
257
+
258
+        foreach ($userList as $k=>$v) {
259
+            $userList[$k]['username']  = $v['realname'];
260
+            $userList[$k]['thumb_img'] = $v['thumb_img'] ? getFullPath($v['thumb_img']) : '';
261
+
262
+            # 员工新增角色ID和角色名称字段
263
+            $userList[$k]['roleId']    = !empty($groupArray[$v['id']]['roleId']) ? implode(',', $groupArray[$v['id']]['roleId']) : '';
264
+            $userList[$k]['roleName']  = !empty($groupArray[$v['id']]['roleName']) ? implode(',', $groupArray[$v['id']]['roleName']) : '';
265
+            # 单独处理admin管理员的角色ID和角色名称字段
266
+            if ($v['id'] == 1 && (empty($groupArray[$v['id']]['roleId']) || empty($groupArray[$v['id']]['roleName']))) {
267
+                $userList[$k]['roleId']   = '1';
268
+                $userList[$k]['roleName'] = '超级管理员角色';
269
+            }
270
+        }
271
+        return resultArray(['data' => $userList ? : []]); 
272
+    }
273
+
274
+    /**
275
+     * 修改头像
276
+     * @param 
277
+     * @return
278
+     */ 
279
+    public function updateImg()
280
+    {
281
+        $fileModel = model('File');
282
+        $param = $this->param;
283
+        $userInfo = $this->userInfo;
284
+        //处理图片
285
+        header('Access-Control-Allow-Origin: *');
286
+        header('Access-Control-Allow-Methods: POST');
287
+        header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept"); 
288
+        $param['file'] = request()->file('file');
289
+		
290
+        $resImg = $fileModel->updateByField($param['file'], 'User', $param['id'], 'img', 'thumb_img', 150, 150);
291
+        if (!$resImg) {
292
+            return resultArray(['error' => $fileModel->getError()]);
293
+        }
294
+        return resultArray(['data' => '上传成功']);
295
+    }
296
+
297
+    /**
298
+     * 重置密码
299
+     * @param 
300
+     * @return
301
+     */     
302
+    public function resetPassword()
303
+    {   
304
+        $param = $this->param;
305
+        $userInfo = $this->userInfo;
306
+        $userModel = model('User');
307
+        if ($param['id'] && (int)$param['id'] !== $userInfo['id']) {
308
+            //权限判断
309
+            if (!checkPerByAction('admin', 'users', 'update')) {
310
+                header('Content-Type:application/json; charset=utf-8');
311
+                exit(json_encode(['code'=>102,'error'=>'无权操作']));
312
+            }  
313
+            $user_id = $param['id'];
314
+            if (!$param['new_pwd']) {
315
+                $this->error = '请输入重置密码';
316
+                return false;
317
+            }
318
+
319
+            $userInfo = $userModel->getDataById($user_id);
320
+            if (user_md5($param['new_pwd'], $userInfo['salt'], $userInfo['username']) == $userInfo['password']) {
321
+                $this->error = '密码没改变';
322
+                return false;
323
+            }
324
+            if (db('admin_user')->where('id', $user_id)->setField('password', user_md5($param['new_pwd'], $userInfo['salt'], $userInfo['username']))) {
325
+                $syncData = [];
326
+                $syncModel = new \app\admin\model\Sync();
327
+                $syncData['user_id'] = $userInfo['id'];
328
+                $syncData['salt'] = $userInfo['salt'];
329
+                $syncData['password'] = user_md5($param['new_pwd'], $userInfo['salt'], $userInfo['username']);
330
+                $resSync = $syncModel->syncData($syncData);                
331
+                return resultArray(['data' => '密码重置成功']);
332
+            } else {
333
+                return resultArray(['error' => '密码重置失败,请重试']);
334
+            }      
335
+        } else {
336
+            $userModel = model('User');
337
+            $old_pwd = $param['old_pwd'];
338
+            $new_pwd = $param['new_pwd'];
339
+            $data = $userModel->updatePaw($userInfo, $old_pwd, $new_pwd);
340
+            if (!$data) {
341
+                return resultArray(['error' => $userModel->getError()]);
342
+            } 
343
+            return resultArray(['data' => $data]);            
344
+        }
345
+    }
346
+
347
+    /**
348
+     * 员工角色关系
349
+     * @param 
350
+     * @return
351
+     */
352
+    public function groups()
353
+    {
354
+        //权限判断
355
+        if (!checkPerByAction('admin', 'groups', 'update')) {
356
+            header('Content-Type:application/json; charset=utf-8');
357
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
358
+        }        
359
+        $param = $this->param;
360
+        if (!$param['users'] && !$param['structures']) {
361
+            return resultArray(['error' => '请选择员工']);
362
+        }
363
+        if (!$param['groups']) {
364
+            return resultArray(['error' => '请选择角色']);
365
+        }
366
+        $userModel = model('User');
367
+        //部门下所有员工
368
+        $userArr = [];
369
+        if (is_array($param['structures'])) {
370
+            foreach ($param['structures'] as $v) {
371
+                $userArr[] = $userModel->getSubUserByStr($v);
372
+            }            
373
+        }
374
+        if ($userArr) $userArr = call_user_func_array('array_merge', $userArr); //数组合并
375
+        if ($userArr && $param['users']) {
376
+            $userIds = array_merge($userArr, $param['users']);
377
+        } elseif ($userArr) {
378
+            $userIds = $userArr;
379
+        } else {
380
+            $userIds = $param['users'];
381
+        }
382
+        $userIds = array_unique($userIds);
383
+        $groups = $param['groups'];
384
+        $accessModel = model('Access');       
385
+        $resData = true;
386
+        foreach ($userIds as $k=>$v) {
387
+            //角色员工关系处理
388
+            $res = $accessModel->userGroup($v, $param['groups']);
389
+            if (!$res) {
390
+                $resData = false;
391
+            }            
392
+        }
393
+        // if ($resData == false) {
394
+        //     return resultArray(['error' => '操作失败,请重试']);      
395
+        // }
396
+        return resultArray(['data' => '创建成功']);       
397
+    }
398
+
399
+    /**
400
+     * 员工角色关系(删除)
401
+     * @param 
402
+     * @return
403
+     */
404
+    public function groupsDel()
405
+    {
406
+        //权限判断
407
+        if (!checkPerByAction('admin', 'groups', 'update')) {
408
+            header('Content-Type:application/json; charset=utf-8');
409
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
410
+        }        
411
+        $param = $this->param;
412
+        if (!$param['user_id']) {
413
+            return resultArray(['error' => '请选择员工']);
414
+        }
415
+        if (!$param['group_id']) {
416
+            return resultArray(['error' => '参数错误']);
417
+        }
418
+
419
+        # 员工至少保留一个角色
420
+        $count = db('admin_access')->where(['user_id' => $param['user_id']])->count();
421
+        if ($count == 1) return resultArray(['error' => '员工至少保留一个角色!']);
422
+
423
+        $res = db('admin_access')->where(['user_id' => $param['user_id'],'group_id' => $param['group_id']])->delete();
424
+        if (!$res) {
425
+            return resultArray(['error' => '操作失败,请重试']);      
426
+        }
427
+        return resultArray(['data' => '删除成功']);         
428
+    }
429
+
430
+    /**
431
+     * [structureUserList 部门员工混合数据]
432
+     * @param 
433
+     * @return
434
+     */ 
435
+    public function structureUserList()
436
+    {
437
+        $structure_list = db('admin_structure')->select();
438
+        $structureList = getSubObj(0, $structure_list, '', 1);
439
+        foreach ($structureList as $k=>$v) {
440
+            $userList = [];
441
+            $userList = db('admin_user')->where(['structure_id' => $v['id'],'status' => array('in',['1','3'])])->field('id,realname')->select();
442
+            $structureList[$k]['userList'] = $userList;
443
+        }
444
+        return $structureList;
445
+    }    
446
+	
447
+	//人资员工导入
448
+	public function tobeusers(){
449
+		$userModel = model('User');
450
+		$param = $this->param;
451
+		$flag = $userModel->beusers($param);
452
+		if ($flag) {
453
+			return resultArray(['data'=>$flag]);
454
+		} else {
455
+			return resultArray(['error'=>$userModel->getError()]);
456
+		}
457
+	}
458
+	
459
+	//根据部门ID获取员工列表
460
+	public function userListByStructId()
461
+	{
462
+		$usermodel = model('User');
463
+		$param = $this->param;
464
+		$structure_id = $param['structure_id']?:'';
465
+		$ret = $usermodel->getUserListByStructureId($structure_id) ? : [];
466
+        return resultArray(['data'=>$ret]);
467
+	}
468
+
469
+    /**
470
+     * 员工账号修改
471
+     * @param 
472
+     * @return
473
+     */    
474
+    public function usernameEdit()
475
+    {
476
+        //权限判断
477
+        if (!checkPerByAction('admin', 'users', 'update')) {
478
+            header('Content-Type:application/json; charset=utf-8');
479
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
480
+        }        
481
+        $param = $this->param;
482
+        $userInfo = $this->userInfo;
483
+        //权限判断
484
+        if ($param['id'] == 1) {
485
+            return resultArray(['error' => '管理员账号暂不能修改']);
486
+        }
487
+        $adminTypes = adminGroupTypes($userInfo['id']);
488
+        if (!in_array(3,$adminTypes) && !in_array(1,$adminTypes) && !in_array(2,$adminTypes)) {
489
+            header('Content-Type:application/json; charset=utf-8');
490
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
491
+        }         
492
+        if (!$param['id'] || !$param['username'] || !$param['password']) {
493
+            return resultArray(['error' => '参数错误!']);
494
+        }
495
+        if (db('admin_user')->where(['id' => ['neq',$param['id']],'username' => $param['username']])->find()) {
496
+            return resultArray(['error' => '手机号码已存在!']);
497
+        }
498
+        $userData = db('admin_user')->where(['id' => $param['id']])->field('username,salt,password')->find();
499
+        $data = [];
500
+        $data['username'] = $param['username'];
501
+        $data['password'] = user_md5($param['password'], $userData['salt'], $param['username']);
502
+        $data['userInfo'] = $userData;
503
+        $resSync = model('Sync')->syncData($data);
504
+        if ($resSync) {
505
+            unset($data['userInfo']);
506
+            $res = db('admin_user')->where(['id' => $param['id']])->update($data);
507
+            return resultArray(['data' => '修改成功!']);
508
+        } else {
509
+            return resultArray(['error' => '修改失败,请重试!']);
510
+        }
511
+    }
512
+
513
+    /**
514
+     * 登录记录
515
+     */
516
+    public function loginRecord()
517
+    {
518
+        if (!checkPerByAction('admin', 'loginRecord', 'index')) {
519
+            header('Content-Type:application/json; charset=utf-8');
520
+            exit(json_encode(['code' => 102, 'error' => '无权操作']));
521
+        }
522
+
523
+        $loginRecordModel = new LoginRecord();
524
+        $where = [];
525
+        getWhereUserByParam($where, 'create_user_id');
526
+        getWhereTimeByParam($where, 'create_time');
527
+
528
+        $limit = $this->param['limit'] ?: 15;
529
+        $data = $loginRecordModel
530
+            ->where($where)
531
+            ->order(['create_time' => 'DESC'])
532
+            ->paginate($limit)
533
+            ->each(function ($val) {
534
+                $val['username'] = $val->create_user_info['realname'];
535
+                $val['type_name'] = $val->type_name;
536
+            })
537
+            ->toArray();
538
+        return resultArray([
539
+            'data' => [
540
+                'list' => $data['data'],
541
+                'dataCount' => $data['total']
542
+            ],
543
+        ]);
544
+    }
545
+
546
+    /**
547
+     * 员工导入模板下载
548
+     * @author Michael_xu
549
+     * @param string $save_path 本地保存路径     用于错误数据导出,在 Admin\Model\Excel::batchImportData()调用
550
+     * @return
551
+     */
552
+    public function excelDownload($save_path = '')
553
+    {
554
+        $param = $this->param;
555
+        $userInfo = $this->userInfo;
556
+        $excelModel = new \app\admin\model\Excel();
557
+
558
+        // 导出的字段列表
559
+        $field_list = UserModel::$import_field_list;
560
+        $excelModel->excelImportDownload($field_list, 'admin_user', $save_path);
561
+    }
562
+
563
+    /**
564
+     * 员工导入
565
+     */
566
+    public function import()
567
+    {
568
+        // 仅允许超管,系统管理员,部门与员工管理员 导入
569
+        if (false === UserModel::checkUserGroup([1, 2, 3])) {
570
+            return resultArray(['error' => '没有该权限']);
571
+        }
572
+        $param = $this->param;
573
+        $userInfo = $this->userInfo;
574
+        $excelModel = new \app\admin\model\Excel();
575
+        $param['types'] = 'admin_user';
576
+        $file = request()->file('file');
577
+        $res = $excelModel->batchImportData($file, $param, $this);
578
+        $list=[];
579
+        $list[]=$excelModel->getError();
580
+        $item=$list[0];
581
+        if (!$res) {
582
+            return resultArray(['data' => $item]);
583
+        }
584
+        Cache::clear('user_info');
585
+        return resultArray(['data' => $item]);
586
+    }
587
+
588
+    /**
589
+     * 批量设置直属上级
590
+     *
591
+     * @author Ymob
592
+     * @datetime 2019-10-28 13:37:57
593
+     */
594
+    public function setParent()
595
+    {
596
+        // 仅允许超管,系统管理员,部门与员工管理员 批量设置
597
+        if (false === UserModel::checkUserGroup([1, 2, 3])) {
598
+            return resultArray(['error' => '没有该权限']);
599
+        }
600
+        $parent_id = (int) $this->param['parent_id'];
601
+        $parent_user = UserModel::find($parent_id);
602
+        if (!$parent_user) {
603
+            return resultArray(['error' => '请选择直属上级']);
604
+        }
605
+        $user_id_list = (array) $this->param['id_list'];
606
+        if (empty($user_id_list)) {
607
+            return resultArray(['error' => '请选择员工']);
608
+        }
609
+        if (in_array(1, $user_id_list)) {
610
+            return resultArray(['error' => '超级管理员不能设置上级']);
611
+        }
612
+
613
+        if (in_array($parent_id, $user_id_list)) {
614
+            return resultArray(['error' => '直属上级不能为员工自己']);
615
+        }
616
+        
617
+        foreach ($user_id_list as $val) {
618
+            if (in_array($parent_id, getSubUserId(true, 0, (int) $val))) {
619
+                return resultArray(['error' => '直属上级不能是自己下属(包含下属的下属)']);
620
+            }
621
+        }
622
+
623
+        $a = new UserModel;
624
+        if ($a->where(['id' => ['IN', $user_id_list]])->update(['parent_id' => $parent_id])) {
625
+            Cache::clear('user_info');
626
+            return resultArray(['data' => '员工直属上级设置成功']);
627
+        } else {
628
+            return resultArray(['error' => '员工直属上级设置失败' . $a->getError()]);
629
+        }
630
+    }
631
+
632
+    /**
633
+     * 通讯录列表
634
+     * @return mixed
635
+     */
636
+    public function queryList(){
637
+        $param = $this->param;
638
+        $userInfo = $this->userInfo;
639
+        $param['user_id']=$userInfo['id'];
640
+        $userLogic=new UserLogic();
641
+        $data=$userLogic->getDataList($param);
642
+        return resultArray(['data' => $data]);
643
+
644
+    }
645
+
646
+    /**
647
+     * 关注的通讯录列表
648
+     * @return mixed
649
+     */
650
+    public function starList(){
651
+        $param = $this->param;
652
+        $userInfo = $this->userInfo;
653
+        $param['user_id']=$userInfo['id'];
654
+        $userLogic=new UserLogic();
655
+        $data=$userLogic->queryList($param);
656
+        return resultArray(['data' => $data]);
657
+    }
658
+    /**
659
+     * 设置关注
660
+     *
661
+     * @return \think\response\Json
662
+     * @throws \think\Exception
663
+     * @throws \think\exception\PDOException
664
+     */
665
+    public function userStar()
666
+    {
667
+        $userInfo = $this->userInfo;
668
+        $userId   =  $userInfo['id'];
669
+        $targetId = $this->param['target_id'];
670
+        $type     = $this->param['type'];
671
+
672
+        if (empty($userId) || empty($targetId) || empty($type)) return resultArray(['error' => '缺少必要参数!']);
673
+
674
+        if (!$this->setStar($type, $userId, $targetId)) {
675
+            return resultArray(['error' => '设置关注失败!']);
676
+        }
677
+
678
+        return resultArray(['data' => '设置关注成功!']);
679
+    }
680
+
681
+    /**
682
+     * 复制员工角色
683
+     *
684
+     * @return \think\response\Json
685
+     */
686
+    public function copyRole()
687
+    {
688
+        $param = $this->param;
689
+
690
+        if (empty($param['user_id']) && empty($param['structure_id'])) return resultArray(['error' => '请选择员工或部门!']);
691
+        if (empty($param['group_id'])) return resultArray(['error' => '请选择角色!']);
692
+
693
+        $userModel = new User();
694
+
695
+        if (!$userModel->copyRole($param)) return resultArray(['error' => '操作失败!']);
696
+
697
+        return resultArray(['data' => '操作成功!']);
698
+    }
699
+
700
+    /**
701
+     * 获取下属(全部层级)
702
+     *
703
+     * @return \think\response\Json
704
+     * @throws \think\db\exception\DataNotFoundException
705
+     * @throws \think\db\exception\ModelNotFoundException
706
+     * @throws \think\exception\DbException
707
+     */
708
+    public function subordinate()
709
+    {
710
+        $userId = $this->userInfo['id'];
711
+
712
+        # 获取下属的ID
713
+        $subIds = getSubUserId(false, 0, $userId);
714
+
715
+        $data = Db::name('admin_user')->field(['id', 'realname', 'thumb_img as img'])->whereIn('id', $subIds)->select();
716
+
717
+        foreach ($data AS $key => $value) {
718
+            $data[$key]['img'] = !empty($data[$key]['img']) ? getFullPath($data[$key]['img']) : '';
719
+        }
720
+
721
+        return resultArray(['data' => $data]);
722
+    }
723
+}

+ 149
- 0
application/admin/controller/Work.php Целия файл

@@ -0,0 +1,149 @@
1
+<?php
2
+/**
3
+ * 项目管理控制器
4
+ *
5
+ * @author qifan
6
+ * @date 2020-12-17
7
+ */
8
+
9
+namespace app\admin\controller;
10
+
11
+use app\admin\logic\WorkLogic;
12
+use think\Hook;
13
+use think\Request;
14
+
15
+class Work extends ApiCommon
16
+{
17
+    /**
18
+     * 用于判断权限
19
+     * @permission 无限制
20
+     * @allow 登录用户可访问
21
+     * @other 其他根据系统设置
22
+     **/
23
+    public function _initialize()
24
+    {
25
+        $action = [
26
+            'permission' => [''],
27
+            'allow' => ['rules', 'roles', 'saverole', 'readrole', 'updaterole', 'deleterole']
28
+        ];
29
+        Hook::listen('check_auth',$action);
30
+        $request = Request::instance();
31
+        $a = strtolower($request->action());
32
+        if (!in_array($a, $action['permission'])) {
33
+            parent::_initialize();
34
+        }
35
+    }
36
+
37
+    /**
38
+     * 规则列表
39
+     *
40
+     * @param WorkLogic $workLogic
41
+     * @return \think\response\Json
42
+     * @throws \think\db\exception\DataNotFoundException
43
+     * @throws \think\db\exception\ModelNotFoundException
44
+     * @throws \think\exception\DbException
45
+     */
46
+    public function rules(WorkLogic $workLogic)
47
+    {
48
+        $data = $workLogic->getRules();
49
+
50
+        $result = [
51
+            'menu_id'   => 0,
52
+            'menu_name' => "项目管理",
53
+            'menu_type' => 1,
54
+            'parent_id' => 0,
55
+            'realm'     => 'work',
56
+            'children'  => []
57
+        ];
58
+
59
+        $result['children'][] = ['id' => 0, 'title' => '项目', 'name' => 'work', 'children' => $data];
60
+
61
+        return resultArray(['data' => $result]);
62
+    }
63
+
64
+    /**
65
+     * 获取角色
66
+     *
67
+     * @param WorkLogic $workLogic
68
+     * @return \think\response\Json
69
+     * @throws \think\db\exception\DataNotFoundException
70
+     * @throws \think\db\exception\ModelNotFoundException
71
+     * @throws \think\exception\DbException
72
+     */
73
+    public function roles(WorkLogic $workLogic)
74
+    {
75
+        $data = $workLogic->getRoles();
76
+
77
+        return resultArray(['data' => $data]);
78
+    }
79
+
80
+    /**
81
+     * 创建角色
82
+     *
83
+     * @param WorkLogic $workLogic
84
+     * @return \think\response\Json
85
+     */
86
+    public function saveRole(WorkLogic $workLogic)
87
+    {
88
+        if (empty($this->param['title'])) return resultArray(['error' => '请填写权限名称!']);
89
+
90
+        if (!$workLogic->saveRole($this->param)) return resultArray(['操作失败!']);
91
+
92
+        return resultArray(['data' => '操作成功!']);
93
+    }
94
+
95
+    /**
96
+     * 权限角色详情
97
+     *
98
+     * @param WorkLogic $workLogic
99
+     * @return \think\response\Json
100
+     * @throws \think\db\exception\DataNotFoundException
101
+     * @throws \think\db\exception\ModelNotFoundException
102
+     * @throws \think\exception\DbException
103
+     */
104
+    public function readRole(WorkLogic $workLogic)
105
+    {
106
+        if (empty($this->param['id'])) return resultArray(['error' => '请选择权限角色!']);
107
+
108
+        $data = $workLogic->readRole($this->param['id']);
109
+
110
+        return resultArray(['data' => $data]);
111
+    }
112
+
113
+    /**
114
+     * 编辑权限角色
115
+     *
116
+     * @param WorkLogic $workLogic
117
+     * @return \think\response\Json
118
+     * @throws \think\Exception
119
+     * @throws \think\exception\PDOException
120
+     */
121
+    public function updateRole(WorkLogic $workLogic)
122
+    {
123
+        if (empty($this->param['id']))    return resultArray(['error' => '请选择要编辑的权限角色!']);
124
+        if (empty($this->param['title'])) return resultArray(['error' => '请填写权限名称!']);
125
+
126
+        if ($workLogic->updateRole($this->param) === false) return resultArray(['error' => '操作失败!']);
127
+
128
+        return resultArray(['data' => '操作成功!']);
129
+    }
130
+
131
+    /**
132
+     * 删除权限角色
133
+     *
134
+     * @param WorkLogic $workLogic
135
+     * @return \think\response\Json
136
+     * @throws \think\Exception
137
+     * @throws \think\exception\PDOException
138
+     */
139
+    public function deleteRole(WorkLogic $workLogic)
140
+    {
141
+        if (empty($this->param['id'])) return resultArray(['error' => '请选择要删除的权限角色!']);
142
+
143
+        $result = $workLogic->deleteRole($this->param['id']);
144
+
145
+        if (empty($result['status'])) return resultArray(['error' => $result['error']]);
146
+
147
+        return resultArray(['data' => '操作成功!']);
148
+    }
149
+}

+ 0
- 0
application/admin/lang/en-us.php Целия файл


+ 4
- 0
application/admin/lang/zh-cn.php Целия файл

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

+ 309
- 0
application/admin/logic/DailyRuleLogic.php Целия файл

@@ -0,0 +1,309 @@
1
+<?php
2
+/**
3
+ * 日志规则逻辑类
4
+ *
5
+ * @author qifan
6
+ * @date 2020-12-03
7
+ */
8
+
9
+namespace app\admin\logic;
10
+
11
+use think\Db;
12
+
13
+class DailyRuleLogic
14
+{
15
+    /**
16
+     * 获取日志欢迎语
17
+     *
18
+     * @return array|mixed
19
+     */
20
+    public function welcome()
21
+    {
22
+        $mark = Db::name('admin_oalog_rule')->where('type', 4)->value('mark');
23
+
24
+        return !empty($mark) ? unserialize($mark) : [];
25
+    }
26
+
27
+    /**
28
+     * 保存欢迎语
29
+     *
30
+     * @param $data
31
+     * @return int|string
32
+     * @throws \think\Exception
33
+     * @throws \think\exception\PDOException
34
+     */
35
+    public function setWelcome($data)
36
+    {
37
+        $result = [];
38
+
39
+        foreach ($data as $key => $value) {
40
+            if (!empty($value)) $result[] = $value;
41
+        }
42
+
43
+        $result = serialize($result);
44
+
45
+        if (Db::name('admin_oalog_rule')->where('type', 4)->value('id')) {
46
+            return Db::name('admin_oalog_rule')->where('type', 4)->update(['mark' => $result]);
47
+        }
48
+
49
+        return Db::name('admin_oalog_rule')->insert([
50
+            'type' => 4,
51
+            'status' => 1,
52
+            'mark' => $result
53
+        ]);
54
+    }
55
+
56
+    /**
57
+     * 获取日志规则
58
+     *
59
+     * @return mixed
60
+     * @throws \think\db\exception\DataNotFoundException
61
+     * @throws \think\db\exception\ModelNotFoundException
62
+     * @throws \think\exception\DbException
63
+     */
64
+    public function workLogRule()
65
+    {
66
+        $result[] = $this->getDayLogRule();
67
+        $result[] = $this->getWeekLogRule();
68
+        $result[] = $this->getMonthLogRule();
69
+
70
+        return $result;
71
+    }
72
+
73
+    /**
74
+     * 设置日志规则
75
+     *
76
+     * @param $param
77
+     * @throws \think\Exception
78
+     * @throws \think\exception\PDOException
79
+     */
80
+    public function setWorkLogRule($param)
81
+    {
82
+        if (!empty($param[0])) $this->setDayLogRule($param[0]);
83
+        if (!empty($param[1])) $this->setWeekLogRule($param[1]);
84
+        if (!empty($param[2])) $this->setMonthLogRule($param[2]);
85
+    }
86
+
87
+    /**
88
+     * 设置日规则
89
+     *
90
+     * @param $param
91
+     * @return int|string
92
+     * @throws \think\Exception
93
+     * @throws \think\exception\PDOException
94
+     */
95
+    private function setDayLogRule($param)
96
+    {
97
+        $data = [
98
+            'type' => 1,
99
+            'userIds' => $param['userIds'],
100
+            'effective_day' => $param['effective_day'],
101
+            'start_time' => $param['start_time'],
102
+            'end_time' => $param['end_time'],
103
+            'status' => $param['status']
104
+        ];
105
+
106
+        if (Db::name('admin_oalog_rule')->where('type', 1)->value('id')) {
107
+            return Db::name('admin_oalog_rule')->where('type', 1)->update($data);
108
+        }
109
+
110
+        return Db::name('admin_oalog_rule')->insert($data);
111
+    }
112
+
113
+    /**
114
+     * 设置周规则
115
+     *
116
+     * @param $param
117
+     * @return int|string
118
+     * @throws \think\Exception
119
+     * @throws \think\exception\PDOException
120
+     */
121
+    private function setWeekLogRule($param)
122
+    {
123
+        $data = [
124
+            'type' => 2,
125
+            'userIds' => $param['userIds'],
126
+            'start_time' => $param['start_time'],
127
+            'end_time' => $param['end_time'],
128
+            'status' => $param['status']
129
+        ];
130
+
131
+        if (Db::name('admin_oalog_rule')->where('type', 2)->value('id')) {
132
+            return Db::name('admin_oalog_rule')->where('type', 2)->update($data);
133
+        }
134
+
135
+        return Db::name('admin_oalog_rule')->insert($data);
136
+    }
137
+
138
+    /**
139
+     * 设置月规则
140
+     *
141
+     * @param $param
142
+     * @return int|string
143
+     * @throws \think\Exception
144
+     * @throws \think\exception\PDOException
145
+     */
146
+    private function setMonthLogRule($param)
147
+    {
148
+        $data = [
149
+            'type' => 3,
150
+            'userIds' => $param['userIds'],
151
+            'start_time' => $param['start_time'],
152
+            'end_time' => $param['end_time'],
153
+            'status' => $param['status']
154
+        ];
155
+
156
+        if (Db::name('admin_oalog_rule')->where('type', 3)->value('id')) {
157
+            return Db::name('admin_oalog_rule')->where('type', 3)->update($data);
158
+        }
159
+
160
+        return Db::name('admin_oalog_rule')->insert($data);
161
+    }
162
+
163
+    /**
164
+     * 获取日规则
165
+     *
166
+     * @return array
167
+     * @throws \think\db\exception\DataNotFoundException
168
+     * @throws \think\db\exception\ModelNotFoundException
169
+     * @throws \think\exception\DbException
170
+     */
171
+    private function getDayLogRule()
172
+    {
173
+        $day = Db::name('admin_oalog_rule')->where('type', 1)->find();
174
+
175
+        return [
176
+            'type' => $day['type'],
177
+            'status' => $day['status'],
178
+            'userIds' => $day['userIds'],
179
+            'user' => $this->getUsers($day['userIds']),
180
+            'effective_day' => $day['effective_day'],
181
+            'start_time' => $day['start_time'],
182
+            'end_time' => $day['end_time']
183
+        ];
184
+    }
185
+
186
+    /**
187
+     * 获取周规则
188
+     *
189
+     * @return array
190
+     * @throws \think\db\exception\DataNotFoundException
191
+     * @throws \think\db\exception\ModelNotFoundException
192
+     * @throws \think\exception\DbException
193
+     */
194
+    private function getWeekLogRule()
195
+    {
196
+        $week = Db::name('admin_oalog_rule')->where('type', 2)->find();
197
+
198
+        return [
199
+            'type' => $week['type'],
200
+            'status' => $week['status'],
201
+            'userIds' => $week['userIds'],
202
+            'user' => $this->getUsers($week['userIds']),
203
+            'effective_day' => $week['effective_day'],
204
+            'start_time' => $week['start_time'],
205
+            'end_time' => $week['end_time']
206
+        ];
207
+    }
208
+
209
+    /**
210
+     * 获取月规则
211
+     *
212
+     * @return array
213
+     * @throws \think\db\exception\DataNotFoundException
214
+     * @throws \think\db\exception\ModelNotFoundException
215
+     * @throws \think\exception\DbException
216
+     */
217
+    private function getMonthLogRule()
218
+    {
219
+        $month = Db::name('admin_oalog_rule')->where('type', 3)->find();
220
+
221
+        return [
222
+            'type' => $month['type'],
223
+            'status' => $month['status'],
224
+            'userIds' => $month['userIds'],
225
+            'user' => $this->getUsers($month['userIds']),
226
+            'effective_day' => $month['effective_day'],
227
+            'start_time' => $month['start_time'],
228
+            'end_time' => $month['end_time']
229
+        ];
230
+    }
231
+
232
+    /**
233
+     * 获取用户列表
234
+     *
235
+     * @param $ids
236
+     * @return bool|\PDOStatement|string|\think\Collection
237
+     * @throws \think\db\exception\DataNotFoundException
238
+     * @throws \think\db\exception\ModelNotFoundException
239
+     * @throws \think\exception\DbException
240
+     */
241
+    private function getUsers($ids)
242
+    {
243
+        return Db::name('admin_user')->field(['id', 'realname'])->whereIn('id', $ids)->select();
244
+    }
245
+
246
+    /**
247
+     * 自定义日程类型列表
248
+     * @return array
249
+     * @throws \think\db\exception\DataNotFoundException
250
+     * @throws \think\db\exception\ModelNotFoundException
251
+     * @throws \think\exception\DbException
252
+     */
253
+    public function schedule()
254
+    {
255
+        $list = Db::name('admin_oa_schedule')->where('type', 2)->field(['name,color,schedule_id as id'])->select();
256
+        $data = [];
257
+        $data['list'] = $list;
258
+        return $data;
259
+    }
260
+
261
+    /**
262
+     * 设置日程自定义规则
263
+     * @param $param
264
+     * @return int|string
265
+     * @throws \think\Exception
266
+     * @throws \think\exception\PDOException
267
+     */
268
+    public function setSchedule($param)
269
+    {
270
+        if (Db::name('admin_oa_schedule')->where('schedule_id', $param['id'])->value('schedule_id')) {
271
+            $data = [
272
+                'name' => $param['name'],
273
+                'update_time' => time(),
274
+                'color' => $param['color'],
275
+            ];
276
+            return Db::name('admin_oa_schedule')->where( 'schedule_id', $param['id'])->update($data);
277
+        }
278
+
279
+    }
280
+
281
+    /**
282
+     * 添加自定义日程规则
283
+     * @param $param
284
+     * @return int|string
285
+     */
286
+    public function addSchedule($param)
287
+    {
288
+        $data = [
289
+            'name' => $param['name'],
290
+            'create_time' => time(),
291
+            'color' => $param['color'],
292
+        ];
293
+        return Db::name('admin_oa_schedule')->insert($data);
294
+    }
295
+
296
+    /**
297
+     * 删除日程自定义规则
298
+     * @param $param
299
+     * @return int
300
+     * @throws \think\Exception
301
+     * @throws \think\exception\PDOException
302
+     */
303
+    public function delSchedule($param)
304
+    {
305
+        if (Db::name('admin_oa_schedule')->where('schedule_id', $param)->value('schedule_id')) {
306
+            return Db::name('AdminOaSchedule')->where('schedule_id', $param)->delete();
307
+        }
308
+    }
309
+}

+ 572
- 0
application/admin/logic/FieldGrantLogic.php Целия файл

@@ -0,0 +1,572 @@
1
+<?php
2
+/**
3
+ * 字段授权逻辑类
4
+ *
5
+ * @author qifan
6
+ * @date 2020-12-01
7
+ */
8
+
9
+namespace app\admin\logic;
10
+
11
+use think\Db;
12
+
13
+class FieldGrantLogic
14
+{
15
+    /**
16
+     * 字段授权列表
17
+     *
18
+     * @param $param
19
+     * @return array|bool|\PDOStatement|string|\think\Model|null
20
+     * @throws \think\db\exception\DataNotFoundException
21
+     * @throws \think\db\exception\ModelNotFoundException
22
+     * @throws \think\exception\DbException
23
+     */
24
+    public function index($param)
25
+    {
26
+        $where = function ($query) use ($param) {
27
+            $query->where('module', $param['module']);
28
+            $query->where('column', $param['column']);
29
+            $query->where('role_id', $param['role_id']);
30
+        };
31
+
32
+        $count = Db::name('admin_field_grant')->where($where)->count();
33
+
34
+        # 如果该角色下没有字段授权数据则自动添加
35
+        if ($count == 0 && Db::name('admin_group')->where('id', $param['role_id'])->find()) {
36
+            $this->createCrmFieldGrant($param['role_id']);
37
+        }
38
+
39
+        $data = Db::name('admin_field_grant')->field(['grant_id', 'content'])->where($where)->find();
40
+
41
+        if (!empty($data['content'])) $data['content'] = unserialize($data['content']);
42
+
43
+        return !empty($data) ? $data : [];
44
+    }
45
+
46
+    /**
47
+     * 更新授权字段
48
+     *
49
+     * @param $grantId
50
+     * @param $content
51
+     * @return int|string
52
+     * @throws \think\Exception
53
+     * @throws \think\exception\PDOException
54
+     */
55
+    public function update($grantId, $content)
56
+    {
57
+        return Db::name('admin_field_grant')->where('grant_id', $grantId)->update(['content' => serialize(array_values($content))]);
58
+    }
59
+
60
+    /**
61
+     * 添加字段授权信息
62
+     *
63
+     * @param $roleId
64
+     * @throws \think\db\exception\DataNotFoundException
65
+     * @throws \think\db\exception\ModelNotFoundException
66
+     * @throws \think\exception\DbException
67
+     */
68
+    public function createCrmFieldGrant($roleId)
69
+    {
70
+        # 添加线索字段授权数据
71
+        $this->createLeadsFieldGrant($roleId);
72
+        # 添加客户字段授权数据
73
+        $this->createCustomerFieldGrant($roleId);
74
+        # 添加联系人字段授权数据
75
+        $this->createContactsFieldGrant($roleId);
76
+        # 添加商机字段授权数据
77
+        $this->createBusinessFieldGrant($roleId);
78
+        # 添加合同字段授权数据
79
+        $this->createContractfieldGrant($roleId);
80
+        # 添加回款字段授权数据
81
+        $this->createReceivablesFieldGrant($roleId);
82
+        # 添加产品字段授权信息
83
+        $this->createProductFieldGrant($roleId);
84
+        # 添加回访字段授权信息
85
+        $this->createVisitFieldGrant($roleId);
86
+    }
87
+
88
+    /**
89
+     * 删除授权字段数据
90
+     *
91
+     * @param $roleId
92
+     * @param string $module
93
+     * @throws \think\Exception
94
+     * @throws \think\exception\PDOException
95
+     */
96
+    public function deleteCrmFieldGrant($roleId)
97
+    {
98
+        Db::name('admin_field_grant')->where('module', 'crm')->where('role_id', $roleId)->delete();
99
+    }
100
+
101
+    /**
102
+     * 拷贝字段授权数据
103
+     *
104
+     * @param $copyId
105
+     * @param $roleId
106
+     * @throws \think\db\exception\DataNotFoundException
107
+     * @throws \think\db\exception\ModelNotFoundException
108
+     * @throws \think\exception\DbException
109
+     */
110
+    public function copyCrmFieldGrant($copyId, $roleId)
111
+    {
112
+        $data = [];
113
+
114
+        $list = Db::name('admin_field_grant')->where('module', 'crm')->where('role_id', $copyId)->select();
115
+
116
+        foreach ($list AS $key => $value) {
117
+            $data[] = [
118
+                'role_id'     => $roleId,
119
+                'module'      => $value['module'],
120
+                'column'      => $value['column'],
121
+                'content'     => $value['content'],
122
+                'create_time' => time(),
123
+                'update_time' => time()
124
+            ];
125
+        }
126
+
127
+        if (!empty($data)) Db::name('admin_field_grant')->insertAll($data);
128
+    }
129
+
130
+    /**
131
+     * 同步更新自定义字段的授权信息
132
+     *
133
+     * @param $types
134
+     * @return bool
135
+     * @throws \think\Exception
136
+     * @throws \think\db\exception\DataNotFoundException
137
+     * @throws \think\db\exception\ModelNotFoundException
138
+     * @throws \think\exception\DbException
139
+     * @throws \think\exception\PDOException
140
+     */
141
+    public function fieldGrantDiyHandle($types)
142
+    {
143
+        $typesArray = explode('_', $types);
144
+
145
+        # 只处理客户管理角色下的字段授权
146
+        if ($typesArray[0] != 'crm') return false;
147
+
148
+        # 查询自定义字段表
149
+        $fieldBaseData = [];
150
+        $fieldList = Db::name('admin_field')->field(['name', 'field'])->where('types', $types)->select();
151
+        foreach ($fieldList AS $key => $value) {
152
+            $fieldBaseData[$value['field']] = $value;
153
+        }
154
+
155
+        # 查询字段授权表
156
+        $grantList = Db::name('admin_field_grant')->field(['grant_id', 'content'])->where('column', $typesArray[1])->select();
157
+
158
+        # 处理授权字段的数据更新
159
+        foreach ($grantList AS $key => $value) {
160
+            $content   = unserialize($value['content']);
161
+            $fieldData = $fieldBaseData;
162
+
163
+            foreach ($content AS $k => $v) {
164
+                # 只处理自定义字段
165
+                if ($v['is_diy'] == 0) continue;
166
+
167
+                if (empty($fieldData[$v['field']])) {
168
+                    # 【处理删除:】没有在$fieldData找到,说明自定义字段被删除,则进行同步删除。
169
+                    unset($content[(int)$k]);
170
+                } else {
171
+
172
+                    # 【处理更新:】如果在$fieldData找到,则进行同步更新。
173
+                    $content[$k]['name'] = $fieldData[$v['field']]['name'];
174
+                    $content[$k]['field'] = $fieldData[$v['field']]['field'];
175
+
176
+                    # 删除$fieldData的数据,方便统计新增的自定义字段。
177
+                    unset($fieldData[(string)$v['field']]);
178
+                }
179
+
180
+            }
181
+
182
+            # 【处理新增】如果$fieldData还有数据,说明是新增的,则进行同步新增。
183
+            if (!empty($fieldData)) {
184
+                foreach ($fieldData AS $k => $v) {
185
+                    $content[] = [
186
+                        'name'            => $v['name'],
187
+                        'field'           => $v['field'],
188
+                        'read'            => 1,
189
+                        'read_operation'  => 1,
190
+                        'write'           => 1,
191
+                        'write_operation' => 1,
192
+                        'is_diy'          => 1
193
+                    ];
194
+                }
195
+            }
196
+
197
+            # todo 暂时将数据库操作写在循环中!!!
198
+            Db::name('admin_field_grant')->where('grant_id', $value['grant_id'])->update(['content' => serialize(array_values($content))]);
199
+        }
200
+
201
+        return true;
202
+    }
203
+
204
+    /**
205
+     * 添加线索字段授权数据
206
+     *
207
+     * @param $roleId
208
+     * @throws \think\db\exception\DataNotFoundException
209
+     * @throws \think\db\exception\ModelNotFoundException
210
+     * @throws \think\exception\DbException
211
+     */
212
+    private function createLeadsFieldGrant($roleId)
213
+    {
214
+        $content = [];
215
+
216
+        $leadsList = Db::name('admin_field')->field(['name', 'field'])->where('types', 'crm_leads')->select();
217
+
218
+        # 处理自定义字段
219
+        foreach ($leadsList AS $key => $value) {
220
+            $content[] = [
221
+                'name'            => $value['name'],
222
+                'field'           => $value['field'],
223
+                'read'            => 1,
224
+                'read_operation'  => in_array($value['field'], ['name', 'next_time']) ? 0 : 1,
225
+                'write'           => 1,
226
+                'write_operation' => $value['field'] == 'next_time' ? 0 : 1,
227
+                'is_diy'          => 1
228
+            ];
229
+        }
230
+
231
+        # 处理固定字段
232
+        $content[] = ['name' => '负责人', 'field' => 'owner_user_id', 'read' => 1, 'read_operation' => 0, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
233
+        $content[] = ['name' => '最后跟进记录', 'field' => 'record', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
234
+        $content[] = ['name' => '创建人', 'field' => 'create_user_id', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
235
+        $content[] = ['name' => '创建时间', 'field' => 'create_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
236
+        $content[] = ['name' => '更新时间', 'field' => 'update_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
237
+
238
+        Db::name('admin_field_grant')->insert([
239
+            'role_id'     => $roleId,
240
+            'module'      => 'crm',
241
+            'column'      => 'leads',
242
+            'content'     => serialize($content),
243
+            'create_time' => time(),
244
+            'update_time' => time()
245
+        ]);
246
+    }
247
+
248
+    /**
249
+     * 添加客户字段授权数据
250
+     *
251
+     * @param $roleId
252
+     * @throws \think\db\exception\DataNotFoundException
253
+     * @throws \think\db\exception\ModelNotFoundException
254
+     * @throws \think\exception\DbException
255
+     */
256
+    private function createCustomerFieldGrant($roleId)
257
+    {
258
+        $content = [];
259
+
260
+        $customerList = Db::name('admin_field')->field(['name', 'field'])->where('types', 'crm_customer')->select();
261
+
262
+        # 处理自定义字段
263
+        foreach ($customerList AS $key => $value) {
264
+            $content[] = [
265
+                'name'            => $value['name'],
266
+                'field'           => $value['field'],
267
+                'read'            => 1,
268
+                'read_operation'  => in_array($value['field'], ['name', 'deal_status']) ? 0 : 1,
269
+                'write'           => 1,
270
+                'write_operation' => $value['field'] == 'deal_status' ? 0 : 1,
271
+            ];
272
+        }
273
+
274
+        # 处理固定字段
275
+        $content[] = ['name' => '合同编号', 'field' => 'contract', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0];
276
+        $content[] = ['name' => '负责人', 'field' => 'owner_user_id', 'read' => 1, 'read_operation' => 0, 'write' => 0, 'write_operation' => 0];
277
+        $content[] = ['name' => '最后跟进记录', 'field' => 'record', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0];
278
+        $content[] = ['name' => '创建人', 'field' => 'create_user_id', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0];
279
+        $content[] = ['name' => '创建时间', 'field' => 'create_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0];
280
+        $content[] = ['name' => '更新时间', 'field' => 'update_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0];
281
+        $content[] = ['name' => '最后跟进时间', 'field' => 'record_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0];
282
+        $content[] = ['name' => '负责人获取客户时间', 'field' => 'deal_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0];
283
+        $content[] = ['name' => '成交状态', 'field' => 'deal_status', 'read' => 1, 'read_operation' => 0, 'write' => 0, 'write_operation' => 0];
284
+        $content[] = ['name' => '锁定状态', 'field' => 'is_lock', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0];
285
+        $content[] = ['name' => '距进入公海天数', 'field' => 'pool_day', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0];
286
+
287
+        Db::name('admin_field_grant')->insert([
288
+            'role_id'     => $roleId,
289
+            'module'      => 'crm',
290
+            'column'      => 'customer',
291
+            'content'     => serialize($content),
292
+            'create_time' => time(),
293
+            'update_time' => time()
294
+        ]);
295
+    }
296
+
297
+    /**
298
+     * 添加联系人字段授权数据
299
+     *
300
+     * @param $roleId
301
+     * @throws \think\db\exception\DataNotFoundException
302
+     * @throws \think\db\exception\ModelNotFoundException
303
+     * @throws \think\exception\DbException
304
+     */
305
+    private function createContactsFieldGrant($roleId)
306
+    {
307
+        $content = [];
308
+
309
+        $contactsList = Db::name('admin_field')->field(['name', 'field'])->where('types', 'crm_contacts')->select();
310
+
311
+        # 处理自定义字段
312
+        foreach ($contactsList AS $key => $value) {
313
+            $content[] = [
314
+                'name'            => $value['name'],
315
+                'field'           => $value['field'],
316
+                'read'            => 1,
317
+                'read_operation'  => in_array($value['field'], ['name', 'next_time']) ? 0 : 1,
318
+                'write'           => 1,
319
+                'write_operation' => $value['field'] == 'next_time' ? 0 : 1,
320
+                'is_diy'          => 1
321
+            ];
322
+        }
323
+
324
+        # 处理固定字段
325
+        $content[] = ['name' => '创建人', 'field' => 'create_user_id', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
326
+        $content[] = ['name' => '负责人', 'field' => 'owner_user_id', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
327
+        $content[] = ['name' => '创建时间', 'field' => 'create_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
328
+        $content[] = ['name' => '更新时间', 'field' => 'update_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
329
+
330
+        Db::name('admin_field_grant')->insert([
331
+            'role_id'     => $roleId,
332
+            'module'      => 'crm',
333
+            'column'      => 'contacts',
334
+            'content'     => serialize($content),
335
+            'create_time' => time(),
336
+            'update_time' => time()
337
+        ]);
338
+    }
339
+
340
+    /**
341
+     * 添加商机字段授权数据
342
+     *
343
+     * @param $roleId
344
+     * @throws \think\db\exception\DataNotFoundException
345
+     * @throws \think\db\exception\ModelNotFoundException
346
+     * @throws \think\exception\DbException
347
+     */
348
+    private function createBusinessFieldGrant($roleId)
349
+    {
350
+        $content = [];
351
+
352
+        $BusinessList = Db::name('admin_field')->field(['name', 'field'])->where('types', 'crm_business')->select();
353
+
354
+        # 处理自定义字段
355
+        foreach ($BusinessList AS $key => $value) {
356
+            $content[] = [
357
+                'name'            => $value['name'],
358
+                'field'           => $value['field'],
359
+                'read'            => 1,
360
+                'read_operation'  => in_array($value['field'], ['customer_id', 'type_id', 'status_id']) == '' ? 0 : 1,
361
+                'write'           => 1,
362
+                'write_operation' => in_array($value['field'], ['customer_id', 'type_id', 'status_id']) ? 0 : 1,
363
+                'is_diy'          => 1
364
+            ];
365
+        }
366
+
367
+        # 处理固定字段
368
+        $content[] = ['name' => '整单折扣', 'field' => 'discount_rate', 'read' => 1, 'read_operation' => 1, 'write' => 1, 'write_operation' => 1, 'is_diy' => 0];
369
+        $content[] = ['name' => '创建人', 'field' => 'create_user_id', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
370
+        $content[] = ['name' => '负责人', 'field' => 'owner_user_id', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
371
+        $content[] = ['name' => '创建时间', 'field' => 'create_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
372
+        $content[] = ['name' => '更新时间', 'field' => 'update_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
373
+
374
+        Db::name('admin_field_grant')->insert([
375
+            'role_id'     => $roleId,
376
+            'module'      => 'crm',
377
+            'column'      => 'business',
378
+            'content'     => serialize($content),
379
+            'create_time' => time(),
380
+            'update_time' => time()
381
+        ]);
382
+    }
383
+
384
+    /**
385
+     * 添加合同字段授权数据
386
+     *
387
+     * @param $roleId
388
+     * @throws \think\db\exception\DataNotFoundException
389
+     * @throws \think\db\exception\ModelNotFoundException
390
+     * @throws \think\exception\DbException
391
+     */
392
+    private function createContractfieldGrant($roleId)
393
+    {
394
+        $content = [];
395
+
396
+        $contractList = Db::name('admin_field')->field(['name', 'field'])->where('types', 'crm_contract')->select();
397
+
398
+        # 处理自定义字段
399
+        foreach ($contractList AS $key => $value) {
400
+            $content[] = [
401
+                'name'            => $value['name'],
402
+                'field'           => $value['field'],
403
+                'read'            => 1,
404
+                'read_operation'  => $value['field'] == 'num' ? 0 : 1,
405
+                'write'           => 1,
406
+                'write_operation' => 1,
407
+                'is_diy'          => 1
408
+            ];
409
+        }
410
+
411
+        # 处理固定字段
412
+        $content[] = ['name' => '创建人', 'field' => 'create_user_id', 'read' => 1, 'read_operation' => 0, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
413
+        $content[] = ['name' => '负责人', 'field' => 'owner_user_id', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
414
+        $content[] = ['name' => '创建时间', 'field' => 'create_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
415
+        $content[] = ['name' => '更新时间', 'field' => 'update_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
416
+        $content[] = ['name' => '最后跟进记录', 'field' => 'record', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
417
+        $content[] = ['name' => '最后跟进记录', 'field' => 'record_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
418
+        $content[] = ['name' => '已收款金额', 'field' => 'received', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
419
+        $content[] = ['name' => '未收款金额', 'field' => 'uncollected', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
420
+        $content[] = ['name' => '审核状态', 'field' => 'check_status', 'read' => 1, 'read_operation' => 0, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
421
+
422
+        Db::name('admin_field_grant')->insert([
423
+            'role_id'     => $roleId,
424
+            'module'      => 'crm',
425
+            'column'      => 'contract',
426
+            'content'     => serialize($content),
427
+            'create_time' => time(),
428
+            'update_time' => time()
429
+        ]);
430
+    }
431
+
432
+    /**
433
+     * 添加回款字段授权数据
434
+     *
435
+     * @param $roleId
436
+     * @throws \think\db\exception\DataNotFoundException
437
+     * @throws \think\db\exception\ModelNotFoundException
438
+     * @throws \think\exception\DbException
439
+     */
440
+    private function createReceivablesFieldGrant($roleId)
441
+    {
442
+        $content = [];
443
+
444
+        $receivablesList = Db::name('admin_field')->field(['name', 'field'])->where('types', 'crm_receivables')->select();
445
+
446
+        # 处理自定义字段
447
+        foreach ($receivablesList AS $key => $value) {
448
+            $content[] = [
449
+                'name'            => $value['name'],
450
+                'field'           => $value['field'],
451
+                'read'            => 1,
452
+                'read_operation'  => 1,
453
+                'write'           => 1,
454
+                'write_operation' => 1,
455
+                'is_diy'          => 1
456
+            ];
457
+        }
458
+
459
+        # 处理固定字段
460
+        $content[] = ['name' => '合同金额', 'field' => 'create_user_id', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
461
+        $content[] = ['name' => '创建人', 'field' => 'create_user_id', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
462
+        $content[] = ['name' => '负责人', 'field' => 'owner_user_id', 'read' => 1, 'read_operation' => 0, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
463
+        $content[] = ['name' => '创建时间', 'field' => 'create_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
464
+        $content[] = ['name' => '更新时间', 'field' => 'update_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
465
+        $content[] = ['name' => '审核状态', 'field' => 'check_status', 'read' => 1, 'read_operation' => 0, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
466
+
467
+        Db::name('admin_field_grant')->insert([
468
+            'role_id'     => $roleId,
469
+            'module'      => 'crm',
470
+            'column'      => 'receivables',
471
+            'content'     => serialize($content),
472
+            'create_time' => time(),
473
+            'update_time' => time()
474
+        ]);
475
+    }
476
+
477
+    /**
478
+     * 添加产品字段授权信息
479
+     *
480
+     * @param $roleId
481
+     * @throws \think\db\exception\DataNotFoundException
482
+     * @throws \think\db\exception\ModelNotFoundException
483
+     * @throws \think\exception\DbException
484
+     */
485
+    private function createProductFieldGrant($roleId)
486
+    {
487
+        $content = [];
488
+
489
+        $productList = Db::name('admin_field')->field(['name', 'field'])->where('types', 'crm_product')->select();
490
+
491
+        # 处理自定义字段
492
+        foreach ($productList AS $key => $value) {
493
+            $readOperation  = 1;
494
+            $writeOperation = 1;
495
+
496
+            if (in_array($value['field'], ['name', 'category_id', 'unit', 'price', 'status'])) $readOperation = 0;
497
+            if (in_array($value['field'], ['status'])) $writeOperation = 0;
498
+
499
+            $content[] = [
500
+                'name'            => $value['name'],
501
+                'field'           => $value['field'],
502
+                'read'            => 1,
503
+                'read_operation'  => $readOperation,
504
+                'write'           => 1,
505
+                'write_operation' => $writeOperation,
506
+                'is_diy'          => 1
507
+            ];
508
+        }
509
+
510
+        # 处理固定字段
511
+        $content[] = ['name' => '负责人', 'field' => 'owner_user_id', 'read' => 1, 'read_operation' => 0, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
512
+        $content[] = ['name' => '创建人', 'field' => 'create_user_id', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
513
+        $content[] = ['name' => '创建时间', 'field' => 'create_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
514
+        $content[] = ['name' => '更新时间', 'field' => 'update_time', 'read' => 1, 'read_operation' => 1, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
515
+
516
+        Db::name('admin_field_grant')->insert([
517
+            'role_id'     => $roleId,
518
+            'module'      => 'crm',
519
+            'column'      => 'product',
520
+            'content'     => serialize($content),
521
+            'create_time' => time(),
522
+            'update_time' => time()
523
+        ]);
524
+    }
525
+
526
+    /**
527
+     * 添加回访字段授权信息
528
+     *
529
+     * @param $roleId
530
+     * @throws \think\db\exception\DataNotFoundException
531
+     * @throws \think\db\exception\ModelNotFoundException
532
+     * @throws \think\exception\DbException
533
+     */
534
+    private function createVisitFieldGrant($roleId)
535
+    {
536
+        $content = [];
537
+
538
+        $visitList = Db::name('admin_field')->field(['name', 'field'])->where('types', 'crm_visit')->select();
539
+
540
+        # 处理自定义字段
541
+        foreach ($visitList AS $key => $value) {
542
+            $content[] = [
543
+                'name'            => $value['name'],
544
+                'field'           => $value['field'],
545
+                'read'            => 1,
546
+                'read_operation'  => 1,
547
+                'write'           => 1,
548
+                'write_operation' => 1,
549
+                'is_diy'          => 1
550
+            ];
551
+        }
552
+
553
+        # 处理固定字段
554
+//        $content[] = ['name' => '回访时间', 'field' => 'visit_time', 'read' => 1, 'read_operation' => 1, 'write' => 1, 'write_operation' => 1, 'is_diy' => 0];
555
+        $content[] = ['name' => '负责人', 'field' => 'owner_user_id', 'read' => 1, 'read_operation' => 0, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
556
+        $content[] = ['name' => '客户', 'field' => 'customer_id', 'read' => 1, 'read_operation' => 0, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
557
+        $content[] = ['name' => '联系人', 'field' => 'contract_id', 'read' => 1, 'read_operation' => 1, 'write' => 1, 'write_operation' => 1, 'is_diy' => 0];
558
+        $content[] = ['name' => '创建时间', 'field' => 'create_time', 'read' => 1, 'read_operation' => 0, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
559
+        $content[] = ['name' => '编辑时间', 'field' => 'update_time', 'read' => 1, 'read_operation' => 0, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
560
+        $content[] = ['name' => '创建人', 'field' => 'create_user_id', 'read' => 1, 'read_operation' => 0, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
561
+        $content[] = ['name' => '合同', 'field' => 'contacts_id', 'read' => 1, 'read_operation' => 0, 'write' => 0, 'write_operation' => 0, 'is_diy' => 0];
562
+
563
+        Db::name('admin_field_grant')->insert([
564
+            'role_id'     => $roleId,
565
+            'module'      => 'crm',
566
+            'column'      => 'visit',
567
+            'content'     => serialize($content),
568
+            'create_time' => time(),
569
+            'update_time' => time()
570
+        ]);
571
+    }
572
+}

+ 996
- 0
application/admin/logic/InitializeLogic.php
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 218
- 0
application/admin/logic/LogLogic.php Целия файл

@@ -0,0 +1,218 @@
1
+<?php
2
+/**
3
+ * 日志逻辑类
4
+ *
5
+ * @author qifan
6
+ * @date 2020-11-30
7
+ */
8
+
9
+namespace app\admin\logic;
10
+
11
+use app\admin\model\LoginRecord;
12
+use app\admin\model\OperationLog;
13
+use app\admin\model\SystemLog;
14
+
15
+class LogLogic
16
+{
17
+    /**
18
+     * 数据操作日志中的模块对应的中文名称
19
+     *
20
+     * @var string[]
21
+     */
22
+    public $recordModules = [
23
+        'crm_leads'       => '线索',
24
+        'crm_customer'    => '客户',
25
+        'crm_pool'        => '客户公海',
26
+        'crm_contacts'    => '联系人',
27
+        'crm_product'     => '产品',
28
+        'crm_business'    => '商机',
29
+        'crm_contract'    => '合同',
30
+        'crm_receivables' => '回款',
31
+        'crm_visit'       => '回访',
32
+        'crm_invoice'     => '回款',
33
+        'oa_log'          => '办公日志',
34
+        'oa_examine'      => '办公审批',
35
+        'work_task'       => '任务',
36
+        'work'            => '项目',
37
+        'label'           => '标签',
38
+        'calendar'        => '日历'
39
+    ];
40
+
41
+    public $systemModules = [
42
+        'company'     => '企业首页',
43
+        'application' => '应用管理',
44
+        'structures'  => '部门管理',
45
+        'employee'    => '员工管理',
46
+        'role'        => '角色管理',
47
+        'approval'    => '审批流程管理',
48
+        'workbench'   => '工作台',
49
+        'project'     => '项目管理',
50
+        'customer'    => '客户管理'
51
+    ];
52
+
53
+    /**
54
+     * 日志记录中的行为所对应的中文名称
55
+     *
56
+     * @var string[]
57
+     */
58
+    private $action = [
59
+        'index'  => '查看数据',
60
+        'save'   => '添加数据',
61
+        'update' => '编辑数据',
62
+        'delete' => '删除数据'
63
+    ];
64
+    private $loginType = [
65
+        '成功', '密码错误', '账号禁用'
66
+    ];
67
+    /**
68
+     * 登录日志
69
+     *
70
+     * @param $param
71
+     * @return array
72
+     * @throws \think\exception\DbException
73
+     */
74
+    public function getLoginRecord($param)
75
+    {
76
+        $loginRecordModel = new LoginRecord();
77
+
78
+        $limit = !empty($param['limit']) ? $param['limit'] : 15;
79
+
80
+        $data  = $loginRecordModel->where(function ($query) use ($param) {
81
+            if (!empty($param['startTime'])) $query->where('create_time', '>=', strtotime($param['startTime']));
82
+            if (!empty($param['endTime'])) $query->where('create_time', '<=', strtotime($param['endTime']));
83
+            if (!empty($param['userIds'])) $query->whereIn('create_user_id', $param['userIds']);
84
+        })->order('id', 'desc')->paginate($limit)->each(function ($value) {
85
+            $value['username']  = $value->create_user_info['realname'];
86
+            $value['type'] = $this->loginType[$value['type']];
87
+        })->toArray();
88
+
89
+        return ['list' => $data['data'], 'count' => $data['total']];
90
+    }
91
+
92
+
93
+
94
+    /**
95
+     * 获取系统操作日志列表
96
+     *
97
+     * @param $param 查询条件、分页参数
98
+     * @return bool|\PDOStatement|string|\think\Collection
99
+     * @throws \think\db\exception\DataNotFoundException
100
+     * @throws \think\db\exception\ModelNotFoundException
101
+     * @throws \think\exception\DbException
102
+     */
103
+    public function getSystemLogs($param)
104
+    {
105
+        $data = SystemLog::with(['toAdminUser'])
106
+            ->where(function ($query) use ($param) {
107
+                if (!empty($param['startTime'])) $query->where('create_time', '>=', strtotime($param['startTime']));
108
+                if (!empty($param['endTime']))   $query->where('create_time', '<=', strtotime($param['endTime']));
109
+                if (!empty($param['modules']))   $query->whereIn('modules', $param['modules']);
110
+                if (!empty($param['userIds']))   $query->whereIn('user_id', $param['userIds']);
111
+            })->limit(($param['page'] - 1) * $param['limit'])->order('log_id', 'desc')->select();
112
+
113
+        return $this->setSystemData($data);
114
+    }
115
+
116
+    /**
117
+     * 获取系统操作日志总数
118
+     *
119
+     * @param $param 查询条件、分页参数
120
+     * @return int|string|null
121
+     */
122
+    public function getSystemLogCount($param)
123
+    {
124
+        return SystemLog::where(function ($query) use ($param) {
125
+            if (!empty($param['startTime'])) $query->where('create_time', '>=', strtotime($param['startTime']));
126
+            if (!empty($param['endTime'])) $query->where('create_time', '<=', strtotime($param['endTime']));
127
+            if (!empty($param['modules'])) $query->whereIn('controller_name', $param['modules']);
128
+            if (!empty($param['userIds'])) $query->whereIn('user_id', $param['userIds']);
129
+        })->count();
130
+    }
131
+
132
+    /**
133
+     * 获取数据操作日志列表
134
+     *
135
+     * @param $param 查询条件、分页参数
136
+     * @return bool|\PDOStatement|string|\think\Collection
137
+     * @throws \think\db\exception\DataNotFoundException
138
+     * @throws \think\db\exception\ModelNotFoundException
139
+     * @throws \think\exception\DbException
140
+     */
141
+    public function getRecordLogs($param)
142
+    {
143
+        $data = OperationLog::with(['toAdminUser'])
144
+            ->where(function ($query) use ($param) {
145
+                if (!empty($param['startTime'])) $query->where('create_time', '>=', strtotime($param['startTime']));
146
+                if (!empty($param['endTime']))   $query->where('create_time', '<=', strtotime($param['endTime']));
147
+                if (!empty($param['modules']))   $query->whereIn('module', $param['modules']);
148
+                if (!empty($param['userIds']))   $query->whereIn('user_id', $param['userIds']);
149
+            })
150
+            ->limit(($param['page'] - 1) * $param['limit'])->order('log_id', 'desc')->select();
151
+
152
+        return $this->setRecordData($data);
153
+    }
154
+
155
+    /**
156
+     * 获取数据操作日志总数
157
+     *
158
+     * @param $param 查询条件、分页参数
159
+     * @return int|string|null
160
+     */
161
+    public function getRecordLogCount($param)
162
+    {
163
+        return OperationLog::where(function ($query) use ($param) {
164
+            if (!empty($param['startTime'])) $query->where('create_time', '>=', strtotime($param['startTime']));
165
+            if (!empty($param['endTime'])) $query->where('create_time', '<=', strtotime($param['endTime']));
166
+            if (!empty($param['modules'])) $query->whereIn('module', $param['module']);
167
+            if (!empty($param['userIds'])) $query->whereIn('user_id', $param['userIds']);
168
+        })->count();
169
+    }
170
+
171
+    /**
172
+     * 组装数据操作日志数据
173
+     *
174
+     * @param $data
175
+     * @return mixed
176
+     */
177
+    private function setRecordData($data)
178
+    {
179
+        $result = [];
180
+
181
+        foreach ($data AS $key => $value) {
182
+            $result[] = [
183
+                'log_id'      => $value['log_id'],
184
+                'source_name' => $value['source_name'],
185
+                'create_time' => date('Y-m-d H:i:s', $value['create_time']),
186
+                'ip'          => $value['client_ip'],
187
+                'module'      => $this->recordModules[$value['module']],
188
+                'content'     => $value['content']
189
+            ];
190
+        }
191
+
192
+        return $result;
193
+    }
194
+
195
+    /**
196
+     * 组装数据操作日志数据
197
+     *
198
+     * @param $data
199
+     * @return mixed
200
+     */
201
+    private function setSystemData($data)
202
+    {
203
+        $result = [];
204
+
205
+        foreach ($data AS $key => $value) {
206
+            $result[] = [
207
+                'log_id'      => $value['log_id'],
208
+                'source_name' => $value['source_name'],
209
+                'create_time' => date('Y-m-d H:i:s', $value['create_time']),
210
+                'ip'          => $value['client_ip'],
211
+                'module'      => $this->systemModules[$value['module']],
212
+                'content'     => $value['content']
213
+            ];
214
+        }
215
+
216
+        return $result;
217
+    }
218
+}

+ 282
- 0
application/admin/logic/MessageLogic.php Целия файл

@@ -0,0 +1,282 @@
1
+<?php
2
+
3
+namespace app\admin\logic;
4
+
5
+use think\Db;
6
+
7
+class MessageLogic
8
+{
9
+    private function label($label)
10
+    {
11
+        $where = '';
12
+        switch ($label) {
13
+
14
+            case '1':  //任务
15
+                $where = array('in', [1, 2, 3]);//
16
+                break;
17
+            case '2':  //日志
18
+                $where = array('in', [4, 5]);//27项目导入
19
+                break;
20
+            case '3':  //办公审批
21
+                $where = array('in', [6, 7, 8]);
22
+                break;
23
+            case '4':  //公告
24
+                $where = array('eq', 9);
25
+                break;
26
+            case '5' :  //日程
27
+                $where = 10;
28
+                break;
29
+            case '6' :  //客户管理
30
+                $where = array('in', [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 16, 27, 28, 29, 30]);
31
+                break;
32
+            case '4' :
33
+                break;
34
+            default:
35
+                $where = array('in', [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 16, 27, 28, 29, 30]);//17181920
36
+        }
37
+        return $where;
38
+    }
39
+
40
+    public function getDataList($param)
41
+    {
42
+        $userId = $param['user_id'];
43
+        unset($param['user_id']);
44
+        //types 1表示已读 0表示未读
45
+        if (isset($param['is_read'])) {
46
+            $where['m.read_time'] = ['=', 0];
47
+        }
48
+        $where['m.to_user_id'] = $userId;
49
+        $where['m.is_delete'] = ['eq', 1];
50
+        $order = [
51
+            'm.send_time' => 'DESC',
52
+        ];
53
+        $where['m.type'] = $this->label($param['label']);
54
+        if ($param['label'] == 4) {
55
+            $where['m.type'] = 9;
56
+            $list = db('admin_message')
57
+                ->alias('m')
58
+                ->join('__ADMIN_USER__ user', 'user.id=m.from_user_id', 'LEFT')
59
+                ->where($where)
60
+                ->field('m.*,user.realname as user_name')
61
+                ->page($param['page'], $param['limit'])
62
+                ->order($order)
63
+                ->select();
64
+            $dataCount = db('admin_message')
65
+                ->alias('m')
66
+                ->join('__ADMIN_USER__ user', 'user.id=m.from_user_id', 'LEFT')
67
+                ->where($where)->count();
68
+        } else {
69
+            $list = db('admin_message')
70
+                ->alias('m')
71
+                ->join('__ADMIN_USER__ user', 'user.id=m.from_user_id', 'LEFT')
72
+                ->where($where)
73
+                ->field('m.*,user.realname as user_name')
74
+                ->page($param['page'], $param['limit'])
75
+                ->order($order)
76
+                ->select();
77
+        }
78
+        $dataCount = db('admin_message')
79
+            ->alias('m')
80
+            ->join('__ADMIN_USER__ user', 'user.id=m.from_user_id', 'LEFT')
81
+            ->where($where)->count();
82
+        //1表示已读 0表示未读
83
+        foreach ($list as $k => $v) {
84
+            if ($v['read_time'] == 0) {
85
+                $list[$k]['is_read'] = 0;
86
+            } else {
87
+                $list[$k]['is_read'] = 1;
88
+            }
89
+            $list[$k]['create_time'] = date('Y-m-d H:i:s', $v['send_time']);
90
+            if ($v['type'] == 4) {
91
+                $content = db('admin_comment')
92
+                    ->where(
93
+                        [   'status' => 1,
94
+                            'comment_id' => $v['action_id'],
95
+                            'type' => ['like', '%' . $v['controller_name' . '%']],
96
+                            'user_id' => $v['from_user_id']
97
+                        ])
98
+                    ->find();
99
+                if (!empty($content)) {
100
+                    $list[$k]['content'] = $content['content'];
101
+                }
102
+            } elseif (in_array($v['type'], ['12', '15'])) {
103
+                $content = db('admin_examine_record')->where(['types_id' => $v['action_id'], 'types' => ['like', '%' . $v['controller_name' . '%']], 'check_user_id' => $v['from_user_id']])->field('content')->find();
104
+                if ($content['content']) {
105
+                    $list[$k]['content'] = $content['content'];
106
+                }
107
+            }
108
+            if ($v['type'] == 10) {
109
+                    $item = db('oa_event_notice')->where('id', $v['action_id'])->find();
110
+
111
+                    if ($item) {
112
+                        $noticetype = $item['noticetype'];
113
+                        if($item['noticetype'] == 1){
114
+                            $advance_time =$v['advance_time'] - ($item['number'] * 60);
115
+                        }elseif ($item['noticetype'] == 2){
116
+                            $advance_time =$v['advance_time'] - ($item['number'] * 60 * 60);
117
+                        }else{
118
+                            $advance_time = $v['advance_time'] - ($item['number'] * 60 * 60 * 24);
119
+                        }
120
+
121
+                        $time = time();
122
+                        if ($time == $advance_time ||$time>$advance_time) {
123
+                            $type['value']=$item['number'];
124
+                            $type['type']=$item['noticetype'];
125
+                            $list[$k]['content']= $type;
126
+                            $list[$k]['action_id'] = $item['event_id'];
127
+                        }
128
+                    }
129
+//                p(222);
130
+            }
131
+            if (in_array($v['type'], ['17', '18', '19', '20', '27'])) {
132
+                $error_file_path = db('admin_import_record')->where('id', $v['action_id'])->find();
133
+                if($error_file_path['error_data_file_path']==''){
134
+                    $list[$k]['title'] = '';
135
+                }
136
+                $list[$k]['error_file_path'] = $error_file_path['error_data_file_path'];
137
+            }
138
+        }
139
+        $data = [];
140
+        $data['page']['list'] = $list;
141
+        $data['page']['dataCount'] = $dataCount ?: 0;
142
+        if ($param['page'] != 1 && ($param['page'] * $param['limit']) >= $dataCount) {
143
+            $data['page']['firstPage'] = false;
144
+            $data['page']['lastPage'] = true;
145
+        } else if ($param['page'] != 1 && (int)($param['page'] * $param['limit']) < $dataCount) {
146
+            $data['page']['firstPage'] = false;
147
+            $data['page']['lastPage'] = false;
148
+        } else if ($param['page'] == 1) {
149
+            $data['page']['firstPage'] = true;
150
+            $data['page']['lastPage'] = false;
151
+        }
152
+        return $data;
153
+    }
154
+
155
+    /**
156
+     * 修改状态变为已读
157
+     * @param $param
158
+     * @return array
159
+     * @throws \think\Exception
160
+     * @throws \think\exception\PDOException
161
+     */
162
+    public function endMessage($param)
163
+    {
164
+        $where = [
165
+            'to_user_id' => $param['id'],
166
+            'message_id' => ['IN', (array)$param['message_id']],
167
+            'read_time' => 0,
168
+        ];
169
+        $list = db('admin_message')
170
+            ->where($where)
171
+            ->update(['read_time' => time()]);
172
+        $data = [];
173
+        $data['list'] = $list;
174
+        return $data;
175
+    }
176
+
177
+    /**
178
+     * 删除
179
+     *
180
+     * @param $messageId
181
+     * @return array|int|string
182
+     * @throws \think\Exception
183
+     * @throws \think\exception\PDOException
184
+     */
185
+    public function delete($param)
186
+    {
187
+        $res = db('admin_message')->where(['message_id' => $param['message_id']])->find();
188
+        if ($res['to_user_id'] != $param['user_id']) {
189
+            return resultArray(['error' => '没有权限!']);
190
+        }
191
+        return db('admin_message')->where(['message_id' => $param['message_id']])->update(['is_delete' => 2]);
192
+    }
193
+
194
+    /**
195
+     * 批量更新
196
+     * @param $param
197
+     * @return array
198
+     * @throws \think\Exception
199
+     * @throws \think\exception\PDOException
200
+     */
201
+    public function readAllMessage($param)
202
+    {
203
+
204
+        $where = [
205
+            'to_user_id' => $param['user_id'],
206
+            'read_time' => 0
207
+        ];
208
+        if ($param['label'] == 4) {
209
+            $list = db('admin_message')
210
+                ->where('type', 9)
211
+                ->where($where)
212
+                ->update(['read_time' => time()]);
213
+        } else {
214
+            $where['type'] = $this->label($param['label']);
215
+            $list = db('admin_message')
216
+                ->where($where)
217
+                ->update(['read_time' => time()]);
218
+        }
219
+        $data = [];
220
+        $data['list'] = $list;
221
+        return $data;
222
+    }
223
+
224
+    /**
225
+     * 批量删除已读
226
+     * @param $param
227
+     * @return array
228
+     * @throws \think\Exception
229
+     * @throws \think\exception\PDOException
230
+     */
231
+    public function clear($param)
232
+    {
233
+        $where = [];
234
+        $where = [
235
+            'to_user_id' => $param['user_id'],
236
+            'is_delete' => 1,
237
+            'read_time' => ['neq', 0],
238
+        ];
239
+        $where['type'] = $this->label($param['label']);
240
+        $list = db('admin_message')
241
+            ->where($where)
242
+            ->update(['is_delete' => 2]);
243
+        $data = [];
244
+        $data['list'] = $list;
245
+        return $data;
246
+    }
247
+
248
+    public function unreadCount($param)
249
+    {
250
+        $userId = $param['user_id'];
251
+        //types 1表示已读 0表示未读
252
+        $where['read_time'] = ['=', 0];
253
+        $label = '';
254
+        $where['to_user_id'] = ['eq', $userId];
255
+        $where['is_delete'] = ['eq', 1];
256
+
257
+        $where['type'] = $this->label('');
258
+        $allCount = db('admin_message')->where($where)->count();
259
+        $where['type'] = $this->label(1);
260
+        $taskCount = db('admin_message')->where($where)->count();
261
+        $where['type'] = $this->label(2);
262
+        $logCount = db('admin_message')->where($where)->count();
263
+        $where['type'] = $this->label(3);
264
+        $jxcCount = db('admin_message')->where($where)->count();
265
+        $where['type'] = 9;
266
+        $announceCount = db('admin_message')->where($where)->count();
267
+        $where['type'] = $this->label(5);
268
+        $eventCount = db('admin_message')->where($where)->where('advance_time', '>=', time())->count();
269
+        $where['type'] = $this->label(6);
270
+        $crmCount = db('admin_message')->where($where)->count();
271
+
272
+        $data = [];
273
+        $data['allCount'] = $allCount ?: 0;
274
+        $data['taskCount'] = $taskCount ?: 0;
275
+        $data['logCount'] = $logCount ?: 0;
276
+        $data['examineCount'] = $jxcCount ?: 0;
277
+        $data['announceCount'] = $announceCount ?: 0;
278
+        $data['eventCount'] = $eventCount ?: 0;
279
+        $data['crmCount'] = $crmCount ?: 0;
280
+        return $data;
281
+    }
282
+}

+ 377
- 0
application/admin/logic/PrintingLogic.php Целия файл

@@ -0,0 +1,377 @@
1
+<?php
2
+/**
3
+ * 打印设置逻辑类
4
+ *
5
+ * @author qifan
6
+ * @date 2020-12-03
7
+ */
8
+
9
+namespace app\admin\logic;
10
+
11
+use app\admin\controller\ApiCommon;
12
+use think\Db;
13
+
14
+class PrintingLogic
15
+{
16
+    /**
17
+     * 打印模板列表
18
+     *
19
+     * @param $page
20
+     * @param $limit
21
+     * @return array
22
+     * @throws \think\db\exception\DataNotFoundException
23
+     * @throws \think\db\exception\ModelNotFoundException
24
+     * @throws \think\exception\DbException
25
+     */
26
+    public function index($page, $limit)
27
+    {
28
+        $result = [];
29
+        $type   = [1 => '商机', 2 => '合同', 3 => '回款'];
30
+        $field  = ['id', 'name', 'type', 'user_name', 'create_time', 'update_time'];
31
+        $count  = Db::name('admin_printing')->count();
32
+        $data   = Db::name('admin_printing')->field($field)->order('id', 'desc')->limit(($page - 1) * $limit, $limit)->select();
33
+
34
+        foreach ($data AS $key => $value) {
35
+            $result[] = [
36
+                'id'          => $value['id'],
37
+                'name'        => $value['name'],
38
+                'type'        => $value['type'],
39
+                'type_name'   => !empty($type[$value['type']]) ? $type[$value['type']] : '',
40
+                'create_time' => date('Y-m-d H:i:s', $value['create_time']),
41
+                'user_name'   => $value['user_name'],
42
+                'update_time' => date('Y-m-d H:i:s', $value['update_time'])
43
+            ];
44
+        }
45
+
46
+        return ['count' => $count, 'list' => $result];
47
+    }
48
+
49
+    /**
50
+     * 创建打印模板
51
+     *
52
+     * @param $param
53
+     * @return int|string
54
+     */
55
+    public function create($param)
56
+    {
57
+        $apiCommon = new ApiCommon();
58
+        $userId   = $apiCommon->userInfo['id'];
59
+        $userName = Db::name('admin_user')->where('id', $userId)->value('realname');
60
+
61
+        $data = [
62
+            'user_id'     => $userId,
63
+            'user_name'   => $userName,
64
+            'name'        => $param['name'],
65
+            'type'        => $param['type'],
66
+            'content'     => htmlspecialchars($param['content']),
67
+            'create_time' => time(),
68
+            'update_time' => time()
69
+        ];
70
+
71
+        return Db::name('admin_printing')->insert($data);
72
+    }
73
+
74
+    /**
75
+     * 获取模板详情
76
+     *
77
+     * @param $id
78
+     * @return array
79
+     */
80
+    public function read($id)
81
+    {
82
+        $content = Db::name('admin_printing')->where('id', $id)->value('content');
83
+
84
+        return ['id' => $id, 'content' => htmlspecialchars_decode($content)];
85
+    }
86
+
87
+    /**
88
+     * 更新模板数据
89
+     *
90
+     * @param $param
91
+     * @return int|string
92
+     * @throws \think\Exception
93
+     * @throws \think\exception\PDOException
94
+     */
95
+    public function update($param)
96
+    {
97
+        if (!empty($param['content'])) $param['content'] = htmlspecialchars($param['content']);
98
+
99
+        return Db::name('admin_printing')->update($param);
100
+    }
101
+
102
+    /**
103
+     * 删除模板数据
104
+     *
105
+     * @param $id
106
+     * @return int
107
+     * @throws \think\Exception
108
+     * @throws \think\exception\PDOException
109
+     */
110
+    public function delete($id)
111
+    {
112
+        return Db::name('admin_printing')->where('id', $id)->delete();
113
+    }
114
+
115
+    /**
116
+     * 复制模板数据
117
+     *
118
+     * @param $id
119
+     * @return false|int|string
120
+     * @throws \think\db\exception\DataNotFoundException
121
+     * @throws \think\db\exception\ModelNotFoundException
122
+     * @throws \think\exception\DbException
123
+     */
124
+    public function copy($id)
125
+    {
126
+        $apiCommon = new ApiCommon();
127
+        $info = Db::name('admin_printing')->where('id', $id)->find();
128
+
129
+        if (!empty($info['id'])) {
130
+            $userId   = $apiCommon->userInfo['id'];
131
+            $userName = Db::name('admin_user')->where('id', $userId)->value('realname');
132
+
133
+            $data = [
134
+                'user_id'     => $userId,
135
+                'user_name'   => $userName,
136
+                'name'        => strlen($info['name']) > 25 ? $info['name'] : $info['name'] . rand(111, 999),
137
+                'type'        => $info['type'],
138
+                'content'     => $info['content'],
139
+                'update_time' => time(),
140
+                'create_time' => time()
141
+            ];
142
+
143
+            return Db::name('admin_printing')->insert($data);
144
+        }
145
+
146
+        return false;
147
+    }
148
+
149
+    /**
150
+     * 获取打印模板需要的字段
151
+     *
152
+     * @param $type 1商机;2合同;3回款
153
+     * @return array[]
154
+     * @throws \think\db\exception\DataNotFoundException
155
+     * @throws \think\db\exception\ModelNotFoundException
156
+     * @throws \think\exception\DbException
157
+     */
158
+    public function getFields($type)
159
+    {
160
+        $result = [];
161
+
162
+        switch ($type) {
163
+            case 1:
164
+                $result['business'] = $this->getBusinessFields();
165
+                $result['customer'] = $this->getCustomerFields();
166
+                $result['product']  = $this->getProductFields();
167
+
168
+                break;
169
+            case 2:
170
+                $result['contract'] = $this->getContractFields();
171
+                $result['customer'] = $this->getCustomerFields();
172
+                $result['contacts'] = $this->getContactsFields();
173
+                $result['product']  = $this->getProductFields();
174
+
175
+                break;
176
+            case 3:
177
+                $result['receivables'] = $this->getReceivablesFields();
178
+                $result['contract']    = $this->getContractFields();
179
+
180
+                break;
181
+            default:
182
+                $result['business']    = $this->getBusinessFields();
183
+                $result['customer']    = $this->getCustomerFields();
184
+                $result['product']     = $this->getProductFields();
185
+                $result['contract']    = $this->getContractFields();
186
+                $result['contacts']    = $this->getContactsFields();
187
+                $result['receivables'] = $this->getReceivablesFields();
188
+        }
189
+
190
+        return $result;
191
+    }
192
+
193
+    /**
194
+     * 获取商机字段
195
+     *
196
+     * @return array
197
+     * @throws \think\db\exception\DataNotFoundException
198
+     * @throws \think\db\exception\ModelNotFoundException
199
+     * @throws \think\exception\DbException
200
+     */
201
+    private function getBusinessFields()
202
+    {
203
+        $result = [];
204
+
205
+        $businessList = Db::name('admin_field')->field(['name', 'field'])->where('types', 'crm_business')->select();
206
+
207
+        # 处理自定义字段
208
+        foreach ($businessList AS $key => $value) {
209
+            if ($value['field'] == 'customer_id') continue;
210
+
211
+            $result[] = [
212
+                'name'  => $value['name'],
213
+                'field' => $value['field']
214
+            ];
215
+        }
216
+
217
+        # 处理固定字段
218
+        $result[] = ['name' => '负责人', 'field' => 'owner_user_id'];
219
+        $result[] = ['name' => '创建人', 'field' => 'create_user_id'];
220
+        $result[] = ['name' => '创建日期', 'field' => 'create_time'];
221
+        $result[] = ['name' => '更新日期', 'field' => 'update_time'];
222
+
223
+        return $result;
224
+    }
225
+
226
+    /**
227
+     * 获取客户字段
228
+     *
229
+     * @return array
230
+     * @throws \think\db\exception\DataNotFoundException
231
+     * @throws \think\db\exception\ModelNotFoundException
232
+     * @throws \think\exception\DbException
233
+     */
234
+    private function getCustomerFields()
235
+    {
236
+        $result = [];
237
+
238
+        $customerList = Db::name('admin_field')->field(['name', 'field'])->where('types', 'crm_customer')->select();
239
+
240
+        # 处理自定义字段
241
+        foreach ($customerList AS $key => $value) {
242
+            if (in_array($value['field'], ['next_time', 'remark'])) continue;
243
+
244
+            $result[] = [
245
+                'name'  => $value['name'],
246
+                'field' => $value['field']
247
+            ];
248
+        }
249
+
250
+        return $result;
251
+    }
252
+
253
+    /**
254
+     * 获取产品字段
255
+     *
256
+     * @return array
257
+     * @throws \think\db\exception\DataNotFoundException
258
+     * @throws \think\db\exception\ModelNotFoundException
259
+     * @throws \think\exception\DbException
260
+     */
261
+    private function getProductFields()
262
+    {
263
+        $result = [];
264
+
265
+        $productList = Db::name('admin_field')->field(['name', 'field'])->where('types', 'crm_product')->select();
266
+
267
+        # 处理自定义字段
268
+        foreach ($productList AS $key => $value) {
269
+            if ($value['field'] == 'status') continue;
270
+
271
+            $result[] = [
272
+                'name'  => $value['name'],
273
+                'field' => $value['field']
274
+            ];
275
+        }
276
+
277
+        # 处理固定字段
278
+        $result[] = ['name' => '售价', 'field' => 'sales_price'];
279
+        $result[] = ['name' => '数量', 'field' => 'count'];
280
+        $result[] = ['name' => '折扣', 'field' => 'discount'];
281
+        $result[] = ['name' => '整单折扣', 'field' => 'discount_rate'];
282
+        $result[] = ['name' => '合计', 'field' => 'subtotal'];
283
+
284
+        return $result;
285
+    }
286
+
287
+    /**
288
+     * 获取合同字段
289
+     *
290
+     * @return array
291
+     * @throws \think\db\exception\DataNotFoundException
292
+     * @throws \think\db\exception\ModelNotFoundException
293
+     * @throws \think\exception\DbException
294
+     */
295
+    private function getContractFields()
296
+    {
297
+        $result = [];
298
+
299
+        $contractList = Db::name('admin_field')->field(['name', 'field'])->where('types', 'crm_contract')->select();
300
+
301
+        # 处理自定义字段
302
+        foreach ($contractList AS $key => $value) {
303
+            $result[] = [
304
+                'name'  => $value['name'],
305
+                'field' => $value['field']
306
+            ];
307
+        }
308
+
309
+        # 处理固定字段
310
+        $result[] = ['name' => '负责人', 'field' => 'owner_user_id'];
311
+        $result[] = ['name' => '创建人', 'field' => 'create_user_id'];
312
+        $result[] = ['name' => '创建日期', 'field' => 'create_time'];
313
+        $result[] = ['name' => '更新日期', 'field' => 'update_time'];
314
+        $result[] = ['name' => '已收款金额', 'field' => 'received'];
315
+        $result[] = ['name' => '未收款金额', 'field' => 'uncollected'];
316
+
317
+        return $result;
318
+    }
319
+
320
+    /**
321
+     * 获取联系人字段
322
+     *
323
+     * @return array
324
+     * @throws \think\db\exception\DataNotFoundException
325
+     * @throws \think\db\exception\ModelNotFoundException
326
+     * @throws \think\exception\DbException
327
+     */
328
+    private function getContactsFields()
329
+    {
330
+        $result = [];
331
+
332
+        $contactsList = Db::name('admin_field')->field(['name', 'field'])->where('types', 'crm_contacts')->select();
333
+
334
+        # 处理自定义字段
335
+        foreach ($contactsList AS $key => $value) {
336
+            if ($value['field'] == 'next_time') continue;
337
+
338
+            $result[] = [
339
+                'name'  => $value['name'],
340
+                'field' => $value['field']
341
+            ];
342
+        }
343
+
344
+        return $result;
345
+    }
346
+
347
+    /**
348
+     * 获取回款字段
349
+     *
350
+     * @return array
351
+     * @throws \think\db\exception\DataNotFoundException
352
+     * @throws \think\db\exception\ModelNotFoundException
353
+     * @throws \think\exception\DbException
354
+     */
355
+    private function getReceivablesFields()
356
+    {
357
+        $result = [];
358
+
359
+        $receivablesList = Db::name('admin_field')->field(['name', 'field'])->where('types', 'crm_receivables')->select();
360
+
361
+        # 处理自定义字段
362
+        foreach ($receivablesList AS $key => $value) {
363
+            $result[] = [
364
+                'name'  => $value['name'],
365
+                'field' => $value['field']
366
+            ];
367
+        }
368
+
369
+        # 处理固定字段
370
+        $result[] = ['name' => '负责人', 'field' => 'owner_user_id'];
371
+        $result[] = ['name' => '创建人', 'field' => 'create_user_id'];
372
+        $result[] = ['name' => '创建日期', 'field' => 'create_time'];
373
+        $result[] = ['name' => '更新日期', 'field' => 'update_time'];
374
+
375
+        return $result;
376
+    }
377
+}

+ 114
- 0
application/admin/logic/WorkLogic.php Целия файл

@@ -0,0 +1,114 @@
1
+<?php
2
+/**
3
+ * 项目管理逻辑类
4
+ *
5
+ * @author qifan
6
+ * @date 2020-12-17
7
+ */
8
+
9
+namespace app\admin\logic;
10
+
11
+use think\Db;
12
+
13
+class WorkLogic
14
+{
15
+    /**
16
+     * 规则列表
17
+     *
18
+     * @return bool|\PDOStatement|string|\think\Collection
19
+     * @throws \think\db\exception\DataNotFoundException
20
+     * @throws \think\db\exception\ModelNotFoundException
21
+     * @throws \think\exception\DbException
22
+     */
23
+    public function getRules()
24
+    {
25
+        return Db::name('admin_rule')->field(['id', 'title', 'name'])->where(['types' => 3, 'level' => 4, 'status' => 0])->select();
26
+    }
27
+
28
+    /**
29
+     * 获取角色
30
+     *
31
+     * @return bool|\PDOStatement|string|\think\Collection
32
+     * @throws \think\db\exception\DataNotFoundException
33
+     * @throws \think\db\exception\ModelNotFoundException
34
+     * @throws \think\exception\DbException
35
+     */
36
+    public function getRoles()
37
+    {
38
+        $data = Db::name('admin_group')->field(['id', 'title', 'rules', 'remark', 'system'])->where(['pid' => 5, 'types' => 7, 'status' => 1])->select();
39
+
40
+        foreach ($data AS $key => $value) {
41
+            $data[$key]['rules'] = explode(',', trim($value['rules'], ','));
42
+        }
43
+
44
+        return $data;
45
+    }
46
+
47
+    /**
48
+     * 创建角色
49
+     *
50
+     * @param $param
51
+     * @return int|string
52
+     */
53
+    public function saveRole($param)
54
+    {
55
+        # 设置参数
56
+        $param['pid']    = 5;
57
+        $param['status'] = 1;
58
+        $param['type']   = 0;
59
+        $param['types']  = 7;
60
+        $param['system'] = 0;
61
+
62
+        return Db::name('admin_group')->insert($param);
63
+    }
64
+
65
+    /**
66
+     * 权限角色详情
67
+     *
68
+     * @param $id
69
+     * @return array|bool|\PDOStatement|string|\think\Model|null
70
+     * @throws \think\db\exception\DataNotFoundException
71
+     * @throws \think\db\exception\ModelNotFoundException
72
+     * @throws \think\exception\DbException
73
+     */
74
+    public function readRole($id)
75
+    {
76
+        $data = Db::name('admin_group')->field(['id', 'title', 'rules', 'remark'])->where('id', $id)->find();
77
+
78
+        $data['rules'] = trim($data['rules'], ',');
79
+
80
+        return $data;
81
+    }
82
+
83
+    /**
84
+     * 编辑权限角色
85
+     *
86
+     * @param $param
87
+     * @return int|string
88
+     * @throws \think\Exception
89
+     * @throws \think\exception\PDOException
90
+     */
91
+    public function updateRole($param)
92
+    {
93
+        return Db::name('admin_group')->update($param);
94
+    }
95
+
96
+    /**
97
+     * 删除权限角色
98
+     *
99
+     * @param $id
100
+     * @return array|bool[]
101
+     * @throws \think\Exception
102
+     * @throws \think\exception\PDOException
103
+     */
104
+    public function deleteRole($id)
105
+    {
106
+        $system = Db::name('admin_group')->where('id', $id)->value('system');
107
+
108
+        if (!empty($system)) return ['status' => false, 'error' => '不允许删除系统默认角色!'];
109
+
110
+        if (!Db::name('admin_group')->where('id', $id)->delete()) return ['status' => false, 'error' => '操作失败!'];
111
+
112
+        return ['status' => true];
113
+    }
114
+}

+ 52
- 0
application/admin/model/Access.php Целия файл

@@ -0,0 +1,52 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 角色员工关系
4
+// +----------------------------------------------------------------------
5
+// | Author:  
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use app\admin\model\Common;
11
+use think\Db;
12
+
13
+class Access extends Common 
14
+{
15
+    /**
16
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
17
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
18
+     */
19
+	protected $name = 'admin_access';
20
+
21
+	/**
22
+	 * [getDataList 获取列表]
23
+	 * @return    [array]            
24
+	 */
25
+	public function userGroup($user_id, $groups, $action = '')
26
+	{
27
+		if (!$user_id) {
28
+			$this->error = '参数错误';
29
+			return false;
30
+		}
31
+		$this->startTrans();
32
+		try {
33
+			if ($action == 'update') {
34
+				$this->where('user_id', $user_id)->delete();
35
+			}
36
+			foreach ($groups as $k => $v) {
37
+				if (!db('admin_access')->where(['user_id' => $user_id,'group_id' => $v])->find()) {
38
+					$userGroup['user_id'] = $user_id;
39
+					$userGroup['group_id'] = $v;
40
+					$userGroups[] = $userGroup;
41
+				}
42
+			}
43
+			$this->saveAll($userGroups);
44
+			$this->commit();
45
+			return true;
46
+		} catch(\Exception $e) {
47
+			$this->rollback();
48
+			$this->error = '编辑失败';
49
+			return false;
50
+		}
51
+	}	
52
+}

+ 111
- 0
application/admin/model/ActionRecord.php Целия файл

@@ -0,0 +1,111 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 字段修改记录
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use app\admin\model\Common;
11
+
12
+class ActionRecord extends Common 
13
+{
14
+    /**
15
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
16
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
17
+     */
18
+	protected $name = 'admin_action_record';
19
+	public $typesArr = ['crm_leads','crm_customer','crm_contacts','crm_product','crm_business','crm_contract','crm_receivables','crm_visit'];
20
+
21
+	/**
22
+	 * [getDataList 获取列表]
23
+	 * @return    [array]                         
24
+	 */
25
+	public function getDataList($request)
26
+	{
27
+		$types = trim($request['types']);
28
+		$action_id = intval($request['action_id']);
29
+		//判断权限
30
+		if (!$this->checkData($types, $action_id, $request['user_id'])) {
31
+			return [];
32
+		}
33
+		$dataList = db('admin_action_record')->where(['types' => $types,'action_id' => $action_id])->order('id','desc')->select();
34
+		if($types == 'crm_customer') {
35
+			$leads_id = db('crm_leads')->where(['customer_id' => $action_id, 'is_transform' => 1])->value('leads_id');
36
+			if($leads_id){
37
+				$leads_dataList = db('admin_action_record')->where(['types' => 'crm_leads','action_id' => $leads_id])->order('id','desc')->select();
38
+				$dataList = array_merge($leads_dataList, $dataList);
39
+			}
40
+		}
41
+		$userModel = model('User');
42
+		foreach ($dataList as $k=>$v) {
43
+			$dataList[$k]['user_id_info'] = isset($v['user_id']) ? $userModel->getUserById($v['user_id']) : [];
44
+			$dataList[$k]['content'] = explode('.|.', $v['content']);
45
+		}
46
+		return $dataList;
47
+	}
48
+
49
+	/**
50
+	 * [checkData 权限判断]
51
+	 * @return    [array]                         
52
+	 */	
53
+	public function checkData($types, $action_id, $user_id)
54
+	{
55
+		if (!in_array($types, $this->typesArr)) {
56
+			return false;
57
+		}
58
+		if (!$action_id) {
59
+			return false;
60
+		}
61
+		$adminTypes = adminGroupTypes($user_id);
62
+        if (in_array(1,$adminTypes)) {
63
+            return true;
64
+        }
65
+
66
+		$checkRes = false;
67
+		switch ($types) {
68
+			case 'crm_leads' :
69
+				$checkRes = checkPerByAction('crm', 'leads', 'read');
70
+				break;			
71
+			case 'crm_customer' :
72
+				$checkRes = checkPerByAction('crm', 'customer', 'read');
73
+				break;
74
+			case 'crm_contacts' :
75
+				$checkRes = checkPerByAction('crm', 'contacts', 'read');
76
+				break;
77
+			case 'crm_product' :
78
+				$checkRes = checkPerByAction('crm', 'product', 'read');
79
+				break;
80
+			case 'crm_business' :
81
+				$checkRes = checkPerByAction('crm', 'business', 'read');
82
+				break;			
83
+			case 'crm_contract' :
84
+				$checkRes = checkPerByAction('crm', 'contract', 'read');
85
+				break;	
86
+			case 'crm_receivables' :
87
+				$checkRes = checkPerByAction('crm', 'receivables', 'read');
88
+				break;	
89
+			case 'crm_visit' :
90
+				$checkRes = checkPerByAction('crm', 'visit', 'read');
91
+				break;									
92
+		}
93
+		if ($checkRes !== false) {
94
+			return true;
95
+		}
96
+	}
97
+
98
+	/**
99
+     * 删除字段修改记录
100
+     * @param 
101
+     * @return
102
+     */
103
+	public function delDataById($request)
104
+	{
105
+		$types = trim($request['types']);
106
+		$action_id = $request['action_id'];
107
+		if ($types && $action_id) {
108
+			$res = db('admin_action_record')->where(['types' => $types,'action_id' => ['in',$action_id]])->delete();
109
+		}
110
+	}    	
111
+}

+ 91
- 0
application/admin/model/Admin.php Целия файл

@@ -0,0 +1,91 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 系统基础公共
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use app\admin\controller\ApiCommon;
11
+use app\admin\model\Common;
12
+use think\Db;
13
+
14
+class Admin extends Common
15
+{
16
+    /**
17
+     * 统计筛选条件
18
+     * @param  $merge 1 user,structure 合并查询,0 user_id 优先级高 $is_last 昨天、上周、、、
19
+     * @param  $perUserIds 权限范围
20
+     * @return
21
+     * @author Michael_xu
22
+     */
23
+    public function getWhere($param, $merge = '', $perUserIds = [], $filter = true, $is_last = false)
24
+    {
25
+        $apiCommon = new ApiCommon();
26
+        $userModel = new \app\admin\model\User();
27
+        $user_id = $apiCommon->userInfo['id'];
28
+        $structure_id = $apiCommon->userInfo['structure_id'];
29
+        //员工IDS
30
+        $user_ids = [];
31
+        if ($param['userId']) {
32
+            $user_ids = array($param['userId']);
33
+        }
34
+        if ($param['deptId']) {
35
+            $userModel->getSubUserByStr($param['deptId'], 2);
36
+        }        
37
+        if ($param['dataType']) {
38
+            switch ($param['dataType']) {
39
+                case 1 : $user_ids = [$user_id];
40
+                    break;
41
+                case 2 : $user_ids = getSubUserId(true, 0, $apiCommon->userInfo['id']);
42
+                    break;
43
+                case 3 : $user_ids = $userModel->getSubUserByStr($structure_id, 1);
44
+                    break;
45
+                case 4 : $user_ids = $userModel->getSubUserByStr($structure_id, 2);
46
+                    break;
47
+                default : $user_ids = [$user_id];
48
+                    break;                                             
49
+            }
50
+        } else {
51
+            if ($merge == 1) {
52
+                if ($param['structure_id']) {
53
+                    $str_user_ids = $userModel->getSubUserByStr($param['structure_id'], 2);
54
+                }
55
+                //合并
56
+                if ($user_ids && $str_user_ids) {
57
+                    $user_ids = array_unique(array_merge($user_ids, $str_user_ids));
58
+                } elseif ($str_user_ids) {
59
+                    $user_ids = $str_user_ids;
60
+                }
61
+            } else {
62
+                if (!$user_ids) {
63
+                    if ($param['structure_id']) {
64
+                        $user_ids = $userModel->getSubUserByStr($param['structure_id'], 2);
65
+                    }
66
+                }
67
+            }
68
+            if (!$user_ids) $user_ids = getSubUserId(true);            
69
+        }
70
+        $perUserIds = $perUserIds ? : getSubUserId(); //权限范围内userIds
71
+        $userIds = [];
72
+        if ($user_ids) {
73
+            $userIds = $perUserIds ? array_intersect($user_ids, $perUserIds) : $perUserIds; //数组交集
74
+        }
75
+        $where['userIds'] = array_map('intval', $userIds);
76
+        if ($param['type']) {
77
+            $between_time = getTimeByType($param['type'], $is_last);
78
+        } else {
79
+            //自定义时间
80
+            if ($param['start_time']) {
81
+                $between_time = array(strtotime($param['start_time']), strtotime($param['end_time']));
82
+            }            
83
+            //自定义时间
84
+            if ($param['startTime']) {
85
+                $between_time = array(strtotime($param['startTime']), strtotime($param['endTime']));
86
+            }
87
+        }
88
+        $where['between_time'] = $between_time;
89
+        return $where ?: [];
90
+    }
91
+}

+ 173
- 0
application/admin/model/Comment.php Целия файл

@@ -0,0 +1,173 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 评论
4
+// +----------------------------------------------------------------------
5
+// | Author:  yykun
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use think\Db;
11
+use think\Model;
12
+use app\admin\model\Common;
13
+use com\verify\HonrayVerify;
14
+use think\Cache;
15
+
16
+class Comment extends Model
17
+{
18
+    /**
19
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
20
+     * 我们约定每个模块的数据表都加上相同的前缀,比如微信模块用weixin作为数据表前缀
21
+     */
22
+	protected $name = 'admin_comment';
23
+    protected $createTime = 'create_time';
24
+    protected $autoWriteTimestamp = true;
25
+	protected $insert = [
26
+		'status' => 1,
27
+	];
28
+
29
+	/**
30
+     * 根据ID查看评论
31
+     * @author Michael_xu
32
+     * @param
33
+     * @return
34
+     */	
35
+	public function read($param)
36
+	{
37
+		$userModel = new \app\admin\model\User();
38
+		$map['comment.type'] = $param['type'] ? : ''; //默认评论类型
39
+		$map['comment.type_id'] = $param['type_id'];
40
+		$map['comment.isreply'] = 0; 
41
+		$list = Db::name('AdminComment')
42
+				->alias('comment')
43
+				->join('admin_user u','u.id=comment.user_id')
44
+				->field('comment.*,u.username,u.realname,u.thumb_img')
45
+				->where($map)
46
+				->select();
47
+		foreach ($list as $key => $value) {
48
+            $list[$key]['userInfo']['id'] = $value['user_id'];
49
+			$list[$key]['userInfo']['username'] = $value['username'];
50
+			$list[$key]['userInfo']['realname'] = $value['realname'];
51
+			$list[$key]['create_time'] = date('Y-m-d H:i:s',$value['create_time']);
52
+			$list[$key]['userInfo']['thumb_img'] = $value['thumb_img'] ? getFullPath($value['thumb_img']) : '';
53
+			$list[$key]['replyuserInfo'] = $userModel->getUserById($value['reply_user_id']);
54
+			$replyList = [];
55
+			$replyList = Db::name('AdminComment')->where(['reply_fid' => $value['comment_id']])->select();
56
+			foreach ($replyList as $k=>$v) {
57
+				$replyList[$k]['userInfo'] = $userModel->getUserById($v['user_id']);
58
+				$replyList[$k]['replyuserInfo'] = $userModel->getUserById($v['reply_user_id']);
59
+			}
60
+			$list[$key]['childCommentList'] = $replyList ? : array();
61
+		}
62
+		return $list;
63
+	}
64
+
65
+	/**
66
+     * 获取回复
67
+     * @author Michael_xu
68
+     * @param
69
+     * @return
70
+     */		
71
+	function commentList($parent_id = 0,&$result = array())
72
+	{   
73
+		$list = $this->where(['status' => 1,'reply_id' => $parent_id])->order("create_time desc")->select();
74
+		if ($list) {
75
+			foreach ($list as $cm) {  
76
+				$thisArr =& $result[];
77
+				$cm["children"] = $this->commentList($cm["comment_id"],$thisArr);    
78
+				$thisArr = $cm;                                    
79
+			}			
80
+		}
81
+		return $result ? : [];
82
+    }
83
+	
84
+	/**
85
+     * 新建评论
86
+     * @author Michael_xu
87
+     * @param
88
+     * @return
89
+     */	 
90
+	public function createData($param)
91
+	{
92
+        $commentInfo = [];
93
+        if (!empty($param['comment_id'])) $commentInfo = Db::name('admin_comment')->where('comment_id', $param['comment_id'])->find();
94
+
95
+        $param['reply_content'] = !empty($commentInfo['content']) ? $commentInfo['content'] : '';  //内容拼接保存
96
+        $param['isreply']       = $param['comment_id'] ? 1 : 0; //是否是回复评论
97
+        $param['reply_id']      = $param['comment_id'] ? $param['comment_id'] : 0;  //回复消息id
98
+        $param['reply_fid']     = !empty($param['main_id']) ? $param['main_id'] : 0; //回复最上级ID
99
+        $param['reply_user_id'] = !empty($commentInfo['user_id']) ? $commentInfo['user_id'] : 0; //回复别人ID
100
+        $param['status']        = 1;
101
+
102
+        unset($param['main_id']);
103
+        unset($param['comment_id']);
104
+//print_r($param);exit;
105
+//		$param['reply_content'] = $param['reply_content'] ? : '';  //内容拼接保存
106
+//		$param['isreply'] = $param['reply_comment_id'] ? 1 : 0; //是否是回复评论
107
+//		$param['reply_id'] = $param['reply_comment_id'] ? $param['reply_comment_id'] : 0;  //回复消息id
108
+//		$param['reply_fid'] = $param['reply_fid'] ? : ''; //回复最上级ID
109
+//		$param['reply_user_id'] = $param['reply_user_id'] ? : ''; //回复别人ID
110
+//		$param['status'] = 1;
111
+		if ($this->data($param)->allowField(true)->save()) {
112
+            $userModel = new \app\admin\model\User();
113
+			$userInfo  = $userModel->getUserById($param['user_id']);
114
+			//发送站内信
115
+			switch ($param['type']) {
116
+				case 'task' : 
117
+					$taskInfo = db('task')->where(['task_id' => $param['type_id']])->field('name,create_user_id,main_user_id,owner_user_id')->find();
118
+					$user_ids[] = $taskInfo['create_user_id'];
119
+					if ($taskInfo['main_user_id']) {
120
+						$user_ids = array_merge($user_ids,array($taskInfo['main_user_id']));
121
+					}
122
+					if (stringToArray($taskInfo['owner_user_id'])) {
123
+						$user_ids = array_merge($user_ids,stringToArray($taskInfo['owner_user_id']));
124
+					}
125
+					$user_ids = array_filter(array_unique($user_ids));
126
+					$sendContent = $userInfo['realname'].',评论了任务《'.$taskInfo['name'].'》:'.$param['content'];
127
+					break;
128
+			}
129
+			if ($user_ids && $sendContent) {
130
+				$resMessage = sendMessage($user_ids, $sendContent, $param['type_id'], 1);
131
+			}
132
+			return Db::name('AdminComment')->where('comment_id',$this->comment_id)->find();
133
+		} else {
134
+			$this->error = '回复失败';
135
+			return false;
136
+		}
137
+	}
138
+
139
+	/**
140
+     * 删除评论
141
+     * @author Michael_xu
142
+     * @param
143
+     * @return
144
+     */	
145
+	public function delDataById($param)
146
+	{
147
+		if ($param['comment_id']) {
148
+			$flag = $this->where(['comment_id' => $param['comment_id']])->delete();
149
+		} else {
150
+			$flag = $this->where(['type' => $param['type'],'type_id' => $param['type_id']])->delete();
151
+		}
152
+		if (!$flag){
153
+			$this->error = '不存在或已删除';
154
+			return false;
155
+		}
156
+		return true;
157
+	}
158
+
159
+	/**
160
+     * 获取评论数
161
+     * @author Michael_xu
162
+     * @param
163
+     * @return
164
+     */	
165
+	public function getCount($type,$type_id)
166
+	{
167
+		$count = 0;
168
+		if ($type && $type_id) {
169
+			$count = $this->where(['type' => $type,'type_id' => $type_id])->count();
170
+		}
171
+		return $count;
172
+	}	
173
+}

+ 336
- 0
application/admin/model/Common.php Целия файл

@@ -0,0 +1,336 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 公共模型,所有模型都可继承此模型,基于RESTFUL CRUD操作
4
+// +----------------------------------------------------------------------
5
+// | Author: 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use think\Model;
11
+use think\Request;
12
+
13
+class Common extends Model 
14
+{
15
+	/**
16
+	 * [Request 请求参数]
17
+	 * @Michael_xu
18
+	 * @return    [array]                       
19
+	 */	
20
+	protected function requestData()
21
+	{
22
+		$m = strtolower(request()->module());
23
+		$c = strtolower(request()->controller());
24
+		$a = strtolower(request()->action());
25
+		$ret = [
26
+			'm' => $m,
27
+			'c' => $c,
28
+			'a' => $a
29
+		];
30
+		return $ret;	
31
+	}
32
+
33
+	/**
34
+	 * [fmtRequest 格式化请求参数]
35
+	 * @Michael_xu
36
+	 * @param     [array]      $request [参数]
37
+	 * @return    [array]                       
38
+	 */
39
+    public function fmtRequest( $request = [] )
40
+    {
41
+        $pageType = $request['pageType'] ? 'all' : ''; //all全部(不分页)
42
+        $page = 1;
43
+        if (isset($request['page']) && is_numeric($request['page']) ) {
44
+            $page = $request['page'];
45
+            unset($request['page']);
46
+        }
47
+        $limit = 15;
48
+        if (isset($request['limit']) && is_numeric($request['limit']) ) {
49
+            $limit = $request['limit'];
50
+            unset($request['limit']);
51
+		}
52
+		$offset = $length = null;
53
+        if ($pageType == 'all') {
54
+        	$page = 1;
55
+        	$limit = 0;
56
+        	unset($request['pageType']);
57
+		} else {
58
+			// 大数据处理-滚动加载-子分页
59
+			if ($request['sub_page'] && $request['sub_limit']) {
60
+				$sub_page = $request['sub_page'];
61
+				$sub_limit = $request['sub_limit'];
62
+				unset($request['sub_page']);
63
+				unset($request['sub_limit']);
64
+				$offset = ($page - 1) * $limit + ($sub_page - 1) * $sub_limit;
65
+				if ($sub_limit * $sub_page > $limit) {
66
+					$length = ($page - 1) * $limit + $limit - $offset;
67
+				} else {
68
+					$length = $sub_limit;
69
+				}
70
+				if ($length < 0) {
71
+					$offset = $length = 0;
72
+				}
73
+			}
74
+		}
75
+		
76
+		if (!isset($offset) || !isset($length)) {
77
+			$offset = ($page - 1) * $limit;
78
+			$length = $limit;
79
+		}
80
+        $ret = [
81
+            'page' => $page,
82
+            'limit' => $limit,
83
+			'map' => $request,
84
+			'offset' => $offset,
85
+			'length' => $length,
86
+		];
87
+        return $ret;
88
+    }
89
+	
90
+	/**
91
+	 * [getDataById 根据主键获取详情]
92
+	 * @param     string                   $id [主键]
93
+	 * @return    [array]                       
94
+	 */
95
+	public function getDataById($id = '')
96
+	{
97
+		$data = $this->get($id);
98
+		if (!$data) {
99
+			$this->error = '暂无此数据';
100
+			return false;
101
+		}
102
+		return $data;
103
+	}
104
+
105
+	/**
106
+	 * [createData 新建]
107
+	 * @param     array                    $param [description]
108
+	 * @return    [array]                         [description]
109
+	 */
110
+	public function createData($param)
111
+	{	
112
+		// 验证
113
+		$validate = validate($this->name);
114
+		if (!$validate->check($param)) {
115
+			$this->error = $validate->getError();
116
+			return false;
117
+		}
118
+		try {
119
+			$this->data($param)->allowField(true)->save();
120
+			return true;
121
+		} catch(\Exception $e) {
122
+			$this->error = '添加失败';
123
+			return false;
124
+		}
125
+	}
126
+
127
+	/**
128
+	 * [updateDataById 编辑]
129
+	 * @param     [type]                   $param [description]
130
+	 * @param     [type]                   $id    [description]
131
+	 * @return    [type]                          [description]
132
+	 */
133
+	public function updateDataById($param, $id)
134
+	{
135
+		$checkData = $this->get($id);
136
+		if (!$checkData) {
137
+			$this->error = '暂无此数据';
138
+			return false;
139
+		}
140
+
141
+		// 验证
142
+		$validate = validate($this->name);
143
+		if (!$validate->scene('edit')->check($param)) {
144
+			$this->error = $validate->getError();
145
+			return false;
146
+		}
147
+
148
+		try {
149
+			$this->allowField(true)->save($param, [$this->getPk() => $id]);
150
+			return true;
151
+		} catch(\Exception $e) {
152
+			$this->error = '编辑失败';
153
+			return false;
154
+		}
155
+	}
156
+
157
+	/**
158
+	 * [delDataById 根据id删除数据]
159
+	 * @param     string                   $id     [主键]
160
+	 * @param     boolean                  $delSon [是否删除子孙数据]
161
+	 * @return    [type]                           [description]
162
+	 */
163
+	public function delDataById($id = '', $delSon = false)
164
+	{
165
+		if (!$id) {
166
+			$this->error = '删除失败';
167
+			return false;
168
+		}
169
+		$this->startTrans();
170
+		try {
171
+			$this->where($this->getPk(), $id)->delete();
172
+			if ($delSon && is_numeric($id)) {
173
+				// 删除子孙
174
+				$childIds = $this->getAllChild($id);
175
+				if($childIds){
176
+					$this->where($this->getPk(), 'in', $childIds)->delete();
177
+				}
178
+			}
179
+			$this->commit();
180
+			return true;
181
+		} catch(\Exception $e) {
182
+			$this->error = '删除失败';
183
+			$this->rollback();
184
+			return false;
185
+		}		
186
+	}
187
+
188
+	/**
189
+	 * [delDatas 批量删除数据]
190
+	 * @param     array                   $ids    [主键数组]
191
+	 * @param     boolean                 $delSon [是否删除子孙数据]
192
+	 * @return    [type]                          [description]
193
+	 */
194
+	public function delDatas($ids = [], $delSon = false)
195
+	{
196
+		if (empty($ids)) {
197
+			$this->error = '删除失败';
198
+			return false;
199
+		}
200
+		
201
+		// 查找所有子元素
202
+		if ($delSon) {
203
+			foreach ($ids as $k => $v) {
204
+				if (!is_numeric($v)) continue;
205
+				$childIds = $this->getAllChild($v);
206
+				$ids = array_merge($ids, $childIds);
207
+			}
208
+			$ids = array_unique($ids);
209
+		}
210
+
211
+		try {
212
+			$this->where($this->getPk(), 'in', $ids)->delete();
213
+			return true;
214
+		} catch (\Exception $e) {
215
+			$this->error = '操作失败';
216
+			return false;
217
+		}		
218
+
219
+	}
220
+
221
+	/**
222
+	 * [enableDatas 批量启用、禁用]
223
+	 * @param     string                   $ids    [主键数组]
224
+	 * @param     integer                  $status [状态1启用0禁用]
225
+	 * @param     [boolean]                $delSon [是否删除子孙数组]
226
+	 * @return    [type]                           [description]
227
+	 */
228
+	public function enableDatas($ids = [], $status = 1, $delSon = false)
229
+	{
230
+		if (empty($ids)) {
231
+			$this->error = '参数错误';
232
+			return false;
233
+		}
234
+
235
+		// 查找所有子元素
236
+		if ($delSon && $status === '0') {
237
+			foreach ($ids as $k => $v) {
238
+				$childIds = $this->getAllChild($v);
239
+				$ids = array_merge($ids, $childIds);
240
+			}
241
+			$ids = array_unique($ids);
242
+		}
243
+		try {
244
+			$this->where($this->getPk(),'in',$ids)->setField('status', $status);
245
+			return true;
246
+		} catch (\Exception $e) {
247
+			$this->error = '操作失败';
248
+			return false;
249
+		}
250
+	}
251
+
252
+	/**
253
+	 * 获取所有子孙
254
+	 */
255
+	public function getAllChild($id, &$data = [])
256
+	{
257
+		$map['pid'] = $id;
258
+		$childIds = $this->where($map)->column($this->getPk());
259
+		if (!empty($childIds)) {
260
+			foreach ($childIds as $v) {
261
+				$data[] = $v;
262
+				$this->getAllChild($v, $data);
263
+			}
264
+		}
265
+		return $data;
266
+	}
267
+
268
+	/**
269
+	 * 逻辑删除,将数据标记为删除状态
270
+	 * @author Michael_xu
271
+	 */	
272
+	public function signDelById($id)
273
+	{
274
+		if (!$id) {
275
+			$this->error = '删除失败';
276
+			return false;
277
+		}
278
+		$this->startTrans();
279
+		try {
280
+			$data['is_deleted'] = 1;
281
+			$data['delete_time'] = time();
282
+			$this->allowField(true)->save($data, [$this->getPk() => $id]);
283
+			$this->commit();
284
+			return true;
285
+		} catch(\Exception $e) {
286
+			$this->error = '删除失败';
287
+			$this->rollback();
288
+			return false;
289
+		}			
290
+	}
291
+
292
+
293
+	/**
294
+	 * 导出数据处理
295
+	 */
296
+	public function exportHandle($list, $field_list, $type = '')
297
+	{
298
+		foreach ($list as &$val) {
299
+			foreach ($field_list as $field) {
300
+				switch ($field['form_type']) {
301
+					case 'user':
302
+						if (isset($val[$field['field'] . '_info']['realname'])) {
303
+							$val[$field['field']] = $val[$field['field'] . '_info']['realname'];
304
+						} else {
305
+							$val[$field['field']] = implode(',', array_column($val[$field['field'] . '_info'], 'realname'));
306
+						}
307
+						break;
308
+					case 'structure':
309
+						$temp = array_map(function ($val) { return $val->toarray(); }, $val[$field['field'] . '_info']);
310
+						$val[$field['field']] = implode(',', array_column($temp, 'name'));
311
+						break;
312
+					case 'datetime':
313
+						$val[$field['field']] = strtotime($val[$field['field']]) ? $val[$field['field']] : date('Y-m-d H:i:s', $val[$field['field']]);
314
+						break;
315
+					case 'customer':
316
+					case 'business':
317
+					case 'contacts':
318
+						$val[$field['field']] = $val[$field['field'] . '_info']['name'];
319
+						break;
320
+                    case 'contacts':
321
+                        $val[$field['field']] = $val[$field['field'] . '_info']['name'];
322
+                        break;
323
+					default :
324
+						switch ($field['field']) {
325
+							// 商机销售阶段、商机状态组
326
+							case 'status_id':
327
+							case 'type_id':
328
+								$val[$field['field']] = $val[$field['field'] . '_info'];
329
+								break;
330
+						}
331
+				}
332
+			}
333
+		}
334
+		return $list;
335
+	}
336
+}

+ 46
- 0
application/admin/model/Config.php Целия файл

@@ -0,0 +1,46 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 应用配置
4
+// +----------------------------------------------------------------------
5
+// | Author: Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use app\admin\model\Common;
11
+use think\Db;
12
+
13
+class Config extends Common 
14
+{
15
+    /**
16
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
17
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
18
+     */
19
+	protected $name = 'admin_config';
20
+
21
+	/**
22
+	 * [getDataList 获取列表]
23
+	 * @return    [array]            
24
+	 */
25
+	public function getDataList()
26
+	{
27
+		$list = Db::name('AdminConfig')->order('type asc')->select();
28
+		return $list;
29
+	}
30
+	
31
+	/**
32
+     * 编辑
33
+     * @author Michael_xu
34
+     * @return
35
+     */	
36
+	public function updateDataById($param, $id)
37
+	{
38
+		$data = [];
39
+		$data['status'] = $param['status'] ? : '0';
40
+		if ($this->where(['id' => $id])->update($data)) {
41
+			return true;
42
+		}
43
+		$this->error = '操作失败';
44
+		return false;		
45
+	}
46
+}

+ 269
- 0
application/admin/model/ExamineFlow.php Целия файл

@@ -0,0 +1,269 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 审批流程
4
+// +----------------------------------------------------------------------
5
+// | Author: Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+namespace app\admin\model;
8
+
9
+use think\Db;
10
+use app\admin\model\Common;
11
+use think\Request;
12
+use think\Validate;
13
+
14
+class ExamineFlow extends Common
15
+{
16
+	/**
17
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
18
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
19
+     */
20
+	protected $name = 'admin_examine_flow';
21
+    protected $createTime = 'create_time';
22
+    protected $updateTime = 'update_time';
23
+	protected $autoWriteTimestamp = true;
24
+	protected $typesArr = ['crm_contract', 'crm_receivables', 'crm_invoice', 'oa_examine'];
25
+
26
+	/**
27
+     * [getDataList 审批流程list]
28
+     * @author Michael_xu
29
+     * @param     [string]                   $map [查询条件]
30
+     * @param     [number]                   $page     [当前页数]
31
+     * @param     [number]                   $limit    [每页数量]
32
+     * @return    [array]                    [description]
33
+     */		
34
+	public function getDataList($request)
35
+    {  	
36
+        $userModel = new \app\admin\model\User();
37
+    	$structureModel = new \app\admin\model\Structure();
38
+        $examineStepModel = new \app\admin\model\ExamineStep();
39
+        $request = $this->fmtRequest( $request );
40
+        $map = $request['map'] ? : [];
41
+        if (isset($map['search'])) {
42
+			//普通筛选
43
+			$map['name'] = ['like', '%'.$map['search'].'%'];
44
+			unset($map['search']);
45
+		}
46
+        $map['is_deleted'] = 0;
47
+		$list_view = db('admin_examine_flow')
48
+					 ->where($map)
49
+				     ->alias('examine_flow')
50
+				     ->join('__ADMIN_USER__ user', 'user.id = examine_flow.update_user_id', 'LEFT');
51
+
52
+		$list = $list_view
53
+        		->page($request['page'], $request['limit'])
54
+        		->field('examine_flow.*,user.realname,user.thumb_img')
55
+                ->order('examine_flow.update_time', 'desc')
56
+        		->select();	
57
+        foreach ($list as $k=>$v) {
58
+            $list[$k]['user_ids_info'] = $userModel->getListByStr($v['user_ids']);
59
+            $list[$k]['structure_ids_info'] = $structureModel->getListByStr($v['structure_ids']);
60
+            $stepList = [];
61
+            $stepList = $examineStepModel->getDataList($v['flow_id']);
62
+            $list[$k]['stepList'] = $stepList ? : [];
63
+            $list[$k]['create_time'] = !empty($v['create_time']) ? date('Y-m-d H:i:s', $v['create_time']) : null;
64
+            $list[$k]['update_time'] = !empty($v['update_time']) ? date('Y-m-d H:i:s', $v['update_time']) : null;
65
+        }
66
+        $dataCount = $list_view->where($map)->count('flow_id');
67
+        $data = [];
68
+        $data['list'] = $list;
69
+        $data['dataCount'] = $dataCount ? : 0;
70
+
71
+        return $data;
72
+    }
73
+
74
+	/**
75
+	 * 创建审批流程信息
76
+	 * @author Michael_xu
77
+	 * @param  
78
+	 * @return                            
79
+	 */	
80
+	public function createData($param)
81
+	{
82
+		//验证
83
+		if (!$param['name']) {
84
+            $this->error = '请填写审批流名称1';
85
+            return false;
86
+        }
87
+
88
+		if ($this->data($param)->allowField(true)->save()) {
89
+			$data = [];
90
+			$data['flow_id'] = $this->flow_id;
91
+			return $data;
92
+		} else {
93
+			$this->error = '添加失败';
94
+			return false;
95
+		}			
96
+	}
97
+
98
+	/**
99
+	 * 编辑审批流程信息
100
+	 * @author Michael_xu
101
+	 * @param  
102
+	 * @return                            
103
+	 */	
104
+	public function updateDataById($param, $flow_id = '')
105
+	{
106
+		unset($param['flow_id']);
107
+		$dataInfo = $this->get($flow_id);
108
+		if (!$dataInfo) {
109
+			$this->error = '数据不存在或已删除';
110
+			return false;
111
+		}
112
+		//过滤不能修改的字段
113
+		$unUpdateField = ['create_user_id','is_deleted','delete_time'];
114
+		foreach ($unUpdateField as $v) {
115
+			unset($param[$v]);
116
+		}
117
+		
118
+		//验证
119
+		if (!$param['name']) {
120
+            $this->error = '请填写审批流名称';
121
+            return false;
122
+        }
123
+//		$param['flow_id'] = $flow_id;
124
+
125
+		if ($this->allowField(true)->save($param)) {
126
+			$data = [];
127
+			$data['flow_id'] = $flow_id;
128
+			return $data;
129
+		} else {
130
+			$this->error = '编辑失败,请重试';
131
+			return false;
132
+		}					
133
+	}
134
+
135
+    /**
136
+     * 审批流程详情
137
+     * @author Michael_xu
138
+     * @param  
139
+     * @return                            
140
+     */ 
141
+    public function getDataById($flow_id = '')
142
+    {
143
+        $userModel = new \app\admin\model\User();
144
+        $dataInfo = $this->get($flow_id);
145
+        if (!$dataInfo) {
146
+            $this->error = '数据不存在或已删除';
147
+            return false;
148
+        }
149
+        //审批步骤
150
+        $stepList = db('admin_examine_step')->where(['flow_id' => $flow_id])->select();
151
+        foreach ($stepList as $k=>$v) {
152
+            $examine_user_id_arr = [];
153
+            switch ($v['status']) {
154
+                case 2 : 
155
+                case 3 : $examine_user_id_arr = stringToArray($v['user_id']); break;
156
+                default : $examine_user_id_arr = []; break;
157
+            }
158
+            $stepList[$k]['user_id_info'] = $userModel->getUserByIdArr($examine_user_id_arr);      
159
+        }
160
+        $dataInfo['stepList'] = $stepList ? : [];
161
+        return $dataInfo;          
162
+    }
163
+
164
+	/**
165
+     * 审批流程(根据对象获取需要执行的审批流程)
166
+     * @param  types 审批对象
167
+     * @param  types_id 审批对象ID(如OA审批类型ID)
168
+     */ 
169
+    public function getFlowByTypes($user_id, $types, $types_id = 0)
170
+    {
171
+        $userModel = new \app\admin\model\User();
172
+    	if (!in_array($types, $this->typesArr)) {
173
+    		$this->error = '参数错误';
174
+    		return false;
175
+    	}
176
+    	$map['types'] = $types;
177
+        $map['status'] = 1;
178
+        $map['is_deleted'] = 0;
179
+        if ($types !== 'oa_examine') {
180
+            $types_id = 0;
181
+        }
182
+    	$map['types_id'] = $types_id;
183
+    	//判断用户使用哪个流程(优先级:所属部门 > 全部)
184
+        $userData = $userModel->getUserById($user_id);
185
+        $userData['map'] = $map;
186
+
187
+        $flowInfo = db('admin_examine_flow')
188
+                    ->where(function ($query) use ($userData) {
189
+                        $userData = $userData;
190
+                        $query->where(['config' => 1])
191
+                                ->where($userData['map'])
192
+                                ->where(function ($query) use ($userData) {
193
+                                    $query->where('structure_ids','like','%,'.$userData['structure_id'].',%')
194
+                                            ->whereOr('user_ids','like','%,'.$userData['id'].',%');
195
+                                });
196
+                    })->whereOr(function ($query) use ($userData) {
197
+                        $query->where(['config' => 1])
198
+                                ->where($userData['map'])
199
+                                ->where('structure_ids','eq','')
200
+                                ->where('user_ids','eq','');                    
201
+                    })->whereOr(function ($query) use ($userData) {
202
+                        $query->where(['config' => 0])
203
+                                ->where($userData['map']);
204
+                    })->order('update_time desc')->find();
205
+    	return $flowInfo ? : [];
206
+    }
207
+
208
+    /**
209
+     * 审批流程权限(创建操作使用)
210
+     * @param  types 审批对象
211
+     * @param  user_id 审批对象申请人ID
212
+     * @param category_id 审批类型ID,或其他类型ID
213
+     */
214
+    public function checkExamine($user_id, $types, $category_id = 0)
215
+    {
216
+        $examineStepModel = new \app\admin\model\ExamineStep();
217
+        //符合条件的审批流
218
+        $resFlow = $this->getFlowByTypes($user_id, $types, $category_id);
219
+        if (!$resFlow) {
220
+            return false;
221
+        }
222
+        if ($resFlow['config'] == 1) {
223
+            //审批流是否为空
224
+            $stepList = $examineStepModel->getStepList($resFlow['flow_id'], $user_id, $types);
225
+            if (!$stepList) {
226
+               return false; 
227
+            }
228
+        }
229
+        return $resFlow;
230
+    }  
231
+
232
+    /**
233
+     * 审批流程下所有审批人ID
234
+     * @param
235
+     * @return
236
+     */  
237
+    public function getUserByFlow($flow_id, $user_id, $check_user_id = '')
238
+    {
239
+        $flowInfo = db('admin_examine_flow')->where(['flow_id' => $flow_id])->find();
240
+        $userIds = [];
241
+        if ($flowInfo['config'] == 1) {
242
+            $stepList = db('admin_examine_step')->where(['flow_id' => $flow_id])->select();
243
+            foreach ($stepList as $k=>$v) {
244
+                if ($v['status'] == 1) {
245
+                    $userInfo = db('admin_user')->where(['id' => $user_id])->find();
246
+                    if ($userInfo['parent_id']) {
247
+                        $userIds[] = $userInfo['parent_id'];
248
+                    } else {
249
+                        $userIds[] = 1;
250
+                    }
251
+                }
252
+                if (stringToArray($v['user_id'])) $userIds = $userIds ? array_merge($userIds, stringToArray($v['user_id'])) : stringToArray($v['user_id']);
253
+            }
254
+        } else {
255
+            $userIds = [];
256
+            $check_user_id = stringToArray($check_user_id);
257
+            //查询已审批人ID(未失效的)
258
+            $is_check_user_id = db('admin_examine_record')->where(['flow_id' => $flow_id,'is_end' => 0])->column('check_user_id');
259
+            if ($check_user_id && $is_check_user_id) {
260
+                $userIds = array_merge($check_user_id, $is_check_user_id);
261
+            } elseif ($check_user_id) {
262
+                $userIds = $check_user_id;
263
+            } else {
264
+                $userIds = $is_check_user_id;
265
+            }
266
+        }
267
+        return $userIds ? : [];
268
+    }     
269
+}

+ 113
- 0
application/admin/model/ExamineRecord.php Целия файл

@@ -0,0 +1,113 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 审批意见
4
+// +----------------------------------------------------------------------
5
+// | Author: Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+namespace app\admin\model;
8
+
9
+use think\Db;
10
+use app\admin\model\Common;
11
+use think\Request;
12
+use think\Validate;
13
+
14
+class ExamineRecord extends Common
15
+{
16
+	/**
17
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
18
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
19
+     */
20
+	protected $name = 'admin_examine_record';
21
+
22
+	/**
23
+     * 审批意见(创建)
24
+     * @param types 关联对象
25
+     * @param types_id 联对象ID
26
+     * @param flow_id 审批流程ID
27
+     * @param step_id 审批步骤ID
28
+     * @param user_id 审批人ID
29
+     * @param status 1通过0驳回
30
+     * @return 
31
+     */
32
+    public function createData($param)
33
+    {
34
+		if ($this->data($param)->allowField(true)->save()) {
35
+			$data = [];
36
+			$data['record_id'] = $this->record_id;
37
+			return $data;
38
+		} else {
39
+			$this->error = '添加失败';
40
+			return false;
41
+		}    	
42
+    }
43
+
44
+	/**
45
+     * 审批意见(列表)
46
+     * @param types 关联对象
47
+     * @param types_id 联对象ID
48
+     * @return 
49
+     */
50
+    public function getDataList($param)
51
+    {
52
+		$userModel = new \app\admin\model\User();
53
+        if (empty($param['types']) || empty($param['types_id'])) {
54
+            return [];
55
+        }
56
+
57
+        $result = [];
58
+
59
+        # 获取创建者信息
60
+        if (in_array($param['types'], ['crm_contract', 'crm_receivables', 'crm_invoice']) && !empty($param['is_record'])) {
61
+            $model      = db($param['types']);
62
+            $primaryKey = null;
63
+            if ($param['types'] == 'crm_contract')    $primaryKey = 'contract_id';
64
+            if ($param['types'] == 'crm_receivables') $primaryKey = 'receivables_id';
65
+            if ($param['types'] == 'crm_invoice')     $primaryKey = 'invoice_id';
66
+
67
+            $info     = $model->field(['create_time', 'owner_user_id'])->where($primaryKey, $param['types_id'])->find();
68
+            $userInfo = $userModel->getUserById($info['owner_user_id']);
69
+
70
+            $result[] = [
71
+                'check_date'         => date('Y-m-d H:i:s', $info['create_time']),
72
+                'check_time'         => $info['create_time'],
73
+                'check_user_id'      => $info['owner_user_id'],
74
+                'check_user_id_info' => $userInfo,
75
+                'content'            => '',
76
+                'flow_id'            => 0,
77
+                'is_end'             => 0,
78
+                'order_id'           => 0,
79
+                'record_id'          => 0,
80
+                'status'             => 3,
81
+                'types'              => $param['types'],
82
+                'types_id'           => $param['types_id']
83
+            ];
84
+        }
85
+        unset($param['is_record']);
86
+
87
+        $list = db('admin_examine_record')->where($param)->order('check_time asc')->select();
88
+        foreach ($list as $k=>$v) {
89
+            $list[$k]['check_user_id_info'] = $userModel->getUserById($v['check_user_id']);
90
+            $list[$k]['check_date'] = date('Y-m-d H:i:s', $v['check_time']);
91
+
92
+            $result[] = $list[$k];
93
+        }
94
+
95
+        return !empty($result) ? $result : [];
96
+    } 
97
+
98
+    /**
99
+     * 审批意见(标记无效,撤销审批时使用)
100
+     * @param types 关联对象
101
+     * @param types_id 关联对象ID
102
+     * @return 
103
+     */
104
+    public function setEnd($param)
105
+    {
106
+        if (empty($param['types']) || empty($param['types_id'])) {
107
+            $this->error = '参数错误';
108
+            return false;
109
+        }        
110
+        $res = $this->where(['types' => $param['types'],'types_id' => $param['types_id']])->update(['is_end' => 1]);
111
+        return true;
112
+    }      
113
+} 

+ 495
- 0
application/admin/model/ExamineStep.php Целия файл

@@ -0,0 +1,495 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 审批步骤
4
+// +----------------------------------------------------------------------
5
+// | Author: Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+namespace app\admin\model;
8
+
9
+use think\Db;
10
+use app\admin\model\Common;
11
+use think\Request;
12
+use think\Validate;
13
+
14
+class ExamineStep extends Common
15
+{
16
+	/**
17
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
18
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
19
+     */
20
+	protected $name = 'admin_examine_step';
21
+
22
+    /**
23
+     * 获取有效审批步骤列表
24
+     * @param  flow_id 审批流程ID
25
+     * @param  user_id 审批申请人ID
26
+     * @return
27
+     */ 
28
+    public function getDataList($flow_id)
29
+    {
30
+        $userModel = new \app\admin\model\User();
31
+        $list = $this->where(['flow_id' => $flow_id])->order('order_id asc')->select();
32
+        foreach ($list as $k=>$v) {
33
+            $list[$k]['user_id_info'] = $userModel->getListByStr($v['user_id']);
34
+        }
35
+        return $list ? : [];
36
+    }   
37
+
38
+	/**
39
+     * 审批步骤(创建、编辑)
40
+     * @param  flow_id 审批流程ID
41
+     * @param status 1负责人主管,2指定用户(任意一人),3指定用户(多人会签),4上一级审批人主管
42
+     * @return 
43
+     */
44
+    public function createStepData($data, $flow_id)
45
+    {
46
+    	if (!intval($flow_id)) {
47
+			$this->error = '审批流程创建失败';
48
+			return false;    		
49
+    	}
50
+        //处理数据
51
+        $resSuccess = true;
52
+        $dataStep = [];
53
+        foreach ($data as $k=>$v) {
54
+            if (!intval($v['status']) || (in_array($v['status'],[2,3]) && !$v['user_id'])) {
55
+                $resSuccess = false;
56
+            }
57
+            $dataStep[$k]['relation'] = 1;
58
+            if (in_array($v['status'],[2,3])) {
59
+                $dataStep[$k]['user_id'] = $v['user_id'] ? arrayToString($v['user_id']) : ''; //处理user_id
60
+                $dataStep[$k]['relation'] = ($v['status'] == 3) ? 1 : 2;
61
+            }
62
+            if ($v['step']) {
63
+                $dataStep[$k]['step_id'] = $v['step'];
64
+            }
65
+            $dataStep[$k]['order_id'] = $k+1;
66
+            $dataStep[$k]['flow_id'] = $flow_id;
67
+            $dataStep[$k]['status'] = $v['status'];
68
+            $dataStep[$k]['create_time'] = time();    
69
+        }
70
+        if ($resSuccess) {
71
+            //提交事务
72
+            $this->startTrans();
73
+            try {
74
+                $this->where(['flow_id' => $flow_id])->delete();
75
+                $this->saveAll($dataStep);
76
+                $this->commit();
77
+                return true;                    
78
+            } catch(\Exception $e) {
79
+                $this->error = '审批步骤创建失败';
80
+                $this->rollback();
81
+                return false;
82
+            }               
83
+        } else {
84
+            $this->error = '参数错误';
85
+            return false;          
86
+        }        
87
+    }
88
+
89
+	/**
90
+     * 审批步骤(排序,防止位置情况造成排序错乱)
91
+     * @param  flow_id 审批流程ID
92
+     * @return 
93
+     */ 
94
+    public function orderData($flow_id)
95
+    {
96
+    	$step_list = db('admin_examine_step')->where(['flow_id' => $flow_id])->order('order_id')->select();
97
+    	foreach ($step_list as $k=>$v) {
98
+    		$data = [];
99
+    		$data = ['step_id' => $v['step_id'],'order_id' => $k];
100
+    		db('admin_examine_step')->update($data);
101
+    	}
102
+    }        
103
+
104
+	/**
105
+     * 下一审批人(审批是否结束)
106
+     * @param  user_id  审批申请人ID
107
+     * @param  flow_id  审批流ID
108
+     * @param  types 关联对象
109
+     * @param  types_id 联对象ID
110
+     * @param  order_id 审批排序ID
111
+     * @param status 1负责人主管,2指定用户(任意一人),3指定用户(多人会签),4上一级审批人主管
112
+     * @param  check_user_id 当前审核人ID
113
+     */ 
114
+    public function nextStepUser($user_id, $flow_id, $types, $types_id, $order_id, $check_user_id)
115
+    {
116
+        $res = nextCheckData($user_id, $flow_id, $types, $types_id, $order_id, $check_user_id);
117
+        return $res ? : [];
118
+    }
119
+
120
+	/**
121
+     * 审批步骤权限
122
+     * @param  step_id 审批步骤ID
123
+     * @param  user_id 审批人ID(当前登录人)
124
+     * @param  create_user_id 申请人ID
125
+     * @param  types 关联对象
126
+     * @param  types_id 联对象ID
127
+     * @param  status 1负责人主管,2指定用户(任意一人),3指定用户(多人会签),4上一级审批人主管
128
+     * @return 
129
+     */ 
130
+    public function checkExamine($user_id, $types, $types_id)
131
+    {
132
+        $data = $this->getDataByTypes($types, $types_id);
133
+        $dataInfo = $data['dataInfo']; //审批主体信息
134
+        $stepInfo = $data['stepInfo']; //审批步骤信息
135
+        if (!$dataInfo) {
136
+            $this->error = '参数错误!';
137
+            return false;            
138
+        }
139
+        if (in_array($dataInfo['check_status'], ['2','3'])) {
140
+            $this->error = '审批已经结束!';
141
+            return false;
142
+        }        
143
+        if ($dataInfo['flow_id'] > 0) {
144
+            //固定流程
145
+            //当前步骤已审批user_id
146
+            $check_user_ids = $this->getUserByCheck($types, $types_id, $dataInfo['order_id']);
147
+            if (in_array($user_id, $check_user_ids)) {
148
+                $this->error = '您已审核,请勿重复操作!';
149
+                return false;            
150
+            }
151
+            $examine_user_id_arr = array();
152
+            // $examine_user_id_arr = $this->getUserByStep($stepInfo['step_id'], $dataInfo['create_user_id']); //获取审批步骤审批人
153
+            $examine_user_id_arr = $dataInfo['check_user_id']; //获取审批步骤审批人
154
+            $examine_user_id_arr = stringToArray($examine_user_id_arr);
155
+        } else {
156
+            $examine_user_id_arr = $this->getUserByPer($types);
157
+        }
158
+    	if (!in_array($user_id, $examine_user_id_arr)) { 		
159
+			$this->error = '没有权限';
160
+  			return false;   		
161
+    	}
162
+        return true;
163
+    }
164
+
165
+	/**
166
+     * 审批对象获取审批相关信息
167
+     * @param  types 关联对象
168
+     * @param  types_id 联对象ID
169
+	 * @return
170
+     */   
171
+    public function getDataByTypes($types, $types_id)
172
+    {
173
+    	if (empty($types) || empty($types_id)) {
174
+    		$this->error = '参数错误';
175
+    		return false;
176
+    	}
177
+
178
+    	switch (trim($types)) {
179
+    		case 'oa_examine' : $dataInfo = db('oa_examine')->where(['examine_id' => intval($types_id)])->field('create_user_id,check_user_id,flow_id,order_id,check_status,update_time')->find(); break;
180
+            case 'crm_contract' : $dataInfo = db('crm_contract')->where(['contract_id' => intval($types_id)])->field('create_user_id,owner_user_id,check_user_id,flow_id,order_id,check_status,update_time')->find(); break;
181
+            case 'crm_receivables' : $dataInfo = db('crm_receivables')->where(['receivables_id' => intval($types_id)])->field('create_user_id,owner_user_id,check_user_id,flow_id,order_id,check_status,update_time')->find(); break;
182
+            case 'crm_invoice': $dataInfo = db('crm_invoice')->where(['invoice_id' => intval($types_id)])->field('create_user_id,owner_user_id,check_user_id,flow_id,order_id,check_status,update_time')->find(); break;
183
+    	}
184
+        $stepInfo = [];
185
+        if ($dataInfo['flow_id'] && !in_array($dataInfo['check_status'],['5'])) {
186
+            //固定审批流
187
+            $stepInfo = db('admin_examine_step')->where(['flow_id' => $dataInfo['flow_id'],'order_id' => $dataInfo['order_id']])->find();
188
+        }
189
+    	$data = [];
190
+    	$data['stepInfo'] = $stepInfo;
191
+    	$data['step_id'] = $stepInfo['step_id'] ? : '';
192
+    	$data['dataInfo'] = $dataInfo;
193
+    	return $data;
194
+    } 
195
+
196
+    /**
197
+     * 获取审批步骤审批人信息
198
+     * @param  step_id 审批步骤ID
199
+     * @param  status 1负责人主管,2指定用户(任意一人),3指定用户(多人会签),4上一级审批人主管
200
+     * @param  user_id  审批主体,申请人user_id
201
+     * @return
202
+     */   
203
+    public function getUserByStep($step_id, $user_id)
204
+    {
205
+        $stepInfo = db('admin_examine_step')->where(['step_id' => $step_id])->find();
206
+        $examine_user_id_arr = [];
207
+        //固定审批流
208
+        switch ($stepInfo['status']) {
209
+            case 1 :
210
+                $examine_user_id = db('admin_user')->where(['id' => $user_id])->value('parent_id');
211
+                if ($examine_user_id) {
212
+                    $examine_user_id_arr[] = $examine_user_id;
213
+                } else {
214
+                    $examine_user_id_arr[] = 1;
215
+                }
216
+                break;
217
+            case 2 : 
218
+            case 3 :$examine_user_id_arr = stringToArray($stepInfo['user_id']); break;
219
+            case 4 : 
220
+                $order_id = $stepInfo['order_id'] ? $stepInfo['order_id']-1 : 0;
221
+                $last_step_id = db('admin_examine_step')->where(['flow_id' => $stepInfo['flow_id'],'order_id' => $order_id])->value('step_id');
222
+                $last_step_info = db('admin_examine_step')->where(['step_id' => $last_step_id])->find();
223
+                $last_user_id = $this->getUserByStep($last_step_id, $user_id);
224
+                if (count(stringToArray($last_user_id)) !== 1) {
225
+                    $this->error = '审批流程出错';
226
+                    return false;
227
+                }
228
+                $last_user_id_arr = stringToArray($last_user_id);
229
+                $examine_user_id = $this->getUserByStep($last_step_id, $last_user_id_arr[0]);
230
+                //$examine_user_id = db('admin_user')->where(['id' => $last_step_info['user_id']])->value('parent_id');
231
+                $examine_user_id_arr = [];
232
+                if ($examine_user_id) {
233
+                    $examine_user_id_arr = stringToArray($examine_user_id);
234
+                }       
235
+                break;
236
+            default : $examine_user_id_arr = [];
237
+        }
238
+        return array_unique($examine_user_id_arr) ? ','.implode(',',array_filter(array_unique($examine_user_id_arr))).',' : '';
239
+    } 
240
+
241
+    /**
242
+     * 获取当前步骤已审批的user_id
243
+     * @param  step_id 审批步骤ID
244
+     * @param  status 1审核通过0审核失败2撤销 
245
+     * @return
246
+     */
247
+    public function getUserByCheck($types, $types_id = 0, $order_id = 0, $status = 1)
248
+    {
249
+        if ($types_id == 0 && $order_id == 0) {
250
+            $check_user_ids = [];
251
+        } else {
252
+            $check_user_ids = db('admin_examine_record')->where(['types' => $types,'types_id' => $types_id,'order_id' => $order_id,'is_end' => 0,'status' => $status])->column('check_user_id');
253
+        }
254
+        return $check_user_ids ? : [];   
255
+    } 
256
+
257
+    /**
258
+     * 获取授权审批的user_id
259
+     * @param  step_id 审批步骤ID
260
+     * @param 
261
+     * @return
262
+     */ 
263
+    public function getUserByPer($types)
264
+    {
265
+        if (!in_array($types,['oa_examine','crm_contract','crm_receivables'])) {
266
+            $this->error = '参数错误';
267
+            return false;
268
+        }
269
+        $userModel = new \app\admin\model\User();
270
+        $adminUserId = model('User')->getAdminId(); //管理员ID
271
+        //获取有审核权限的user_id
272
+        switch ($types) {
273
+            case 'oa_examine' : $examine_user_id_arr = $userModel->getUserByPer('oa', 'examine', 'check'); break;
274
+            case 'crm_contract' : $examine_user_id_arr = $userModel->getUserByPer('crm', 'contract', 'check'); break;
275
+            case 'crm_receivables' : $examine_user_id_arr = $userModel->getUserByPer('crm', 'receivables', 'check'); break;
276
+            case 'crm_invoice' : $examine_user_id_arr = $userModel->getUserByPer('crm', 'invoice', 'check'); break;
277
+        }
278
+        $examine_user_id_arr = $examine_user_id_arr ? array_merge($examine_user_id_arr, $adminUserId) : $adminUserId;
279
+        return $examine_user_id_arr;
280
+    }  
281
+
282
+    /**
283
+     * 获取审批步骤相关userId
284
+     * @param  flow_id 流程ID
285
+     * @param  order_id 排序ID
286
+     * @return
287
+     */
288
+    public function getStepUserByOrder($flow_id, $order_id, $user_id)
289
+    {
290
+        $user_ids = [];
291
+        if ($flow_id && $order_id) {
292
+            $stepInfo = db('admin_examine_step')->where(['flow_id' => $flow_id,'order_id' => $order_id])->find();
293
+            $user_ids = $this->getUserByStep($stepInfo['step_id'], $user_id);
294
+        }
295
+        return $user_ids ? : [];
296
+    }
297
+
298
+    /**
299
+     * 获取有效审批步骤列表(固定审批)
300
+     * @param  flow_id 审批流程ID
301
+     * @param  user_id 审批申请人ID
302
+     * @param  check_user_id 当前操作人ID
303
+     * @return
304
+     */ 
305
+    public function getStepList($flow_id, $user_id, $types, $types_id = 0, $check_user_id = 0, $action = '', $category_id = '')
306
+    {
307
+        $userModel = new \app\admin\model\User();
308
+        $newlist = [];
309
+        
310
+        $dataInfo['order_id'] = 0;
311
+        if ($types_id) {
312
+            $typesInfo = $this->getDataByTypes($types, $types_id);
313
+            $dataInfo = $typesInfo['dataInfo'];
314
+        }
315
+
316
+        $is_check = 0; //审批权限(1有)
317
+        $is_recheck = 0; //撤销审批权限(1有)
318
+
319
+        $admin_user_ids = $userModel->getAdminId();
320
+        //创建人或负责人或管理员有撤销权限
321
+        //if ($dataInfo['create_user_id'] == $check_user_id || $dataInfo['owner_user_id'] == $check_user_id || in_array($check_user_id, $admin_user_ids)) {
322
+        if ($dataInfo['create_user_id'] == $check_user_id || $dataInfo['owner_user_id'] == $check_user_id) {
323
+            if (!in_array($dataInfo['check_status'],['2','3','4'])) {
324
+                $is_recheck = 1;
325
+            }
326
+        }
327
+        if (in_array($check_user_id, stringToArray($dataInfo['check_user_id'])) && !in_array($dataInfo['check_status'],['2','3'])) {
328
+            $is_check = 1;
329
+        }
330
+
331
+        if ($action == 'view') {
332
+
333
+            $createUserInfo = $userModel->getUserById($dataInfo['create_user_id']);
334
+            $createUserInfo['check_time'] = !empty($dataInfo['update_time']) ? date('Y-m-d H:i:s', $dataInfo['update_time']) : null;
335
+            if ($dataInfo['check_status'] == 4) {
336
+                $createUserInfo['check_type'] = 2;
337
+                $newlist[0]['type'] = '2'; //撤销
338
+            } else {
339
+
340
+                $createUserInfo['check_type'] = 3;
341
+                $newlist[0]['type'] = '3'; //创建
342
+            }
343
+            $newlist[0]['user_id_info'] = array($createUserInfo);
344
+            $newlist[0]['time'] = !empty($dataInfo['update_time']) ? date('Y-m-d H:i:s', $dataInfo['update_time']) : null;
345
+        }
346
+        $stepList = [];
347
+        if ($dataInfo['check_status'] !== 4 || $action !== 'view') {
348
+            $list = db('admin_examine_step')->where(['flow_id' => $flow_id])->order('order_id asc')->select();
349
+            $is_break = false;
350
+            foreach ($list as $k=>$v) {
351
+                $type = 4;
352
+                $examine_user_ids = '';
353
+                //判断步骤审批人是否存在
354
+                $examine_user_ids = $this->getUserByStep($v['step_id'], $user_id);
355
+                $examine_user_arr = stringToArray($examine_user_ids);
356
+                if ($examine_user_arr) {
357
+                    $newStepInfo = $v;
358
+                    $user_id_info_arr = [];
359
+                    foreach ($examine_user_arr as $key=>$val) {
360
+                        $user_id_info = [];
361
+                        $user_id_info = $userModel->getUserById($val);
362
+                        $check_type = 4; //type 0失败,1通过,2撤销,3创建,4待审核,5未提交
363
+                        //当前步骤已审批user_id
364
+                        $check_user_ids = [];
365
+                        $check_user_ids = $this->getUserByCheck($types, $types_id, $v['order_id'], 1);
366
+                        if (in_array($val, $check_user_ids)) {
367
+                            $check_type = 1;
368
+                            $type = !empty($dataInfo['check_user_id']) ? 4 : 1;
369
+                        }
370
+                        $re_check_user_ids = $this->getUserByCheck($types, $types_id, $v['order_id'], 2); //撤销人员
371
+                        if ($dataInfo['check_status'] == 4) {
372
+                            if ($re_check_user_ids) {
373
+                                $is_break = true;
374
+                                $check_type = 2;
375
+                                $type = 2;
376
+                            }
377
+                        }
378
+                        $fail_check_user_ids = $this->getUserByCheck($types, $types_id, $v['order_id'], 0); //拒绝人员
379
+                        if ($dataInfo['check_status'] == 3) {
380
+                            if (in_array($val,$fail_check_user_ids)) {
381
+                                $is_break = true;
382
+                                $check_type = 0;
383
+                                $type = 0;
384
+                            }
385
+                            //if ($action == 'view') break;
386
+                        }
387
+                        $user_id_info['check_type'] = $check_type;
388
+                        $check_time = '';
389
+                        $check_time = db('admin_examine_record')->where(['types' => $types,'types_id' => $types_id,'flow_id' => $flow_id,'order_id' => $v['order_id'],'check_user_id' => $val,'is_end' =>0])->value('check_time');
390
+                        $user_id_info['check_time'] = !empty($check_time) ? date('Y-m-d H:i:s', $check_time) : '';
391
+                        $user_id_info_arr[] = $user_id_info;
392
+                    }
393
+                    $newStepInfo['user_id'] = $examine_user_ids;
394
+                    $newStepInfo['user_id_info'] = $user_id_info_arr;
395
+                    if ($dataInfo['order_id'] > $v['order_id']) {
396
+                        $type = 1;
397
+                    }
398
+                    //if ($is_break !== false) break; 
399
+                    $newStepInfo['type'] = $type;          
400
+                    $stepList[] = $newStepInfo;
401
+                }
402
+            }            
403
+        }
404
+        $newStepList = [];
405
+        if ($newlist && $stepList) {
406
+            $newStepList = array_merge($newlist, $stepList);
407
+        } elseif ($stepList) {
408
+            $newStepList = $stepList;
409
+        } else {
410
+            $newStepList = $newlist;
411
+        }
412
+        $data['steplist'] = $newStepList ? : [];
413
+        $data['is_check'] = $is_check;
414
+        $data['is_recheck'] = $is_recheck;
415
+        return $data ? : [];
416
+    }
417
+
418
+    /**
419
+     * 根据order_id获取审批步骤
420
+     * @param  flow_id 审批流程ID
421
+     * @param  order_id 审批排序ID
422
+     * @return
423
+     */ 
424
+    public function getStepByOrder($flow_id, $order_id)
425
+    {
426
+        $data = db('admin_examine_step')->where(['flow_id' => $flow_id,'order_id' => $order_id])->find();
427
+        return $data ? : [];
428
+    } 
429
+
430
+    /**
431
+     * 获取有效审批步骤列表(自选审批)
432
+     * @param  types 类型
433
+     * @param  types_id 类型ID
434
+     * @param  action 操作类型: view、save
435
+     * @return
436
+     */ 
437
+    public function getPerStepList($types, $types_id, $user_id, $check_user_id, $action = '')
438
+    {
439
+        $examineRecordModel = new \app\admin\model\ExamineRecord();
440
+        $userModel = new \app\admin\model\User();
441
+        $userList = [];
442
+        //有效的审批记录
443
+        $where = [];
444
+        $where['types'] = $types;
445
+        $where['types_id'] = $types_id;
446
+        $where['is_end'] = 0;
447
+        $recordList = $examineRecordModel->getDataList($where);
448
+    
449
+        $typeInfo = $this->getDataByTypes($types, $types_id);
450
+        $dataInfo = $typeInfo['dataInfo'];
451
+        $createUserInfo = $userModel->getUserById($dataInfo['create_user_id']);
452
+        $userList[0]['userInfo'] = $createUserInfo;
453
+        $userList[0]['type'] = 3; //创建
454
+        $userList[0]['time'] = $dataInfo['update_time'] ? : '';
455
+ 
456
+        //type 0失败,1通过,2撤销,3创建,4待审核,5未提交
457
+        $i = 1;
458
+        foreach ($recordList as $k=>$v) {
459
+            $userList[$i]['userInfo'] = $userModel->getUserById($v['check_user_id']);
460
+            $userList[$i]['type'] = $v['status'];
461
+            $userList[$i]['time'] = $v['check_time'];
462
+            $i++;
463
+        }
464
+        if ($dataInfo['check_status'] <= 1 && $dataInfo['check_user_id']) {
465
+            $check_user_id_arr = stringToArray($dataInfo['check_user_id']);
466
+            $userList[$i]['userInfo'] = $userModel->getUserById($check_user_id_arr[0]);
467
+            $userList[$i]['type'] = '4';
468
+        }
469
+        if ($dataInfo['check_status'] == 5 && $dataInfo['check_user_id']) {
470
+            $userList = [];
471
+            $check_user_id_arr = stringToArray($dataInfo['check_user_id']);
472
+            $userList[0]['userInfo'] = $userModel->getUserById($check_user_id_arr[0]);
473
+            $userList[0]['type'] = '5';
474
+        }        
475
+        $is_check = 0; //审批权限(1有)
476
+        $is_recheck = 0; //撤销审批权限(1有)
477
+
478
+        $admin_user_ids = $userModel->getAdminId();
479
+        //创建人或负责人或管理员有撤销权限
480
+//        if ($dataInfo['create_user_id'] == $check_user_id || $dataInfo['owner_user_id'] == $check_user_id || in_array($check_user_id, $admin_user_ids)) {
481
+        if ($dataInfo['create_user_id'] == $check_user_id || $dataInfo['owner_user_id'] == $check_user_id) {
482
+            if (!in_array($dataInfo['check_status'],['2','3','4','5'])) {
483
+                $is_recheck = 1;
484
+            }
485
+        }
486
+        if (in_array($check_user_id, stringToArray($dataInfo['check_user_id'])) && !in_array($dataInfo['check_status'],['2','3','5'])) {
487
+            $is_check = 1;
488
+        }
489
+
490
+        $data['steplist'] = $userList;
491
+        $data['is_check'] = $is_check;
492
+        $data['is_recheck'] = $is_recheck;
493
+        return $data ? : [];
494
+    }           
495
+}

+ 2332
- 0
application/admin/model/Excel.php
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 1714
- 0
application/admin/model/Field.php
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 570
- 0
application/admin/model/File.php Целия файл

@@ -0,0 +1,570 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 附件
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use app\admin\model\Common;
11
+use app\crm\model\Activity;
12
+use app\crm\model\Invoice;
13
+use think\Db;
14
+use think\Request;
15
+
16
+class File extends Common 
17
+{
18
+
19
+    /**
20
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
21
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
22
+     */
23
+	protected $name = 'admin_file';
24
+	protected $module_arr = [
25
+	    'other',
26
+        'crm_leads',
27
+        'crm_customer',
28
+        'crm_contacts',
29
+        'crm_business',
30
+        'crm_product',
31
+        'crm_contract',
32
+        'oa_log',
33
+        'oa_examine',
34
+        'oa_examine_travel',
35
+        'work_task',
36
+        'admin_record',
37
+        'oa_travel',
38
+        'hrm_pact',
39
+        'hrm_file',
40
+        'crm_invoice',
41
+        'crm_activity',
42
+        'crm_visit',
43
+        'crm_receivables'
44
+    ];
45
+	
46
+	/**
47
+	 * [createData 添加附件]
48
+	 * @author Michael_xu
49
+	 * @param     $files 附件数组 
50
+	 * @param     $param [module : 模块, module_id : 模块ID]
51
+	 * @param     $x 裁剪图的长 ,$y 裁剪图的宽
52
+	 * @return    [array]                         
53
+	 */
54
+	public function createData($files, $param = [], $x = '150', $y = '150')
55
+	{	
56
+        if (empty($files)) {
57
+			$this->error = '请选择上传文件';
58
+			return false;
59
+        }
60
+        $resData = [];
61
+        $get_filesize_byte = get_upload_max_filesize_byte();
62
+        foreach ($files as $k=>$v) {
63
+        	$info = '';
64
+            $upload_name = $v['obj']->getInfo()['name'];
65
+            if ($upload_name == 'blob') {
66
+                $upload_name = 'logo.png';
67
+                $new_info = [];
68
+                $new_info = $v['obj']->getInfo();
69
+                $new_info['name'] = $upload_name;
70
+                $v['obj']->setUploadInfo($new_info);
71
+            }
72
+			$info = $v['obj']->validate(['size'=>$get_filesize_byte,'ext'=>'jpg,jpeg,png,gif,zip,rar,doc,docx,xls,xlsx,ppt,pptx,txt,pdf,csv'])->move(FILE_PATH . 'public' . DS . 'uploads'); //验证规则
73
+			// getimagesize($file["tmp_name"]
74
+			if (!$info) {
75
+				$this->error = $v['obj']->getError();
76
+				return false;
77
+				//$resData[$k] = ['key' => $k,'name' => $fileInfo['name'],'status' => 0,'error' => $v['obj']->getError()];
78
+				break;
79
+			}
80
+			$fileInfo = $info->getInfo(); //附件数据
81
+			$rSuccess = false;
82
+			$ext = '';
83
+			$saveName = '';
84
+			$thumbSaveName = '';
85
+			if ($info) {
86
+				//如果是图片类型,生成缩略图
87
+	            $ext = $info->getExtension();	           
88
+	            $saveName = $info->getSaveName();
89
+	            $fileName = $info->getFilename();
90
+	            if (in_array($ext, ['jpg','png','jpeg']) && $fileInfo['size'] < 8388608) {
91
+	                // $image = \think\Image::open($v['obj']);
92
+	                $image = \think\Image::open(UPLOAD_PATH . str_replace(DS, '/', $saveName));
93
+	                $thumbSaveName = str_replace(DS, DS.'thumb_', $saveName);
94
+	                $image->thumb($x, $y,\think\Image::THUMB_FILLED)->save(FILE_PATH . 'public'. DS .'uploads'. DS .$thumbSaveName); //THUMB_SCALING 或 THUMB_FILLED
95
+	            } 
96
+	            if ($ext == 'gif') {
97
+	            	$thumbSaveName = $saveName;
98
+	            } 
99
+	            //附件信息存储
100
+	            $saveData = [];
101
+	            $saveData['name'] = $fileInfo['name'];
102
+	            $saveData['size'] = $fileInfo['size'];
103
+	            $saveData['create_user_id'] = $param['create_user_id'];
104
+	            $saveData['create_time'] = time();
105
+	            $saveData['file_path'] = UPLOAD_PATH . str_replace(DS, '/', $saveName);
106
+	            $saveData['file_path_thumb'] = $thumbSaveName ? UPLOAD_PATH . str_replace(DS, '/', $thumbSaveName) : '';
107
+	            $saveData['save_name'] = str_replace(DS, '/', $saveName);
108
+	            $saveData['types'] = $v['types'] ? : 'file';
109
+	            if ($k > 0) {
110
+					$this->data($saveData)->allowField(true)->isUpdate(false)->save();
111
+	            } else {
112
+					$this->data($saveData)->allowField(true)->save();
113
+	            }
114
+	            
115
+	            $file_id = $this->file_id;
116
+	            if ($file_id) {
117
+	            	$rSuccess = true;
118
+	            	//如果是关系表,则保存关系表数据
119
+		            if (in_array($param['module'],$this->module_arr) && $param['module_id']) {
120
+		            	switch ($param['module']) {
121
+		            		case 'crm_leads' : $r = db('crm_leads_file'); $r_name = 'leads_id'; break;
122
+		            		case 'crm_customer' : $r = db('crm_customer_file'); $r_name = 'customer_id'; break;
123
+		            		case 'crm_contacts' : $r = db('crm_contacts_file'); $r_name = 'contacts_id'; break;
124
+		            		case 'crm_business' : $r = db('crm_business_file'); $r_name = 'business_id'; break;
125
+		            		case 'crm_product' : $r = db('crm_product_file'); $r_name = 'product_id'; break;
126
+		            		case 'crm_contract' : $r = db('crm_contract_file'); $r_name = 'contract_id'; break;
127
+		            		case 'oa_log' : $r = db('oa_log_file'); $r_name = 'log_id'; break;
128
+		            		case 'oa_examine' : $r = db('oa_examine_file'); $r_name = 'examine_id'; break;
129
+		            		case 'work_task' : $r = db('work_task_file'); $r_name = 'task_id'; break;
130
+		            		case 'admin_record' : $r = db('admin_record_file'); $r_name = 'record_id'; break;
131
+		            		case 'oa_travel' : $r = db('oa_travel_file'); $r_name = 'travel_id'; break;
132
+							case 'hrm_pact' : $r = db('hrm_pact_file'); $r_name = 'pact_id'; break;
133
+							case 'hrm_file' : $r = db('hrm_user_file'); $r_name = 'user_id'; break;
134
+                            case 'crm_invoice' : $r = db('crm_invoice_file'); $r_name = 'invoice_id'; break;
135
+                            case 'crm_activity': $r = db('crm_activity_file'); $r_name = 'activity_id'; break;
136
+                            case 'crm_visit': $r = db('crm_visit_file'); $r_name = 'visit_id'; break;
137
+                            case 'crm_receivables': $r = db('crm_receivables_file'); $r_name = 'receivables_id'; break;
138
+		            		default : break;
139
+		            	}
140
+		            	$rData = [];
141
+		            	$rData[$r_name] = intval ($param['module_id']);
142
+		            	$rData['file_id'] = $file_id;
143
+		            	$rRes = $r->insert($rData);
144
+		            	if (!$rRes) {
145
+		            		$rSuccess = false;
146
+							//删除文件
147
+			            	@unlink($saveData['file_path']);
148
+			            	@unlink($saveData['file_path_thumb']);		            		
149
+		            	}
150
+		            }
151
+	            }
152
+	            if ($rSuccess !== false) {
153
+	            	$path =  (UPLOAD_PATH.$saveName);
154
+	            	# 应前端要求,将url字段改成跟path一样的内容,格式改为一位数组
155
+                    $resData = ['key' => $k, 'name' => $fileInfo['name'], 'status' => 1, 'path' => getFullPath($path), 'save_name' => str_replace(DS, '/', $saveName), 'url' => getFullPath($path), 'size' => format_bytes($fileInfo['size']), 'file_id' => $file_id];
156
+	            } else {
157
+	            	$resData[$k] = ['key' => $k,'name' => $fileInfo['name'],'status' => 0,'error' => '上传出错'];
158
+	            }
159
+			} else {
160
+				$resData[$k] = ['key' => $k,'name' => $fileInfo['name'],'status' => 0,'error' => $v['obj']->getError()];
161
+			}
162
+        }
163
+        return $resData;		
164
+	}
165
+
166
+	/**
167
+	 * 修改上传文件名
168
+	 * @param  [type] $save_name [description]
169
+	 * @param  [type] $name      [description]
170
+	 * @return [type]            [description]
171
+	 */
172
+	public function updateNameBySaveName($save_name,$name)
173
+	{
174
+		$flag = $this->where(['save_name' => $save_name])->setField('name',$name);
175
+		if ( $flag ) {
176
+			return true;
177
+		} else {
178
+			$this->error = '操作失败';
179
+			return false;
180
+		}
181
+	}
182
+
183
+	/**
184
+	 * [delFileById 删除附件]
185
+	 * @author Michael_xu
186
+	 * @param     $save_name 附件保存名称 
187
+	 * @param     $param [module : 模块, module_id : 模块ID]
188
+	 * @return    [array]                         
189
+	 */	
190
+	public function delFileBySaveName($save_name, $param = [])
191
+	{
192
+		if (!$save_name) {
193
+			$this->error = '请选择需要删除的附件';
194
+			return false;    
195
+		}
196
+		$fileInfo = $this->where(['save_name' => trim($save_name)])->find();
197
+		if (!$fileInfo) {
198
+			$this->error = '附件不存在或已删除';
199
+			return false;
200
+		}
201
+		$file_id = $fileInfo['file_id'];
202
+		$res = db('admin_file')->where(['file_id' => $file_id])->delete();
203
+		if ($res) {
204
+			@unlink($fileInfo['file_path']);//删除文件
205
+			if ($fileInfo['file_path_thumb']) @unlink($fileInfo['file_path_thumb']);
206
+			//处理附表信息
207
+			if (in_array($param['module'], $this->module_arr)) {
208
+				switch ($param['module']) {
209
+					case 'crm_leads' : $r = db('crm_leads_file'); break;
210
+					case 'crm_customer' : $r = db('crm_customer_file'); break;
211
+            		case 'crm_contacts' : $r = db('crm_contacts_file'); break;
212
+            		case 'crm_business' : $r = db('crm_business_file'); break;
213
+            		case 'crm_product' : $r = db('crm_product_file'); break;
214
+            		case 'crm_contract' : $r = db('crm_contract_file'); break;
215
+            		case 'oa_log' : $r = db('oa_log_file'); break;
216
+            		case 'oa_examine' : $r = db('oa_examine_file'); break;
217
+            		case 'work_task' : $r = db('work_task_file'); break;
218
+            		case 'admin_record' : $r = db('admin_record_file'); break;
219
+            		case 'oa_travel' : $r = db('oa_travel_file'); break;
220
+					case 'hrm_pact' : $r = db('hrm_pact_file'); break;
221
+					case 'hrm_file' : $r = db('hrm_user_file'); break;
222
+                    case 'crm_invoice' : $r = db('crm_invoice_file'); break;
223
+                    case 'crm_activity': $r = db('crm_activity_file'); break;
224
+                    case 'crm_visit': $r = db('crm_visit_file'); break;
225
+                    case 'crm_receivables': $r = db('crm_receivables_file'); break;
226
+            		default : break;
227
+				}
228
+				$resDel = $r->where(['file_id'=>$file_id])->delete();
229
+			}
230
+			return true;
231
+		} else {
232
+			$this->error = '删除失败';
233
+			return false;
234
+		}
235
+	}
236
+
237
+	/**
238
+	 * 根据主键获取详情
239
+	 * @author Michael_xu
240
+	 * @param  array   $param  [description]
241
+	 */ 
242
+	public function getDataBySaveName($save_name = '')
243
+	{
244
+		if (!$save_name) {
245
+			$this->error = '参数错误';
246
+			return false;
247
+		}
248
+		$data = $this->where(['save_name' => trim($save_name)])->find();
249
+		$data['full_path'] = getFullPath($data['file_path']);
250
+		$data['full_path_thumb'] = getFullPath($data['file_path_thumb']);
251
+		if (!$data) {
252
+			$this->error = '数据不存在或已删除';
253
+			return false;
254
+		}
255
+		return $data;		
256
+	}
257
+
258
+	/**
259
+	 * 根据ID获取列表
260
+	 * @author Michael_xu
261
+	 * @param  string   module  [类型]
262
+	 * @param  string   by = all 全部(不分页)
263
+	 * @param  int   module_id  [类型ID]
264
+	 */	 
265
+	public function getDataList($request, $by = '')
266
+	{   
267
+		if (!in_array($request['module'], $this->module_arr) || !$request['module_id']) {
268
+			$this->error = '参数错误';
269
+			return false;
270
+		}
271
+		$module_ids = $request['module_id'];
272
+		if (!is_array($request['module_id'])) {
273
+			$module_ids = array($request['module_id']);
274
+		}
275
+
276
+		switch ($request['module']) {
277
+			case 'crm_leads' : $r = db('crm_leads_file'); $module = db('crm_leads'); break;
278
+			case 'crm_customer' : $r = db('crm_customer_file'); $module = db('crm_customer'); break;
279
+			case 'crm_contacts' : $r = db('crm_contacts_file'); $module = db('crm_contacts'); break;
280
+			case 'crm_business' : $r = db('crm_business_file'); $module = db('crm_business'); break;
281
+			case 'crm_product' : $r = db('crm_product_file'); $module = db('crm_product'); break;
282
+			case 'crm_contract' : $r = db('crm_contract_file'); $module = db('crm_contract'); break;
283
+			case 'oa_log' : $r = db('oa_log_file'); $module = db('oa_log'); break;
284
+			case 'oa_examine' : $r = db('oa_examine_file'); $module = db('oa_examine'); break;
285
+			case 'oa_examine_travel' : $r = db('oa_examine_travel_file'); $module = db('oa_examine_travel'); break;
286
+			case 'work_task' : $r = db('work_task_file'); $module = db('task'); break;
287
+			case 'admin_record' : $r = db('admin_record_file'); $module = db('admin_record'); break;
288
+			case 'oa_travel' : $r = db('oa_travel_file'); $module = db('oa_travel'); break;
289
+			case 'hrm_pact' : $r = db('hrm_pact_file'); $module = db('hrm_pact'); break;
290
+			case 'hrm_file' : $r = db('hrm_user_file'); $module = db('admin_user'); break;
291
+            case 'crm_invoice' : $r = db('crm_invoice_file'); $module = db('crm_invoice'); break;
292
+            case 'crm_activity' : $r = db('crm_activity_file'); $module = db('crm_activity'); break;
293
+            case 'crm_visit' : $r = db('crm_visit_file'); $module = db('crm_visit'); break;
294
+            case 'crm_receivables' : $r = db('crm_receivables_file'); $module = db('crm_receivables'); break;
295
+			default : break;
296
+		}
297
+		if ($r) {
298
+			$fileIds = $r->where([$module->getPk() => ['in',$module_ids]])->column('file_id');
299
+			$request['file_id'] = ['in', $fileIds];			
300
+		}
301
+		unset($request['module']);
302
+		unset($request['module_id']);
303
+		unset($request['by']);
304
+
305
+		$userModel = new \app\admin\model\User();
306
+		$request = $this->fmtRequest( $request );
307
+        $map = $request['map'];
308
+        $order = 'create_time desc';
309
+        $dataCount = $this->where($map)->count('file_id');
310
+        if ($by == 'all') {
311
+        	$list = Db::name('AdminFile')->where($map)->order($order)->select();
312
+        } else {
313
+        	$list = Db::name('AdminFile')->where($map)->page($request['page'], $request['limit'])->order($order)->select();	
314
+        }
315
+        foreach ($list as $k=>$v) {
316
+            $createUserInfo = isset($v['create_user_id']) ? $userModel->getUserById($v['create_user_id']) : [];
317
+        	$list[$k]['size'] = format_bytes($v['size']); //字节转换
318
+        	$list[$k]['create_time'] = date('Y-m-d H:i:s',$v['create_time']);
319
+        	$list[$k]['create_user_id_info'] = $createUserInfo;
320
+        	$list[$k]['createName'] = !empty($createUserInfo['realname']) ? $createUserInfo['realname'] : '';
321
+        	$list[$k]['ext'] = getExtension($v['save_name']);
322
+        	$list[$k]['file_path'] = getFullPath($v['file_path']);
323
+        	$list[$k]['file_path_thumb'] = getFullPath($v['file_path_thumb']);
324
+        }
325
+        $data = [];
326
+        $data['list'] = $list ? : [];
327
+        $data['dataCount'] = $dataCount ? : 0;
328
+        return $data;		
329
+	}
330
+	
331
+	/**
332
+	 * 根据表、字段更新上传图片
333
+	 * @author Michael_xu
334
+	 * @param  $file 附件信息
335
+	 * @param  $module 模块(判断权限),一般是控制器,并且和表名一致
336
+	 * @param  $module_id 模块ID(判断权限)
337
+	 * @param  $file 字段
338
+	 * @param  $thumb_field 缩略图字段
339
+	 * @param  $x 裁剪宽度
340
+	 * @param  $y 裁剪高度
341
+	 */	
342
+	public function updateByField($file, $module, $module_id, $field, $thumb_field = '', $x = '150', $y = '150')
343
+	{
344
+		if (empty($module) || empty($module_id) || empty($field)) {
345
+			$this->error = '参数错误';
346
+			return false;
347
+		}
348
+		
349
+		$info = $file->move(FILE_PATH . 'public' . DS . 'uploads'); //验证规则
350
+		$fileInfo = $info->getInfo(); //附件数据
351
+		$saveName = '';
352
+		$thumbSaveName = '';
353
+		if ($info) {
354
+			//如果是图片类型,生成缩略图
355
+            $ext = $info->getExtension();	           
356
+            $saveName = $info->getSaveName();
357
+            $fileName = $info->getFilename();
358
+            $thumbSaveName = str_replace(DS, DS.'thumb_', $saveName);
359
+			//附件信息存储
360
+            $saveData = [];
361
+
362
+            if ($thumb_field) {
363
+            	// $image = \think\Image::open($file);
364
+            	$image = \think\Image::open(UPLOAD_PATH . str_replace(DS, '/', $saveName));
365
+            	$thumbSaveName = str_replace(DS, DS.'thumb_', $saveName);
366
+            	$image->thumb($x, $y,\think\Image::THUMB_FILLED)->save(FILE_PATH . 'public'. DS .'uploads'. DS .$thumbSaveName); //THUMB_SCALING 或 THUMB_FILLED
367
+            	$saveData[$thumb_field] = $thumbSaveName ? UPLOAD_PATH . str_replace(DS, '/', $thumbSaveName) : '';
368
+            }
369
+            $saveData[$field] = UPLOAD_PATH . str_replace(DS, '/', $saveName);  
370
+            switch ($module) {
371
+            	case 'crm_customer' : $moduleModel = new \app\crm\model\Customer(); break;
372
+				case 'crm_contacts' : $moduleModel = new \app\crm\model\Contacts(); break;
373
+				case 'crm_business' : $moduleModel = new \app\crm\model\Business(); break;
374
+				case 'crm_product' : $moduleModel = new \app\crm\model\Product(); break;
375
+				case 'crm_contract' : $moduleModel = new \app\crm\model\Contract(); break;		
376
+				case 'User' : $moduleModel = new \app\admin\model\User(); break;
377
+				case 'admin_system': $moduleModel = new \app\admin\model\System(); break;
378
+                case 'crm_invoice' : $moduleModel = new Invoice(); break;
379
+                case 'crm_activity' : $moduleModel = new Activity(); break;
380
+                case 'crm_receivables' : $moduleModel = new \app\crm\model\Receivables(); break;
381
+                case 'crm_visit' : $moduleModel = new \app\crm\model\Visit(); break;
382
+            }
383
+
384
+            $resFile = $moduleModel->allowField([$field,$thumb_field])->save($saveData, [$moduleModel->getPk() => $module_id]);
385
+            if (!$resFile) {
386
+				$this->error = '上传失败';
387
+            	return false;            	
388
+            }
389
+            return true;
390
+        }		
391
+	}
392
+
393
+	/**
394
+	 * 根据ID保存,处理逻辑关系
395
+	 * @author Michael_xu
396
+	 * @param  $ids 附件ID数组
397
+	 * @param  $module 表名
398
+	 * @param  $module_id 模块ID
399
+	 */	
400
+	public function createDataById($ids, $module, $module_id)
401
+	{
402
+		if (!$ids || !in_array($module, $this->module_arr) || !$module_id) {
403
+			$this->error = '参数错误';
404
+			return false;
405
+		}
406
+
407
+		switch (trim($module)) {
408
+			case 'crm_customer' : $rDb = db('crm_customer_file'); $r_name = 'customer_id'; break;
409
+			case 'crm_contacts' : $rDb = db('crm_contacts_file'); $r_name = 'contacts_id'; break;
410
+			case 'crm_business' : $rDb = db('crm_business_file'); $r_name = 'business_id'; break;
411
+			case 'crm_product' : $rDb = db('crm_product_file'); $r_name = 'product_id'; break;
412
+			case 'crm_contract' : $rDb = db('crm_contract_file'); $r_name = 'contract_id'; break;
413
+			case 'oa_log' : $rDb = db('oa_log_file'); $r_name = 'log_id'; break;
414
+			case 'oa_examine' : $rDb = db('oa_examine_file'); $r_name = 'examine_id'; break;
415
+			case 'oa_examine_travel' : $rDb = db('oa_examine_travel_file'); $r_name = 'travel_id'; break;
416
+			case 'admin_record' : $rDb = db('admin_record_file'); $r_name = 'record_id'; break;
417
+			case 'oa_travel' : $rDb = db('oa_travel_file'); $r_name = 'travel_id'; break;
418
+            case 'crm_invoice' : $rDb = db('crm_invoice_file'); $r_name = 'invoice_id'; break;
419
+            case 'crm_activity' : $rDb = db('crm_activity_file'); $r_name = 'activity_id'; break;
420
+            case 'crm_visit' : $rDb = db('crm_visit_file'); $r_name = 'activity_id'; break;
421
+            case 'crm_receivables' : $rDb = db('crm_receivables_file'); $r_name = 'receivables_id'; break;
422
+		}
423
+
424
+		$res_success = true;
425
+		$data = [];
426
+		$data[$r_name] = intval ($module_id);
427
+		foreach ($ids as $v) {
428
+			$data['file_id'] = intval($v);
429
+			if (!$rDb->insert($data)) {
430
+				$res_success = false;
431
+			}
432
+		}
433
+		if ($res_success == false) {
434
+			$this->error = '附件上传失败';
435
+		}
436
+		return true;
437
+	}
438
+
439
+
440
+	/**
441
+	 * 删除关系表附件
442
+	 * @author Michael_xu
443
+	 * @param  $module 模块
444
+	 * @param  $module_id 模块ID
445
+	 */	
446
+	public function delRFileByModule($module, $module_id)
447
+	{
448
+		if (in_array($module,$this->module_arr) && $module_id) {
449
+        	switch ($module) {
450
+        		case 'crm_leads' : 
451
+        			$r = db('crm_leads_file'); 
452
+        			$r_name = 'leads_id'; 
453
+        			break;
454
+        		case 'crm_customer' : 
455
+        			$r = db('crm_customer_file'); 
456
+        			$r_name = 'customer_id'; 
457
+        			break;
458
+        		case 'crm_contacts' : 
459
+        			$r = db('crm_contacts_file'); 
460
+        			$r_name = 'contacts_id'; 
461
+        			break;
462
+        		case 'crm_business' : 
463
+        			$r = db('crm_business_file'); 
464
+        			$r_name = 'business_id'; 
465
+        			break;
466
+        		case 'crm_product' : 
467
+        			$r = db('crm_product_file'); 
468
+        			$r_name = 'product_id'; 
469
+        			break;
470
+        		case 'crm_contract' : 
471
+        			$r = db('crm_contract_file'); 
472
+        			$r_name = 'contract_id'; 
473
+        			break;
474
+        		case 'oa_log' : 
475
+        			$r = db('oa_log_file'); 
476
+        			$r_name = 'log_id'; 
477
+        			break;
478
+        		case 'oa_examine' : 
479
+        			$r = db('oa_examine_file'); 
480
+        			$r_name = 'examine_id'; 
481
+        			break;
482
+        		case 'work_task' : 
483
+        			$r = db('work_task_file'); 
484
+        			$r_name = 'task_id'; 
485
+        			break;
486
+        		case 'admin_record' : 
487
+        			$r = db('admin_record_file'); 
488
+        			$r_name = 'record_id'; 
489
+        			break;
490
+        		case 'oa_travel' : 
491
+        			$r = db('oa_travel_file'); 
492
+        			$r_name = 'travel_id'; 
493
+        			break;
494
+				case 'hrm_pact' : 
495
+					$r = db('hrm_pact_file'); 
496
+					$r_name = 'pact_id'; 
497
+					break;
498
+				case 'hrm_file' : 
499
+					$r = db('hrm_user_file'); 
500
+					$r_name = 'user_id';
501
+					break;
502
+                case 'crm_invoice' :
503
+                    $r = db('crm_invoice_file');
504
+                    $r_name = 'invoice_id'; break;
505
+                case 'crm_visit' :
506
+                    $r = db('crm_visit_file');
507
+                    $r_name = 'visit_id';
508
+                    break;
509
+                case 'crm_activity' :
510
+                    $r = db('crm_activity_file');
511
+                    $r_name = 'activity_id';
512
+                    break;
513
+                case 'crm_receivables' :
514
+                    $r = db('crm_receivables_file');
515
+                    $r_name = 'receivables_id';
516
+        		default : break;
517
+        	}
518
+        	$rWhere = [];
519
+        	if(!is_array($module_id)){
520
+        		$module_id = [intval ($module_id)];
521
+        	}
522
+        	$rWhere[$r_name] = ['in',$module_id];
523
+        	$rFileIds = $r->where($rWhere)->column('file_id');
524
+        	$rRes = $r->where($rWhere)->delete();
525
+        	if ($rRes && $rFileIds) {
526
+        		$fileList = db('admin_file')->where(['file_id' => ['in',$rFileIds]])->field('file_path,file_path_thumb')->select();
527
+        		foreach ($fileList as $v) {
528
+					//删除文件
529
+	            	@unlink($v['file_path']);
530
+	            	@unlink($v['file_path_thumb']);
531
+        		}		            		
532
+        	}
533
+        }		
534
+	}
535
+
536
+    /**
537
+     * 全部删除(活动、产品)
538
+     *
539
+     * @param $param
540
+     * @return bool
541
+     * @throws \think\Exception
542
+     * @throws \think\exception\PDOException
543
+     */
544
+	public function deleteAll($param)
545
+    {
546
+        if (!empty($param['module']) && !empty($param['module_id'])) {
547
+            $module     = db('crm_activity_file');
548
+            $primaryKey = 'activity_id';
549
+
550
+            switch ($param['module']) {
551
+                case 'crm_activity' : $module = db('crm_activity_file'); $primaryKey = 'activity_id'; break;
552
+                case 'crm_product' : $module = db('crm_product_file'); $primaryKey = 'product_id'; break;
553
+            }
554
+
555
+            $fileIds = $module->where($primaryKey, $param['module_id'])->column('file_id');
556
+
557
+            # 删除关联数据
558
+            $module->where($primaryKey, $param['module_id'])->delete();
559
+
560
+            # 删除附件
561
+            db('admin_file')->whereIn('file_id', $fileIds)->delete();
562
+        }
563
+
564
+        if (!empty($param['file_id'])) {
565
+            db('admin_file')->whereIn('file_id', $param['file_id'])->delete();
566
+        }
567
+
568
+        return true;
569
+    }
570
+}

+ 192
- 0
application/admin/model/Group.php Целия файл

@@ -0,0 +1,192 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 用户组
4
+// +----------------------------------------------------------------------
5
+// | Author:  
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use app\admin\model\Common;
11
+
12
+class Group extends Common 
13
+{
14
+    /**
15
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
16
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
17
+     */
18
+	protected $name = 'admin_group';
19
+
20
+	/**
21
+	 * [getDataList 获取列表]
22
+	 * @param  tree 1 属性
23
+	 * @param  rules 1 二维数组
24
+	 * @param  pid 分类:0客户自定义角色,1系统默认管理角色,2客户管理角色,3人力资源管理角色(原客户),4财务管理角色(原客户),5项目管理角色,6办公管理角色,7人力资源管理角色,8财务管理角色,9项目管理员角色
25
+	 * @param  备注:原自定义角色0,人事管理角色3,财务管理角色4,划分至新客户管理角色中
26
+	 * @param  rule:types 0系统设置1工作台2客户管理3项目管理4人力资源5财务管理6商业智能(客戶)
27
+	 * @return    [array]            
28
+	 */
29
+	public function getDataList($param)
30
+	{
31
+		$ruleModel = new \app\admin\model\Rule();
32
+		$map = [];	
33
+		if ($param['tree'] == 1) {
34
+			$list = $this->getTypeList();
35
+			foreach ($list as $k=>$v) {
36
+				$where = [];
37
+				$where = $this->getNewGroupPid($v['pid']);
38
+				$groupList = db('admin_group')->where($where)->select() ? : [];
39
+				$list[$k]['list'] = $groupList ? : [];				
40
+			}
41
+		} else {
42
+			$where = [];
43
+			if (isset($param['type'])) {
44
+				$where['pid'] = $param['pid'];
45
+				$where['type'] = $param['type'];
46
+			} else {
47
+				$where = $this->getNewGroupPid($param['pid']);
48
+			}
49
+			$list = db('admin_group')->where($where)->select() ? : [];		
50
+			if ($param['rules'] == 1) {
51
+				//角色权限分类关系
52
+				$ruleTypes = $ruleModel->groupsToRules($param['pid']);
53
+				if ($ruleTypes) {
54
+					foreach ($list as $key => $val) {
55
+						$dataRules = [];
56
+						$biRules = [];
57
+						$rules = stringToArray($val['rules']) ? : [];
58
+						foreach ($rules as $k1=>$v1) {
59
+							$ruleInfo = [];
60
+							$ruleInfo = db('admin_rule')->where(['id' => $v1])->find();
61
+							if ($ruleInfo['types'] == $ruleTypes[0]) {
62
+								$dataRules[] = $v1;
63
+							} elseif ($ruleInfo['types'] == $ruleTypes[1]) {
64
+								$biRules[] = $v1;
65
+							}
66
+						}
67
+						$list[$key]['rules'] = [];
68
+						$list[$key]['rules']['data'] = $dataRules ? : [];
69
+						$list[$key]['rules']['bi'] = $biRules ? : [];
70
+						if ($val['pid'] == 1 || $val['pid'] == 5 || $val['pid'] == 6 || $val['pid'] == 9) {
71
+							$list[$key]['type'] = 0;
72
+						}
73
+					}				
74
+				}
75
+			}			
76
+		}
77
+		return $list ? : [];
78
+	}
79
+	
80
+	//新建角色
81
+	public function createData($param)
82
+	{
83
+		unset($param['types']);
84
+		if ($param['pid'] == 5 && $param['type'] == 'work') {
85
+			//项目模块下角色
86
+			$param['type'] = 0;
87
+		}
88
+		$flag = $this->insertGetId($param);
89
+		if ($flag) {
90
+			return $flag;
91
+		} else {
92
+			$this->error = '操作失败';
93
+			return false;
94
+		}
95
+	}
96
+	
97
+	//编辑角色
98
+	public function updateDataById($param,$group_id)
99
+	{
100
+		$dataInfo = $this->get($group_id);
101
+		if(!$dataInfo){
102
+			$this->error = '该角色不存在或已删除';
103
+			return false;
104
+		}
105
+		unset($param['types']);
106
+
107
+		# 处理编辑时,前端可能不传父id的问题(admin_rule表level为1的主键)
108
+        if (!empty($param['rules'])) {
109
+            $rulesParam   = stringToArray($param['rules']);
110
+            $rulesList    = db('admin_rule')->field(['id', 'level', 'pid'])->whereIn('id', $rulesParam)->select();
111
+            foreach ($rulesList AS $key => $value) {
112
+                if (!empty($value['level']) && $value['level'] == 2) $rulesParam[] = $value['pid'];
113
+                if (!empty($value['level']) && $value['level'] == 3) {
114
+                    $rulesParam[] = $value['pid'];
115
+                    $rulesParam[] = db('admin_rule')->where('id', $value['pid'])->value('pid');
116
+                }
117
+            }
118
+            $param['rules'] = arrayToString(array_unique($rulesParam));
119
+        }
120
+
121
+		$flag = $this->where('id = '.$group_id)->update($param);
122
+		if ($flag) {
123
+			return true;
124
+		} else {
125
+			$this->error = '操作失败';
126
+			return false;
127
+		}
128
+	}
129
+	
130
+	//删除角色
131
+	public function delGroupById($group_id = '')
132
+	{
133
+		$dataInfo = $this->get($group_id);
134
+		if(!$dataInfo){
135
+			$this->error = '该角色不存在或已删除';
136
+			return false;
137
+		}
138
+		if ($dataInfo['types']) {
139
+			$this->error = '系统角色不能删除';
140
+			return false;			
141
+		}
142
+		$flag = $this->where('id = '.$group_id)->delete();
143
+		if ($flag) {
144
+			return true;
145
+		} else {
146
+			$this->error = '删除失败';
147
+			return false;
148
+		}
149
+	}
150
+
151
+	/**
152
+	 * [getTypeList 获取分类列表]
153
+	 * @param  备注:原自定义角色0,人事管理角色3,财务管理角色4,划分至客户管理角色中
154
+	 * @return    [array]            
155
+	 */
156
+	public function getTypeList()
157
+	{
158
+		$list = ['0' => ['name' => '系统管理角色','pid' => 1],'1' => ['name' => '办公管理角色','pid' => 6],'2' => ['name' => '客户管理角色','pid' => 2],'3' => ['name' => '项目管理角色','pid' => '9']];
159
+		return $list ? : [];
160
+	}
161
+
162
+	/**
163
+	 * [getNewGroupPid 兼容9.0.5版本group pid对应关系]
164
+	 * @param  备注:原自定义角色0,人事管理角色3,财务管理角色4,划分至客户管理角色中
165
+	 * @return    [array]            
166
+	 */	
167
+	protected function getNewGroupPid($pid)
168
+	{
169
+		switch ($pid) {
170
+			case '1' : 
171
+				$where['pid'] = 1;
172
+				$where['types'] = ['not in',['7']];
173
+				break;
174
+			case '2' : 
175
+				$where = function($query) {
176
+				        		$query->where(['pid' => ['in',['0','2','3','4']]])
177
+			                    ->whereOr('type != 0 AND pid = 5');
178
+							};				
179
+				break;	
180
+			case '9' : 
181
+				$where = function($query) {
182
+				        		$query->where(['pid' => 9])
183
+			                    ->whereOr('types = 7 AND pid = 1');
184
+							};	
185
+				break;											
186
+			default : 
187
+				$where['pid'] = $pid;
188
+				break;
189
+		}
190
+		return $where ? : [];	
191
+	}
192
+}

+ 55
- 0
application/admin/model/ImportRecord.php Целия файл

@@ -0,0 +1,55 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 导入记录
4
+// +----------------------------------------------------------------------
5
+// | Author:  ymob
6
+// +----------------------------------------------------------------------
7
+namespace app\admin\model;
8
+
9
+class ImportRecord extends Common
10
+{
11
+    protected $name = 'admin_import_record';
12
+
13
+    protected $autoWriteTimestamp = true;
14
+    protected $createTime = 'create_time';
15
+    protected $updateTime = false;
16
+
17
+    /**
18
+     * 保存记录
19
+     *
20
+     * @param array     $data
21
+     * @return void
22
+     * @author Ymob
23
+     * @datetime 2019-10-22 11:46:41
24
+     */
25
+    public function createData($data)
26
+    {
27
+        $res = $this->save($data);
28
+
29
+        $message_type_list = [
30
+            'crm_customer' => Message::IMPORT_CUSTOMER,
31
+            'crm_contacts' => Message::IMPORT_CONTACTS,
32
+            'crm_leads' => Message::IMPORT_LEADS,
33
+            'crm_product' => Message::IMPORT_PRODUCT,
34
+            'task' => Message::IMPORT_TASK,
35
+        ];
36
+
37
+        if ($res) {
38
+            (new Message())->send(
39
+                $message_type_list[$data['type']],
40
+                [
41
+                    'total' => $data['total'],
42
+                    'error' => $data['error'],
43
+                    'done' => $data['done'],
44
+                    'success' => $data['done'] - $data['error'],
45
+                    'cover' => $data['cover'],
46
+                    'title' => $data['error'] > 0 ? '点击下载错误数据' : '',
47
+                    'action_id' => $this->id,
48
+                ],
49
+                User::userInfo('id'),
50
+                false
51
+            );
52
+        }
53
+    }
54
+
55
+}

+ 133
- 0
application/admin/model/LoginRecord.php Целия файл

@@ -0,0 +1,133 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 应用配置
4
+// +----------------------------------------------------------------------
5
+// | Author: Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use com\Scan;
11
+
12
+class LoginRecord extends Common
13
+{
14
+    /**
15
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
16
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
17
+     */
18
+    protected $name = 'admin_login_record';
19
+
20
+    protected $autoWriteTimestamp = true;
21
+    protected $createTime = 'create_time';
22
+    protected $updateTime = false;
23
+
24
+    /**
25
+     * 登录成功
26
+     */
27
+    const TYPE_SUCCESS = 0;
28
+
29
+    /**
30
+     * 密码错误
31
+     */
32
+    const TYPE_PWD_ERROR = 1;
33
+
34
+    /**
35
+     * 账号被禁用
36
+     */
37
+    const TYPE_USER_BANNED = 2;
38
+
39
+    // 类型
40
+    public $typeList = [
41
+        self::TYPE_SUCCESS => '登录成功',
42
+        self::TYPE_PWD_ERROR => '密码错误',
43
+        self::TYPE_USER_BANNED => '账号被禁用',
44
+    ];
45
+
46
+    /**
47
+     * 登录员工ID
48
+     */
49
+    public $user_id = 0;
50
+
51
+    /**
52
+     * 添加登录记录
53
+     *
54
+     * @param int $type
55
+     */
56
+    public function createRecord($type = 0)
57
+    {
58
+        $data = [];
59
+        $data['type'] = $type;
60
+        $data['create_user_id'] = $this->user_id;
61
+        $data['create_time'] = time();
62
+        $data['ip'] = (new Scan())->get_client_ip();
63
+        $data['os'] = getOS();
64
+        $data['browser'] = getBrowser();
65
+
66
+        $ip_address = getAddressById($data['ip']);
67
+        $data['address'] = $ip_address['country'];
68
+
69
+        // 效果图有这个备注字段,不知道存啥,就把UA记录了一下
70
+        $data['remark'] = $_SERVER['HTTP_USER_AGENT'];
71
+
72
+        $this->save($data);
73
+    }
74
+
75
+    /**
76
+     * 创建人
77
+     */
78
+    public function getCreateUserInfoAttr($val, $data)
79
+    {
80
+        return User::getUserById($data['create_user_id']) ?: [];
81
+    }
82
+
83
+    /**
84
+     * 获取登录记录类型
85
+     */
86
+    public function getTypeNameAttr($val, $data)
87
+    {
88
+        return $this->typeList[$data['type']];
89
+    }
90
+
91
+    /**
92
+     * 
93
+     */
94
+    /**
95
+     * 固定时间内登录密码错超过限制
96
+     *
97
+     * @param integer $count    登录出错次数
98
+     * @param integer $time     等待时间 (分钟)
99
+     * @return bool
100
+     */
101
+    public function verify($count = 3, $time = 5)
102
+    {
103
+        $where = [
104
+            'create_user_id' => $this->user_id,
105
+            'create_time' => ['GT', time() - 60 * $time],
106
+            'type' => 1
107
+        ];
108
+        $last_record = $this->order(['id' => 'DESC'])
109
+            ->where($where)
110
+            ->find();
111
+        // 登录记录
112
+        if ($last_record) {
113
+            $last_time = strtotime($last_record['create_time']);
114
+            $where['create_time'] = [
115
+                'BETWEEN',
116
+                [
117
+                    $last_time - 60 * $time,
118
+                    $last_time
119
+                ]
120
+            ];
121
+            $list = $this->where($where)
122
+                ->order(['id' => 'DESC'])
123
+                ->column('type');
124
+            if (count($list) >= $count) {
125
+                $surplusTime = getTimeBySec(60 * $time - (time()-strtotime($last_record['create_time'])));
126
+                $this->error = "密码错误次数过多,请在{$surplusTime}后重试!";
127
+                return false;
128
+            }
129
+        }
130
+        return true;
131
+    }
132
+
133
+}

+ 94
- 0
application/admin/model/Menu.php Целия файл

@@ -0,0 +1,94 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 菜单
4
+// +----------------------------------------------------------------------
5
+// | Author:  
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use think\Db;
11
+use app\admin\model\Common;
12
+
13
+class Menu extends Common 
14
+{
15
+
16
+    /**
17
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
18
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
19
+     */
20
+    protected $name = 'admin_menu';
21
+	/**
22
+	 * [getDataList 获取列表]
23
+	 * @return    [array]                         
24
+	 */
25
+	public function getDataList()
26
+	{	
27
+        $cat = new \com\Category('admin_menu', array('id', 'pid', 'title', 'title'));     
28
+        $data = $cat->getList('', 0, 'sort'); 
29
+		return $data;
30
+	}
31
+
32
+	/**
33
+	 * [getDataById 根据主键获取详情]
34
+	 * @param     string                   $id [主键]
35
+	 * @return    [array]                       
36
+	 */
37
+	public function getDataById($id = '')
38
+	{
39
+		$data = $this
40
+				->alias('menu')
41
+				->where('menu.id', $id)
42
+				->join('__ADMIN_RULE__ rule', 'menu.rule_id=rule.id', 'LEFT')
43
+				->field('menu.*, rule.title as rule_name')
44
+				->find();
45
+		if (!$data) {
46
+			$this->error = '暂无此数据';
47
+			return false;
48
+		}
49
+		return $data;
50
+	}
51
+
52
+
53
+	/**
54
+	 * 整理菜单树形结构
55
+	 * @param  array   $param  [description]
56
+	 */
57
+    protected function getMenuTree()
58
+    {	
59
+    	$userInfo = $GLOBALS['userInfo'];
60
+    	if (!$userInfo) {
61
+    		return [];
62
+    	}
63
+    	
64
+    	$u_id = $userInfo['id'];
65
+    	if ($u_id === 1) {
66
+    		$map['status'] = 1;
67
+    		$menusList = Db::name('admin_menu')->where($map)->order('sort asc')->select();
68
+    	} else {
69
+    		$groups = model('User')->get($u_id)->groups;
70
+    		
71
+            $ruleIds = [];
72
+    		foreach($groups as $k => $v) {
73
+    			$ruleIds = array_unique(array_merge($ruleIds, explode(',', $v['rules'])));
74
+    		}
75
+            $ruleMap['id'] = array('in', $ruleIds);
76
+            $ruleMap['status'] = 1;
77
+            // 重新设置ruleIds,除去部分已删除或禁用的权限。
78
+            $ruleIds =  Db::name('admin_rule')->where($ruleMap)->column('id');
79
+            empty($ruleIds)&&$ruleIds = '';
80
+    		$menuMap['status'] = 1;
81
+            $menuMap['rule_id'] = array('in',$ruleIds);
82
+            $menusList =  Db::name('admin_menu')->where($menuMap)->order('sort asc')->select();
83
+        }
84
+        if (!$menusList) {
85
+            return [];
86
+        }
87
+        //处理成树状
88
+        // $tree = new \com\Tree();
89
+        // $menusList = $tree->list_to_tree($menusList, 'id', 'pid', 'child', 0, true, array('pid'));
90
+        // $menusList = memuLevelClear($menusList);
91
+        
92
+        return $menusList? $menusList: [];
93
+    }
94
+}

+ 470
- 0
application/admin/model/Message.php Целия файл

@@ -0,0 +1,470 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 站内信
4
+// +----------------------------------------------------------------------
5
+// | Author:  ymob
6
+// +----------------------------------------------------------------------
7
+namespace app\admin\model;
8
+
9
+use app\admin\model\ImportRecord as ImportRecordModel;
10
+use app\admin\model\User as UserModel;
11
+use app\crm\model\Contract as ContractModel;
12
+use app\crm\model\Invoice;
13
+use app\crm\model\Receivables as ReceivablesModel;
14
+use app\oa\model\Announcement as AnnouncementModel;
15
+use app\oa\model\Event as EventModel;
16
+use app\oa\model\Examine as ExamineModel;
17
+use app\oa\model\ExamineCategory;
18
+use app\oa\model\Log as LogModel;
19
+use app\work\model\Task as TaskModel;
20
+
21
+class Message extends Common
22
+{
23
+    protected $name = 'admin_message';
24
+
25
+    protected $autoWriteTimestamp = true;
26
+    protected $createTime = 'send_time';
27
+    protected $updateTime = false;
28
+
29
+    /**
30
+     * 错误信息
31
+     */
32
+    public $error = '';
33
+
34
+    /**
35
+     * 将要发送的消息内容
36
+     */
37
+    protected $content = '';
38
+
39
+    /**
40
+     * 消息类型
41
+     */
42
+    protected $type = 0;
43
+
44
+    /**
45
+     * 任务分配
46
+     */
47
+    const TASK_ALLOCATION = 1;
48
+    /**
49
+     * 任务邀请
50
+     */
51
+    const TASK_INVITE = 2;
52
+    /**
53
+     * 任务结束
54
+     */
55
+    const TASK_OVER = 3;
56
+    /**
57
+     * 回复日志
58
+     */
59
+    const LOG_REPLAY = 4;
60
+    /**
61
+     * 发送日志
62
+     */
63
+    const LOG_SEND = 5;
64
+    /**
65
+     * 审批待处理
66
+     */
67
+    const EXAMINE_TO_DO = 6;
68
+    /**
69
+     * 审批驳回
70
+     */
71
+    const EXAMINE_REJECT = 7;
72
+    /**
73
+     * 审批通过
74
+     */
75
+    const EXAMINE_PASS = 8;
76
+    /**
77
+     * 公告
78
+     */
79
+    const NOTICE_MESSAGE = 9;
80
+    /**
81
+     * 日程
82
+     */
83
+    const EVENT_MESSAGE = 10;
84
+    /**
85
+     * 合同待审批
86
+     */
87
+    const CONTRACT_TO_DO = 11;
88
+    /**
89
+     * 合同审批驳回
90
+     */
91
+    const CONTRACT_REJECT = 12;
92
+    /**
93
+     * 合同审批通过
94
+     */
95
+    const CONTRACT_PASS = 13;
96
+    /**
97
+     * 回款待审批
98
+     */
99
+    const RECEIVABLES_TO_DO = 14;
100
+    /**
101
+     * 回款审批驳回
102
+     */
103
+    const RECEIVABLES_REJECT = 15;
104
+    /**
105
+     * 回款审批通过
106
+     */
107
+    const RECEIVABLES_PASS = 16;
108
+    /**
109
+     * 客户导入
110
+     */
111
+    const IMPORT_CUSTOMER = 17;
112
+    /**
113
+     * 联系人
114
+     */
115
+    const IMPORT_CONTACTS = 18;
116
+    /**
117
+     * 线索
118
+     */
119
+    const IMPORT_LEADS = 19;
120
+    /**
121
+     * 产品
122
+     */
123
+    const IMPORT_PRODUCT = 20;
124
+    /**
125
+     * 团队成员-客户
126
+     */
127
+    const TEAM_CUSTOMER = 21;
128
+    /**
129
+     * 团队成员-商机
130
+     */
131
+    const TEAM_BUSINESS = 22;
132
+    /**
133
+     * 团队成员-合同
134
+     */
135
+    const TEAM_CONTRACT = 23;
136
+    /**
137
+     * 发票待审批
138
+     */
139
+    const INVOICE_TO_DO = 24;
140
+    /**
141
+     * 发票审批驳回
142
+     */
143
+    const INVOICE_REJECT = 25;
144
+    /**
145
+     * 发票审批通过
146
+     */
147
+    const INVOICE_PASS = 26;
148
+    /**
149
+     * 项目任务导入
150
+     */
151
+    const IMPORT_TASK = 27;
152
+    /**
153
+     * 退出商机团队
154
+     */
155
+    const BUSINESS_PASS = 28;
156
+    /**
157
+     * 退出客户团队
158
+     */
159
+    const CUSTOMER_PASS = 29;
160
+    /**
161
+     * 退出合同团队
162
+     */
163
+    const CONTRACT_END = 30;
164
+
165
+    /**
166
+     * 消息类型
167
+     *
168
+     * @var array
169
+     * @author Ymob
170
+     * @datetime 2019-10-17 15:27:43
171
+     */
172
+    protected $typeList = [
173
+        1 => [
174
+            'template' => '{from_user} 将 {title} 任务分配给您,请及时查看。',
175
+        ],
176
+        2 => [
177
+            'template' => '{from_user} 邀请您参与 {title} 任务,请及时查看。',
178
+        ],
179
+        3 => [
180
+            'template' => '{from_user} 将 {title} 任务标记结束。',
181
+        ],
182
+        4 => [
183
+            'template' => '{from_user} 回复了您的 {title} 日志:“今天工作状态不错,继续加油!”,请及时查看',
184
+        ],
185
+        5 => [
186
+            'template' => '{from_user} 将日志 {title} 发送给您,请及时查看。',
187
+        ],
188
+        6 => [
189
+            'template' => '{from_user} 提交 {title} 审批,请及时处理。',
190
+        ],
191
+        7 => [
192
+            'template' => '{from_user} 拒绝您的 {title} 审批,拒绝理由:“日期填写错误”,请及时处理。',
193
+        ],
194
+        8 => [
195
+            'template' => '{from_user} 已经审核通过您的 {title} ,请及时查看。',
196
+        ],
197
+        9 => [
198
+            'template' => '您有一个新公告 {title} ,请及时查看。',
199
+        ],
200
+        10 => [
201
+            'template' => '{from_user} 邀请您参与 {title} 日程,将于**分钟后开始,请及时查看。',
202
+        ],
203
+        11 => [
204
+            'template' => '{from_user} 提交 {title} 合同审批待您处理,请及时查看。',
205
+        ],
206
+        12 => [
207
+            'template' => '{from_user} 拒绝您的 {title} 合同审批,拒绝理由:“日期填写错误”,请及时处理。',
208
+        ],
209
+        13 => [
210
+            'template' => '{from_user} 已经审核通过您的 {title} 合同,请及时查看',
211
+        ],
212
+        14 => [
213
+            'template' => '{from_user} 提交 {title} 回款审批待您处理,请及时查看。',
214
+        ],
215
+        15 => [
216
+            'template' => '{from_user} 拒绝您的 {title} 回款审批,拒绝理由:“日期填写错误”,请及时处理。',
217
+        ],
218
+        16 => [
219
+            'template' => '{from_user} 已经审核通过您的 {title} 回款,请及时查看。',
220
+        ],
221
+        17 => [
222
+            // 'template' => '{from_user} 导入客户数据,共 {total} 条,已导入 {done} 条 , 成功 {success} 条, 覆盖 {cover} 条, 失败 {error} 条。',
223
+            'template' => '{total},{cover},{success},{error}',
224
+        ],
225
+        18 => [
226
+            // 'template' => '{from_user} 导入联系人数据,共 {total} 条,已导入 {done} 条 , 成功 {success} 条, 覆盖 {cover} 条, 失败 {error} 条。',
227
+            'template' => '{total},{cover},{success},{error}',
228
+        ],
229
+        19 => [
230
+            // 'template' => '{from_user} 导入线索数据,共 {total} 条,已导入 {done} 条 , 成功 {success} 条, 覆盖 {cover} 条, 失败 {error} 条。',
231
+            'template' => '{total},{cover},{success},{error}',
232
+        ],
233
+        20 => [
234
+            // 'template' => '{from_user} 导入产品数据,共 {total} 条,已导入 {done} 条 , 成功 {success} 条, 覆盖 {cover} 条, 失败 {error} 条。',
235
+            'template' => '{total},{cover},{success},{error}',
236
+        ],
237
+        21 => [
238
+            'template' => '{from_user} 将您添加为客户 {title} 的成员。',
239
+        ],
240
+        22 => [
241
+            'template' => '{from_user} 将您添加为商机 {title} 的成员。',
242
+        ],
243
+        23 => [
244
+            'template' => '{from_user} 将您添加为合同 {title} 的成员。',
245
+        ],
246
+        24 => [
247
+            'template' => '{from_user} 提交 {title} 发票审批待您处理,请及时查看。',
248
+        ],
249
+        25 => [
250
+            'template' => '{from_user} 拒绝您的 {title} 发票审批,请及时处理。',
251
+        ],
252
+        26 => [
253
+            'template' => '您的 {title} 发票已经审批通过,请及时查看。',
254
+        ],
255
+        27 => [
256
+            // 'template' => '{date},{from_user} 导入任务,共 {total} 条,已导入 {done} 条 , 成功 {success} 条, 覆盖 {cover} 条, 失败 {error} 条。{title}',
257
+            'template' => '{total},{cover},{success},{error}',
258
+        ],
259
+        28 => [
260
+            'template' => '{from_user} 退出了您商机 {title} 的团队。',
261
+        ],
262
+        29 => [
263
+            'template' => '{from_user} 退出了您客户 {title} 的团队。',
264
+        ],
265
+
266
+        30 => [
267
+            'template' => '{from_user} 退出了您合同 {title} 的团队。',
268
+        ],
269
+    ];
270
+
271
+    /**
272
+     * 消息类型分组
273
+     */
274
+    public static $typeGroup = [
275
+        'announcement' => [
276
+            self::NOTICE_MESSAGE,
277
+        ],
278
+        'examine' => [
279
+            self::EXAMINE_TO_DO,
280
+            self::EXAMINE_REJECT,
281
+            self::EXAMINE_PASS,
282
+        ],
283
+        'task' => [
284
+            self::TASK_ALLOCATION,
285
+            self::TASK_INVITE,
286
+            self::TASK_OVER,
287
+            self::IMPORT_TASK,
288
+        ],
289
+        'log' => [
290
+            self::LOG_REPLAY,
291
+            self::LOG_SEND,
292
+        ],
293
+        'event' => [
294
+            self::EVENT_MESSAGE,
295
+        ],
296
+        'crm' => [
297
+            self::CONTRACT_TO_DO,
298
+            self::CONTRACT_REJECT,
299
+            self::CONTRACT_PASS,
300
+            self::RECEIVABLES_TO_DO,
301
+            self::RECEIVABLES_REJECT,
302
+            self::RECEIVABLES_PASS,
303
+            self::IMPORT_CUSTOMER,
304
+            self::IMPORT_CONTACTS,
305
+            self::IMPORT_LEADS,
306
+            self::IMPORT_PRODUCT,
307
+            self::TEAM_CUSTOMER,
308
+            self::TEAM_BUSINESS,
309
+            self::TEAM_CONTRACT,
310
+            self::INVOICE_TO_DO,
311
+            self::INVOICE_REJECT,
312
+            self::INVOICE_PASS,
313
+            self::BUSINESS_PASS,
314
+            self::CUSTOMER_PASS,
315
+            self::CONTRACT_END,
316
+        ]
317
+    ];
318
+
319
+    /**
320
+     * 发送系统通知
321
+     *
322
+     * @param int $type 消息类型
323
+     * @param array $data 关联信息
324
+     * @param array|int $user_id 接收消息员工ID
325
+     * @param boolean $system 是否系统消息
326
+     * @return bool
327
+     * @author Ymob
328
+     * @datetime 2019-10-17 17:23:05
329
+     */
330
+    public function send($type, $data, $user_id_list, $system = false)
331
+    {
332
+        if (!isset($this->typeList[$type])) {
333
+            $this->error = '消息类型错误';
334
+            return false;
335
+        }
336
+        $user_id_list = (array)$user_id_list;
337
+        $user_id_list = array_unique(array_filter($user_id_list));
338
+        if (empty($user_id_list)) {
339
+            $this->error = '接收人不能为空';
340
+            return false;
341
+        }
342
+
343
+        $action_id = $data['action_id'];
344
+        $title = $data['title'];
345
+        $content = $this->typeList[$type]['template'];
346
+        foreach ($data as $key => $val) {
347
+            $content = str_replace('{' . $key . '}', $val, $content);
348
+        }
349
+        $advance_time= $data['advance_time'];
350
+        $content = str_replace('{from_user}', User::userInfo('realname'), $content);
351
+        $content = str_replace('{date}', date('Y-m-d'), $content);
352
+        $data = [];
353
+        $data['type'] = $type;
354
+        $data['content'] = $content;
355
+        $data['action_id'] = $action_id;
356
+        $data['read_time'] = 0;
357
+        $data['from_user_id'] = $system ? 0 : User::userInfo('id');
358
+        $data['title'] = $title;
359
+        $data['advance_time'] = $advance_time ?: 0;
360
+        $request = request();
361
+        $data['controller_name'] = strtolower($request->controller());
362
+        $data['module_name'] = strtolower($request->module());
363
+        $data['action_name'] = strtolower($request->action());
364
+
365
+        $from_user_id = $data['from_user_id'];
366
+        if (!in_array($type,[9,17,18,19,20,27])) {
367
+            $user_id_list = array_filter($user_id_list, function ($val) use ($from_user_id) {
368
+                return $val !== $from_user_id;
369
+            });
370
+        }
371
+
372
+        $all_data = [];
373
+        foreach ($user_id_list as $user_id) {
374
+            $temp = $data;
375
+            $temp['to_user_id'] = $user_id;
376
+            $all_data[] = $temp;
377
+        }
378
+        if (!empty($from_user_id) && class_exists('DingTalk')) {
379
+            (new Dingtalk())->message($user_id_list, $content);
380
+        }
381
+        $this->saveAll($all_data);
382
+    }
383
+
384
+    /**
385
+     * 获取关联模块数据
386
+     *
387
+     * @author Ymob
388
+     * @datetime 2019-10-22 15:34:35
389
+     */
390
+    public function getRelationTitleAttr($val, $data)
391
+    {
392
+        switch ($data['type']) {
393
+            // 任务
394
+            case self::TASK_ALLOCATION:
395
+            case self::TASK_INVITE:
396
+            case self::TASK_OVER:
397
+                return TaskModel::where(['task_id' => $data['action_id']])->value('name') ?: '';
398
+
399
+            // 日志
400
+            case self::LOG_REPLAY:
401
+            case self::LOG_SEND:
402
+                return LogModel::where(['log_id' => $data['action_id']])->value('title') ?: '';
403
+
404
+            // 审批
405
+            case self::EXAMINE_TO_DO:
406
+            case self::EXAMINE_REJECT:
407
+            case self::EXAMINE_PASS:
408
+                $category_id = ExamineModel::where(['examine_id' => $data['action_id']])->value('category_id') ?: 0;
409
+                $categoryInfo = (new ExamineCategory())->getDataById($category_id);
410
+                return $categoryInfo['title'];
411
+
412
+            // 公告
413
+            case self::NOTICE_MESSAGE:
414
+                return AnnouncementModel::where(['announcement_id' => $data['action_id']])->value('title') ?: '';
415
+
416
+            // 日程
417
+            case self::EVENT_MESSAGE:
418
+                return EventModel::where(['event_id' => $data['action_id']])->value('title') ?: '';
419
+
420
+            // 合同
421
+            case self::CONTRACT_TO_DO:
422
+            case self::CONTRACT_REJECT:
423
+            case self::CONTRACT_PASS:
424
+            case self::TEAM_CONTRACT:
425
+                return ContractModel::where(['contract_id' => $data['action_id']])->value('name') ?: '';
426
+
427
+            // 回款
428
+            case self::RECEIVABLES_TO_DO:
429
+            case self::RECEIVABLES_REJECT:
430
+            case self::RECEIVABLES_PASS:
431
+                return ReceivablesModel::where(['receivables_id' => $data['action_id']])->value('number') ?: '';
432
+
433
+            // 发票
434
+            case self::INVOICE_TO_DO:
435
+            case self::INVOICE_REJECT:
436
+            case self::INVOICE_PASS:
437
+                return Invoice::where(['invoice_id' => $data['action_id']])->value('invoice_apple_number') ?: '';
438
+
439
+            // 导入数据
440
+            case self::IMPORT_CUSTOMER:
441
+            case self::IMPORT_CONTACTS:
442
+            case self::IMPORT_LEADS:
443
+            case self::IMPORT_PRODUCT:
444
+            case self::IMPORT_TASK:
445
+                $error = ImportRecordModel::where(['id' => $data['action_id']])->value('error');
446
+                return $error ? '点击下载错误数据' : '';
447
+
448
+            // 客户
449
+            case self::TEAM_CUSTOMER:
450
+            case self::CUSTOMER_PASS:
451
+                return CustomerModel::where(['customer_id' => $data['action_id']])->value('name') ?: '';
452
+
453
+            // 商机
454
+            case self::TEAM_BUSINESS:
455
+            case self::BUSINESS_PASS:
456
+                return BusinessModel::where(['business_id' => $data['action_id']])->value('name') ?: '';
457
+
458
+        }
459
+
460
+        return '';
461
+    }
462
+
463
+    /**
464
+     * 发送人
465
+     */
466
+    public function getFromUserIdInfoAttr($val, $data)
467
+    {
468
+        return $data['from_user_id'] ? UserModel::getUserById($data['from_user_id']) : [];
469
+    }
470
+}

+ 12
- 0
application/admin/model/OaSchedule.php Целия файл

@@ -0,0 +1,12 @@
1
+<?php
2
+
3
+namespace app\admin\model;
4
+
5
+use app\admin\model\Common;
6
+class OaSchedule extends Common{
7
+    /**
8
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
9
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
10
+     */
11
+    protected $name = 'admin_group';
12
+}

+ 28
- 0
application/admin/model/OperationLog.php Целия файл

@@ -0,0 +1,28 @@
1
+<?php
2
+/**
3
+ * 数据操作日志
4
+ *
5
+ * @author qifna
6
+ * @date 2020-12-29
7
+ */
8
+
9
+namespace app\admin\model;
10
+
11
+use think\Model;
12
+
13
+class OperationLog extends Model
14
+{
15
+    protected $name = 'admin_operation_log';
16
+
17
+    protected $pk = 'log_id';
18
+
19
+    /**
20
+     * 关联后台员工表姓名
21
+     *
22
+     * @return \think\model\relation\HasOne
23
+     */
24
+    public function toAdminUser()
25
+    {
26
+        return $this->hasOne('User', 'id', 'user_id')->bind(['source_name' => 'realname']);
27
+    }
28
+}

+ 44
- 0
application/admin/model/Post.php Целия файл

@@ -0,0 +1,44 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 岗位
4
+// +----------------------------------------------------------------------
5
+// | Author:  
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use app\admin\model\Common;
11
+
12
+class Post extends Common 
13
+{
14
+
15
+    /**
16
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
17
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
18
+     */
19
+	protected $name = 'admin_post';
20
+    protected $createTime = 'create_time';
21
+    protected $updateTime = false;
22
+	protected $autoWriteTimestamp = true;
23
+	protected $insert = [
24
+		'status' => 1,
25
+	];  
26
+
27
+	/**
28
+	 * [getDataList 获取列表]
29
+	 * @return    [array]                         
30
+	 */
31
+	public function getDataList($request)
32
+	{
33
+		$request = $this->fmtRequest( $request );
34
+		$map = $request['map'];
35
+		if (isset($map['search'])) {
36
+			$map['name'] = ['like', '%'.$map['search'].'%'];
37
+			unset($map['search']);
38
+		} else {
39
+			$map = where_arr($map, 'member'); //高级筛选
40
+		}	
41
+		$data = $this->where($map)->page($request['page'], $request['limit'])->select();
42
+		return $data;
43
+	}
44
+}

+ 652
- 0
application/admin/model/Record.php Целия файл

@@ -0,0 +1,652 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 跟进记录
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+namespace app\admin\model;
8
+
9
+use think\Db;
10
+use app\admin\model\Common;
11
+use think\Request;
12
+use think\Validate;
13
+
14
+class Record extends Common
15
+{
16
+	/**
17
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
18
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
19
+     */
20
+	protected $name = 'admin_record';
21
+    protected $createTime = 'create_time';
22
+    protected $updateTime = 'update_time';
23
+	protected $autoWriteTimestamp = true;
24
+	protected $types_arr = ['crm_leads','crm_customer','crm_contacts','crm_product','crm_business','crm_contract','oa_log','admin_record'];
25
+
26
+	/**
27
+     * [getDataList 跟进记录list]
28
+     * @author Michael_xu
29
+     * @param     [string]                   $map [查询条件]
30
+     * @param     [number]                   $page     [当前页数]
31
+     * @param     [number]                   $limit    [每页数量]
32
+     * @param     [string]                   $by    [分类]
33
+     * @param     [string]                   $types    [类别]
34
+     * @param     [number]                   $types_id    [类别Id]
35
+     * @return    [array]                    
36
+     */		
37
+	public function getDataList($request, $by = '')
38
+    {  	
39
+    	$userModel = new \app\admin\model\User();
40
+    	$commonModel = new \app\admin\model\Comment();
41
+    	$fileModel = new \app\admin\model\File();
42
+    	$structureModel = new \app\admin\model\Structure();
43
+    	$lableModel = new \app\work\model\WorkLable();
44
+    	$taskModel = new \app\work\model\Task();
45
+
46
+        $request = $this->fmtRequest( $request );
47
+        $map = $request['map'] ? : [];
48
+		if (!$map['types'] || !$map['types_id']) {
49
+			$this->error = '参数错误';
50
+			return false;
51
+		}
52
+		switch ($by) {
53
+			case 'record' : 
54
+				$where_record = [];
55
+				$where_record['types'] = $map['types'];
56
+				$where_record['types_id'] = $map['types_id'];
57
+                $contactsWhere = [];
58
+                $businessWhere = [];
59
+                $contractWhere = [];
60
+				//客户模块下包含被转化线索的跟进记录
61
+				if ($map['types'] == 'crm_customer') {
62
+					if ($leads_id = db('crm_leads')->where(['customer_id' => $map['types_id']])->value('leads_id')) {
63
+						$whereOr = [];
64
+						$whereOr['types'] = 'crm_leads';
65
+						$whereOr['types_id'] = $leads_id;
66
+					}
67
+
68
+					$customerWhere['customer_id'] = $where_record['types_id'];
69
+					# 查询客户的联系人ID串
70
+                    $contacts = Db::name('crm_contacts')->field(['contacts_id'])->where($customerWhere)->select();
71
+                    if (!empty($contacts)) {
72
+                        $contactsWhere['types']    = 'crm_contacts';
73
+                        $contactsWhere['types_id'] = array_reduce($contacts, function ($result, $value) {
74
+                            return array_merge($result, array_values($value));
75
+                        }, []);
76
+                    }
77
+
78
+                    # 查询客户的商机ID串
79
+                    $business = Db::name('crm_business')->field(['business_id'])->where($customerWhere)->select();
80
+                    if (!empty($business)) {
81
+                        $businessWhere['types']    = 'crm_business';
82
+                        $businessWhere['types_id'] = array_reduce($business, function ($result, $value) {
83
+                            return array_merge($result, array_values($value));
84
+                        }, []);
85
+                    }
86
+
87
+                    # 查询客户的合同ID串
88
+                    $contract = Db::name('crm_contract')->field(['contract_id'])->where($customerWhere)->select();
89
+                    if (!empty($contract)) {
90
+                        $contractWhere['types'] = 'crm_contract';
91
+                        $contractWhere['types_id'] = array_reduce($contract, function ($result, $value) {
92
+                            return array_merge($result, array_values($value));
93
+                        }, []);
94
+                    }
95
+				}
96
+				//联系人下包含关联的客户的跟进记录
97
+				if ($map['types'] == 'crm_contacts') {
98
+					$whereOr = [];
99
+					$whereOr['contacts_ids'] = array('like','%,'.$map['types_id'].',%');
100
+				}
101
+				if ($map['types'] == 'crm_business') {
102
+					$whereOr = [];
103
+					$whereOr['business_ids'] = array('like','%,'.$map['types_id'].',%');
104
+				}
105
+				$list = db('admin_record')
106
+					->page($request['page'], $request['limit'])
107
+					->order('create_time desc')
108
+					->select(function($query) use ($where_record, $whereOr, $contractWhere, $businessWhere, $contactsWhere){
109
+					        $query->where($where_record)
110
+                            ->whereOr(function ($query) use ($whereOr) {
111
+                                $query->where($whereOr);
112
+                            })
113
+                            ->whereOr(function ($query) use ($contractWhere) {
114
+                                if (!empty($contractWhere['types_id'])) $query->where('types', $contractWhere['types']);
115
+                                if (!empty($contractWhere['types_id'])) $query->whereIn('types_id', $contractWhere['types_id']);
116
+                            })
117
+                            ->whereOr(function ($query) use ($businessWhere) {
118
+                                if (!empty($businessWhere['types_id'])) $query->where('types', $businessWhere['types']);
119
+                                if (!empty($businessWhere['types_id'])) $query->whereIn('types_id', $businessWhere['types_id']);
120
+                            })
121
+                            ->whereOr(function ($query) use ($contactsWhere) {
122
+                                if (!empty($contactsWhere['types_id'])) $query->where('types', $contactsWhere['types']);
123
+                                if (!empty($contactsWhere['types_id'])) $query->whereIn('types_id', $contactsWhere['types_id']);
124
+                            });
125
+					});
126
+				foreach ($list as $k=>$v) {
127
+					$list[$k]['id'] = $v['record_id'];
128
+					$list[$k]['cate'] = 1;
129
+				}
130
+				$dataCount = db('admin_record')
131
+							->where(function($query) use ($where_record, $whereOr, $contractWhere, $businessWhere, $contactsWhere){
132
+								    $query->where($where_record)->whereOr(function ($query) use ($whereOr) {
133
+                                        $query->where($whereOr);
134
+                                    })
135
+                                    ->whereOr(function ($query) use ($contractWhere) {
136
+                                        if (!empty($contractWhere['types'])) $query->where('types', $contractWhere['types']);
137
+                                        if (!empty($contractWhere['types_id'])) $query->whereIn('types_id', $contractWhere['types_id']);
138
+                                    })
139
+                                    ->whereOr(function ($query) use ($businessWhere) {
140
+                                        if (!empty($businessWhere['types'])) $query->where('types', $businessWhere['types']);
141
+                                        if (!empty($businessWhere['types_id'])) $query->whereIn('types_id', $businessWhere['types_id']);
142
+                                    })
143
+                                    ->whereOr(function ($query) use ($contactsWhere) {
144
+                                        if (!empty($contactsWhere['types'])) $query->where('types', $contactsWhere['types']);
145
+                                        if (!empty($contactsWhere['types_id'])) $query->whereIn('types_id', $contactsWhere['types_id']);
146
+                                    });
147
+							})->count();
148
+				break;
149
+			case 'log' :
150
+				$where_log = [];
151
+				$r_logs = $this->getRelationIdsByType($map['types'], $map['types_id'], 'oa_log') ? : [];
152
+				$where_log['log_id'] = ['in',$r_logs];
153
+				$list = db('oa_log')
154
+					->page($request['page'], $request['limit'])
155
+					->order('create_time desc')				
156
+					->where($where_log)
157
+					->select();
158
+				foreach ($list as $k=>$v) {
159
+					$list[$k]['id'] = $v['log_id'];
160
+					$list[$k]['cate'] = 2;
161
+				}				
162
+				$dataCount = db('oa_log')->where($where_log)->count();
163
+				break;
164
+			case 'examine' :
165
+				$where_examine = [];
166
+				$r_logs = $this->getRelationIdsByType($map['types'], $map['types_id'], 'oa_examine') ? : [];
167
+				$where_examine['examine_id'] = ['in',$r_logs];			
168
+				$list = db('oa_examine')
169
+					->page($request['page'], $request['limit'])
170
+					->order('create_time desc')				
171
+					->where($where_examine)
172
+					->select();
173
+				foreach ($list as $k=>$v) {
174
+					$list[$k]['id'] = $v['examine_id'];
175
+					$list[$k]['cate'] = 3;
176
+				}				
177
+				$dataCount = db('oa_examine')->where($where_examine)->count();	
178
+				break;
179
+			case 'task' :
180
+				$where_task = [];
181
+				$r_logs = $this->getRelationIdsByType($map['types'], $map['types_id'], 'task') ? : [];
182
+				$where_task['task_id'] = ['in',$r_logs];				
183
+				$list = db('task')
184
+					->page($request['page'], $request['limit'])
185
+					->order('create_time desc')				
186
+					->where($where_task)
187
+					->select();
188
+				foreach ($list as $k=>$v) {
189
+					$list[$k]['id'] = $v['task_id'];
190
+					$list[$k]['cate'] = 4;
191
+				}				
192
+				$dataCount = db('task')->where($where_task)->count();
193
+				break;
194
+			case 'event' :
195
+				$where_event = [];
196
+				$r_logs = $this->getRelationIdsByType($map['types'], $map['types_id'], 'oa_event') ? : [];
197
+				$where_event['event_id'] = ['in',$r_logs];				
198
+				$list = db('oa_event')
199
+					->page($request['page'], $request['limit'])
200
+					->order('create_time desc')				
201
+					->where($where_event)
202
+					->select();
203
+				foreach ($list as $k=>$v) {
204
+					$list[$k]['id'] = $v['event_id'];
205
+					$list[$k]['cate'] = 5;
206
+				}				
207
+				$dataCount = db('oa_event')->where($where_event)->count();
208
+				break;											
209
+			default : 
210
+				$where_log = [];
211
+				$r_logs = $this->getRelationIdsByType($map['types'], $map['types_id'], 'oa_log') ? : [];
212
+				$where_log['log_id'] = ['in',$r_logs];			
213
+				$sqlArr[] = Db::table('__OA_LOG__')
214
+	                ->where($where_log)
215
+	                ->field(['log_id as id,create_time,create_user_id,2 as cate,content'])
216
+	                ->buildSql();
217
+
218
+				$where_examine = [];
219
+				$r_logs = $this->getRelationIdsByType($map['types'], $map['types_id'], 'oa_examine') ? : [];
220
+				$where_examine['examine_id'] = ['in',$r_logs];		            
221
+				$sqlArr[] = Db::table('__OA_EXAMINE__')
222
+	                ->where($where_examine)
223
+	                ->field(['examine_id as id,create_time,create_user_id,3 as cate,content'])
224
+	                ->buildSql();
225
+
226
+				$where_task = [];
227
+				$r_logs = $this->getRelationIdsByType($map['types'], $map['types_id'], 'task') ? : [];
228
+				$where_task['task_id'] = ['in',$r_logs];	                
229
+				$sqlArr[] = Db::table('__TASK__')
230
+	                ->where($where_task)
231
+	                ->field(['task_id as id,create_time,create_user_id,4 as cate,name as content'])
232
+	                ->buildSql();	            	            
233
+
234
+				$where_record = [];
235
+				$where_record['types'] = $map['types'];
236
+				$where_record['types_id'] = $map['types_id'];
237
+				//客户模块下包含被转化线索的跟进记录
238
+				if ($map['types'] == 'crm_customer') {
239
+					if ($leads_id = db('crm_leads')->where(['customer_id' => $map['types_id']])->value('leads_id')) {
240
+						$whereOr = [];
241
+						$whereOr['types'] = 'crm_leads';
242
+						$whereOr['types_id'] = $leads_id;
243
+					}
244
+				}				                
245
+	            $e = Db::table('__ADMIN_RECORD__')
246
+	            	->alias('record')
247
+	            	->where($where_record)            	
248
+	            	->whereOr($whereOr)            	
249
+	            	->field(['record_id as id,create_time,create_user_id,1 as cate,content'])
250
+	            	->union($sqlArr)
251
+	            	->buildSql();
252
+
253
+	            $list = Db::table($e.' a')
254
+		            ->page($request['page'], $request['limit'])
255
+					->order('create_time desc')
256
+					->select();
257
+				$dataCount = Db::table($e.' a')->count();
258
+				break;
259
+		}
260
+		$admin_user_ids = $userModel->getAdminId();
261
+		foreach ($list as $k=>$v) {
262
+			$create_user_info = isset($v['create_user_id']) ? $userModel->getUserById($v['create_user_id']) : [];
263
+			$list[$k]['create_user_info'] = $create_user_info;
264
+			$content = '';
265
+			$fileList = [];
266
+			$imgList = [];
267
+			$where = [];
268
+			$where['module_id'] = $v['id'];
269
+			$relation_list = [];
270
+
271
+			switch ($v['cate']) {
272
+				case '1' : 
273
+					$where['module'] = 'admin_record';
274
+					$relation_list = $this->getListByRelationId('record', $v['id']);
275
+					$dataInfo = [];
276
+					break;
277
+				case '2' : 
278
+					$where['module'] = 'oa_log';
279
+					$dataInfo = $v;
280
+					$dataInfo['create_user_info'] = $create_user_info;
281
+					$dataInfo['sendUserList'] = $userModel->getDataByStr($dataInfo['send_user_ids']) ? : [];
282
+					$dataInfo['sendStructList'] = $structureModel->getDataByStr($dataInfo['send_structure_ids']) ? : [];
283
+					$param['type_id'] = $dataInfo['log_id'];
284
+					$param['type'] = 'oa_log';
285
+					$dataInfo['replyList'] = $commonModel->read($param);
286
+
287
+					$is_update = 0;
288
+					$is_delete = 0;
289
+					//3天内的日志可删,可修改
290
+					if (($dataInfo['create_user_id'] == $user_id) && date('Ymd',$dataInfo['create_time']) > date('Ymd',(strtotime(date('Ymd',time()))-86400*3))) {
291
+						$is_update = 1;
292
+						$is_delete = 1;			
293
+					}
294
+					$permission['is_update'] = $is_update;
295
+					$permission['is_delete'] = $is_delete;
296
+					$dataInfo['permission']  = $permission;					
297
+
298
+					$relation_list = $this->getListByRelationId('log', $v['id']);
299
+					break;
300
+				case '3' : 
301
+					$where['module'] = 'oa_examine';
302
+					$dataInfo = $v;
303
+					$dataInfo['category_name'] = db('oa_examine_category')->where(['category_id' => $dataInfo['category_id']])->value('title');
304
+					$dataInfo['create_user_info'] = $create_user_info;
305
+		       		$causeCount = 0;
306
+		       		$causeTitle = '';
307
+		       		$duration = $dataInfo['duration'] ? : '0.0';
308
+		       		$money = $dataInfo['money'] ? : '0.00';
309
+		       		if (in_array($dataInfo['category_id'],['3','5'])) {
310
+		       			$causeCount = db('oa_examine_travel')->where(['examine_id' => $dataInfo['examine_id']])->count() ? : 0;
311
+		       			if ($dataInfo['category_id'] == 3) $causeTitle = $causeCount.'个行程,共'.$duration.'天';
312
+		       			if ($dataInfo['category_id'] == 5) $causeTitle = $causeCount.'个报销事项,共'.$money.'元';
313
+		       		}
314
+		       		$dataInfo['causeTitle'] = $causeTitle;
315
+		       		$dataInfo['causeCount'] = $causeCount ? : 0;
316
+
317
+					//权限
318
+					//创建人或管理员有撤销权限
319
+					$permission = [];
320
+					$is_recheck = 0;
321
+					$is_update = 0;
322
+					$is_delete = 0;
323
+			        if (((int)$dataInfo['create_user_id'] == $user_id || !in_array($userr_id, $admin_user_ids)) && (!in_array($dataInfo['check_status'],['2','3']) || (empty($dataInfo['check_status']) && empty($dataInfo['check_user_id'])))) {
324
+			            $is_recheck = 1;
325
+			        }
326
+			        //创建人(待审状态且无审批人时可编辑)
327
+					if (($user_id == (int)$dataInfo['create_user_id']) && $dataInfo['check_status'] == 0 && empty($dataInfo['check_user_id'])) {
328
+				        $is_update = 1;
329
+						$is_delete = 1;
330
+				    }
331
+				    $permission['is_recheck'] = $is_recheck;	        
332
+			        $permission['is_update'] = $is_update;
333
+			        $permission['is_delete'] = $is_delete;
334
+			        $dataInfo['permission']	= $permission;
335
+
336
+					$relation_list = $this->getListByRelationId('examine', $v['id']);
337
+					break;
338
+				case '4' : 
339
+					$where['module'] = 'work_task';
340
+					$relation_list = $this->getListByRelationId('task', $v['id']);
341
+					$dataInfo = $v;
342
+					$dataInfo['task_name'] = $dataInfo['name'];
343
+					if ($dataInfo['pid'] > 0) {
344
+						$p_det = Db::name('Task')->field('task_id,name')->where('task_id ='.$dataInfo['pid'])->find();
345
+						$dataInfo['pname'] = $p_det['name'];
346
+					} else {
347
+						$dataInfo['pname'] = '';
348
+					}
349
+					$subcount = Db::name('Task')->where(' ishidden =0 and ( status=1 ) and  pid ='.$dataInfo['task_id'])->count();
350
+					$subdonecount = Db::name('Task')->where(' ishidden = 0 and status = 5 and pid ='.$dataInfo['task_id'])->count();
351
+					$dataInfo['subcount'] = $subcount; //子任务
352
+					$dataInfo['subdonecount'] = $subdonecount; //已完成子任务
353
+					$dataInfo['commentcount'] = Db::name('AdminComment')->where('type=1 and type_id ='.$dataInfo['task_id'])->count();
354
+					$dataInfo['filecount'] = Db::name('WorkTaskFile')->where('task_id ='.$dataInfo['task_id'])->count();	
355
+					if ($dataInfo['lable_id']) {
356
+						$dataInfo['lableList'] = $lableModel->getDataByStr($dataInfo['lable_id']);
357
+					}else{
358
+						$dataInfo['lableList'] = array();
359
+					}
360
+					//参与人列表数组
361
+					//$userlist =$userModel->getDataByStr($value['owner_user_id']);
362
+					//$dataInfo['own_list'] = $userlist?$userlist: array(); 
363
+					//负责人信息
364
+					$dataInfo['main_user'] = $dataInfo['main_user_id'] ? $userModel->getUserById($dataInfo['main_user_id']) : array();
365
+					$dataInfo['relationCount'] = $taskModel->getRelationCount($dataInfo['task_id']);					
366
+					break;					
367
+				case '5' : 
368
+					$where['module'] = 'oa_event';
369
+					$relation_list = $this->getListByRelationId('event', $v['id']);
370
+					$dataInfo = $v;
371
+					$dataInfo['create_user_info'] = $userModel->getUserById($dataInfo['create_user_id']);
372
+					$dataInfo['ownerList'] = $userModel->getDataByStr($dataInfo['owner_user_ids']) ? : [];
373
+					$dataInfo['remindtype'] = (int)$dataInfo['remindtype'];
374
+					$noticeList = Db::name('OaEventNotice')->where('event_id = '.$dataInfo['event_id'])->find();
375
+					if (!$noticeList) {
376
+						$dataInfo['is_repeat'] = 0;
377
+					} else {
378
+						$dataInfo['is_repeat'] = 1;
379
+					}
380
+					$dataInfo['stop_time'] = $noticeList ? $noticeList['stop_time'] : '';
381
+					$dataInfo['noticetype'] = $noticeList ? $noticeList['noticetype'] : '';
382
+					if ($noticeList['noticetype'] == '2') {
383
+						$dataInfo['repeat'] =  $noticeList['repeated'] ? explode('|||',$noticeList['repeated']) : [];
384
+					} else {
385
+						$dataInfo['repeat'] =  '';
386
+					}
387
+					break;					
388
+				case '6' : 
389
+					$where['module'] = 'work';
390
+					$relation_list = $this->getListByRelationId('work', $v['id']);
391
+					break;														
392
+			}
393
+			$newFileList = [];
394
+			$newFileList = $fileModel->getDataList($where, 'all');
395
+			if ($newFileList['list']) {
396
+				foreach ($newFileList['list'] as $val) {
397
+					if ($val['types'] == 'file') {
398
+						$fileList[] = $val;
399
+					} else {
400
+						$imgList[] = $val;
401
+					}
402
+				}				
403
+			}
404
+			$dataInfo['fileList'] = $fileList ? : [];
405
+			$dataInfo['imgList'] = $imgList ? : [];
406
+			$dataInfo['customerList'] = $relation_list['customerList'] ? : [];
407
+			$dataInfo['contactsList'] = $relation_list['contactsList'] ? : [];
408
+			$dataInfo['businessList'] = $relation_list['businessList'] ? : [];
409
+			$dataInfo['contractList'] = $relation_list['contractList'] ? : [];
410
+
411
+			if ($v['cate'] != 1) {
412
+				$list[$k] = ['dataInfo' => $dataInfo];
413
+			} else {
414
+				$list[$k]['dataInfo'] = $dataInfo;
415
+			}
416
+		}
417
+        $data = [];
418
+        $data['list'] = $list ? : [];
419
+        $data['dataCount'] = $dataCount ? : 0;
420
+        return $data;
421
+    }
422
+
423
+	/**
424
+	 * 创建跟进记录信息
425
+	 * @author Michael_xu
426
+	 * @param  
427
+	 * @return                            
428
+	 */	
429
+	public function createData($param)
430
+	{
431
+		$eventModel = new \app\oa\model\Event();
432
+		if (!$param['types'] || !$param['types_id'] || !in_array($param['types'], $this->types_arr)) {
433
+			$this->error = '参数错误';
434
+			return false;
435
+		}
436
+		//验证
437
+		$validate = validate($this->name);
438
+		if (!$validate->check($param)) {
439
+			$this->error = $validate->getError();
440
+			return false;
441
+		}
442
+		$param['business_ids'] = arrayToString($param['business_ids']);
443
+		$param['contacts_ids'] = arrayToString($param['contacts_ids']);
444
+
445
+		$fileArr = $param['file_id']; //接收表单附件
446
+		unset($param['file_id']);
447
+		if ($this->data($param)->allowField(true)->save()) {
448
+			//下次联系时间
449
+			$this->updateNexttime($param['types'], $param['types_id'], $param['next_time']);
450
+
451
+			//处理附件关系
452
+	        if ($fileArr) {
453
+	            $fileModel = new \app\admin\model\File();
454
+	            $resData = $fileModel->createDataById($fileArr, 'admin_record', $this->record_id);
455
+				if ($resData == false) {
456
+		        	$this->error = '附件上传失败';
457
+		        	return false;
458
+		        }
459
+	        }
460
+
461
+			$data = [];
462
+			$data['record_id'] = $this->record_id;
463
+			return $data;
464
+		} else {
465
+			$this->error = '添加失败';
466
+			return false;
467
+		}			
468
+	}
469
+
470
+	/**
471
+	 * 根据主键获取详情
472
+	 * @param  array   $param  [description]
473
+	 */ 
474
+	public function getDataById($id = '')
475
+	{
476
+		$map['record_id'] = $id;
477
+		$dataInfo = db('admin_record')->where($map)->find();
478
+		if (!$dataInfo) {
479
+			$this->error = '暂无此数据';
480
+			return false;
481
+		}
482
+		$userModel = new \app\admin\model\User();
483
+		$dataInfo['create_user_info'] = $userModel->getUserById($dataInfo['create_user_id']);
484
+		return $dataInfo;		
485
+	}  
486
+
487
+	/**
488
+	 * 相关业务ids
489
+	 * @param $types 相关业务
490
+	 * @param $types_id  相关业务ID
491
+	 * @param $relation  相关模块
492
+	 */ 	
493
+	public function getRelationIdsByType($types, $types_id, $relation)
494
+	{
495
+		$rIds = [];
496
+		switch ($relation) {
497
+			case 'oa_log' : $dbName = db('oa_log_relation'); $relationId = 'log_id'; break; //相关日志
498
+			case 'oa_event' : $dbName = db('oa_event_relation'); $relationId = 'event_id'; break; //相关日程
499
+			case 'task' : $dbName = db('task_relation'); $relationId = 'task_id'; break; //相关任务
500
+			case 'task_work' : $dbName = db('work_relation'); $relationId = 'work_id'; break; //相关项目
501
+			case 'oa_examine' : $dbName = db('oa_examine_relation'); $relationId = 'examine_id'; break; //相关审批
502
+			default : return []; break;
503
+		}
504
+		switch ($types) {
505
+			case 'crm_customer' : $rIds = $dbName->where(['customer_ids' => ['like', '%,'.$types_id.',%']])->column($relationId); break;
506
+			case 'crm_contacts' : $rIds = $dbName->where(['contacts_ids' => ['like', '%,'.$types_id.',%']])->column($relationId); break;
507
+			case 'crm_business' : $rIds = $dbName->where(['business_ids' => ['like', '%,'.$types_id.',%']])->column($relationId); break;
508
+			case 'crm_contract' : $rIds = $dbName->where(['contract_ids' => ['like', '%,'.$types_id.',%']])->column($relationId); break;
509
+		}
510
+		return $rIds ? : [];
511
+	}	
512
+
513
+	/**
514
+	 * 相关业务list
515
+	 * @param $types 相关业务
516
+	 * @param $types_id  相关业务ID
517
+	 * @param $relation  相关模块
518
+	 */ 
519
+	public function getListByRelationId($relation, $relation_id)
520
+	{
521
+
522
+		$BusinessModel = new \app\crm\model\Business();
523
+		$ContactsModel = new \app\crm\model\Contacts();
524
+		$ContractModel = new \app\crm\model\Contract();
525
+		$CustomerModel = new \app\crm\model\Customer();
526
+        $LeadsModel = new \app\crm\model\Leads();
527
+        $data = [];
528
+		switch ($relation) {
529
+			case 'log' : $data = db('oa_log_relation')->where(['log_id' => $relation_id])->find(); break;
530
+			case 'event' : $data = db('oa_event_relation')->where(['event_id' => $relation_id])->find(); break;
531
+			case 'task' : $data = db('task_relation')->where(['task_id' => $relation_id])->find(); break;
532
+			case 'work' : $data = db('work_relation')->where(['work_id' => $relation_id])->find(); break;
533
+			case 'examine' : $data = db('oa_examine_relation')->where(['examine_id' => $relation_id])->find(); break;
534
+			case 'record' : $data = db('admin_record')->where(['record_id' => $relation_id])->find(); break;
535
+            case 'activity' : $data = db('crm_activity')->where(['activity_id' => $relation_id])->find(); break;
536
+			default : $data = []; break;
537
+		}
538
+		$data['customerList'] = $data['customer_ids'] ? $CustomerModel->getDataByStr($data['customer_ids']) : [];
539
+		$data['contactsList'] = $data['contacts_ids'] ? $ContactsModel->getDataByStr($data['contacts_ids']) : [];
540
+		$data['businessList'] = $data['business_ids'] ? $BusinessModel->getDataByStr($data['business_ids']) : [];
541
+		$data['contractList'] = $data['contract_ids'] ? $ContractModel->getDataByStr($data['contract_ids']) : [];
542
+        $data['leadsList'] = $data['leads_ids'] ? $LeadsModel->getDataByStr($data['leads_ids']) : [];
543
+		return $data ? : [];
544
+	}
545
+    /**
546
+     * 多标签list
547
+     * @param $types 相关业务
548
+     * @param $types_id  相关业务ID
549
+     * @param $relation  相关模块
550
+     */
551
+    public function getListByLableId($relation, $relation_id)
552
+    {
553
+        $TaskModel = new \app\work\model\Task();
554
+        $data = [];
555
+        switch ($relation) {
556
+            case 'task' : $data = db('task')->where(['task_id' => $relation_id])->field('lable_id')->find(); break;
557
+            case 'work' : $data = db('work_relation')->where(['work_id' => $relation_id])->find(); break;
558
+            default : $data = []; break;
559
+        }
560
+        $data['lable'] = $data['lable_id'] ? $TaskModel->getDataByStr($data['lable_id']) : [];
561
+
562
+        return $data ? : [];
563
+    }
564
+	/**
565
+	 * 相关模块下次联系时间
566
+	 * @param types 类型
567
+	 * @param types 类型ID
568
+	 * @param next_time 下次联系时间
569
+	 */ 
570
+	public function updateNexttime($types, $types_id, $next_time)
571
+	{
572
+		switch ($types) {
573
+			case 'crm_customer' : $dbName = db('crm_customer'); $dbId = 'customer_id'; break;
574
+			case 'crm_leads' : $dbName = db('crm_leads'); $dbId = 'leads_id'; break;
575
+			case 'crm_contacts' : $dbName = db('crm_contacts'); $dbId = 'contacts_id'; break;
576
+			case 'crm_business' : $dbName = db('crm_business'); $dbId = 'business_id'; break;
577
+			default : break;
578
+		}
579
+		if (!$dbName || !$dbId) {
580
+			return true;
581
+		}
582
+		$data = [];
583
+		if ($next_time) {
584
+	      	$data['next_time'] = $next_time;
585
+	    } else {
586
+			// 如果未填写下次联系时间,并且 原下次联系时间为当天,则把下次联系时间置空
587
+			$next_time = $dbName->where([$dbId => $types_id])->value('next_time');
588
+			list($start, $end) = getTimeByType();
589
+			if ($next_time >= $start && $next_time <= $end) {
590
+				$data['next_time'] = 0;
591
+			}
592
+	    }
593
+		$data['update_time'] = time();
594
+		if (in_array($types,['crm_customer','crm_leads'])) $data['follow'] = '已跟进';
595
+		$dbName->where([$dbId => $types_id])->update($data);
596
+		return true;
597
+	}
598
+
599
+	/**
600
+	 * 跟进记录删除
601
+	 * @param types 类型
602
+	 * @param types 类型ID数组
603
+	 * @param 
604
+	 */ 
605
+	public function delDataByTypes($types, $types_id)
606
+	{
607
+		if (!is_array($types_id)) {
608
+			$types_id[] = $types_id;
609
+		}
610
+		$fileModel = new \app\admin\model\File();
611
+		$record_ids = db('crm_activity')->where(['activity_type' => $types,'activity_type_id' => ['in',$types_id]])->column('activity_id');
612
+        db('crm_activity')->where(['activity_type' => $types,'activity_type_id' => ['in',$types_id],'type'=>1])->delete();
613
+		//删除关联附件
614
+        $fileModel->delRFileByModule('crm_activity',$record_ids);
615
+		return true;
616
+	}	
617
+
618
+    /**
619
+     * 查询最近更进记录
620
+     *
621
+     * @param string $types 关联类型
622
+     * @param array $types_id_list 类型ID
623
+     * @return array
624
+     * @author Ymob
625
+     * @datetime 2019-12-11 10:43:04
626
+     */
627
+    public static function getLastRecord($types, $types_id_list)
628
+    {
629
+		$prefix = config('database.prefix');
630
+		$types_ids = implode(',', $types_id_list) ?: '-1';
631
+        $list = self::field(['types_id', 'content'])
632
+        ->where("
633
+            `record_id` IN (
634
+				SELECT
635
+					MAX(`record_id`)
636
+				FROM
637
+					`{$prefix}admin_record`
638
+				WHERE
639
+					`types` = '{$types}'
640
+					AND `types_id` IN ({$types_ids})
641
+				GROUP BY
642
+					`types_id`
643
+            )
644
+		")
645
+		->select();
646
+		$res = [];
647
+		foreach ($list as $val) {
648
+			$res[$val['types_id']] = $val['content'];
649
+		}
650
+		return $res;
651
+    }
652
+}

+ 131
- 0
application/admin/model/Rule.php Целия файл

@@ -0,0 +1,131 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 规则
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use app\admin\model\Common;
11
+use \think\Db;
12
+
13
+class Rule extends Common 
14
+{
15
+    /**
16
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
17
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
18
+     */
19
+	protected $name = 'admin_rule';
20
+
21
+	/**
22
+	 * [getDataList 获取列表]
23
+	 * @param     string   $type [是否为树状结构]
24
+	 * @param     int   $pid 角色分类:0客户自定义角色,1系统默认管理角色,2客户管理角色,3人力资源管理角色,4财务管理角色,5项目管理角色,6办公管理角色
25
+	 * @return    [array]                         
26
+	 */
27
+	public function getDataList($param)
28
+	{
29
+		$type = $param['type'];
30
+		$groupPid = $param['pid'] ? : 0;
31
+		$types = $this->groupsToRules($groupPid);
32
+		// 若type为tree,则返回树状结构
33
+		if ($type == 'tree') {
34
+			$cat = new \com\Category('admin_rule', array('id', 'pid', 'title', 'title'));
35
+			$data = $cat->getList('', 0, 'id');
36
+			foreach ($data as $k => $v) {
37
+				if ($v['id'] == '31') {
38
+					unset($data[$k]); 
39
+					continue;
40
+				}
41
+				$data[$k]['check'] = false;
42
+				if ($types && !in_array((int)$v['types'], $types)) {
43
+					unset($data[$k]);
44
+				}
45
+				if (empty($v['status'])) {
46
+					unset($data[$k]);
47
+				}		
48
+			}
49
+			$data = array_merge($data);
50
+			$tree = new \com\Tree();
51
+			$list = $tree->list_to_tree($data, 'id', 'pid', 'child', 0, true, array('pid'));
52
+		} elseif ($types) {
53
+			$list = Db::name('AdminRule')->where(['types' => ['in',$types]])->select();
54
+		}
55
+		return $list;
56
+	}
57
+
58
+	//添加规则
59
+	public function createData($param)
60
+	{
61
+		if($param['pid'] && $param['name']&&$param['title']){
62
+			$pdet = Db::name('AdminRule')->where('id ='.$param['pid'].'')->find();
63
+			if ($pdet['level'] == 1) {
64
+				$data['level'] = 2;
65
+			} elseif ( $pdet['level'] == 2){
66
+				$data['level'] = 3;
67
+			} else {
68
+				$this->error = '等级参数错误';
69
+				return false;
70
+			}
71
+			$data['pid'] = $param['pid']; //上级ID
72
+			$data['name'] = $param['name']; //方法名
73
+			$data['title'] = $param['title'];//名称 
74
+			$data['status'] = 1;  //状态1 显示
75
+
76
+			//1超级管理员2系统设置管理员3部门与员工管理员4审批流管理员5工作台管理员6客户管理员7项目管理员8公告管理员
77
+			$data['types'] = $param['types'];
78
+			$flag = $this->insert($data);
79
+			if ($flag) {
80
+				return true;
81
+			} else {
82
+				$this->error = '添加失败';
83
+				return false;
84
+			}
85
+		} else {
86
+			$this->error = '参数错误';
87
+			return false;
88
+		}
89
+	}
90
+
91
+	//编辑规则
92
+	public function updateDataById($param,$id)
93
+	{
94
+		if ($param['id']) {
95
+			$flag = $this->where('id ='.$param['id'].'')->update($param);
96
+			return true;
97
+		} else {
98
+			$this->error = '参数错误';
99
+			return false;
100
+		}
101
+	}
102
+
103
+	/**
104
+     * 角色与规则对照表
105
+     * @param $groupPid 角色分类:0客户自定义角色,1系统默认管理角色,2客户管理角色,3人力资源管理角色(原客户),4财务管理角色(原客户),5项目管理角色,6办公管理角色,7人力资源管理角色,8财务管理角色
106
+     * @param  rule:types 0系统设置1工作台2客户管理3项目管理4人力资源5财务管理6商业智能(客戶)
107
+     * @return
108
+     */	
109
+    public function groupsToRules($groupPid)
110
+    {
111
+    	$ruleTypes = [];
112
+    	switch ($groupPid) {
113
+    		case '0' : 
114
+    		case '2' : 
115
+    			$ruleTypes = ['2','6']; 
116
+    			break;
117
+    		case '1' : 
118
+    			$ruleTypes = ['0']; 
119
+    			break;  		
120
+			case '5' : 
121
+    			$ruleTypes = ['3']; 
122
+    			break;  
123
+			case '6' : 
124
+    			$ruleTypes = ['1','7']; 
125
+    			break;      		
126
+    		default : $ruleTypes = [$groupPid]; 
127
+    			break;			  			
128
+    	}
129
+    	return $ruleTypes;
130
+    }
131
+}

+ 529
- 0
application/admin/model/Scene.php Целия файл

@@ -0,0 +1,529 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 场景
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com  
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use think\Db;
11
+use app\admin\model\Common;
12
+
13
+class Scene extends Common 
14
+{
15
+    /**
16
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
17
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
18
+     */
19
+	protected $name = 'admin_scene';
20
+	protected $createTime = 'create_time';
21
+	protected $updateTime = false;
22
+	protected $autoWriteTimestamp = true;
23
+
24
+	private $types_arr = ['crm_leads','crm_customer','crm_customer_pool','crm_contacts','crm_product','crm_business','crm_contract','crm_receivables','crm_visit','crm_invoice']; //支持场景的分类
25
+
26
+	protected $type = [
27
+        'data'    =>  'array',
28
+    ];
29
+
30
+	/**
31
+	 * 创建场景
32
+	 * @param  
33
+	 * @return                            
34
+	 */	
35
+	public function createData($param, $types = '')
36
+	{
37
+		if (empty($types)) {
38
+			$this->error = '参数错误';
39
+			return false;
40
+		}
41
+		if (empty($param['name'])) {
42
+			$this->error = '场景名称必填';
43
+			return false;
44
+		}
45
+		$user_id = $param['user_id'];
46
+		if ($this->where(['types'=>$types,'user_id'=>$user_id,'name'=>$param['name']])->find()) {
47
+			$this->error = '场景名称已存在';
48
+			return false;
49
+		}
50
+		# 转自定义场景结构
51
+        $sceneData = [];
52
+        foreach ($param['data'] AS $key => $value) {
53
+            foreach ($value AS $k => $v) {
54
+                $sceneData[$k] = [
55
+                    'condition' => trim($v['condition']),
56
+                    'value' => $v['value'],
57
+                    'form_type' => $v['form_type'],
58
+                    'name' => $v['name'],
59
+                    'type' => $v['type']
60
+                ];
61
+            }
62
+        }
63
+        if (!empty($sceneData)) $param['data'] = $sceneData;
64
+		$max_order_id = $this->getMaxOrderid($types, $user_id);
65
+		$param['order_id'] = $max_order_id ? $max_order_id+1 : 0;
66
+		$param['update_time'] = time();
67
+		$param['type'] = 0;
68
+		$param['bydata'] = '';
69
+		$res = $this->allowField(true)->save($param);
70
+		if ($res) {
71
+			//设置默认
72
+			if ($param['is_default']) {
73
+				$defaultData = [];
74
+				$defaultData['types'] = $types;
75
+				$defaultData['user_id'] = $user_id;
76
+				$this->defaultDataById($defaultData, $this->scene_id);
77
+			}			
78
+			return true;
79
+		} else {
80
+			$this->error = '添加失败';
81
+			return false;			
82
+		}			
83
+	}
84
+
85
+	/**
86
+     * [getDataList 场景list]
87
+     * @param  types 分类
88
+     * @author Michael_xu
89
+     * @return    [array]
90
+     */		
91
+	public function getDataList($types, $user_id)
92
+    {
93
+    	$fieldModel = new \app\admin\model\Field();
94
+    	$userModel = new \app\admin\model\User();
95
+    	if (!in_array($types, $this->types_arr)) {
96
+			$this->error = '参数错误';
97
+			return false;    		
98
+    	}
99
+        $map['user_id'] = $user_id;
100
+        $map['is_hide'] = 0;
101
+        $map['types'] = $types;
102
+        $list = db('admin_scene')
103
+        		->where($map)
104
+        		->whereOr(function ($query) use ($types) {
105
+				    $query->where(['types' => $types,'type' => 1]);
106
+				})->order('order_id asc,scene_id asc')
107
+        		->select();
108
+        $defaultSceneId = db('admin_scene_default')->where(['types' => $types,'user_id' => $user_id])->value('scene_id');
109
+        $fieldList = $fieldModel->getField(['types' => $types]);
110
+        $newFieldList = [];
111
+        foreach ($fieldList as $k=>$v) {
112
+        	$field = $v['field'];
113
+        	if ($v['field'] == 'customer_id') $field = 'customer_name'; 
114
+        	$newFieldList[$field] = $v;
115
+        }
116
+        foreach ($list as $k=>$v) {
117
+        	if ($v['scene_id'] == $defaultSceneId) {
118
+        		$list[$k]['is_default'] = 1;
119
+        	}
120
+        	$data = $v['data'] ? json_decode($v['data'],true) : [];
121
+        	if ($data) {
122
+				foreach ($data as $key=>$val) {
123
+					$setting = $newFieldList[$key]['setting'];
124
+	    			$data[$key]['setting'] = $setting;
125
+	    			if ($val['form_type'] == 'user' && $val['value']) {
126
+	    				$userInfo = $userModel->getUserById($val['value']);
127
+	    				$data[$key]['setting']['realname'] = $userInfo['realname'];
128
+	    				$data[$key]['setting']['id'] = $userInfo['id'];
129
+	    			} 
130
+	    		}        		
131
+        	}
132
+    		$list[$k]['data'] = $data ? : [];
133
+        }
134
+        $map['is_hide'] = 1;
135
+        $hideList = $this->where($map)->order('order_id asc')->select();
136
+        $data = [];
137
+        $data['list'] = $list;
138
+        $data['hideList'] = $hideList;
139
+        return $data;
140
+    }
141
+
142
+	/**
143
+	 * 根据主键获取详情
144
+	 * @param  array   $param  [description]
145
+	 * @author Michael_xu
146
+	 */ 
147
+	public function getDataById($id = '', $user_id = '', $types = '')
148
+	{
149
+		$where = [];
150
+		$where['scene_id'] = $id;
151
+		// $where['user_id'] = [['=',$user_id],['=',0],'or'];
152
+		$data = db('admin_scene')->where($where)->find();
153
+		if (!$types) {
154
+			$types = $data['types'] ? : '';
155
+		}
156
+		//处理data
157
+		if ($data['bydata'] && $types) {
158
+			$data = $this->getByData($types, $data['bydata'], $user_id);
159
+		} else {
160
+			$data = json_decode($data['data'],true);
161
+			if (is_array($data)) {
162
+				foreach ($data as $k=>$v) {
163
+					if ($v['form_type'] == 'business_type') {
164
+						$data[$k]['value'] = $v['type_id'];
165
+					}
166
+				}	
167
+			}
168
+		}
169
+		return $data ? : [];		
170
+	}   
171
+
172
+	/**
173
+	 * 根据主键修改
174
+	 * @param  array   $param  [description]
175
+	 * @author Michael_xu
176
+	 */	
177
+	public function updateDataById($param, $id)
178
+	{
179
+		$checkData = $this->get($id);
180
+		$sceneInfo = $checkData->data;
181
+		$user_id = $param['user_id'];
182
+		if (!$sceneInfo) {
183
+			$this->error = '暂无数据';
184
+			return false;
185
+		}
186
+		//权限(只能编辑自己的)
187
+		if ($sceneInfo['user_id'] !== $user_id) {
188
+			$this->error = '参数错误';
189
+			return false;			
190
+		}
191
+		if (empty($param['name'])) {
192
+			$this->error = '场景名称必填';
193
+			return false;
194
+		}
195
+		if ($this->where(['scene_id'=>['neq',$id],'types'=>$types,'user_id'=>$user_id,'name'=>$param['name']])->find()) {
196
+			$this->error = '场景名称已存在';
197
+			return false;
198
+		}
199
+        # 转自定义场景结构
200
+        $sceneData = [];
201
+        foreach ($param['data'] AS $key => $value) {
202
+            foreach ($value AS $k => $v) {
203
+                $sceneData[$k] = $v;
204
+            }
205
+        }
206
+        if (!empty($sceneData)) $param['data'] = $sceneData;
207
+		$param['update_time'] = time();		
208
+		// $scene_data = $this->dataChangeString($param);
209
+		//处理data数据
210
+		$res = $this->allowField(true)->save($param, ['scene_id' => $id]);
211
+		if ($param['is_default'] == 1) {
212
+			$this->defaultDataById($param,$param['id']);
213
+		}
214
+		if ($res) {
215
+			return true;
216
+		} else {
217
+			$this->error = '修改失败';
218
+			return false;	
219
+		}
220
+	}
221
+
222
+	/**
223
+	 * 场景设置为默认
224
+	 * @param types 类型
225
+	 * @param user_id 人员ID
226
+	 * @param id 场景ID
227
+	 * @author Michael_xu
228
+	 */	
229
+	public function defaultDataById($param, $id)	
230
+	{
231
+		if (!$param['types'] || !$id) {
232
+			$this->error = '参数错误';
233
+			return false;
234
+		}
235
+		$resInfo = db('admin_scene_default')->where(['types' => $param['types'],'user_id' => $param['user_id']])->find();
236
+		if ($resInfo) {
237
+			$res = db('admin_scene_default')->where(['types' => $param['types'],'user_id' => $param['user_id']])->update(['scene_id' => $id]);
238
+		} else {
239
+			$data = [];
240
+			$data['types'] = $param['types'];
241
+			$data['user_id'] = $param['user_id'];
242
+			$data['scene_id'] = $id;
243
+			$res = db('admin_scene_default')->insert($data);
244
+		}
245
+		if (!$res) {
246
+			$this->error = '设置失败或数据无变化';
247
+			return false;
248
+		}
249
+		return true;
250
+	}
251
+
252
+	/**
253
+	 * 场景数据转换(字符串形式存储)
254
+	 * @param  
255
+	 * @author Michael_xu
256
+	 * @return                            
257
+	 */
258
+	public function dataChangeString($param = [])
259
+	{
260
+		$scene_data = '[';
261
+		$field_arr = [];
262
+		$i = 0;
263
+		foreach ($param['data'] as $k=>$v) {
264
+			if ($v != '' && !in_array($v['field'], $field_arr)) {
265
+				$i++;
266
+				if ($i == 1) {
267
+					$scene_data .= $v['field']."=>[";
268
+				} else {
269
+					$scene_data .= ",".$v['field']."=>[";
270
+				}
271
+				$scene_data .= "field=>".$v['field'].",";
272
+				//处理条件和值
273
+				foreach ($param as $k1=>$v1) {
274
+					switch ($k1) {
275
+						case 'condition' : $scene_data .= "condition=>".$v1.","; break;
276
+						case 'value' : $scene_data .= "value=>".$v1.","; break;
277
+						case 'state' : 
278
+						case 'city' : 
279
+						case 'area' : 
280
+							//处理地址类型数据
281
+							$scene_data .= $k1."=>".$v1.","; break;
282
+						case 'start' :	$scene_data .= "start=>".$v1.","; break;				
283
+						case 'end' :	$scene_data .= "end=>".$v1.","; break;			
284
+						case 'start_date' :	$scene_data .= "start_date=>".$v1.","; break;			
285
+						case 'end_date' :	$scene_data .= "end_date=>".$v1.","; break;			
286
+					}
287
+				}
288
+				$form_type = '';
289
+				//处理字段类型
290
+				if ($v['field'] == 'create_time' || $v['field'] == 'update_time') {
291
+					$form_type = 'datetime';
292
+				} else {
293
+					$form_type = db('admin_fields')->where(['types'=>$param['types'],'field'=>$v['field'],'is_main'=>1])->column('form_type');
294
+				}
295
+				$scene_data .= "form_type=>".$form_type;
296
+				$field_arr[] = $v['field'];
297
+			}
298
+			$scene_data .= ']';
299
+		}
300
+		$scene_data .= ']';
301
+		return $scene_data;
302
+	}
303
+
304
+	/**
305
+	 * 场景排序最大值
306
+	 * @param  
307
+	 * @author Michael_xu
308
+	 * @return                            
309
+	 */	
310
+	public function getMaxOrderid($types, $user_id)
311
+	{
312
+		$maxOrderid = $this->where(['types' => $types, 'user_id' => $user_id])->max('order_id');
313
+		return $maxOrderid ? : 0;
314
+	}
315
+
316
+	/**
317
+	 * 场景数据(转数组格式),用于where条件
318
+	 * @param  
319
+	 * @author Michael_xu
320
+	 * @return                            
321
+	 */		
322
+	public function dataChangeArray($string)
323
+	{
324
+		$data_arr = [];
325
+		$where = [];
326
+		eval('$data_arr = '.$string.';');
327
+		foreach ($data_arr as $k=>$v) {
328
+			if ($v['state']) {
329
+				$address_where[] = '%'.$v['state'].'%';
330
+				if ($v['city']) {
331
+					$address_where[] = '%'.$v['city'].'%';
332
+					if ($v['area']) {
333
+						$address_where[] = '%'.$v['area'].'%';
334
+					}
335
+				}
336
+				if ($v['condition'] == 'not_contain') {
337
+					$where[$k] = ['notlike', $address_where, 'OR'];
338
+				} else {
339
+					$where[$k] = ['like', $address_where, 'AND'];
340
+				}
341
+			} elseif (!empty($v['start']) || !empty($v['end'])) {
342
+				if ($v['start'] && $v['end']) {
343
+					$where[$k] = ['between',[strtotime($v['start']),strtotime($v['end'])+86399]];
344
+				} elseif ($v['start']) {
345
+					$where[$k] = ['egt',strtotime($v['start'])];
346
+				} else {
347
+					$where[$k] = ['elt',strtotime($v['end'])+86399];
348
+				}
349
+			} elseif (!empty($v['value'])) {
350
+				$where[$k] = field($v['value'],$v['condition']);
351
+			}
352
+		}
353
+		return $where ? : [];
354
+	}
355
+	
356
+	/**
357
+	 * 场景排序
358
+	 * @param  ids 场景id数组
359
+	 * @param  hide_ids 隐藏场景id数组
360
+	 * @author Michael_xu
361
+	 * @return                            
362
+	 */		  
363
+	public function listOrder($param, $user_id)
364
+	{
365
+		$res = true;
366
+		$resHide = true;
367
+		//使用
368
+		$data = [];
369
+		foreach ($param['ids'] as $k=>$v) {
370
+			$data[] = ['scene_id' => $v,'order_id' => $k,'update_time' => time(),'user_id' => $user_id,'is_hide' => 0];
371
+		}
372
+		if ($param['ids']) $res = $this->isUpdate()->saveAll($data);
373
+		//隐藏
374
+		$hideData = [];
375
+		foreach ($param['hide_ids'] as $k=>$v) {
376
+			$hideData[] = ['scene_id' => $v,'order_id' => $k,'update_time' => time(),'user_id' => $user_id,'is_hide' => 1];
377
+		}
378
+		if ($param['hide_ids']) $resHide = $this->isUpdate()->saveAll($hideData);
379
+		if ($res == false || $resHide == false) {
380
+			$this->error = '设置出错,请重试';
381
+			return false;
382
+		}	
383
+		return true;
384
+	}
385
+
386
+	/**
387
+     * [getDefaultData 默认场景]
388
+     * @param  types 分类
389
+     * @author Michael_xu
390
+     * @return    [array]
391
+     */		
392
+	public function getDefaultData($types, $user_id)
393
+	{
394
+		$where = [];
395
+		$where['types'] = $types;
396
+		$where['user_id'] = $user_id;
397
+		$scene_id = db('admin_scene_default')->where($where)->value('scene_id');
398
+		if (!$scene_id && in_array($types,['crm_leads','crm_customer','crm_business','crm_contacts','crm_contract','crm_receivables','crm_visit'])) {
399
+			$resData['bydata'] = 'all';
400
+		} else {
401
+			$resData = db('admin_scene')->where(['scene_id' => $scene_id])->find();
402
+		}
403
+		if ($resData['bydata']) {
404
+			$data = $this->getByData($types, $resData['bydata'], $user_id);
405
+		} else {
406
+			//处理data
407
+			$data = $resData ? json_decode($resData,true) : [];			
408
+		}		
409
+		return $data;				
410
+	}
411
+
412
+	/**
413
+     * [getByData 系统场景数据]
414
+     * @param  types 分类
415
+     * @author Michael_xu
416
+     * @return    [array]
417
+     */	
418
+    public function getByData($types, $bydata, $user_id)
419
+    {
420
+//        print_r($types . '--');
421
+//        print_r($bydata . '--');
422
+//        print_r($user_id);
423
+//        exit;
424
+    	$map           = [];
425
+    	$auth_user_ids = [];
426
+    	$part_user_ids = [];
427
+
428
+    	switch ($bydata) {
429
+    		case 'me' :
430
+                # 我负责的
431
+    		    $auth_user_ids[] = $user_id;
432
+    		    break;
433
+    		case 'mePart' :
434
+                # 我参与的(即相关团队)
435
+    		    $part_user_ids = $user_id;
436
+    		    break;
437
+    		case 'sub' :
438
+                # 下属负责的
439
+    		    $auth_user_ids = getSubUserId(false) ? : ['-1'];
440
+    		    break;
441
+    		case 'all' :
442
+                # 全部
443
+    		    $auth_user_ids = '';
444
+    		    break;
445
+    		case 'is_transform' :
446
+                # 已转化线索
447
+    		    $map['is_transform'] = ['condition' => 'eq', 'value' => 1, 'form_type' => 'text', 'name' => ''];
448
+    		    break;
449
+    		case 'pool' :
450
+    		    # 今日进入公海的客户
451
+    		    $customerModel = new \app\crm\model\Customer();
452
+    			$map = $customerModel->getWhereByToday();
453
+    			break;
454
+            case 'win_business' :
455
+                # 赢单的商机
456
+                $map['is_end'] = ['condition' => 'eq', 'value' => 1];
457
+                break;
458
+            case 'fail_business' :
459
+                # 输单的商机
460
+                $map['is_end'] = ['condition' => 'eq', 'value' => 2];
461
+                break;
462
+            case 'star' :
463
+                $where = $this->getStarParam($types, $user_id);
464
+                if (!empty($where)) $map = $where;
465
+                break;
466
+    		default :
467
+                # 全部
468
+    		    $auth_user_ids = '';
469
+    	}
470
+
471
+    	$auth_user_ids = $auth_user_ids ? : [];
472
+
473
+    	if ($auth_user_ids) {
474
+    		$map['owner_user_id'] = ['condition' => 'in','value' => $auth_user_ids,'form_type' => 'text','name' => ''];
475
+    	}
476
+
477
+    	if ($part_user_ids) {
478
+    		$map['ro_user_id'] = $part_user_ids ? : '';
479
+    		$map['rw_user_id'] = $part_user_ids ? : '';
480
+    	}
481
+
482
+    	return $map;
483
+    }
484
+
485
+    /**
486
+     * 获取我的关注条件
487
+     *
488
+     * @param $types
489
+     * @return array
490
+     * @throws \think\db\exception\DataNotFoundException
491
+     * @throws \think\db\exception\ModelNotFoundException
492
+     * @throws \think\exception\DbException
493
+     */
494
+    public function getStarParam($types, $user_id)
495
+    {
496
+        $where  = [];
497
+        $result = [];
498
+
499
+        $data = Db::name('crm_star')->field(['target_id'])->where(['user_id' => $user_id, 'type' => 'crm_' . $types])->select();
500
+
501
+        foreach ($data AS $key => $value) $result[] = $value['target_id'];
502
+
503
+        if ($types == 'leads')    $where['leads_id']    = $result ? ['condition' => 'in', 'value' => implode(',', $result)] : 0;
504
+        if ($types == 'customer') $where['customer_id'] = $result ? ['condition' => 'in', 'value' => implode(',', $result)] : 0;
505
+        if ($types == 'contacts') $where['contacts_id'] = $result ? ['condition' => 'in', 'value' => implode(',', $result)] : 0;
506
+        if ($types == 'business') $where['business_id'] = $result ? ['condition' => 'in', 'value' => implode(',', $result)] : 0;
507
+
508
+        return $where;
509
+    }
510
+
511
+	/**
512
+     * [updateData 跳过验证的编辑]
513
+     * @param  types 分类
514
+     * @author Michael_xu
515
+     * @return    [array]
516
+     */	
517
+    public function updateData($data, $scene_id)
518
+    {
519
+    	$param['data'] = is_array($data) ? $data : '';
520
+    	$param['update_time'] = time();
521
+   		$res = $this->allowField(true)->save($param, ['scene_id' => $scene_id]);
522
+		if ($res) {
523
+			return true;
524
+		} else {
525
+			$this->error = '修改失败';
526
+			return false;	
527
+		}
528
+    }
529
+}

+ 118
- 0
application/admin/model/Structure.php Целия файл

@@ -0,0 +1,118 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 组织架构
4
+// +----------------------------------------------------------------------
5
+// | Author:  
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use app\admin\model\Common;
11
+use think\Db;
12
+
13
+class Structure extends Common 
14
+{
15
+
16
+    /**
17
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
18
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
19
+     */
20
+	protected $name = 'admin_structure';
21
+
22
+	/**
23
+	 * [getDataList 获取列表]
24
+	 * @return    [array]                         
25
+	 */
26
+	public function getDataList($type='')
27
+	{	
28
+		$cat = new \com\Category('admin_structure', array('id', 'pid', 'name', 'title'));
29
+		$data = $cat->getList('', 0, 'id');
30
+		// 若type为tree,则返回树状结构
31
+		if ($type == 'tree') {
32
+			$tree = new \com\Tree();
33
+			$data = $tree->list_to_tree($data, 'id', 'pid', 'child', 0, true, array(''));
34
+		}		
35
+		return $data;
36
+	}
37
+	
38
+	/*
39
+	*根据字符串展示参与部门 use by work
40
+	*add by yykun
41
+	*/
42
+	public function getDataByStr($idstr)
43
+	{
44
+		$isArr = stringToArray($idstr);
45
+		if (!$isArr) {
46
+			return false;
47
+		}
48
+		$list = $this->field('id as structure_id,name')->where(['id' => ['in',$isArr]])->select();
49
+		return $list;
50
+	}
51
+	
52
+	/*
53
+	*根据部门ID获取信息 use by work 
54
+	*add by yykun
55
+	*/
56
+	public function getDataByID( $id ='')
57
+	{
58
+		$det = Db::name('AdminStructure')->where('id ='.$id)->find();
59
+		return $det;
60
+	}
61
+
62
+	public function delStrById($id)
63
+	{
64
+		if (!$id) {
65
+			$this->error = '删除失败';
66
+			return false;
67
+		}
68
+		$dataInfo = $this->getDataByID($id);
69
+		if (empty($dataInfo['pid'])) {
70
+			$this->error = '删除失败';
71
+			return false;			
72
+		}
73
+		//部门是否被使用
74
+		$allStrIds = [];
75
+		$allStrIds[] = $id;
76
+		$allSubStrIds = $this->getAllChild($id);
77
+		$allStrIds = array_merge($allStrIds, $allSubStrIds); //全部关联部门(包含下属部门)
78
+		$resUser = db('AdminUser')->where(['structure_id' => ['in',$allStrIds]])->find();
79
+		if ($resUser) {
80
+			$this->error = '该部门或其下属部门已存在员工,不能删除';
81
+			return false;
82
+		}
83
+		$resDel = $this->delDataById($id, true);
84
+		if (!$resDel) {
85
+			$this->error = '删除失败';
86
+			return false;
87
+		} else {
88
+			return true;
89
+		}	
90
+	}
91
+
92
+	/**
93
+	 * [getStructureNameByArr 根据主键获取详情]
94
+	 * @param     string     $id [主键]
95
+	 * @return    [array]
96
+	 */
97
+	public function getStructureNameByArr($ids = [])
98
+	{
99
+		if (!is_array($ids)) {
100
+			$idArr[] = $ids;
101
+		} else {
102
+			$idArr = $ids;
103
+		}		
104
+		$data = $this->where(['id' => array('in', $idArr)])->column('name');
105
+		return $data ? : [];
106
+	}
107
+
108
+	/*
109
+	*根据字符串展示参与部门 use by work
110
+	*add by yykun
111
+	*/
112
+	public function getListByStr($str)
113
+	{
114
+		$idArr = stringToArray($str);
115
+		$list = $this->field('id,name')->where(['id' => ['in',$idArr]])->select();
116
+		return $list;
117
+	}
118
+}

+ 18
- 0
application/admin/model/Sync.php Целия файл

@@ -0,0 +1,18 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use app\admin\model\Common;
11
+
12
+class Sync extends Common 
13
+{
14
+	public function syncData($param)
15
+	{
16
+		return true;
17
+	}	
18
+}

+ 41
- 0
application/admin/model/System.php Целия файл

@@ -0,0 +1,41 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 系统基础
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\admin\model;
9
+
10
+use app\admin\model\Common;
11
+use think\Db;
12
+
13
+class System extends Common 
14
+{
15
+
16
+	protected $name = 'admin_system';
17
+
18
+	//列表
19
+	public function getDataList()
20
+	{
21
+		$list = Db::name('AdminSystem')->select();
22
+		$temp = array();
23
+		foreach ($list as $key => $value) {
24
+			$temp[$value['name']] = $value['value'];
25
+		} 
26
+		$temp['logo'] = !empty($temp['logo']) ? getFullPath($temp['logo']) : '';
27
+		return $temp;
28
+	}
29
+
30
+	//新建
31
+	public function createData($param)
32
+	{
33
+		if( isset($param['name'])){
34
+			$data['name'] = 'name';
35
+			$data['value'] = $param['name'];
36
+			$data['description'] = '网站名称';
37
+			$this->where('id=1')->update($data);
38
+		} 
39
+		return true;
40
+	}
41
+}

+ 28
- 0
application/admin/model/SystemLog.php Целия файл

@@ -0,0 +1,28 @@
1
+<?php
2
+/**
3
+ * 系统日志模型
4
+ *
5
+ * @author qifan
6
+ * @date 2020-11-30
7
+ */
8
+
9
+namespace app\admin\model;
10
+
11
+use think\Model;
12
+
13
+class SystemLog extends Model
14
+{
15
+    protected $name = 'admin_system_log';
16
+
17
+    protected $pk = 'log_id';
18
+
19
+    /**
20
+     * 关联后台员工表姓名
21
+     *
22
+     * @return \think\model\relation\HasOne
23
+     */
24
+    public function toAdminUser()
25
+    {
26
+        return $this->hasOne('User', 'id', 'user_id')->bind(['source_name' => 'realname']);
27
+    }
28
+}

+ 1346
- 0
application/admin/model/User.php
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 198
- 0
application/admin/model/UserField.php Целия файл

@@ -0,0 +1,198 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 字段列表配置
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com
6
+// +----------------------------------------------------------------------
7
+namespace app\admin\model;
8
+
9
+use think\Config;
10
+use think\Db;
11
+use think\Model;
12
+
13
+class UserField extends Model
14
+{
15
+    protected $name = 'admin_user_field';
16
+    protected $createTime = 'create_time';
17
+    protected $updateTime = 'update_time';
18
+    protected $autoWriteTimestamp = true;    
19
+
20
+	protected $type = [
21
+        'datas'    =>  'array',
22
+    ];
23
+
24
+    /**
25
+     * 设置配置信息
26
+     * @author Michael_xu
27
+     * @param types 分类
28
+     * @param param 参数
29
+     * @param id 主键ID
30
+     * @return                            
31
+     */
32
+    public function updateConfig($types, $param, $id = '')
33
+    {
34
+        if (!is_array($param['value']) || ($param['hide_value'] && !is_array($param['hide_value']))) {
35
+            $this->error = '参数错误';
36
+            return false;
37
+        }
38
+        $data = [];
39
+        if ($id) {
40
+            $resInfo = $this->where(['id' => $id])->find();
41
+        } else {
42
+            $resInfo = $this->where(['types' => $types,'user_id' => $param['user_id']])->find();
43
+        }
44
+        if (!$resInfo) {
45
+            $data['types'] = $types;
46
+            $data['user_id'] = $param['user_id'];
47
+        }         
48
+        //处理value
49
+        $valueData = [];
50
+        //展示列
51
+        if ($param['value']) {
52
+            foreach ($param['value'] as $k=>$v) {
53
+                $valueData[$v['field']]['width'] = $v['width'];
54
+                $valueData[$v['field']]['is_hide'] = 0;
55
+            }
56
+        }
57
+        
58
+        //隐藏列
59
+        if ($param['hide_value']) {
60
+            foreach ($param['hide_value'] as $k=>$v) {
61
+                $valueData[$v['field']]['width'] = $v['width'];
62
+                $valueData[$v['field']]['is_hide'] = 1;
63
+            }
64
+        }
65
+        
66
+        $data['datas'] = $valueData;
67
+        if ($resInfo) {
68
+            $data['id'] = $resInfo['id'];
69
+            $res = $this->update($data);
70
+        } else {
71
+            $res = $this->save($data);
72
+        }
73
+        if ($res == false) {
74
+            $this->error = '设置出错';
75
+            return false;            
76
+        }
77
+        return true;
78
+    }
79
+
80
+    /**
81
+     * 配置信息详情
82
+     * @author Michael_xu
83
+     * @param types 分类
84
+     * @return                            
85
+     */
86
+    public function getConfig($types, $user_id)
87
+    {
88
+        $data = $this->where(['types' => $types,'user_id' => $user_id])->value('datas');
89
+        return $data ? : [];
90
+    }
91
+
92
+    /**
93
+     * 配置列宽度
94
+     * @author Michael_xu
95
+     * @param types 分类
96
+     * @param field 字段
97
+     * @param width 宽度
98
+     * @return                            
99
+     */
100
+    public function setColumnWidth($types, $field, $width, $user_id)
101
+    {
102
+        $info = db('admin_user_field')->where(['types' => $types,'user_id' => $user_id])->find();
103
+        if ($info) {
104
+            $datas = json_decode($info['datas'], true);
105
+            $datas[$field]['width'] = $width;
106
+            $datas = json_encode($datas);
107
+            $res = $this->where(['id' => $info['id']])->update(['datas' => $datas]);       
108
+        } else {
109
+            $newTypes = $types;
110
+            if ($types == 'crm_customer_pool') $newTypes = 'crm_customer';
111
+            $fieldArr = db('admin_field')->where(['types' => ['in',['',$newTypes]]])->field('field,name')->order('types desc,order_id asc')->select();
112
+            $value = [];
113
+            foreach ($fieldArr as $k=>$v) {
114
+                $field_width = '';
115
+                if ($field == $v['field']) {
116
+                    $field_width = $width;
117
+                }
118
+                $value[$v['field']]['width'] = $field_width;
119
+                $value[$v['field']]['is_hide'] = 0;
120
+                $value[$v['field']]['field'] = $v['field'];
121
+            }
122
+            $param['value'] = $value;
123
+            $param['hide_value'] = [];
124
+            $param['user_id'] = $user_id;
125
+            $res = $this->updateConfig($types, $param);
126
+        }
127
+        if (!$res) {
128
+            $this->error = '设置出错,请重试!';
129
+            return false;
130
+        }
131
+        return true;
132
+    }
133
+
134
+    /**
135
+     * 列表数据
136
+     * @author Michael_xu
137
+     * @param types 分类
138
+     * @return                            
139
+     */
140
+    public function getDataList($types, $user_id)
141
+    {
142
+        $fieldArr = (new Field)->getFieldList($types);
143
+        $fieldList = [];
144
+        $field_list = [];
145
+        foreach ($fieldArr as $k=>$v) {
146
+            $fieldList[] = $v['field'];
147
+            $field_list[$v['field']]['name'] = $v['name'];
148
+            $fieldArr[$k]['width'] = '';
149
+        }
150
+       
151
+        //已设置字段
152
+        $value = $this->where(['types' => $types,'user_id' => $user_id])->value('datas');
153
+        $value = $value ? json_decode($value, true) : [];
154
+
155
+        $valueList = [];
156
+        $value_list = []; //显示列
157
+        
158
+        $hideList = [];
159
+        $hide_list = []; //隐藏列
160
+
161
+        if ($value) {
162
+            $a = 0;
163
+            $b = 0;
164
+            foreach ($value as $k=>$v) {
165
+                if (empty($v['is_hide'])) {
166
+                    $valueList[] = $k;
167
+                    $value_list[$a]['field'] = $k; 
168
+                    $value_list[$a]['width'] = $v['width']; 
169
+                    $value_list[$a]['name'] = $field_list[$k]['name']; 
170
+                    $a++;
171
+                } else {
172
+                    $hideList[] = $k;
173
+                    $hide_list[$b]['field'] = $k;
174
+                    $hide_list[$b]['width'] = $v['width'];  
175
+                    $hide_list[$b]['name'] = $field_list[$k]['name'];
176
+                    $b++;
177
+                }
178
+            }
179
+            $diffList = $valueList ? array_diff($fieldList, $valueList) : $fieldList;
180
+            //隐藏的列(新增的字段数据)
181
+            $hideList = $hideList ? array_diff($diffList,$hideList) : $diffList;
182
+            foreach ($hideList as $k=>$v) {
183
+                $hide_list[$b]['field'] = $v;
184
+                $hide_list[$b]['width'] = '';
185
+                $hide_list[$b]['name'] = $field_list[$v]['name'];
186
+                $b++;
187
+            }    
188
+        } else {
189
+            $value_list = array_values($fieldArr);
190
+            $hide_list = [];
191
+        }
192
+
193
+        $data = [];
194
+        $data['value_list'] = $value_list ? : []; //展示列
195
+        $data['hide_list'] = $hide_list ? : []; //隐藏列
196
+        return $data ? : [];
197
+    }    
198
+}

+ 22
- 0
application/admin/validate/AdminField.php Целия файл

@@ -0,0 +1,22 @@
1
+<?php
2
+
3
+namespace app\admin\validate;
4
+use think\Validate;
5
+/**
6
+* 设置模型
7
+*/
8
+class AdminField extends Validate{
9
+
10
+	protected $rule = [
11
+		'field'  		=> ['regex'=>'/^[a-z]([a-z]|_)+[a-z]$/i'],
12
+		'name'      	=> 'require',
13
+		'types'      	=> 'require',
14
+		'form_type'      	=> 'require',
15
+	];
16
+	protected $message = [
17
+		'field.regex'    	=> '字段名称格式不正确!',
18
+		'name.require'    	=> '字段标识必须填写',
19
+		'types.require'    	=> '分类必须填写',
20
+		'form_type.require'    	=> '字段类型必须填写',
21
+	];
22
+}

+ 21
- 0
application/admin/validate/AdminGroup.php Целия файл

@@ -0,0 +1,21 @@
1
+<?php
2
+
3
+namespace app\admin\validate;
4
+use think\Validate;
5
+/**
6
+* 设置模型
7
+*/
8
+class AdminGroup extends Validate{
9
+
10
+	protected $rule = [
11
+		'title'   => 'require',
12
+		'types'   => 'require',
13
+	];
14
+	protected $message = [
15
+		'title.require'    => '角色名称必须填写',
16
+		'types.require'    => '角色类型必须选择',
17
+	];
18
+	protected $scene = [
19
+        'edit'  =>  ['id'],
20
+    ];
21
+}

+ 16
- 0
application/admin/validate/AdminPost.php Целия файл

@@ -0,0 +1,16 @@
1
+<?php
2
+
3
+namespace app\admin\validate;
4
+use think\Validate;
5
+/**
6
+* 设置模型
7
+*/
8
+class AdminPost extends Validate{
9
+
10
+	protected $rule = [
11
+		'name'   => 'require',
12
+	];
13
+	protected $message = [
14
+		'name.require'    => '岗位名称必须填写',
15
+	];
16
+}

+ 21
- 0
application/admin/validate/AdminRecord.php Целия файл

@@ -0,0 +1,21 @@
1
+<?php
2
+
3
+namespace app\admin\validate;
4
+use think\Validate;
5
+/**
6
+* 设置模型
7
+*/
8
+class AdminRecord extends Validate{
9
+
10
+	protected $rule = [
11
+		'category'  	=> 'require',
12
+		'content'  => 'require',
13
+	];
14
+	protected $message = [
15
+		'category.require'    => '跟进类型必须填写',
16
+		'content.require'    	=> '日志内容必须填写',					
17
+	];
18
+	protected $scene = [
19
+        'edit'  =>  [],
20
+    ];
21
+}

+ 20
- 0
application/admin/validate/AdminRule.php Целия файл

@@ -0,0 +1,20 @@
1
+<?php
2
+
3
+namespace app\admin\validate;
4
+use think\Validate;
5
+/**
6
+* 设置模型
7
+*/
8
+class AdminRule extends Validate{
9
+
10
+	protected $rule = [
11
+		'title' => 'require',
12
+		'name'  => 'require',
13
+		'level' => 'require'
14
+	];
15
+	protected $message = [
16
+		'title.require'    	=> '标题必须填写',
17
+		'name.require'    	=> '规则定义必须填写',
18
+		'level.require'    	=> '级别类型必须填写',
19
+	];
20
+}

+ 16
- 0
application/admin/validate/AdminStructure.php Целия файл

@@ -0,0 +1,16 @@
1
+<?php
2
+
3
+namespace app\admin\validate;
4
+use think\Validate;
5
+/**
6
+* 设置模型
7
+*/
8
+class AdminStructure extends Validate{
9
+
10
+	protected $rule = [
11
+		'name'      => 'require',
12
+	];
13
+	protected $message = [
14
+		'name.require' => '部门名称必须填写',
15
+	];
16
+}

+ 25
- 0
application/admin/validate/AdminUser.php Целия файл

@@ -0,0 +1,25 @@
1
+<?php
2
+
3
+namespace app\admin\validate;
4
+use think\Validate;
5
+/**
6
+* 设置模型
7
+*/
8
+class AdminUser extends Validate{
9
+
10
+	protected $rule = array(
11
+		'realname'      	=> 'require',
12
+		'username'      	=> 'require|unique:admin_user|regex:^1[3456789][0-9]{9}?$',
13
+		'structure_id'      	=> 'require',
14
+		'password'      	=> 'require|regex:^(?![0-9]*$)[a-zA-Z0-9]{6,20}$',
15
+	);
16
+	protected $message = array(
17
+		'realname.require'    	=> '姓名必须填写',
18
+		'username.require'    	=> '手机号码必须填写',
19
+		'username.unique'    	=> '手机号码已存在',
20
+		'username.regex'    	=> '手机号码格式错误',
21
+		'password.require'    	=> '密码必须填写',
22
+		'password.regex'    	=> '密码由6-20位字母、数字组成',
23
+		'structure_id.require'    	=> '请选择所属部门',
24
+	);
25
+}

+ 77
- 0
application/admin/view/install/index.html Целия файл

@@ -0,0 +1,77 @@
1
+<!DOCTYPE html>
2
+<html lang="zh-CN">
3
+<head>
4
+  <meta charset="UTF-8">
5
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
6
+  <title>悟空CRM安装向导</title>
7
+  <link rel="shortcut icon" href="__STATIC__/icon/favicon.ico">
8
+  <link rel="stylesheet" href="__STATIC__/style/base.css">
9
+  <link rel="stylesheet" href="__STATIC__/style/index.css">
10
+  <script src="__STATIC__/js/jquery-3.3.1.min.js"></script>
11
+</head>
12
+<body>
13
+  <div class="header-wrapper">
14
+	{include file="public/header"}   
15
+  </div>
16
+  <div class="top">
17
+	<div class="agreement-title">悟空CRM系统开源版使用协议</div>
18
+  </div>
19
+
20
+  <div class="container">
21
+	<div class="agreement">
22
+		<p style="text-align:center;font-size:18px;">悟空CRM开源版使用协议</p>
23
+		<br>
24
+			悟空CRM(Customer Relationship Management)即:悟空客户关系管理软件(以下简称悟空CRM)由郑州卡卡罗特软件科技有限公司(以下简称卡卡罗特)开发。卡卡罗特依法拥有悟空CRM的所有版权和所有权益。本着共享开放的角度,卡卡罗特以开放源代码的形式发布悟空CRM,您可以在遵守该协议的前提下使用悟空CRM。<br>
25
+		<br>
26
+			自您安装悟空CRM开始,您和卡卡罗特之间的合同关系自动成立,成为卡卡罗特用户(以下简称为用户)。除非您停止使用悟空CRM或与卡卡罗特有签署额外合同,您须认真遵循该用户协议约定的每一项条款。<br>
27
+		<br>
28
+			官方地址:<a target="_blank" href="http://www.5kcrm.com">www.5kcrm.com</a> / <a target="_blank" href="https://www.72crm.com">www.72crm.com</a><br>
29
+			官方电话:400-0812-558<br>
30
+			官方邮箱:service@5kcrm.com<br>
31
+			官方社区:<a target="_blank" href="http://www.72crm.net">bbs.72crm.net</a><br>
32
+			官方社群:<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=f4687b809bf63f08f707aa1c56dee8dbcb9526237c429c4532222021d65bf83c">悟空CRM交流10群(486745026)</a><br>
33
+		<br>
34
+		<p>一、协议中提到的名词约定</p>
35
+			1.1下述条款中所指悟空CRM的标志包括如下方面:<br>
36
+			悟空CRM源代码及文档中关于悟空CRM的版权提示、文字、图片和链接。<br>
37
+			悟空CRM运行时界面上呈现出来的有关悟空CRM的文字、图片和链接。<br>
38
+			1.2不包括如下方面:<br>
39
+			悟空CRM提供的演示数据中关于悟空CRM的文字、图片和链接。<br>
40
+		<br>
41
+		<p>二、免责声明</p>
42
+			2.1用户出于自愿而使用本软件,必须了解使用本软件的风险,在尚未购买产品技术服务或商业授权之前,我们不承诺对免费用户提供任何形式的技术支持、使用担保,也不承担任何因使用本软件而产生问题的相关责任。<br>
43
+			2.2电子文本形式的使用协议如同双方书面签署的协议一样,具有完全的和等同的法律效力。您一旦开始确认本协议并安装悟空CRM,即被视为完全理解并接受本协议的各项条款,在享有以下条款授予的权力的同时,受到相关的约束和限制。<br>
44
+			2.3协议许可范围以外的行为,将直接违反本授权协议并构成侵权,我们有权随时终止授权,责令停止损害,并保留追究相关责任的权利。<br>
45
+		<br>
46
+		<p>三、协议许可的权利</p>
47
+			3.1  如果您以学习或研究为目的使用悟空CRM,卡卡罗特不对您做任何限制。<br>
48
+			3.2  您可以在您个人任意数量的电脑上运行悟空CRM,卡卡罗特不对电脑的数量做任何限制。<br>
49
+			3.3 您可以对悟空CRM源代码进行修改以适应您个人学习研究的要求,您做的改动无需对外发布。<br>
50
+			3.4卡卡罗特依法拥有悟空CRM的所有版权和软件权益,未经商业授权,您无任何版权及软件相关权益。<br>
51
+		<br>
52
+		<p>四、协议规定的约束和限制</p>
53
+			4.1当您开始将悟空CRM用于企业内部管理使用,意味着已经商用,需购买相应的商业授权 <br>
54
+			4.2未获得商业授权之前,不得将本软件用于商业用途(包括但不限于企业内部使用、二次开发后进行销售、以营利为目的或实现盈利等形式)。<br>
55
+			4.3未经官方许可,禁止在悟空CRM的整体或任何部分基础上发展任何派生版本、修改版本或第三方版本用于重新分发,包括但不限于基于悟空CRM开发SAAS平台等相关服务。<br>
56
+			4.4如果您未能遵守本协议的条款,您的授权将被终止,所被许可的权利将被收回,并承担相应法律责任。<br>
57
+			4.5 您使用悟空CRM时,必须保留悟空CRM的所有标志,不得以任何方式隐藏或遮掩任一标志。<br>
58
+		<br>
59
+		<p>五、未尽事项</p>
60
+			如果上述条款无法满足您使用悟空CRM的要求,可联系卡卡罗特签署额外的合同以获得更灵活的授权许可。<br>
61
+		<br>
62
+		<p>六、合同约束</p>
63
+			如果您违反了该协议的任一条款,该用户协议将自动终止,您必须停止使用,卡卡罗特保留通过法律手段追究责任的权利。<br>
64
+		<br>
65
+	</div>
66
+	<div class="agree-btn">我同意</div>
67
+  </div>
68
+  <div class="footer-wrapper">
69
+	 {include file="public/footer"}
70
+  </div>
71
+</body>
72
+<script>
73
+  $('.agree-btn').click(function () {
74
+	window.location = 'step1.html'
75
+  });
76
+</script>
77
+</html>

+ 101
- 0
application/admin/view/install/step1.html Целия файл

@@ -0,0 +1,101 @@
1
+<!DOCTYPE html>
2
+<html lang="zh-CN">
3
+    <head>
4
+        <meta charset="UTF-8">
5
+        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
6
+        <title>悟空CRM安装向导</title>
7
+        <link rel="shortcut icon" href="__STATIC__/icon/favicon.ico">
8
+        <link rel="stylesheet" href="__STATIC__/style/base.css">
9
+        <link rel="stylesheet" href="__STATIC__/style/step1.css">
10
+        <script src="__STATIC__/js/jquery-3.3.1.min.js"></script>
11
+    </head>
12
+    <body>
13
+        <div class="header-wrapper">
14
+        {include file="public/header"}   
15
+        </div>
16
+        <div class="top">
17
+            <div class="step-group">
18
+                <div class="step active">
19
+                    <div class="sort">1</div>
20
+                    <div class="desc">检查安装环境</div>
21
+                </div>
22
+                <div class="step line"></div>
23
+                <div class="step">
24
+                    <div class="sort">2</div>
25
+                    <div class="desc">创建数据库</div>
26
+                </div>
27
+                <div class="step line"></div>
28
+                <div class="step">
29
+                    <div class="sort">3</div>
30
+                    <div class="desc">安装成功</div>
31
+                </div>
32
+            </div>
33
+        </div>
34
+        <div class="container">
35
+            <div class="content">
36
+                <div class="base-top">
37
+                    <span class="title">1 检查安装环境</span>
38
+                    <span class="version">当前版本:{$data['version']['VERSION']} {$data['version']['RELEASE']}</span>
39
+                </div>
40
+                <div class="table">
41
+                    <table class="table_01">
42
+                        <thead>
43
+                            <tr>
44
+                                <th>检查项</th>
45
+                                <th>当前环境</th>
46
+                                <th>悟空CRM建议</th>
47
+                                <th>当前状态</th>
48
+                            </tr>
49
+                        </thead>
50
+                        <tbody>
51
+                            {volist name="data['env']" id="row"}
52
+                                <tr>
53
+                                    <td>{$row[0]}</td>
54
+                                    <td>{$row[1]}</td>
55
+                                    <td>{$row[2]}</td>
56
+                                    <td>
57
+                                        {if condition="$row['3'] == 'ok'"}
58
+                                            <img src="__STATIC__/icon/success.png" width="20">
59
+                                        {else /}
60
+                                            <img src="__STATIC__/icon/error.png" width="20">
61
+                                        {/if}
62
+                                    </td>
63
+                                </tr>
64
+                            {/volist}
65
+                        </tbody>
66
+                    </table>
67
+                    <table class="catalogue-table">
68
+                        <thead>
69
+                            <tr>
70
+                                <th>目录文件</th>
71
+                                <th>所需状态</th>
72
+                                <th>当前状态</th>
73
+                            </tr>
74
+                        </thead>
75
+                        <tbody>
76
+                            <?php foreach($data['dir'] as $value){ ?>
77
+                            <tr>
78
+                                <td>{$value[1]}</td>
79
+                                <td>{$value[3]}</td>
80
+                            <?php if($value[5] =='ok') { ?>
81
+                                <td><img src="__STATIC__/icon/success.png" width="20"></td>
82
+                            <?php } else { ?>
83
+                                <td><img src="__STATIC__/icon/error.png" width="20"></td>
84
+                            <?php } ?>
85
+                            </tr>
86
+                            <?php } ?>
87
+                        </tbody>
88
+                    </table>
89
+                </div>
90
+                <div class="control">
91
+                    <div class="prev btn">上一步</div>
92
+                    <div class="next btn primary">下一步</div>
93
+                </div>
94
+            </div>
95
+        </div>
96
+        <div class="footer-wrapper">
97
+            {include file="public/footer"}
98
+        </div>
99
+    </body>
100
+    <script src="__STATIC__/js/step1.js"></script>
101
+</html>

+ 97
- 0
application/admin/view/install/step2.html Целия файл

@@ -0,0 +1,97 @@
1
+<!DOCTYPE html>
2
+<html lang="zh-CN">
3
+    <head>
4
+        <meta charset="UTF-8">
5
+        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
6
+        <title>悟空CRM安装向导</title>
7
+        <link rel="shortcut icon" href="__STATIC__/icon/favicon.ico">
8
+        <link rel="stylesheet" href="__STATIC__/style/base.css">
9
+        <link rel="stylesheet" href="__STATIC__/style/step2.css">
10
+        <script src="__STATIC__/js/jquery-3.3.1.min.js"></script>
11
+    </head>
12
+    <body>
13
+        <div class="header-wrapper">
14
+            {include file="public/header"}   
15
+        </div>
16
+        <div class="top">
17
+            <div class="step-group">
18
+                <div class="step active">
19
+                    <div class="sort">1</div>
20
+                    <div class="desc">检查安装环境</div>
21
+                </div>
22
+                <div class="step active line"></div>
23
+                <div class="step active">
24
+                    <div class="sort">2</div>
25
+                    <div class="desc">创建数据库</div>
26
+                </div>
27
+                <div class="step line"></div>
28
+                <div class="step">
29
+                    <div class="sort">3</div>
30
+                    <div class="desc">安装成功</div>
31
+                </div>
32
+            </div>
33
+        </div>
34
+
35
+        <div class="container">
36
+            <div class="content">
37
+                <div class="base-top">
38
+                    <span class="title">2 创建数据库</span>
39
+                    <span class="version">当前版本:{$envir_data['version']['VERSION']} {$envir_data['version']['RELEASE']}</span>
40
+                </div>
41
+                <div class="form">
42
+                    <div class="form-sec-title">请填写数据库信息</div>
43
+                        <div class="form-item">
44
+                            <div class="form-label">数据库主机:</div>
45
+                            <input type="text" name="databaseUrl">
46
+                            <!--<div class="error" style="display: none">数据库主机不能空</div>-->
47
+                            <div class="remind">数据库地址一般为127.0.0.1</div>
48
+                        </div>
49
+                        <div class="form-item">
50
+                            <div class="form-label">数据库名:</div>
51
+                            <input type="text" name="databaseName">
52
+                        </div>
53
+                        <div class="form-item">
54
+                            <div class="form-label">端口:</div>
55
+                            <input type="text" name="databasePort">
56
+                            <div class="remind">一般为 3306</div>
57
+                        </div>
58
+                        <div class="form-item">
59
+                            <div class="form-label">数据库用户名:</div>
60
+                            <input type="text" name="databaseUser">
61
+                            <div class="remind">生产环境建议创建独立账号</div>
62
+                        </div>
63
+                        <div class="form-item">
64
+                            <div class="form-label">数据库密码:</div>
65
+                            <input type="password" name="databasePwd">
66
+                        </div>
67
+                        <div class="form-item">
68
+                        <div class="form-label">表前缀:</div>
69
+                            <input type="text" name="databaseTable">
70
+                            <div class="remind">默认为5kcrm_</div>
71
+                        </div>
72
+                        <div class="form-sec-title">请填写管理员信息</div>
73
+                        <div class="form-item">
74
+                            <div class="form-label">管理员账号:</div>
75
+                            <input type="text" name="root" placeholder="请输入手机号码">
76
+                        </div>
77
+                        <div class="form-item">
78
+                        <div class="form-label">管理员密码:</div>
79
+                        <input type="password" name="pwd">
80
+                    </div>
81
+                </div>
82
+                <div class="install_progress_a">
83
+                <!-- <progress class="install_progress" max="97" value="8"></progress> -->
84
+                </div>
85
+                <div class="control">
86
+                    <div class="prev btn">上一步</div>
87
+                    <div class="next btn primary">下一步</div>
88
+                </div>
89
+            </div>
90
+        </div>
91
+        <div class="footer-wrapper">
92
+            {include file="public/footer"}
93
+        </div>
94
+    </body>
95
+<!-- <script src="__STATIC__/js/base.js"></script> -->
96
+<script src="__STATIC__/js/step2.js"></script> 
97
+</html>

+ 55
- 0
application/admin/view/install/step3.html Целия файл

@@ -0,0 +1,55 @@
1
+<!DOCTYPE html>
2
+<html lang="zh-CN">
3
+    <head>
4
+        <meta charset="UTF-8">
5
+        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
6
+        <title>悟空CRM安装向导</title>
7
+        <link rel="shortcut icon" href="__STATIC__/icon/favicon.ico">
8
+        <link rel="stylesheet" href="__STATIC__/style/base.css">
9
+        <link rel="stylesheet" href="__STATIC__/style/step3.css">
10
+        <script src="__STATIC__/js/jquery-3.3.1.min.js"></script>
11
+    </head>
12
+    <body>
13
+        <div class="header-wrapper">
14
+            {include file="public/header"}   
15
+        </div>
16
+        <div class="top">
17
+            <div class="step-group">
18
+                <div class="step active">
19
+                    <div class="sort">1</div>
20
+                    <div class="desc">检查安装环境</div>
21
+                </div>
22
+                <div class="step active line"></div>
23
+                <div class="step active">
24
+                    <div class="sort">2</div>
25
+                    <div class="desc">创建数据库</div>
26
+                </div>
27
+                <div class="step line active"></div>
28
+                <div class="step">
29
+                    <div class="sort">3</div>
30
+                    <div class="desc">安装成功</div>
31
+                </div>
32
+            </div>
33
+        </div>
34
+        <div class="container">
35
+            <div class="result">
36
+                <div class="status-box">
37
+                    <img class="pic" src="__STATIC__/icon/error.png" alt="">
38
+                    <span class="status">安装失败</span>
39
+                </div>
40
+                <div class="desc">未按照正确的方式进行安装</div>
41
+                <div class="control">
42
+                    <div class="prev btn primary">返回上一步</div>
43
+                </div>
44
+            </div>
45
+        </div>
46
+        <div class="footer-wrapper">
47
+            {include file="public/footer"}
48
+        </div>
49
+    </body>
50
+    <script>
51
+        $('.prev').click(function () {
52
+            window.location = 'step2.html'
53
+        })
54
+    </script>
55
+</html>

+ 6
- 0
application/admin/view/public/footer.html Целия файл

@@ -0,0 +1,6 @@
1
+<footer class="footer">
2
+  <div class="content">
3
+    悟空CRM受国家计算机软件著作权保护,未经授权不得进行商业行为,违者必究。<br>
4
+    &copy;2021 悟空软件<a target="_blank" href="http://www.5kcrm.com">www.5kcrm.com</a>
5
+  </div>
6
+</footer>

+ 14
- 0
application/admin/view/public/header.html Целия файл

@@ -0,0 +1,14 @@
1
+<header class="header">
2
+  <div class="header-content">
3
+    <h1 class="logo">
4
+      <a href="http://www.5kcrm.com"><img class="pic" src="__STATIC__/img/logo.png" alt=""></a>
5
+    </h1>
6
+    <div class="title">
7
+      悟空CRM11.0安装向导
8
+    </div>
9
+    <div class="concat-us">
10
+      <img class="icon" src="__STATIC__/icon/phone.png" alt="">
11
+      <span class="desc">官方电话:400-0812-558</span>
12
+    </div>
13
+  </div>
14
+</header>

+ 18
- 0
application/bi/common.php Целия файл

@@ -0,0 +1,18 @@
1
+<?php
2
+//权限控制
3
+\think\Hook::add('check_auth','app\\common\\behavior\\AuthenticateBehavior');
4
+
5
+use think\Db;
6
+
7
+//获取一年中每个月开始结束时间
8
+function getMonthStart($year)
9
+{
10
+    $i = 1;
11
+    for($i=1;$i<13;$i++) {
12
+        $time = $year.'-'.$i.'-01';
13
+        $data[$i]= strtotime($time);
14
+    }
15
+    $newyear = $year+1;
16
+    $data[13] = strtotime($newyear.'-01-01');
17
+    return $data;
18
+}

+ 14
- 0
application/bi/config.php Целия файл

@@ -0,0 +1,14 @@
1
+<?php
2
+// 基础模块配置文件
3
+
4
+return [
5
+	//'配置项'=>'配置值'
6
+    'LANG_SWITCH_ON'     =>     true,    //开启语言包功能        
7
+    'LANG_AUTO_DETECT'     =>     true, // 自动侦测语言
8
+    'DEFAULT_LANG'         =>     'zh-cn', // 默认语言        
9
+    'LANG_LIST'            =>    'en-us,zh-cn,zh-tw', //必须写可允许的语言列表
10
+    'VAR_LANGUAGE'     => 'l', // 默认语言切换变量
11
+];
12
+
13
+
14
+

+ 419
- 0
application/bi/controller/Achievement.php Целия файл

@@ -0,0 +1,419 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 商业智能-业绩目标
4
+// +----------------------------------------------------------------------
5
+// | Author: Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\bi\controller;
9
+
10
+use app\admin\controller\ApiCommon;
11
+use think\Db;
12
+use think\Hook;
13
+use think\Request;
14
+use app\bi\logic\ExcelLogic;
15
+
16
+class Achievement extends ApiCommon
17
+{
18
+    /**
19
+     * 用于判断权限
20
+     * @permission 无限制
21
+     * @allow 登录用户可访问
22
+     * @other 其他根据系统设置
23
+     **/
24
+    public function _initialize()
25
+    {
26
+        $action = [
27
+            'permission' => [''],
28
+            'allow' => ['statistics', 'excelexport']
29
+        ];
30
+        Hook::listen('check_auth', $action);
31
+        $request = Request::instance();
32
+        $a = strtolower($request->action());
33
+        if (!in_array($a, $action['permission'])) {
34
+            parent::_initialize();
35
+        }
36
+        if (!checkPerByAction('bi', 'achievement', 'read')) {
37
+            header('Content-Type:application/json; charset=utf-8');
38
+            exit(json_encode(['code' => 102, 'error' => '无权操作']));
39
+        }
40
+    }
41
+
42
+    /**
43
+     * 业绩目标完成情况
44
+     *
45
+     * @return \think\response\Json
46
+     * @throws \think\db\exception\DataNotFoundException
47
+     * @throws \think\db\exception\ModelNotFoundException
48
+     * @throws \think\exception\DbException
49
+     */
50
+    public function statistics($param = '')
51
+    {
52
+        if($param['excel_type']!=1){
53
+            $param = $this->param;
54
+        }
55
+//        $achievementModel = new \app\crm\model\Achievement();
56
+//        $list = $achievementModel->getList($param) ? : [];
57
+        $list = $this->getAchievementStatistics($param) ?: [];
58
+        //导出使用
59
+        if (!empty($param['excel_type'])) {
60
+            $list = $this->excelStatistics($param) ?: [];
61
+            return $list;
62
+        }
63
+
64
+        return resultArray(['data' => $list]);
65
+    }
66
+
67
+    /**
68
+     * 业绩目标完成情况列表
69
+     *
70
+     * @param $param
71
+     * @return array
72
+     * @throws \think\db\exception\DataNotFoundException
73
+     * @throws \think\db\exception\ModelNotFoundException
74
+     * @throws \think\exception\DbException
75
+     */
76
+    private function getAchievementStatistics($param)
77
+    {
78
+        # 结果数据
79
+        $result = [];
80
+
81
+        # 参数
82
+        $status      = !empty($param['status'])       ? $param['status']       : 1; # 类型:1合同目标;2回款目标;
83
+        $year        = !empty($param['year'])         ? $param['year']         : 0; # 年份
84
+        $structureId = !empty($param['structure_id']) ? $param['structure_id'] : 0; # 部门
85
+        $userId      = !empty($param['user_id'])      ? $param['user_id']      : 0; # 员工
86
+        $type        = !empty($param['type'])         ? $param['type']         : 1; # 类型:1部门;2员工
87
+
88
+        # 设置业绩目标条件
89
+        $achievementWhere['year'] = $year;
90
+        $achievementWhere['status'] = $status;
91
+        $achievementWhere['type'] = !empty($type) && $type == 1 ? 2 : 3;
92
+        if (!empty($userId)) $achievementWhere['obj_id'] = $userId;
93
+        if (!empty($structureId)) $achievementWhere['obj_id'] = $structureId;
94
+
95
+        # 查询业绩目标数据
96
+        $achievementList = Db::name('crm_achievement')->where($achievementWhere)->select();
97
+
98
+        if (empty($achievementList)) return [];
99
+
100
+        # 部门
101
+        if ($type == 1) {
102
+            foreach ($achievementList as $key => $value) {
103
+                # 组装结果数据
104
+                $result[$value['obj_id']] = [
105
+                    'name' => $value['name'],
106
+                    'list' => [
107
+                        '01' => ['achievement' => (int)$value['january'], 'money' => 0, 'rate' => 0, 'month' => '一月'],
108
+                        '02' => ['achievement' => (int)$value['february'], 'money' => 0, 'rate' => 0, 'month' => '二月'],
109
+                        '03' => ['achievement' => (int)$value['march'], 'money' => 0, 'rate' => 0, 'month' => '三月'],
110
+                        '04' => ['achievement' => (int)$value['april'], 'money' => 0, 'rate' => 0, 'month' => '四月'],
111
+                        '05' => ['achievement' => (int)$value['may'], 'money' => 0, 'rate' => 0, 'month' => '五月'],
112
+                        '06' => ['achievement' => (int)$value['june'], 'money' => 0, 'rate' => 0, 'month' => '六月'],
113
+                        '07' => ['achievement' => (int)$value['july'], 'money' => 0, 'rate' => 0, 'month' => '七月'],
114
+                        '08' => ['achievement' => (int)$value['august'], 'money' => 0, 'rate' => 0, 'month' => '八月'],
115
+                        '09' => ['achievement' => (int)$value['september'], 'money' => 0, 'rate' => 0, 'month' => '九月'],
116
+                        '10' => ['achievement' => (int)$value['october'], 'money' => 0, 'rate' => 0, 'month' => '十月'],
117
+                        '11' => ['achievement' => (int)$value['november'], 'money' => 0, 'rate' => 0, 'month' => '十一月'],
118
+                        '12' => ['achievement' => (int)$value['december'], 'money' => 0, 'rate' => 0, 'month' => '十二月']
119
+                    ]
120
+                ];
121
+
122
+                # 获取部门下的员工ID
123
+                $userIds = Db::name('admin_user')->where('structure_id', $value['obj_id'])->column('id');
124
+
125
+                # 业绩完成字段
126
+                $finishField = ["DATE_FORMAT(FROM_UNIXTIME(`create_time`,'%Y-%m-%d'),'%m') AS time", 'sum(money) AS money'];
127
+
128
+                # 业绩完成条件
129
+                $finishWhere['check_status'] = 2;
130
+                $finishWhere['owner_user_id'] = ['in', $userIds];
131
+
132
+                # 合同
133
+                if ($status == 1) {
134
+                    $finishArray = Db::name('crm_contract')->field($finishField)->where($finishWhere)->group('time')->select();
135
+                }
136
+
137
+                # 回款
138
+                if ($status == 2) {
139
+                    $finishArray = Db::name('crm_receivables')->field($finishField)->where($finishWhere)->group('time')->select();
140
+                }
141
+
142
+                # 计算完成情况
143
+                foreach ($finishArray as $k => $v) {
144
+                    if (!empty($result[$value['obj_id']]['list'][$v['time']])) {
145
+                        $achievement = $result[$value['obj_id']]['list'][$v['time']]['achievement'];
146
+
147
+                        $result[$value['obj_id']]['list'][$v['time']]['money'] = (int)$v['money'];
148
+                        $result[$value['obj_id']]['list'][$v['time']]['rate'] = (int)(($v['money'] / $achievement) * 100);
149
+
150
+                    }
151
+                }
152
+
153
+                $result[$value['obj_id']]['list'] = array_values($result[$value['obj_id']]['list']);
154
+            }
155
+        }
156
+
157
+        # 员工
158
+        if ($type == 2) {
159
+            $userData = [];
160
+            $userList = db('admin_user')->field(['id', 'realname'])->select();
161
+            foreach ($userList AS $key => $value) {
162
+                $userData[$value['id']] = $value['realname'];
163
+            }
164
+
165
+            foreach ($achievementList as $key => $value) {
166
+                # 组装结果数据
167
+                $result[$value['obj_id']] = [
168
+                    'name' => !empty($value['name']) ? $value['name'] : $userData[$value['obj_id']],
169
+                    'list' => [
170
+                        '01' => ['achievement' => (int)$value['january'], 'money' => 0, 'rate' => 0, 'month' => '一月'],
171
+                        '02' => ['achievement' => (int)$value['february'], 'money' => 0, 'rate' => 0, 'month' => '二月'],
172
+                        '03' => ['achievement' => (int)$value['march'], 'money' => 0, 'rate' => 0, 'month' => '三月'],
173
+                        '04' => ['achievement' => (int)$value['april'], 'money' => 0, 'rate' => 0, 'month' => '四月'],
174
+                        '05' => ['achievement' => (int)$value['may'], 'money' => 0, 'rate' => 0, 'month' => '五月'],
175
+                        '06' => ['achievement' => (int)$value['june'], 'money' => 0, 'rate' => 0, 'month' => '六月'],
176
+                        '07' => ['achievement' => (int)$value['july'], 'money' => 0, 'rate' => 0, 'month' => '七月'],
177
+                        '08' => ['achievement' => (int)$value['august'], 'money' => 0, 'rate' => 0, 'month' => '八月'],
178
+                        '09' => ['achievement' => (int)$value['september'], 'money' => 0, 'rate' => 0, 'month' => '九月'],
179
+                        '10' => ['achievement' => (int)$value['october'], 'money' => 0, 'rate' => 0, 'month' => '十月'],
180
+                        '11' => ['achievement' => (int)$value['november'], 'money' => 0, 'rate' => 0, 'month' => '十一月'],
181
+                        '12' => ['achievement' => (int)$value['december'], 'money' => 0, 'rate' => 0, 'month' => '十二月']
182
+                    ]
183
+                ];
184
+
185
+                # 业绩完成字段
186
+                $finishField = ["DATE_FORMAT(FROM_UNIXTIME(`create_time`,'%Y-%m-%d'),'%m') AS time", 'sum(money) AS money'];
187
+
188
+                # 业绩完成条件
189
+                $finishWhere = ['check_status' => 2, 'owner_user_id' => $value['obj_id']];
190
+
191
+                # 合同
192
+                if ($status == 1) {
193
+                    $finishArray = Db::name('crm_contract')->field($finishField)->where($finishWhere)->group('time')->select();
194
+                }
195
+
196
+                # 回款
197
+                if ($status == 2) {
198
+                    $finishArray = Db::name('crm_receivables')->field($finishField)->where($finishWhere)->group('time')->select();
199
+                }
200
+
201
+                # 计算完成情况
202
+                foreach ($finishArray as $k => $v) {
203
+                    if (!empty($result[$value['obj_id']]['list'][$v['time']])) {
204
+                        $achievement = $result[$value['obj_id']]['list'][$v['time']]['achievement'];
205
+
206
+                        $result[$value['obj_id']]['list'][$v['time']]['money'] = (int)$v['money'];
207
+                        $result[$value['obj_id']]['list'][$v['time']]['rate'] = (int)(($v['money'] / $achievement) * 100);
208
+                    }
209
+                }
210
+
211
+                $result[$value['obj_id']]['list'] = array_values($result[$value['obj_id']]['list']);
212
+            }
213
+        }
214
+
215
+        return array_values($result);
216
+    }
217
+
218
+    public function excelStatistics($param)
219
+    {
220
+        # 结果数据
221
+        $result = [];
222
+
223
+        # 参数
224
+        $status = !empty($param['status']) ? $param['status'] : 1; # 类型:1合同目标;2回款目标;
225
+        $year = !empty($param['year']) ? $param['year'] : 0; # 年份
226
+        $structureId = !empty($param['structure_id']) ? $param['structure_id'] : 0; # 部门
227
+        $userId = !empty($param['user_id']) ? $param['user_id'] : 0; # 员工
228
+        $type = !empty($param['type']) ? $param['type'] : 1; # 类型:1部门;2员工
229
+
230
+        # 设置业绩目标条件
231
+        $achievementWhere['year'] = $year;
232
+        $achievementWhere['status'] = $status;
233
+        $achievementWhere['type'] = !empty($type) && $type == 1 ? 2 : 3;
234
+        if (!empty($userId)) $achievementWhere['obj_id'] = $userId;
235
+        if (!empty($structureId)) $achievementWhere['obj_id'] = $structureId;
236
+
237
+        # 查询业绩目标数据
238
+        $achievementList = Db::name('crm_achievement')->where($achievementWhere)->select();
239
+
240
+        if (empty($achievementList)) return [];
241
+
242
+        # 部门
243
+        if ($type == 1) {
244
+            foreach ($achievementList as $key => $value) {
245
+                # 组装结果数据
246
+                $result[] = [
247
+                    ['name' => $value['name'], 'achievement' => (int)$value['january'], 'money' => 0, 'rate' => 0, 'month' => '一月'],
248
+                    ['name' => $value['name'], 'achievement' => (int)$value['february'], 'money' => 0, 'rate' => 0, 'month' => '二月'],
249
+                    ['name' => $value['name'], 'achievement' => (int)$value['march'], 'money' => 0, 'rate' => 0, 'month' => '三月'],
250
+
251
+                    ['name' => '', 'achievement' => 0, 'money' => 0, 'rate' => 0, 'month' => '第一季度'],
252
+
253
+                    ['name' => $value['name'], 'achievement' => (int)$value['april'], 'money' => 0, 'rate' => 0, 'month' => '四月'],
254
+                    ['name' => $value['name'], 'achievement' => (int)$value['may'], 'money' => 0, 'rate' => 0, 'month' => '五月'],
255
+                    ['name' => $value['name'], 'achievement' => (int)$value['june'], 'money' => 0, 'rate' => 0, 'month' => '六月'],
256
+
257
+                    ['name' => $value['name'], 'achievement' => (int)$value['april'], 'money' => 0, 'rate' => 0, 'month' => '第二季度'],
258
+
259
+                    ['name' => $value['name'], 'achievement' => (int)$value['july'], 'money' => 0, 'rate' => 0, 'month' => '七月'],
260
+                    ['name' => $value['name'], 'achievement' => (int)$value['august'], 'money' => 0, 'rate' => 0, 'month' => '八月'],
261
+                    ['name' => $value['name'], 'achievement' => (int)$value['september'], 'money' => 0, 'rate' => 0, 'month' => '九月'],
262
+
263
+                    ['name' => $value['name'], 'achievement' => 0, 'money' => 0, 'rate' => 0, 'month' => '第三季度'],
264
+
265
+                    ['name' => $value['name'], 'achievement' => (int)$value['october'], 'money' => 0, 'rate' => 0, 'month' => '十月'],
266
+                    ['name' => $value['name'], 'achievement' => (int)$value['november'], 'money' => 0, 'rate' => 0, 'month' => '十一月'],
267
+                    ['name' => $value['name'], 'achievement' => (int)$value['december'], 'money' => 0, 'rate' => 0, 'month' => '十二月'],
268
+
269
+                    ['name' => $value['name'], 'achievement' => 0, 'money' => 0, 'rate' => 0, 'month' => '第四季度'],
270
+                    ['name' => $value['name'], 'achievement' => (int)$value['yeartarget'], 'money' => 0, 'rate' => 0, 'month' => '全年'],
271
+                ];
272
+
273
+                # 获取部门下的员工ID
274
+                $userIds = Db::name('admin_user')->where('structure_id', $value['obj_id'])->column('id');
275
+
276
+                # 业绩完成字段
277
+                $finishField = ["DATE_FORMAT(FROM_UNIXTIME(`create_time`,'%Y-%m-%d'),'%m') AS time", 'sum(money) AS money'];
278
+
279
+                # 业绩完成条件
280
+                $finishWhere['check_status'] = 2;
281
+                $finishWhere['owner_user_id'] = ['in', $userIds];
282
+
283
+                # 合同
284
+                if ($status == 1) {
285
+                    $finishArray = Db::name('crm_contract')->field($finishField)->where($finishWhere)->group('time')->select();
286
+                }
287
+
288
+                # 回款
289
+                if ($status == 2) {
290
+                    $finishArray = Db::name('crm_receivables')->field($finishField)->where($finishWhere)->group('time')->select();
291
+                }
292
+
293
+                # 计算完成情况
294
+                foreach ($finishArray as $k => $v) {
295
+                    if (!empty($result[$v['time']])) {
296
+                        $achievement = $result[$v['time']]['achievement'];
297
+                        $result[$v['time']]['money'] = (int)$v['money'];
298
+                        $result[$v['time']]['rate'] = (int)(($v['money'] / $achievement) * 100);
299
+                    }
300
+
301
+                }
302
+                foreach ($result as &$val){
303
+                    $val[3]['money']=$val[0]['money']+$val[1]['money']+$val[2]['money'];
304
+                    $val[3]['rate']=$val[0]['rate']+$val[1]['rate']+$val[2]['rate'];
305
+                    $val[7]['money']=$val[4]['money']+$val[5]['money']+$val[6]['money'];
306
+                    $val[7]['rate']=$val[4]['rate']+$val[5]['rate']+$val[6]['rate'];
307
+                    $val[11]['money']=$val[7]['money']+$val[9]['money']+$val[10]['money'];
308
+                    $val[11]['rate']=$val[8]['rate']+$val[9]['rate']+$val[10]['rate'];
309
+                    $val[15]['money']=$val[12]['money']+$val[13]['money']+$val[14]['money'];
310
+                    $val[15]['rate']=$val[12]['rate']+$val[13]['rate']+$val[14]['rate'];
311
+                    $val[15]['money']=$val[12]['money']+$val[13]['money']+$val[14]['money'];
312
+                    $val[15]['rate']=$val[12]['rate']+$val[13]['rate']+$val[14]['rate'];
313
+                    $val[16]['money']=$val[3]['money']+$val[7]['money']+$val[11]['money']+$val[15]['money'];
314
+                    $val[16]['rate']=$val[3]['rate']+$val[7]['rate']+$val[11]['rate']+$val[15]['rate'];
315
+                }
316
+
317
+                $result = array_values($result);
318
+            }
319
+        }
320
+
321
+        # 员工
322
+        if ($type == 2) {
323
+            foreach ($achievementList AS $key => $value) {
324
+                # 组装结果数据
325
+
326
+
327
+                $result[] = [
328
+                    ['name' => $value['name'], 'achievement' => (int)$value['january'], 'money' => 0, 'rate' => 0, 'month' => '一月'],
329
+                    ['name' => $value['name'], 'achievement' => (int)$value['february'], 'money' => 0, 'rate' => 0, 'month' => '二月'],
330
+                    ['name' => $value['name'], 'achievement' => (int)$value['march'], 'money' => 0, 'rate' => 0, 'month' => '三月'],
331
+
332
+                    ['name' => '', 'achievement' => 0, 'money' => 0, 'rate' => 0, 'month' => '第一季度'],
333
+
334
+                    ['name' => $value['name'], 'achievement' => (int)$value['april'], 'money' => 0, 'rate' => 0, 'month' => '四月'],
335
+                    ['name' => $value['name'], 'achievement' => (int)$value['may'], 'money' => 0, 'rate' => 0, 'month' => '五月'],
336
+                    ['name' => $value['name'], 'achievement' => (int)$value['june'], 'money' => 0, 'rate' => 0, 'month' => '六月'],
337
+
338
+                    ['name' => $value['name'], 'achievement' => (int)$value['april'], 'money' => 0, 'rate' => 0, 'month' => '第二季度'],
339
+
340
+                    ['name' => $value['name'], 'achievement' => (int)$value['july'], 'money' => 0, 'rate' => 0, 'month' => '七月'],
341
+                    ['name' => $value['name'], 'achievement' => (int)$value['august'], 'money' => 0, 'rate' => 0, 'month' => '八月'],
342
+                    ['name' => $value['name'], 'achievement' => (int)$value['september'], 'money' => 0, 'rate' => 0, 'month' => '九月'],
343
+
344
+                    ['name' => $value['name'], 'achievement' => 0, 'money' => 0, 'rate' => 0, 'month' => '第三季度'],
345
+
346
+                    ['name' => $value['name'], 'achievement' => (int)$value['october'], 'money' => 0, 'rate' => 0, 'month' => '十月'],
347
+                    ['name' => $value['name'], 'achievement' => (int)$value['november'], 'money' => 0, 'rate' => 0, 'month' => '十一月'],
348
+                    ['name' => $value['name'], 'achievement' => (int)$value['december'], 'money' => 0, 'rate' => 0, 'month' => '十二月'],
349
+
350
+                    ['name' => $value['name'], 'achievement' => 0, 'money' => 0, 'rate' => 0, 'month' => '第四季度'],
351
+                    ['name' => $value['name'], 'achievement' => (int)$value['yeartarget'], 'money' => 0, 'rate' => 0, 'month' => '全年'],
352
+                ];
353
+
354
+
355
+
356
+                # 业绩完成字段
357
+                $finishField = ["DATE_FORMAT(FROM_UNIXTIME(`create_time`,'%Y-%m-%d'),'%m') AS time", 'sum(money) AS money'];
358
+
359
+                # 业绩完成条件
360
+                $finishWhere = ['check_status' => 2, 'owner_user_id' => $value['obj_id']];
361
+
362
+                # 合同
363
+                if ($status == 1) {
364
+                    $finishArray = Db::name('crm_contract')->field($finishField)->where($finishWhere)->group('time')->select();
365
+                }
366
+
367
+                # 回款
368
+                if ($status == 2) {
369
+                    $finishArray = Db::name('crm_receivables')->field($finishField)->where($finishWhere)->group('time')->select();
370
+                }
371
+
372
+                # 计算完成情况
373
+                foreach ($finishArray AS $k => $v) {
374
+                    if (!empty($result[$v['time']])) {
375
+                        $achievement = $result[$v['time']]['achievement'];
376
+
377
+                        $result[$v['time']]['money'] = (int)$v['money'];
378
+                        $result[$v['time']]['rate']  = (int)(($v['money'] / $achievement) * 100);
379
+                    }
380
+                }
381
+
382
+                foreach ($result as &$val){
383
+                    $val[3]['money']=$val[0]['money']+$val[1]['money']+$val[2]['money'];
384
+                    $val[3]['rate']=$val[0]['rate']+$val[1]['rate']+$val[2]['rate'];
385
+                    $val[7]['money']=$val[4]['money']+$val[5]['money']+$val[6]['money'];
386
+                    $val[7]['rate']=$val[4]['rate']+$val[5]['rate']+$val[6]['rate'];
387
+                    $val[11]['money']=$val[7]['money']+$val[9]['money']+$val[10]['money'];
388
+                    $val[11]['rate']=$val[8]['rate']+$val[9]['rate']+$val[10]['rate'];
389
+                    $val[15]['money']=$val[12]['money']+$val[13]['money']+$val[14]['money'];
390
+                    $val[15]['rate']=$val[12]['rate']+$val[13]['rate']+$val[14]['rate'];
391
+                    $val[15]['money']=$val[12]['money']+$val[13]['money']+$val[14]['money'];
392
+                    $val[15]['rate']=$val[12]['rate']+$val[13]['rate']+$val[14]['rate'];
393
+                    $val[16]['money']=$val[3]['money']+$val[7]['money']+$val[11]['money']+$val[15]['money'];
394
+                    $val[16]['rate']=$val[3]['rate']+$val[7]['rate']+$val[11]['rate']+$val[15]['rate'];
395
+                }
396
+                $result = array_values($result);
397
+            }
398
+        }
399
+
400
+        return array_values($result);
401
+    }
402
+
403
+    /**
404
+     * 导出
405
+     * @param $type
406
+     * @param $types
407
+     */
408
+    public function excelExport()
409
+    {
410
+        $param = $this->param;
411
+        $list = $this->statistics($param);
412
+        if(empty($list)){
413
+            return resultArray(['data'=>'数据不存在']);
414
+        }
415
+        $excelLogic = new ExcelLogic();
416
+        $data = $excelLogic->achienementExcel($param, $list);
417
+        return $data;
418
+    }
419
+}

+ 287
- 0
application/bi/controller/Business.php Целия файл

@@ -0,0 +1,287 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 商业智能-商机分析
4
+// +----------------------------------------------------------------------
5
+// | Author: Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\bi\controller;
9
+
10
+use app\admin\controller\ApiCommon;
11
+use app\bi\traits\SortTrait;
12
+use think\Db;
13
+use think\Hook;
14
+use think\Request;
15
+
16
+class Business extends ApiCommon
17
+{
18
+    use SortTrait;
19
+
20
+    /**
21
+     * 用于判断权限
22
+     * @permission 无限制
23
+     * @allow 登录用户可访问
24
+     * @other 其他根据系统设置
25
+    **/    
26
+    public function _initialize()
27
+    {
28
+        $action = [
29
+            'permission'=>[''],
30
+            'allow'=>[
31
+                'funnel',
32
+                'businesstrend',
33
+                'trendlist',
34
+                'win',
35
+                'winlist'
36
+            ]
37
+        ];
38
+        Hook::listen('check_auth',$action);
39
+        $request = Request::instance();
40
+        $a = strtolower($request->action());        
41
+        if (!in_array($a, $action['permission'])) {
42
+            parent::_initialize();
43
+        }
44
+        if (!checkPerByAction('bi', 'business' , 'read')) {
45
+            header('Content-Type:application/json; charset=utf-8');
46
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
47
+        }        
48
+    } 
49
+  
50
+    /**
51
+     * 销售漏斗
52
+     * @author Michael_xu
53
+     * @param 
54
+     * @return
55
+     */
56
+    public function funnel()
57
+    {
58
+        if (empty($this->param['type_id'])) return resultArray(['error' => '请选择商机组!']);
59
+
60
+        $businessModel = new \app\crm\model\Business();
61
+
62
+        $param = $this->param;
63
+
64
+        $sortField = !empty($param['sort_field']) ? $param['sort_field'] : '';
65
+        $sortValue = !empty($param['sort_value']) ? $param['sort_value'] : '';
66
+        unset($param['sort_field']);
67
+        unset($param['sort_value']);
68
+
69
+        if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
70
+        if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
71
+
72
+        $data = $businessModel->getFunnel($param);
73
+        foreach ($data['list'] AS $key => $value) {
74
+            if (empty($value['money']) && empty($value['count'])) unset($data['list'][(int)$key]);
75
+        }
76
+        if (empty($data['total']['money_count']) && empty($data['total']['count'])) return resultArray(['data' => ['list' => []]]);
77
+
78
+        $data['list'] = array_values($data['list']);
79
+
80
+        # 排序
81
+        if (!empty($data['list'])) $data['list'] = $this->sortCommon($data['list'], $sortField, $sortValue);
82
+
83
+        return resultArray(['data' => $data]);
84
+    }  
85
+
86
+    /**
87
+     * 新增商机数与金额趋势分析
88
+     * @return 
89
+     */
90
+    public function businessTrend()
91
+    {
92
+        $businessModel = new \app\crm\model\Business();
93
+        $userModel     = new \app\admin\model\User();
94
+        $adminModel    = new \app\admin\model\Admin();
95
+        $param         = $this->param;
96
+
97
+        $perUserIds = $userModel->getUserByPer('bi', 'business', 'read'); //权限范围内userIds
98
+        $whereArr = $adminModel->getWhere($param, '', $perUserIds); //统计条件
99
+        $userIds = $whereArr['userIds'];
100
+
101
+        if(empty($param['type']) && empty($param['start_time'])){
102
+            $param['type'] = 'month';
103
+        }
104
+
105
+        if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
106
+        if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
107
+        $time  = getTimeArray($param['start_time'], $param['end_time']);
108
+        $where = [
109
+            'owner_user_id' => !empty($userIds) ? implode(',',$userIds) : '9999999999'
110
+        ];
111
+        $sql = [];
112
+
113
+        foreach ($time['list'] as $val) {
114
+            $whereArr = $where;
115
+            $whereArr['type'] = $val['type'];
116
+            $whereArr['start_time'] = $val['start_time'];
117
+            $whereArr['end_time'] = $val['end_time'];
118
+            $sql[] = $businessModel->getTrendql($whereArr);
119
+        }
120
+
121
+        $sql = implode(' UNION ALL ', $sql);
122
+        $list = queryCache($sql);
123
+        return resultArray(['data' => $list]);
124
+    }
125
+
126
+    /**
127
+     * 新增商机数与金额趋势分析 列表
128
+     *
129
+     * @return \think\response\Json
130
+     * @throws \think\db\exception\DataNotFoundException
131
+     * @throws \think\db\exception\ModelNotFoundException
132
+     * @throws \think\exception\DbException
133
+     */
134
+    public function trendList()
135
+    {
136
+        $businessModel = new \app\bi\model\Business();
137
+        $crmBusinessModel = new \app\crm\model\Business();
138
+        $userModel = new \app\admin\model\User();
139
+        $param = $this->param;
140
+        unset($param['types']);
141
+
142
+        # 日期条件
143
+        if (!empty($param['type'])) {
144
+            $param['start_time'] = strtotime($param['type'] . '-01 00:00:00');
145
+            $endMonth = strtotime(date('Y-m-d', $param['start_time']) . " +1 month -1 day");
146
+            $param['end_time'] = strtotime(date('Y-m-d 23:59:59', $endMonth));
147
+            unset($param['type']);
148
+        } else {
149
+            if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
150
+            if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
151
+        }
152
+
153
+        # 排序参数
154
+        $sortField = !empty($param['sort_field']) ? $param['sort_field'] : '';
155
+        $sortValue = !empty($param['sort_value']) ? $param['sort_value'] : '';
156
+
157
+        $dataList = $businessModel->getDataList($param);
158
+        foreach ($dataList['list'] as $k => $v) {
159
+            $business_info = $crmBusinessModel->getDataById($v['business_id']);
160
+            $dataList['list'][$k]['business_name'] = $business_info['name'];
161
+            $dataList['list'][$k]['create_time'] = date('Y-m-d',strtotime($business_info['create_time']));
162
+            $dataList['list'][$k]['customer_id'] = $v['customer_id'];
163
+            $customer = db('crm_customer')->field('name')->where('customer_id',$v['customer_id'])->find();
164
+            $dataList['list'][$k]['customer_name'] = $customer['name'];
165
+            $create_user_id_info = isset($v['create_user_id']) ? $userModel->getUserById($v['create_user_id']) : [];
166
+            $dataList['list'][$k]['create_user_name'] = $create_user_id_info['realname'];
167
+            $owner_user_id_info = isset($v['owner_user_id']) ? $userModel->getUserById($v['owner_user_id']) : [];
168
+            $dataList['list'][$k]['owner_user_name'] = $owner_user_id_info['realname'];
169
+            $dataList['list'][$k]['business_stage'] = db('crm_business_status')->where('status_id',$v['status_id'])->value('name');//销售阶段
170
+            $dataList['list'][$k]['business_type'] = db('crm_business_type')->where('type_id',$v['type_id'])->value('name');//商机状态组
171
+        }
172
+
173
+        # 排序
174
+        if (!empty($dataList)) $dataList = $this->sortCommon($dataList, $sortField, $sortValue);
175
+        
176
+        return resultArray(['data' => $dataList]);
177
+    }
178
+
179
+    /**
180
+     * 赢单机会转化率趋势分析
181
+     *
182
+     * @return \think\response\Json
183
+     * @throws \think\db\exception\DataNotFoundException
184
+     * @throws \think\db\exception\ModelNotFoundException
185
+     * @throws \think\exception\DbException
186
+     */
187
+    public function win()
188
+    {
189
+        $businessModel = new \app\crm\model\Business();
190
+        $userModel = new \app\admin\model\User();
191
+        $adminModel = new \app\admin\model\Admin(); 
192
+        $param = $this->param;
193
+
194
+        $perUserIds = $userModel->getUserByPer('bi', 'customer', 'read'); //权限范围内userIds
195
+        $whereArr   = $adminModel->getWhere($param, '', $perUserIds); //统计条件
196
+        $userIds    = $whereArr['userIds'];
197
+
198
+        if(empty($param['type']) && empty($param['start_time'])){
199
+            $param['type'] = 'month';
200
+        }
201
+
202
+        if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
203
+        if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
204
+        $time = getTimeArray($param['start_time'], $param['end_time']);
205
+        $sql = db('crm_business')->alias('business')->field([
206
+                    "FROM_UNIXTIME(business.create_time, '{$time['time_format']}')" => 'type',
207
+                    'COUNT(business.business_id)' => 'business_num',
208
+                    'SUM(
209
+                            CASE WHEN
210
+                                `check_status` = 2
211
+                            THEN 1 ELSE 0 END
212
+                        )' => 'business_end'
213
+                ])->join('__CRM_CONTRACT__ contract', 'contract.business_id = business.business_id', 'left')
214
+                ->where([
215
+                    'business.owner_user_id' => ['IN', $userIds],
216
+                    'business.create_time' => ['BETWEEN', $time['between']]
217
+                ])
218
+                ->group('type')
219
+                ->fetchSql()
220
+                ->select();
221
+        $res = queryCache($sql);
222
+        $res = array_column($res, null, 'type');
223
+        foreach ($time['list'] as $key =>$val) {
224
+            $val['business_num'] = (int) $res[$val['type']]['business_num'];
225
+            $val['business_end'] = (int) $res[$val['type']]['business_end'];
226
+            if($res[$val['type']]['business_num']== 0 || $res[$val['type']]['business_end'] == 0){
227
+                $val['proportion'] = 0;
228
+            }else{
229
+                $val['proportion'] = round(($res[$val['type']]['business_end']/$res[$val['type']]['business_num']),4)*100;
230
+            }
231
+            $time['list'][$key] = $val;
232
+        }
233
+        return resultArray(['data' => $time['list']]);
234
+    }
235
+
236
+    /**
237
+     * 商机转化率分析 列表
238
+     *
239
+     * @return \think\response\Json
240
+     * @throws \think\db\exception\DataNotFoundException
241
+     * @throws \think\db\exception\ModelNotFoundException
242
+     * @throws \think\exception\DbException
243
+     */
244
+    public function winList()
245
+    {
246
+        $businessModel = new \app\bi\model\Business();
247
+        $crmBusinessModel = new \app\crm\model\Business();
248
+        $userModel = new \app\admin\model\User();
249
+        $param = $this->param;
250
+
251
+        # 日期条件
252
+        if (!empty($param['date'])) {
253
+            $param['start_time'] = strtotime($param['date'] . '-01 00:00:00');
254
+            $endMonth = strtotime(date('Y-m-d', $param['start_time']) . " +1 month -1 day");
255
+            $param['end_time'] = strtotime(date('Y-m-d 23:59:59', $endMonth)) ;
256
+            unset($param['type']);
257
+        }
258
+
259
+        # 排序参数
260
+        $sortField = !empty($param['sort_field']) ? $param['sort_field'] : '';
261
+        $sortValue = !empty($param['sort_value']) ? $param['sort_value'] : '';
262
+
263
+        # 赢单条件
264
+        $param['is_end'] = 1;
265
+
266
+        $dataList = $businessModel->getDataList($param);
267
+        foreach ($dataList as $k => $v) {
268
+            $business_info = $crmBusinessModel->getDataById($v['business_id']);
269
+            $dataList[$k]['business_name'] = $business_info['name'];
270
+            $dataList[$k]['create_time'] = date('Y-m-d',strtotime($business_info['create_time']));
271
+            $dataList[$k]['customer_id'] = $v['customer_id'];
272
+            $customer = db('crm_customer')->field('name')->where('customer_id',$v['customer_id'])->find();
273
+            $dataList[$k]['customer_name'] = $customer['name'];
274
+            $create_user_id_info = isset($v['create_user_id']) ? $userModel->getUserById($v['create_user_id']) : [];
275
+            $dataList[$k]['create_user_name'] = $create_user_id_info['realname'];
276
+            $owner_user_id_info = isset($v['owner_user_id']) ? $userModel->getUserById($v['owner_user_id']) : [];
277
+            $dataList[$k]['owner_user_name'] = $owner_user_id_info['realname'];
278
+            $dataList[$k]['business_stage'] = db('crm_business_status')->where('status_id',$v['status_id'])->value('name');//销售阶段
279
+            $dataList[$k]['business_type'] = db('crm_business_type')->where('type_id',$v['type_id'])->value('name');//商机状态组
280
+        }
281
+
282
+        # 排序
283
+        if (!empty($dataList)) $dataList = $this->sortCommon($dataList, $sortField, $sortValue);
284
+
285
+        return resultArray(['data' => $dataList]);
286
+    }
287
+}

+ 359
- 0
application/bi/controller/Contract.php Целия файл

@@ -0,0 +1,359 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 商业智能-员工业绩分析
4
+// +----------------------------------------------------------------------
5
+// | Author: Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\bi\controller;
9
+
10
+use app\admin\controller\ApiCommon;
11
+use app\bi\traits\SortTrait;
12
+use app\crm\model\Contract as ContractModel;
13
+use app\crm\model\Receivables as ReceivablesModel;
14
+use think\Db;
15
+use think\Hook;
16
+use think\Request;
17
+use app\bi\logic\ExcelLogic;
18
+class Contract extends ApiCommon
19
+{
20
+    use SortTrait;
21
+
22
+    /**
23
+     * 用于判断权限
24
+     * @permission 无限制
25
+     * @allow 登录用户可访问
26
+     * @other 其他根据系统设置
27
+     **/
28
+    public function _initialize()
29
+    {
30
+        $action = [
31
+            'permission' => [''],
32
+            'allow' => [
33
+                'analysis',
34
+                'summary',
35
+                'invoice',
36
+                'excelexport'
37
+            ]
38
+        ];
39
+        Hook::listen('check_auth', $action);
40
+        $request = Request::instance();
41
+        $a = strtolower($request->action());
42
+        if (!in_array($a, $action['permission'])) {
43
+            parent::_initialize();
44
+        }
45
+        if (!checkPerByAction('bi', 'contract', 'read')) {
46
+            header('Content-Type:application/json; charset=utf-8');
47
+            exit(json_encode(['code' => 102, 'error' => '无权操作']));
48
+        }
49
+    }
50
+
51
+    /**
52
+     * 合同数量分析/金额分析/回款金额分析
53
+     *
54
+     * @param string $param
55
+     * @return array|\think\response\Json
56
+     * @throws \think\db\exception\DataNotFoundException
57
+     * @throws \think\db\exception\ModelNotFoundException
58
+     * @throws \think\exception\DbException
59
+     */
60
+    public function analysis($param='')
61
+    {
62
+        $userModel  = new \app\admin\model\User();
63
+        $adminModel = new \app\admin\model\Admin();
64
+        if ($param['excel_type'] != 1) {
65
+            $param = $this->param;
66
+        }
67
+
68
+        $perUserIds = $userModel->getUserByPer('bi', 'contract', 'read'); // 权限范围内userIds
69
+        $whereArr   = $adminModel->getWhere($param, '', $perUserIds);       // 统计条件
70
+        $userIds    = $whereArr['userIds'];
71
+
72
+        $year       = !empty($param['year']) ? $param['year'] : date('Y');
73
+        $start_time = strtotime(date(($year - 1) . '-01-01'));
74
+        $end_time   = strtotime('+2 year', $start_time) - 1;
75
+        $time       = getTimeArray($start_time, $end_time);
76
+
77
+        if ($param['type'] == 'back' || $param['excel_type'] == 'back') {
78
+            $model = new ReceivablesModel;
79
+            $time_field = 'return_time';
80
+        } else {
81
+            $model = new ContractModel;
82
+            $time_field = 'order_date';
83
+        }
84
+        if ($param['type'] == 'count' || $param['$excel_type'] == 'count') {
85
+            $field['COUNT(*)'] = 'total';
86
+        } else {
87
+            $field['SUM(`money`)'] = 'total';
88
+        }
89
+        $between_time = [date('Y-m-d', $time['between'][0]), date('Y-m-d', $time['between'][1])];
90
+        $field["SUBSTR(`{$time_field}`, 1, 7)"] = 'type';
91
+        $sql = $model->field($field)
92
+            ->where([
93
+                'owner_user_id' => ['IN', $userIds],
94
+                'check_status' => 2,
95
+                $time_field => ['BETWEEN', $between_time]
96
+            ])
97
+            ->group('type')
98
+            ->fetchSql()
99
+            ->select();
100
+        $res = queryCache($sql);
101
+        $res = array_column($res, null, 'type');
102
+
103
+        $data = [];
104
+        for ($i = 12; $i < 24; $i++) {
105
+            $k  = $time['list'][$i]['type'];
106
+            $k2 = $time['list'][$i - 1]['type'];
107
+            $k3 = $time['list'][$i - 12]['type'];
108
+            $item['month'] = ($i - 11) < 10 ? $param['year']. '0' . $i - 11 : $param['year'] . $i - 11;
109
+
110
+            $item['thisMonth']       = $res[$k]  ? $res[$k]['total']  : 0; # 本月
111
+            $item['lastMonthGrowth'] = $res[$k2] ? $res[$k2]['total'] : 0; # 上月
112
+            $item['lastYearGrowth']  = $res[$k3] ? $res[$k3]['total'] : 0; # 上年本月
113
+
114
+            # 环比
115
+            $item['chain_ratio'] = $item['thisMonth'] && $item['lastMonthGrowth'] ? round(($item['thisMonth'] / $item['lastMonthGrowth'])  * 100, 4) : 0;
116
+            # 同比
117
+            $item['year_on_year'] = $item['thisMonth'] && $item['lastYearGrowth'] ? round(($item['thisMonth'] / $item['lastYearGrowth'])  * 100, 4) : 0;
118
+
119
+            $data[] = $item;
120
+        }
121
+        //导出使用
122
+        if (!empty($param['excel_type'])) {
123
+            return $data;
124
+        }
125
+        return resultArray(['data' => $data]);
126
+    }
127
+
128
+    /**
129
+     * 合同汇总表
130
+     *
131
+     * @return \think\response\Json
132
+     * @throws \think\db\exception\DataNotFoundException
133
+     * @throws \think\db\exception\ModelNotFoundException
134
+     * @throws \think\exception\DbException
135
+     */
136
+    public function summary($param='')
137
+    {
138
+        $userModel  = new \app\admin\model\User();
139
+        $adminModel = new \app\admin\model\Admin();
140
+        if($param['excel_type']!=1){
141
+            $param = $this->param;
142
+        }
143
+
144
+        $perUserIds = $userModel->getUserByPer('bi', 'contract', 'read'); //权限范围内userIds
145
+        $whereArr   = $adminModel->getWhere($param, '', $perUserIds); //统计条件
146
+        $userIds    = $whereArr['userIds'];
147
+
148
+        if (empty($param['type']) && empty($param['start_time'])) {
149
+            $param['type'] = 'month';
150
+        }
151
+
152
+        $sortField = !empty($param['sort_field']) ? $param['sort_field'] : '';
153
+        $sortValue = !empty($param['sort_value']) ? $param['sort_value'] : '';
154
+        unset($param['sort_field']);
155
+        unset($param['sort_value']);
156
+
157
+        $year       = !empty($param['year']) ? $param['year'] : date('Y');
158
+        $start_time = strtotime($year . '-01-01');
159
+        $end_time   = strtotime('+1 year', $start_time) - 1;
160
+        $time       = getTimeArray($start_time, $end_time);
161
+        $ax         = 7;
162
+        if ($time['time_format'] == '%Y-%m-%d') {
163
+            $ax = 10;
164
+        }
165
+        $between_time = [date('Y-m-d', $time['between'][0]), date('Y-m-d', $time['between'][1])];
166
+        $sql = ContractModel::field([
167
+            'SUBSTR(`order_date`, 1, ' . $ax . ')' => 'type',
168
+            'COUNT(*)' => 'count',
169
+            'SUM(`money`)' => 'money'
170
+        ])
171
+            ->where([
172
+                'owner_user_id' => ['IN', $userIds],
173
+                'check_status' => 2,
174
+                'order_date' => ['BETWEEN', $between_time]
175
+            ])
176
+            ->group('type')
177
+            ->fetchSql()
178
+            ->select();
179
+        $contract_data = queryCache($sql);
180
+        $contract_data = array_column($contract_data, null, 'type');
181
+        $sql = ReceivablesModel::field([
182
+            'SUBSTR(`return_time`, 1, ' . $ax . ')' => 'type',
183
+            'SUM(`money`)' => 'money'
184
+        ])
185
+            ->where([
186
+                'owner_user_id' => ['IN', $userIds],
187
+                'check_status' => 2,
188
+                'return_time' => ['BETWEEN', $between_time]
189
+            ])
190
+            ->group('type')
191
+            ->fetchSql()
192
+            ->select();
193
+        $receivables_data = queryCache($sql);
194
+        $receivables_data = array_column($receivables_data, null, 'type');
195
+
196
+        $items = [];
197
+        $count_zong = 0;
198
+        $money_zong = 0;
199
+        $back_zong = 0;
200
+        foreach ($time['list'] as $val) {
201
+            $item = ['type' => $val['type']];
202
+            $count_zong += $item['count'] = $contract_data[$val['type']]['count']   ?: 0;
203
+            $money_zong += $item['money'] = $contract_data[$val['type']]['money']   ?: 0;
204
+            $back_zong  += $item['back']  = $receivables_data[$val['type']]['money'] ?: 0;
205
+            $items[] = $item;
206
+        }
207
+        $data = [
208
+            'list'        => $items,
209
+            'count_zong'  => $count_zong,
210
+            'money_zong'  => $money_zong,
211
+            'back_zong'   => $back_zong,
212
+            'w_back_zong' => $money_zong - $back_zong,
213
+        ];
214
+
215
+        if (!empty($data['list'])) $data['list'] = $this->sortCommon($data['list'], $sortField, $sortValue);
216
+        //导出使用
217
+        if (!empty($param['excel_type'])) return $data;
218
+        return resultArray(['data' => $data]);
219
+    }
220
+
221
+    /**
222
+     * 发票统计分析
223
+     *
224
+     * @return \think\response\Json
225
+     * @throws \think\db\exception\DataNotFoundException
226
+     * @throws \think\db\exception\ModelNotFoundException
227
+     * @throws \think\exception\DbException
228
+     */
229
+    public function invoice($param='')
230
+    {
231
+        $userModel  = new \app\admin\model\User();
232
+        $adminModel = new \app\admin\model\Admin();
233
+        if($param['excel_type']!=1){
234
+            $param = $this->param;
235
+        }
236
+
237
+        $perUserIds = $userModel->getUserByPer('bi', 'contract', 'read'); //权限范围内userIds
238
+        $whereArr   = $adminModel->getWhere($param, '', $perUserIds); //统计条件
239
+        $userIds    = $whereArr['userIds'];
240
+        if (empty($param['type']) && empty($param['start_time'])) {
241
+            $param['type'] = 'month';
242
+        }
243
+
244
+        $sortField = !empty($param['sort_field']) ? $param['sort_field'] : '';
245
+        $sortValue = !empty($param['sort_value']) ? $param['sort_value'] : '';
246
+        unset($param['sort_field']);
247
+        unset($param['sort_value']);
248
+
249
+        $time = getTimeArray();
250
+        $ax = 7;
251
+        if ($time['time_format'] == '%Y-%m-%d') {
252
+            $ax = 10;
253
+        }
254
+        $between_time = [date('Y-m-d', $time['between'][0]), date('Y-m-d', $time['between'][1])];
255
+        $sql = Db::name('crm_invoice')->field([
256
+            'SUBSTR(`invoice_date`, 1, ' . $ax . ')' => 'type',
257
+            'SUM(`invoice_money`)' => 'money'
258
+        ])
259
+            ->where([
260
+                'owner_user_id' => ['IN', $userIds],
261
+                'check_status' => 2,
262
+                'invoice_status' => 1,
263
+                'invoice_date' => ['BETWEEN', $between_time]
264
+            ])
265
+            ->group('type')
266
+            ->fetchSql()
267
+            ->select();
268
+        $invoice_data = queryCache($sql);
269
+        $invoice_data = array_column($invoice_data, null, 'type');
270
+
271
+        $sql = ReceivablesModel::field([
272
+            'SUBSTR(`return_time`, 1, ' . $ax . ')' => 'type',
273
+            'SUM(`money`)' => 'money'
274
+        ])
275
+            ->where([
276
+                'owner_user_id' => ['IN', $userIds],
277
+                'check_status' => 2,
278
+                'return_time' => ['BETWEEN', $between_time]
279
+            ])
280
+            ->group('type')
281
+            ->fetchSql()
282
+            ->select();
283
+        $receivables_data = queryCache($sql);
284
+        $receivables_data = array_column($receivables_data, null, 'type');
285
+
286
+        $items = [];
287
+        $invoiceCount = 0;
288
+        $receivablesCount = 0;
289
+        foreach ($time['list'] as $val) {
290
+            $receivablesModel = !empty($receivables_data[$val['type']]['money']) ? $receivables_data[$val['type']]['money'] : 0;
291
+            $invoiceModel     = !empty($invoice_data[$val['type']]['money']) ? $invoice_data[$val['type']]['money'] : 0;
292
+
293
+            $items[] = [
294
+                'type' => $val['type'],
295
+                'receivables_money' => $receivablesModel,
296
+                'invoice_money'     => $invoiceModel,
297
+                'not_invoice'       => $receivablesModel - $invoiceModel > 0 ? $receivablesModel - $invoiceModel : 0,
298
+                'not_receivables'   => $invoiceModel - $receivablesModel > 0 ? $invoiceModel - $receivablesModel : 0
299
+            ];
300
+
301
+            $invoiceCount     += $invoiceModel;
302
+            $receivablesCount += $receivablesModel;
303
+
304
+        }
305
+        $data = [
306
+            'list' => $items,
307
+            'receivables_count' => $receivablesCount,
308
+            'invoice_count' => $invoiceCount
309
+        ];
310
+
311
+        if (!empty($data['list'])) $data['list'] = $this->sortCommon($data['list'], $sortField, $sortValue);
312
+        //导出使用
313
+        if (!empty($param['excel_type'])) return $data;
314
+        return resultArray(['data' => $data]);
315
+    }
316
+
317
+    /**
318
+     * 导出
319
+     * @param $type
320
+     * @param $types
321
+     */
322
+    public function excelExport()
323
+    {
324
+
325
+        $param = $this->param;
326
+        $excel_type = $param['excel_type'];
327
+        $type=[];
328
+        $type['excel_types']=$param['excel_types'];
329
+
330
+        switch ($param['excel_types']) {
331
+            case 'analysis':
332
+                if ($param['type'] == 'count') {
333
+                    $type['type'] = '合同数量分析';
334
+
335
+                } elseif ($param['type'] == 'back') {
336
+                    $type['type'] = '回款金额分析';
337
+                } else {
338
+                    $type['type'] = '金额分析';
339
+                }
340
+                $list = $this->analysis($param);
341
+                break;
342
+            case 'summary':
343
+                $list = $this->summary($excel_type);
344
+                $type['type'] = '合同汇总表';
345
+                break;
346
+            case 'invoice':
347
+                $list = $this->invoice($excel_type);
348
+                $type['type'] = '发票统计分析表';
349
+                break;
350
+        }
351
+        if(empty($list)){
352
+            return resultArray(['data'=>'数据不存在']);
353
+        }
354
+        $excelLogic = new ExcelLogic();
355
+        $data = $excelLogic->contractExcel($type, $list);
356
+        return $data;
357
+    }
358
+
359
+}

+ 1215
- 0
application/bi/controller/Customer.php
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 173
- 0
application/bi/controller/Examine.php Целия файл

@@ -0,0 +1,173 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 商业智能-审核统计
4
+// +----------------------------------------------------------------------
5
+// | Author: zhi | zhijunfu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\bi\controller;
9
+
10
+use app\admin\controller\ApiCommon;
11
+use think\Hook;
12
+use think\Request;
13
+use think\Db;
14
+
15
+class Examine extends ApiCommon
16
+{
17
+    /**
18
+     * 用于判断权限
19
+     * @permission 无限制
20
+     * @allow 登录用户可访问
21
+     * @other 其他根据系统设置
22
+    **/    
23
+    public function _initialize()
24
+    {
25
+        $action = [
26
+            'permission'=>[''],
27
+            'allow'=>['statistics','index','excelexport']            
28
+        ];
29
+        Hook::listen('check_auth',$action);
30
+        $request = Request::instance();
31
+        $a = strtolower($request->action());        
32
+        if (!in_array($a, $action['permission'])) {
33
+            parent::_initialize();
34
+        }
35
+        if (!checkPerByAction('bi', 'oa', 'read')) {
36
+            header('Content-Type:application/json; charset=utf-8');
37
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
38
+        }        
39
+    }
40
+
41
+    /**
42
+     * 审核统计列表
43
+     *
44
+     * @return \think\response\Json
45
+     * @throws \think\db\exception\DataNotFoundException
46
+     * @throws \think\db\exception\ModelNotFoundException
47
+     * @throws \think\exception\DbException
48
+     */
49
+    public function statistics()
50
+    {  
51
+        $param  = $this->param;
52
+        if ($param['type']) {
53
+            $timeArr = getTimeByType($param['type']);
54
+            $param['start_time'] = $timeArr[0];
55
+            $param['end_time'] = $timeArr[1];
56
+        } else {
57
+            if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
58
+            if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
59
+        }
60
+        $examineModel = new \app\bi\model\Examine();
61
+        $list = $examineModel->getStatistics($param) ? : [];
62
+        return resultArray(['data'=>$list]);
63
+    }
64
+
65
+    /**
66
+     * 审核统计详情列表
67
+     * @return 
68
+     */    
69
+    public function index()
70
+    {       
71
+        $examineModel = new \app\oa\model\Examine();
72
+        $param = $this->param;
73
+        $user_id = $param['user_id'];
74
+        $category_id = $param['category_id'];
75
+        $type = $param['type'];
76
+        if (!$user_id || !$category_id) {
77
+            return resultArray(['error'=>'参数错误']);
78
+        }
79
+        //时间
80
+        if ($type) {
81
+            $timeArr = getTimeByType($type);
82
+            $start_time = $timeArr[0];
83
+            $end_time = $timeArr[1];
84
+        } else {
85
+            $start_time = $param['start_time'] ? : strtotime(date('Y-m-d',time()));
86
+            $end_time = $param['end_time'] ? : strtotime(date('Y-m-d',time()))+86399;            
87
+        }
88
+        $create_time = array('between',array($start_time,$end_time));        
89
+
90
+        $where = [];
91
+        $where['create_user_id'] = $user_id;
92
+        $where['check_status'] = 2;
93
+        $where['create_time'] = $create_time;
94
+        $where['category_id'] = $category_id;
95
+        $sumData = 0;
96
+        $categoryName = '普通审批';
97
+        switch ($category_id) {
98
+            case '2' : 
99
+                $sumData = db('oa_examine')->where($where)->sum('duration');
100
+                $categoryName = '请假审批';
101
+                break;
102
+            case '3' : 
103
+                $sumData = db('oa_examine')->where($where)->sum('duration');
104
+                $categoryName = '出差审批';
105
+                break;
106
+            case '4' : 
107
+                $sumData = db('oa_examine')->where($where)->sum('duration');
108
+                $categoryName = '加班审批';
109
+                break; 
110
+            case '5' : 
111
+                $sumData = db('oa_examine')->where($where)->sum('money');
112
+                $categoryName = '差旅报销';
113
+                break; 
114
+            case '6' : 
115
+                $sumData = db('oa_examine')->where($where)->sum('money');
116
+                $categoryName = '借款申请';
117
+                break;
118
+            default :
119
+                $categoryName = db('oa_examine_category')->where(['category_id' => $category_id])->value('title');
120
+                break;     
121
+        } 
122
+        unset($where['create_time']);
123
+        unset($where['create_user_id']);
124
+        unset($where['create_user_id']);
125
+        $where['check_status'] = 'all';
126
+        $where['page'] = $param['page'];
127
+        $where['limit'] = $param['limit'];
128
+        $where['user_id'] = $user_id;
129
+        $where['between_time'] = array($start_time,$end_time);
130
+        $list = $examineModel->getDataList($where);
131
+
132
+        $data = [];
133
+        $data['list'] = $list ? : [];
134
+        $data['sumData'] = $sumData;
135
+        $data['categoryName'] = $categoryName;
136
+        return resultArray(['data'=>$data]);
137
+    }
138
+
139
+    /**
140
+     * 统计导出
141
+     * @author Michael_xu
142
+     * @param 
143
+     * @return
144
+     */
145
+    public function excelExport()
146
+    {
147
+        $param = $this->param;
148
+        $excelModel = new \app\admin\model\Excel();
149
+        // 导出的字段列表
150
+        $category_list = db('oa_examine_category')->where(['status' => 1,'is_deleted' => ['neq',1]])->field('title,category_id')->select();
151
+        $field_list = [];
152
+        $field_list[0]['name'] = '员工';
153
+        $field_list[0]['field'] = 'realname';
154
+        $i = 1;
155
+        foreach ($category_list as $k=>$v) {
156
+            $field_list[$i]['name'] = strstr($v['title'],'审批') ? str_replace('审批','次数',$v['title']) : $v['title'].'次数';
157
+            $field_list[$i]['field'] = 'count_'.$v['category_id'];
158
+            $i++;
159
+        }
160
+        // 文件名
161
+        $file_name = '5kcrm_examine_'.date('Ymd');
162
+        $excelModel->dataExportCsv($file_name, $field_list, function($list) use ($param){
163
+            $examineModel = new \app\bi\model\Examine();
164
+            if ($param['type']) {
165
+                $timeArr = getTimeByType($param['type']);
166
+                $param['start_time'] = $timeArr[0];
167
+                $param['end_time'] = $timeArr[1];
168
+            }            
169
+            $list = $examineModel->getStatistics($param);
170
+            return $list['userList'];
171
+        });
172
+    }
173
+}

+ 93
- 0
application/bi/controller/Log.php Целия файл

@@ -0,0 +1,93 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 商业智能-日志分析
4
+// +----------------------------------------------------------------------
5
+// | Author: Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\bi\controller;
9
+
10
+use app\admin\controller\ApiCommon;
11
+use think\Db;
12
+use think\Hook;
13
+use think\Request;
14
+
15
+class Log extends ApiCommon
16
+{
17
+    /**
18
+     * 用于判断权限
19
+     * @permission 无限制
20
+     * @allow 登录用户可访问
21
+     * @other 其他根据系统设置
22
+    **/    
23
+    public function _initialize()
24
+    {
25
+        $action = [
26
+            'permission'=>[''],
27
+            'allow'=>['statistics','excelexport']     
28
+        ];
29
+        Hook::listen('check_auth',$action);
30
+        $request = Request::instance();
31
+        $a = strtolower($request->action());        
32
+        if (!in_array($a, $action['permission'])) {
33
+            parent::_initialize();
34
+        }
35
+        if (!checkPerByAction('bi', 'oa', 'read')) {
36
+            header('Content-Type:application/json; charset=utf-8');
37
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
38
+        }        
39
+    }
40
+
41
+    /**
42
+     * 日志统计列表
43
+     * @return 
44
+     */
45
+    public function statistics()
46
+    {  
47
+        $param  = $this->param;
48
+
49
+        if ($param['type']) {
50
+            $timeArr = getTimeByType($param['type']);
51
+            $param['start_time'] = $timeArr[0];
52
+            $param['end_time'] = $timeArr[1];
53
+        } else {
54
+            if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
55
+            if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
56
+        }
57
+        $loglModel = new \app\bi\model\Log();
58
+        $list = $loglModel->getStatistics($param) ? : [];
59
+        return resultArray(['data'=>$list]);
60
+    }
61
+
62
+    /**
63
+     * 统计导出
64
+     * @author Michael_xu
65
+     * @param 
66
+     * @return
67
+     */
68
+    public function excelExport()
69
+    {
70
+        $param = $this->param;
71
+        $excelModel = new \app\admin\model\Excel();
72
+        // 导出的字段列表
73
+        $field_list = [
74
+            '0' => ['field' => 'realname','name' => '员工'],
75
+            '1' => ['field' => 'count','name' => '填写数'],
76
+            '2' => ['field' => 'unReadCont','name' => '接收人未读数'],
77
+            '3' => ['field' => 'unCommentCount','name' => '未评论数'],
78
+            '4' => ['field' => 'commentCount','name' => '已评论数'],
79
+        ];
80
+        // 文件名
81
+        $file_name = '5kcrm_log_'.date('Ymd');
82
+        $excelModel->dataExportCsv($file_name, $field_list, function($list) use ($param){
83
+            $loglModel = new \app\bi\model\Log();
84
+            if ($param['type']) {
85
+                $timeArr = getTimeByType($param['type']);
86
+                $param['start_time'] = $timeArr[0];
87
+                $param['end_time'] = $timeArr[1];
88
+            }            
89
+            $list = $loglModel->getStatistics($param);
90
+            return $list ? : [];
91
+        });
92
+    }    
93
+}

+ 150
- 0
application/bi/controller/Product.php Целия файл

@@ -0,0 +1,150 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 商业智能-产品分析
4
+// +----------------------------------------------------------------------
5
+// | Author: Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\bi\controller;
9
+
10
+use app\admin\controller\ApiCommon;
11
+use think\Db;
12
+use think\Hook;
13
+use think\Request;
14
+use app\bi\logic\ExcelLogic;
15
+
16
+class Product extends ApiCommon
17
+{
18
+    /**
19
+     * 用于判断权限
20
+     * @permission 无限制
21
+     * @allow 登录用户可访问
22
+     * @other 其他根据系统设置
23
+     **/
24
+    public function _initialize()
25
+    {
26
+        $action = [
27
+            'permission' => [''],
28
+            'allow' => ['statistics', 'productcategory', 'excelexport']
29
+        ];
30
+        Hook::listen('check_auth', $action);
31
+        $request = Request::instance();
32
+        $a = strtolower($request->action());
33
+        if (!in_array($a, $action['permission'])) {
34
+            parent::_initialize();
35
+        }
36
+        if (!checkPerByAction('bi', 'product', 'read')) {
37
+            header('Content-Type:application/json; charset=utf-8');
38
+            exit(json_encode(['code' => 102, 'error' => '无权操作']));
39
+        }
40
+    }
41
+
42
+    /**
43
+     * 产品销量统计
44
+     *
45
+     * @param string $param
46
+     * @return mixed|\think\response\Json
47
+     * @throws \think\db\exception\DataNotFoundException
48
+     * @throws \think\db\exception\ModelNotFoundException
49
+     * @throws \think\exception\DbException
50
+     */
51
+    public function statistics($param = '')
52
+    {
53
+        $productModel = new \app\crm\model\Product();
54
+        if($param['excel_type']!=1){
55
+            $param = $this->param;
56
+        }
57
+
58
+        if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
59
+        if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
60
+
61
+        $list = $productModel->getStatistics($param);
62
+
63
+        //导出使用
64
+        if (!empty($param['excel_type'])) {
65
+            return $list;
66
+        }
67
+        return resultArray(['data' => $list]);
68
+    }
69
+
70
+    /**
71
+     * 产品分类销量分析
72
+     *
73
+     * @return \think\response\Json
74
+     * @throws \think\db\exception\DataNotFoundException
75
+     * @throws \think\db\exception\ModelNotFoundException
76
+     * @throws \think\exception\DbException
77
+     */
78
+    public function productCategory()
79
+    {
80
+        $param = $this->param;
81
+
82
+        $productModel = new \app\bi\model\Product();
83
+
84
+        if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
85
+        if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
86
+
87
+        $list = $productModel->getStatistics($param);
88
+
89
+        return resultArray(['data' => $list]);
90
+    }
91
+
92
+    /**
93
+     * 导出
94
+     *
95
+     * @return mixed
96
+     * @throws \think\db\exception\DataNotFoundException
97
+     * @throws \think\db\exception\ModelNotFoundException
98
+     * @throws \think\exception\DbException
99
+     */
100
+    public function excelExport()
101
+    {
102
+        $param = $this->param;
103
+        $list = $this->statistics($param);
104
+        $data = [];
105
+        $subtotalCount = [];
106
+        $sumCount = [];
107
+        $item = [];
108
+        $unm = 0;
109
+        $subtotal = 0;
110
+        $res = [];
111
+        foreach ($list as $val) {
112
+            $res[] = $val['product_id'];
113
+            $data[$val['product_id']][] = $val;
114
+        }
115
+        $res = array_unique($res);
116
+        foreach ($res as $e) {
117
+            foreach ($list as $v) {
118
+                if ($e == $v['product_id']) {
119
+                    $unm += $v['num'];
120
+                    $subtotal += $v['subtotal'];
121
+                    $sumCount[$e] = $unm + $v['num'];
122
+                    $subtotalCount[$e] = (float)$subtotal + $v['subtotal'];
123
+                }
124
+            }
125
+            $item[$e][] = [
126
+                'type' => '',
127
+                'category_id_info' => '',
128
+                'product_name' => '',
129
+                'contract_name' => '',
130
+                'realname' => '',
131
+                'name' => '',
132
+                'price' => '合计',
133
+                'num' => $sumCount[$e],
134
+                'subtotal' => $subtotalCount[$e],
135
+            ];
136
+        }
137
+        $items = [];
138
+        foreach ($data as $key => $value) {
139
+            $items[] = array_merge($data[$key], $item[$key]);
140
+        }
141
+        foreach ($items as $u) {
142
+            foreach ($u as $d) {
143
+                $field[] = $d;
144
+            }
145
+        }
146
+        $excelLogic = new ExcelLogic();
147
+        $data = $excelLogic->productExcel($param, $field);
148
+        return $data;
149
+    }
150
+}

+ 565
- 0
application/bi/controller/Ranking.php Целия файл

@@ -0,0 +1,565 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 商业智能-排行榜
4
+// +----------------------------------------------------------------------
5
+// | Author: Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\bi\controller;
9
+
10
+use app\admin\controller\ApiCommon;
11
+use app\bi\traits\SortTrait;
12
+use think\Hook;
13
+use think\Request;
14
+use think\Db;
15
+use app\bi\model\Customer as CustomerModel;
16
+use app\bi\model\Contract as ContractModel;
17
+use app\bi\logic\ExcelLogic;
18
+
19
+class Ranking extends ApiCommon
20
+{
21
+    use SortTrait;
22
+
23
+    /**
24
+     * 用于判断权限
25
+     * @permission 无限制
26
+     * @allow 登录用户可访问
27
+     * @other 其他根据系统设置
28
+     **/
29
+    public function _initialize()
30
+    {
31
+        $action = [
32
+            'permission' => [''],
33
+            'allow' => [
34
+                'contract',
35
+                'receivables',
36
+                'signing',
37
+                'addcustomer',
38
+                'addcontacts',
39
+                'recordnun',
40
+                'recordcustomer',
41
+                'examine',
42
+                'product',
43
+                'excelexport'
44
+            ]
45
+        ];
46
+        Hook::listen('check_auth', $action);
47
+        $request = Request::instance();
48
+        $a = strtolower($request->action());
49
+        if (!in_array($a, $action['permission'])) {
50
+            parent::_initialize();
51
+        }
52
+        if (!checkPerByAction('bi', 'ranking', 'read')) {
53
+            header('Content-Type:application/json; charset=utf-8');
54
+            exit(json_encode(['code' => 102, 'error' => '无权操作']));
55
+        }
56
+    }
57
+
58
+    /**
59
+     * 合同金额排行
60
+     * @param
61
+     * @return
62
+     * @author Michael_xu
63
+     */
64
+    public function contract($param = '')
65
+    {
66
+        if($param['excel_type']!=1){
67
+            $param = $this->param;
68
+        }
69
+
70
+        if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
71
+        if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
72
+
73
+        $whereArr = $this->com($param, 'contract');
74
+        $whereArr['check_status'] = 2;
75
+
76
+        //导出使用
77
+        if (!empty($param['excel_type'])) return $this->handel(
78
+            new \app\bi\model\Contract,
79
+            $whereArr,
80
+            ['field' => 'SUM(`money`)', 'alias' => 'money', 'default' => '0.00'],
81
+            $param['excel_type']
82
+        );
83
+        return $this->handel(
84
+            new \app\bi\model\Contract,
85
+            $whereArr,
86
+            ['field' => 'SUM(`money`)', 'alias' => 'money', 'default' => '0.00']
87
+        );
88
+    }
89
+
90
+    /**
91
+     * 回款金额排序
92
+     * @return
93
+     */
94
+    public function receivables($param = '')
95
+    {
96
+        if($param['excel_type']!=1){
97
+            $param = $this->param;
98
+        }
99
+        if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
100
+        if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
101
+        $whereArr = $this->com($param, 'receivables');
102
+        $whereArr['check_status'] = 2;
103
+
104
+        //导出使用
105
+        if (!empty($param['excel_type'])) return $this->handel(
106
+            new \app\bi\model\Receivables,
107
+            $whereArr,
108
+            ['field' => 'SUM(`money`)', 'alias' => 'money', 'default' => '0.00'],
109
+            $param['excel_type']
110
+        );
111
+        return $this->handel(
112
+            new \app\bi\model\Receivables,
113
+            $whereArr,
114
+            ['field' => 'SUM(`money`)', 'alias' => 'money', 'default' => '0.00']
115
+        );
116
+    }
117
+
118
+    /**
119
+     * 签约合同排序
120
+     * @return
121
+     */
122
+    public function signing($param = '')
123
+    {
124
+        if($param['excel_type']!=1){
125
+            $param = $this->param;
126
+        }
127
+        if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
128
+        if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
129
+        $whereArr = $this->com($param, 'contract');
130
+        $whereArr['check_status'] = 2;
131
+
132
+        //导出使用
133
+        if (!empty($param['excel_type'])) $this->handel(
134
+            new ContractModel,
135
+            $whereArr,
136
+            ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0],
137
+            $param['excel_type']
138
+        );
139
+        return $this->handel(
140
+            new ContractModel,
141
+            $whereArr,
142
+            ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0]
143
+        );
144
+    }
145
+
146
+    /**
147
+     * 新增客户排序
148
+     * @return
149
+     */
150
+    public function addCustomer($param = '')
151
+    {
152
+        if($param['excel_type']!=1){
153
+            $param = $this->param;
154
+        }
155
+        if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
156
+        if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
157
+        $whereArr = $this->com($param, 'customer');
158
+
159
+        $poolWhere = $this->getWhereByPool();
160
+        $poolId    = db('crm_customer')->alias('customer')->where($poolWhere)->column('customer_id');
161
+        if (!empty($poolId)) $whereArr['customer_id'] = ['notin', $poolId];
162
+
163
+        //导出使用
164
+        if (!empty($param['excel_type'])) return $this->handel(
165
+            new \app\bi\model\Customer,
166
+            $whereArr,
167
+            ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0],
168
+            $param['excel_type']
169
+        );
170
+        return $this->handel(
171
+            new \app\bi\model\Customer,
172
+            $whereArr,
173
+            ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0]
174
+        );
175
+    }
176
+
177
+    /**
178
+     * 新增联系人排序
179
+     * @return
180
+     */
181
+    public function addContacts()
182
+    {
183
+        $param = $this->param;
184
+        if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
185
+        if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
186
+        $whereArr = $this->com($param, 'contacts');
187
+
188
+        //导出使用
189
+        if (!empty($param['excel_type'])) return $this->handel(
190
+            new \app\bi\model\Contacts,
191
+            $whereArr,
192
+            ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0],
193
+            $param['excel_type']
194
+        );
195
+        return $this->handel(
196
+            new \app\bi\model\Contacts,
197
+            $whereArr,
198
+            ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0]
199
+        );
200
+    }
201
+
202
+    /**
203
+     * 跟进次数排行
204
+     *
205
+     * @param string $param
206
+     * @return array|\think\response\Json
207
+     * @throws \think\db\exception\DataNotFoundException
208
+     * @throws \think\db\exception\ModelNotFoundException
209
+     * @throws \think\exception\DbException
210
+     */
211
+    public function recordNun($param = '')
212
+    {
213
+        if($param['excel_type']!=1){
214
+            $param = $this->param;
215
+        }
216
+        if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
217
+        if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
218
+        $whereArr = $this->com($param, 'record');
219
+
220
+        # 权限内的员工列表
221
+        $userData = [];
222
+        $userList = db('admin_user')->alias('user')
223
+                    ->field(['user.id', 'user.realname AS user_name', 'structure.name AS structure_name'])
224
+                    ->join('__ADMIN_STRUCTURE__ structure', 'structure.id = user.structure_id')
225
+                    ->whereIn('user.id', $whereArr['create_user_id'][1])->select();
226
+        foreach ($userList AS $key => $value) {
227
+            $userData[$value['id']]['user_name']      = $value['user_name'];
228
+            $userData[$value['id']]['structure_name'] = $value['structure_name'];
229
+        }
230
+
231
+        # 跟进记录列表
232
+        $data = [];
233
+        $recordWhere['type']           = 1;
234
+        $recordWhere['activity_type']  = 2;
235
+        $recordWhere['create_user_id'] = ['in', $whereArr['create_user_id'][1]];
236
+        $recordWhere['create_time']    = ['between', [$whereArr['create_time'][1][0], $whereArr['create_time'][1][1]]];
237
+        $recordList = db('crm_activity')->field(['count(*) as count', 'create_user_id'])->where($recordWhere)
238
+            ->group('create_user_id')->order('count', 'desc')->select();
239
+
240
+        foreach ($recordList AS $key => $value) {
241
+            $data[] = [
242
+                'count'          => $value['count'],
243
+                'user_name'      => $userData[$value['create_user_id']]['user_name'],
244
+                'structure_name' => $userData[$value['create_user_id']]['structure_name']
245
+            ];
246
+        }
247
+
248
+        //导出使用
249
+        if (!empty($param['excel_type'])) return $data;
250
+
251
+        return resultArray(['data' => $data]);
252
+    }
253
+
254
+    /**
255
+     * 跟进客户数排行
256
+     *
257
+     * @param string $param
258
+     * @return mixed|\think\response\Json
259
+     * @throws \think\db\exception\DataNotFoundException
260
+     * @throws \think\db\exception\ModelNotFoundException
261
+     * @throws \think\exception\DbException
262
+     */
263
+    public function recordCustomer($param = '')
264
+    {
265
+        if($param['excel_type']!=1){
266
+            $param = $this->param;
267
+        }
268
+        if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
269
+        if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
270
+        $whereArr = $this->com($param, 'record');
271
+
272
+        # 权限内的员工列表
273
+        $userData = [];
274
+        $userList = db('admin_user')->alias('user')
275
+            ->field(['user.id', 'user.realname AS user_name', 'structure.name AS structure_name'])
276
+            ->join('__ADMIN_STRUCTURE__ structure', 'structure.id = user.structure_id')
277
+            ->whereIn('user.id', $whereArr['create_user_id'][1])->select();
278
+        foreach ($userList AS $key => $value) {
279
+            $userData[$value['id']]['user_name']      = $value['user_name'];
280
+            $userData[$value['id']]['structure_name'] = $value['structure_name'];
281
+        }
282
+
283
+        # 跟进记录列表
284
+        $data = [];
285
+        $recordWhere['type']           = 1;
286
+        $recordWhere['activity_type']  = 2;
287
+        $recordWhere['create_user_id'] = ['in', $whereArr['create_user_id'][1]];
288
+        $recordWhere['create_time']    = ['between', [$whereArr['create_time'][1][0], $whereArr['create_time'][1][1]]];
289
+        $recordList = db('crm_activity')->field(['create_user_id', 'activity_type_id'])->where($recordWhere)
290
+            ->group('create_user_id, activity_type_id')->select();
291
+
292
+        foreach ($recordList AS $key => $value) {
293
+            if (empty($data[$value['create_user_id']]['user_name'])) {
294
+                $data[$value['create_user_id']]['user_name']      = $userData[$value['create_user_id']]['user_name'];
295
+                $data[$value['create_user_id']]['structure_name'] = $userData[$value['create_user_id']]['structure_name'];
296
+                $data[$value['create_user_id']]['count']          = 1;
297
+            } else {
298
+                $data[$value['create_user_id']]['count'] = $data[$value['create_user_id']]['count'] + 1;
299
+            }
300
+        }
301
+
302
+        $data = $this->sortCommon($data, 'count', 'desc');
303
+
304
+        //导出使用
305
+        if (!empty($param['excel_type'])) return $data;
306
+
307
+        return resultArray(['data' => $data]);
308
+    }
309
+
310
+    /**
311
+     * 出差次数排行
312
+     * @return
313
+     */
314
+    public function examine($param = '')
315
+    {
316
+        if($param['excel_type']!=1){
317
+            $param = $this->param;
318
+        }
319
+        if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
320
+        if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
321
+        $whereArr = $this->com($param, 'record');
322
+        $whereArr['category_id'] = 3; // 审批类型,3出差
323
+        $whereArr['check_status'] = 2;
324
+
325
+        //导出使用
326
+        if (!empty($param['excel_type'])) return $this->handel(
327
+            new \app\bi\model\Examine,
328
+            $whereArr,
329
+            ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0],
330
+            $param['excel_type'],
331
+            'create_user_id'
332
+        );
333
+
334
+        return $this->handel(
335
+            new \app\bi\model\Examine,
336
+            $whereArr,
337
+            ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0],
338
+            '',
339
+            'create_user_id'
340
+        );
341
+    }
342
+
343
+    /**
344
+     * 产品销量排行
345
+     * @return
346
+     */
347
+    public function product($param = '')
348
+    {
349
+        $userModel = new \app\admin\model\User();
350
+        $productModel = new \app\bi\model\Product();
351
+        if($param['excel_type']!=1){
352
+            $param = $this->param;
353
+        }
354
+        if (!empty($param['start_time'])) $param['start_time'] = strtotime($param['start_time'] . ' 00:00:00');
355
+        if (!empty($param['end_time']))   $param['end_time']   = strtotime($param['end_time'] . ' 23:59:59');
356
+        $list = $productModel->getSortByProduct($param);
357
+        $list = array_column($list, null, 'owner_user_id');
358
+
359
+        $whereArr = $this->com($param, 'contract');
360
+
361
+        $data = [];
362
+        foreach ($whereArr['owner_user_id'][1] as $val) {
363
+            $user = $userModel->getUserById($val);
364
+            $item = [];
365
+            $item['num'] = !empty($list[$val]['num']) ? (int)$list[$val]['num'] : 0;
366
+            $item['user_name'] = $user['realname'];
367
+            $item['structure_name'] = $user['structure_name'];
368
+            $data[] = $item;
369
+        }
370
+
371
+        # 排序
372
+        if (!empty($data)) $data = $this->sortCommon($data, 'num', 'desc');
373
+        //导出使用
374
+        if (!empty($param['excel_type'])) return $data;
375
+
376
+        return resultArray(['data' => $data]);
377
+    }
378
+
379
+    /**
380
+     * 查询条件
381
+     * @return
382
+     */
383
+    private function com($param, $type = '')
384
+    {
385
+        $userModel = new \app\admin\model\User();
386
+        $adminModel = new \app\admin\model\Admin();
387
+        $perUserIds = $userModel->getUserByPer('bi', 'ranking', 'read'); //权限范围内userIds
388
+        $whereData = $adminModel->getWhere($param, '', $perUserIds); //统计条件
389
+        $userIds = $whereData['userIds'];
390
+        $between_time = $whereData['between_time'];
391
+        if ($type == 'contract') {
392
+            $where_time = 'order_date';
393
+        } elseif (in_array($type, ['record', 'customer', 'contacts'])) {
394
+            $where_time = 'create_time';
395
+        } elseif ($type == 'receivables') {
396
+            $where_time = 'return_time';
397
+        } else {
398
+            $where_time = 'start_time';
399
+        }
400
+        //时间戳:新增客户排行
401
+        if ($type == 'contract' || $type == 'receivables') {
402
+            $whereArr[$where_time] = array('between', array(date('Y-m-d', $between_time[0]), date('Y-m-d', $between_time[1])));
403
+        } else {
404
+            $whereArr[$where_time] = array('between', array($between_time[0], $between_time[1]));
405
+        }
406
+
407
+        if (in_array($type, ['customer', 'contract', 'receivables', 'contacts'])) {
408
+            $whereArr['owner_user_id'] = ['IN', $userIds];
409
+        } else {
410
+            $whereArr['create_user_id'] = ['IN', $userIds];
411
+        }
412
+
413
+        return $whereArr;
414
+    }
415
+
416
+    /**
417
+     * 查询统计数据
418
+     *
419
+     * @param model $model
420
+     * @param array $whereArr
421
+     * @return void
422
+     * @author Ymob
423
+     * @datetime 2019-11-25 11:11:59
424
+     */
425
+    private function handel($model, $whereArr, $field, $excel_type = '', $user_field = 'owner_user_id')
426
+    {
427
+        $userModel = new \app\admin\model\User();
428
+        $sql = $model->field([
429
+            $user_field,
430
+            $field['field'] => $field['alias']
431
+        ])
432
+            ->where($whereArr)
433
+            ->group($user_field)
434
+            ->fetchSql()
435
+            ->select();
436
+
437
+        $list = queryCache($sql);
438
+        $list = array_column($list, null, $user_field);
439
+        $data = [];
440
+
441
+        foreach ($whereArr[$user_field][1] as $val) {
442
+            $user = $userModel->getUserById($val);
443
+            $item = [];
444
+            $item[$field['alias']] = $list[$val][$field['alias']] ?: $field['default'];
445
+            $item['user_name'] = $user['realname'];
446
+            $item['structure_name'] = $user['structure_name'];
447
+            $data[] = $item;
448
+        }
449
+        array_multisort($data, SORT_DESC, array_column($data, $field['alias']));
450
+        if (!empty($excel_type)) return $data;
451
+
452
+        return resultArray(['data' => $data]);
453
+    }
454
+
455
+    /**
456
+     * 导出
457
+     * @param $type
458
+     * @param $types
459
+     */
460
+    public function excelExport()
461
+    {
462
+        $param = $this->param;
463
+        $excel_type = $param['excel_type'];
464
+        $type = [];
465
+        $type['excel_types'] = $param['excel_types'];
466
+        switch ($param['excel_types']) {
467
+            case 'contract':
468
+                $list = $this->contract($param);
469
+
470
+                foreach ($list as $key => $v) {
471
+                    $list[$key]['id'] = $key + 1;
472
+                }
473
+                $type['type'] = '合同金额排行';
474
+                break;
475
+            case'receivables':
476
+                $list = $this->receivables($param);
477
+                $type['type'] = '回款金额排行';
478
+                break;
479
+            case 'signing':
480
+                $list = $this->signing($param);
481
+                $type['type'] = '签约合同排行';
482
+                break;
483
+            case 'product':
484
+                $list = $this->product($param);
485
+                $type['type'] = '产品销量排行';
486
+                break;
487
+            case 'addCustomer':
488
+                $list = $this->addCustomer($param);
489
+                $type['type'] = '新增客户数排行';
490
+                break;
491
+            case 'addContacts':
492
+                $list = $this->addContacts($param);
493
+                $type['type'] = '新增联系人数排行';
494
+                break;
495
+            case 'recordNun':
496
+                $list = $this->recordNun($param);
497
+                $type['type'] = '跟进次数排行';
498
+                break;
499
+            case 'recordCustomer':
500
+                $list = $this->recordCustomer($param);
501
+                $type['type'] = '跟进客户数排行';
502
+                break;
503
+            case 'examine':
504
+                $list = $this->examine($param);
505
+                $type['type'] = '出差次数排行';
506
+                break;
507
+        }
508
+        if(empty($list)){
509
+            return resultArray(['data'=>'数据不存在']);
510
+        }
511
+        $excelLogic = new ExcelLogic();
512
+        $data = $excelLogic->rankingExcle($param, $list);
513
+        return $data;
514
+    }
515
+
516
+    /**
517
+     * [客户公海条件]
518
+     * @author Michael_xu
519
+     * @param
520
+     * @return
521
+     */
522
+    public function getWhereByPool()
523
+    {
524
+        $configModel = new \app\crm\model\ConfigData();
525
+        $configInfo = $configModel->getData();
526
+        $config = $configInfo['config'] ? : 0;
527
+        $follow_day = $configInfo['follow_day'] ? : 0;
528
+        $deal_day = $configInfo['deal_day'] ? : 0;
529
+        $whereData = [];
530
+        //启用
531
+        if ($config == 1) {
532
+            //默认公海条件(没有负责人或已经到期)
533
+            $data['follow_time'] = time()-$follow_day*86400;
534
+            $data['deal_time'] = time()-$deal_day*86400;
535
+            $data['deal_status'] = '未成交';
536
+            if ($follow_day < $deal_day) {
537
+                $whereData = function($query) use ($data){
538
+                    $query->where(['customer.owner_user_id'=>0])
539
+                        ->whereOr(function ($query) use ($data) {
540
+                            $query->where(function ($query) use ($data) {
541
+                                $query->where(['customer.update_time' => array('elt',$data['follow_time'])])
542
+                                    ->whereOr(['customer.deal_time' => array('elt',$data['deal_time'])]);
543
+                            })
544
+                                ->where(['customer.is_lock' => 0])
545
+                                ->where(['customer.deal_status' => ['neq','已成交']]);
546
+                        });
547
+                };
548
+            } else {
549
+                $whereData = function($query) use ($data){
550
+                    $query->where(['customer.owner_user_id'=>0])
551
+                        ->whereOr(function ($query) use ($data) {
552
+                            $query->where(function ($query) use ($data) {
553
+                                $query->where(['customer.deal_time' => array('elt',$data['deal_time'])]);
554
+                            })
555
+                                ->where(['customer.is_lock' => 0])
556
+                                ->where(['customer.deal_status' => ['neq','已成交']]);
557
+                        });
558
+                };
559
+            }
560
+        } else {
561
+            $whereData['customer.owner_user_id'] = 0;
562
+        }
563
+        return $whereData ? : '';
564
+    }
565
+}

+ 90
- 0
application/bi/controller/Receivables.php Целия файл

@@ -0,0 +1,90 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 商业智能-回款分析
4
+// +----------------------------------------------------------------------
5
+// | Author: Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\bi\controller;
9
+
10
+use app\admin\controller\ApiCommon;
11
+use think\Hook;
12
+use think\Request;
13
+
14
+class Receivables extends ApiCommon
15
+{
16
+    /**
17
+     * 用于判断权限
18
+     * @permission 无限制
19
+     * @allow 登录用户可访问
20
+     * @other 其他根据系统设置
21
+    **/    
22
+    public function _initialize()
23
+    {
24
+        $action = [
25
+            'permission'=>[''],
26
+            'allow'=>['statistics','statisticlist']            
27
+        ];
28
+        Hook::listen('check_auth',$action);
29
+        $request = Request::instance();
30
+        $a = strtolower($request->action());        
31
+        if (!in_array($a, $action['permission'])) {
32
+            parent::_initialize();
33
+        }
34
+        if (!checkPerByAction('bi', 'receivables' , 'read')) {
35
+            header('Content-Type:application/json; charset=utf-8');
36
+            exit(json_encode(['code'=>102,'error'=>'无权操作']));
37
+        }         
38
+    } 
39
+  
40
+    //回款统计列表
41
+    public function statisticList()
42
+    {
43
+        $receivablesModel = new \app\crm\model\Receivables();
44
+        $param = $this->param;
45
+        $ret = $receivablesModel->getstatisticsData($param);
46
+        return resultArray(['data'=>$ret]);
47
+    }
48
+
49
+    /**
50
+     * 回款统计 柱状图
51
+     * @author Michael_xu
52
+     * @param year 年份 , month 月份
53
+     * @return
54
+     */
55
+    public function statistics()
56
+    {        
57
+        $receivablesModel = new \app\crm\model\Receivables();
58
+        $userModel = new \app\admin\model\User();
59
+        $param = $this->param;
60
+        $adminModel = new \app\admin\model\Admin(); 
61
+        $perUserIds = $userModel->getUserByPer('bi', 'receivables', 'read'); //权限范围内userIds
62
+        $whereData = $adminModel->getWhere($param, '', $perUserIds); //统计条件
63
+        $userIds = $whereData['userIds'];       
64
+
65
+        $year = $param['year'];
66
+        //时间段
67
+        if ($param['month']) {
68
+            //根据月份计算天数
69
+            $days = getmonthdays(strtotime($param['month']));
70
+            //获取时间范围内的每日时间戳数组(当月)
71
+            $start = strtotime($param['month'].'-'.'01');
72
+            $end = (strtotime($param['month'].'-'.$days) > time()) ? time() : strtotime($date.'-'.$days);
73
+            $create_time = array($start,$end);
74
+        } elseif ($param['year']) {
75
+            $next_year = $param['year']+1;
76
+            $create_time = array(strtotime($param['year'].'-01-01'),strtotime($next_year.'-01-01'));
77
+        } else {
78
+            $create_time = getTimeByType('year');
79
+        }
80
+        unset($param['month']);
81
+        unset($param['year']); 
82
+        $param['create_time']['start'] = $create_time[0];
83
+        $param['create_time']['end'] = $create_time[1];     
84
+        $chartParam = $param;
85
+        $chartParam['year'] = $year;
86
+        $chartParam['userIds'] = $userIds ? : [];
87
+        $chartList = $receivablesModel->getStatistics($chartParam); //柱状图
88
+        return resultArray(['data' => $chartList]);
89
+    }
90
+}

+ 5
- 0
application/bi/lang/en-us.php Целия файл

@@ -0,0 +1,5 @@
1
+<?php
2
+return [
3
+     'hello thinkphp'  => 'hello thinkphp',
4
+     'data type error' => 'data type error',
5
+];

+ 4
- 0
application/bi/lang/zh-cn.php Целия файл

@@ -0,0 +1,4 @@
1
+<?php
2
+return [
3
+    'CUSTOMER' => '客户', 
4
+];

+ 145
- 0
application/bi/logic/BiCustomerLogic.php Целия файл

@@ -0,0 +1,145 @@
1
+<?php
2
+/**
3
+ * 员工客户分析逻辑类
4
+ *
5
+ * @author qifan
6
+ * @date 2020-12-24
7
+ */
8
+
9
+namespace app\bi\logic;
10
+
11
+use app\bi\traits\SortTrait;
12
+use think\Db;
13
+
14
+class BiCustomerLogic
15
+{
16
+    use SortTrait;
17
+
18
+    /**
19
+     * 员工客户满意度分析
20
+     *
21
+     * @param $param
22
+     * @return array
23
+     * @throws \think\db\exception\DataNotFoundException
24
+     * @throws \think\db\exception\ModelNotFoundException
25
+     * @throws \think\exception\DbException
26
+     */
27
+    public function getCustomerSatisfaction($param)
28
+    {
29
+        $result = [];
30
+
31
+        $userModel = new \app\admin\model\User();
32
+
33
+        $perUserIds = $userModel->getUserByPer('bi', 'customer', 'read'); # 权限范围内userIds
34
+        $userIds    = $perUserIds; # 数组交集
35
+        if (empty($userIds)) return [];
36
+
37
+        # 员工信息
38
+        $userList = db('admin_user')->field(['id', 'realname'])->whereIn('id', $userIds)->select();
39
+        foreach ($userList AS $key => $value) {
40
+            $result[$value['id']] = [
41
+                'realname' => $value['realname'],
42
+                'visitContractNum' => 0,
43
+                '很满意' => 0,
44
+                '满意' => 0,
45
+                '一般' => 0,
46
+                '不满意' => 0,
47
+                '很不满意' => 0,
48
+            ];
49
+        }
50
+
51
+        $visitField = ['owner_user_id', 'satisfaction', 'count(`satisfaction`) AS satisfactionCount', 'count(`contract_id`) AS contractCount'];
52
+        $where['owner_user_id'] = ['in', $userIds];
53
+        $where['create_time']   = ['between', [$param['start_time'], $param['end_time']]];
54
+        $where['deleted_state'] = 0;
55
+        $visitList = db('crm_visit')->field($visitField)->where($where)->group('owner_user_id, satisfaction')->select();
56
+        foreach ($visitList AS $key => $value) {
57
+            if (!empty($value['satisfaction']) && trim($value['satisfaction']) == '很满意') {
58
+                $result[$value['owner_user_id']]['很满意'] += $value['satisfactionCount'];
59
+            }
60
+            if (!empty($value['satisfaction']) && trim($value['satisfaction']) == '满意') {
61
+                $result[$value['owner_user_id']]['满意'] += $value['satisfactionCount'];
62
+            }
63
+            if (!empty($value['satisfaction']) && trim($value['satisfaction']) == '一般') {
64
+                $result[$value['owner_user_id']]['一般'] += $value['satisfactionCount'];
65
+            }
66
+            if (!empty($value['satisfaction']) && trim($value['satisfaction']) == '不满意') {
67
+                $result[$value['owner_user_id']]['不满意'] += $value['satisfactionCount'];
68
+            }
69
+            if (!empty($value['satisfaction']) && trim($value['satisfaction']) == '很不满意') {
70
+                $result[$value['owner_user_id']]['很不满意'] += $value['satisfactionCount'];
71
+            }
72
+            $result[$value['owner_user_id']]['visitContractNum'] += $value['contractCount'];
73
+        }
74
+
75
+        $result = $this->sortCommon($result, 'visitContractNum', 'desc');
76
+
77
+        return array_values($result);
78
+    }
79
+
80
+    /**
81
+     * 产品满意度分析
82
+     *
83
+     * @param $param
84
+     * @return array
85
+     * @throws \think\db\exception\DataNotFoundException
86
+     * @throws \think\db\exception\ModelNotFoundException
87
+     * @throws \think\exception\DbException
88
+     */
89
+    public function getProductSatisfaction($param)
90
+    {
91
+        $productData = [];
92
+
93
+        $userModel = new \app\admin\model\User();
94
+
95
+        $perUserIds = $userModel->getUserByPer('bi', 'customer', 'read'); # 权限范围内userIds
96
+        $userIds    = !empty($param['user_id']) ? array_intersect([$param['user_id']], $perUserIds) : $perUserIds; # 数组交集
97
+        if (empty($userIds)) return [];
98
+
99
+        # 产品列表(上架中)
100
+        $productList = db('crm_product')->field(['product_id', 'name'])->where('status', '上架')->select();
101
+        foreach ($productList AS $key => $value) {
102
+            $productData[$value['product_id']] = [
103
+                'productName' => $value['name'],
104
+                'visitNum' => 0,
105
+                '很满意' => 0,
106
+                '满意' => 0,
107
+                '一般' => 0,
108
+                '不满意' => 0,
109
+                '很不满意' => 0,
110
+            ];
111
+        }
112
+
113
+        # 回访条件
114
+        $where['visit.owner_user_id'] = ['in', $userIds];
115
+        $where['visit.create_time']   = ['between', [$param['start_time'], $param['end_time']]];
116
+        $where['visit.deleted_state'] = 0;
117
+
118
+        # 回访数据
119
+        $visitList = db('crm_visit')->alias('visit')->field(['visit.contract_id', 'visit.satisfaction'])
120
+                    ->join('__CRM_CONTRACT__ contract', 'contract.contract_id = visit.contract_id')
121
+                    ->where($where)->select();
122
+
123
+        # 整理数据
124
+        foreach ($visitList AS $key => $value) {
125
+            if (empty($value['satisfaction'])) continue;
126
+
127
+            $productIds = db('crm_contract_product')->where('contract_id', $value['contract_id'])->column('product_id');
128
+            foreach ($productIds AS $k => $v) {
129
+                if ($productData[$v]) {
130
+                    if (trim($value['satisfaction']) == '很满意') $productData[$v]['很满意']++;
131
+                    if (trim($value['satisfaction']) == '满意') $productData[$v]['满意']++;
132
+                    if (trim($value['satisfaction']) == '一般') $productData[$v]['一般']++;
133
+                    if (trim($value['satisfaction']) == '不满意') $productData[$v]['不满意']++;
134
+                    if (trim($value['satisfaction']) == '很不满意') $productData[$v]['很不满意']++;
135
+
136
+                    $productData[$v]['visitNum']++;
137
+                }
138
+            }
139
+        }
140
+
141
+        $productData = $this->sortCommon($productData, 'visitNum', 'desc');
142
+
143
+        return array_values($productData);
144
+    }
145
+}

+ 300
- 0
application/bi/logic/ExcelLogic.php Целия файл

@@ -0,0 +1,300 @@
1
+<?php
2
+
3
+namespace app\bi\logic;
4
+
5
+class ExcelLogic
6
+{
7
+    /**
8
+     * 员工客户分析导出
9
+     * @param $type
10
+     * @param $param
11
+     * @return mixed
12
+     */
13
+    public function biexcle($type, $param)
14
+    {
15
+        $excelModel = new \app\admin\model\Excel();
16
+        $file_name='';
17
+        $field_list=[];
18
+        switch ($type['excel_types']) {
19
+            case 'statistics':
20
+                $file_name = 'totalCustomerTable';
21
+                $field_list = [
22
+                    '0' => ['name' => '员工姓名', 'field' => 'realname'],
23
+                    '1' => ['name' => '新增客户数', 'field' => 'customer_num'],
24
+                    '2' => ['name' => '成交客户数', 'field' => 'deal_customer_num'],
25
+                    '3' => ['name' => '客户成交率', 'field' => 'deal_customer_rate'],
26
+                    '4' => ['name' => '合同总金额', 'field' => 'un_receivables_money'],
27
+                    '5' => ['name' => '回款金额', 'field' => 'receivables_money'],
28
+                ];
29
+                break;
30
+            case 'recordList':
31
+                $file_name = 'customerRecordInfo';
32
+                $field_list = [
33
+                    '0' => ['name' => '员工姓名', 'field' => 'realname'],
34
+                    '1' => ['name' => '跟进次数', 'field' => 'record_num'],
35
+                    '2' => ['name' => '跟进客户数', 'field' => 'customer_num'],
36
+                ];
37
+                break;
38
+            case 'recordMode':
39
+                $file_name = 'customerRecordCategoryStats';
40
+                $field_list = [
41
+                    '0' => ['name' => '员工姓名', 'field' => 'realname'],
42
+                    '1' => ['name' => '跟进次数', 'field' => 'record_num'],
43
+                    '2' => ['name' => '跟进客户数', 'field' => 'customer_num'],
44
+                ];
45
+                break;
46
+            case 'poolList':
47
+                $file_name = 'poolTable';
48
+                $field_list = [
49
+                    '0' => ['name' => '员工姓名', 'field' => 'realname'],
50
+                    '1' => ['name' => '部门', 'field' => 'username'],
51
+                    '2' => ['name' => '公海池领取客户数', 'field' => 'receive'],
52
+                    '3' => ['name' => '进入公海客户数', 'field' => 'put_in'],
53
+                ];
54
+                break;
55
+            case 'userCycle':
56
+                $file_name = 'employeeCycleInfo';
57
+                $field_list = [
58
+                    '0' => ['name' => '员工姓名', 'field' => 'realname'],
59
+                    '1' => ['name' => '成交周期(天)', 'field' => 'cycle'],
60
+                    '2' => ['name' => '成交客户数', 'field' => 'customer_num'],
61
+                ];
62
+                break;
63
+            case 'customerSatisfaction':
64
+                $file_name = 'customerSatisfaction';
65
+                $field_list = [
66
+                    '0' => ['name' => '员工姓名', 'field' => 'realname'],
67
+                    '1' => ['name' => '回访合同总数', 'field' => 'visit'],
68
+                    '2' => ['name' => '很满意', 'field' => 'satisfaction1'],
69
+                    '3' => ['name' => '满意', 'field' => 'satisfaction2'],
70
+                    '4' => ['name' => '一般', 'field' => 'satisfaction3'],
71
+                    '5' => ['name' => '不满意', 'field' => 'satisfaction4'],
72
+                    '6' => ['name' => '很不满意', 'field' => 'satisfaction5'],
73
+                ];
74
+                break;
75
+            case 'productSatisfaction':
76
+                $file_name = 'productSatisfaction';
77
+                $field_list = [
78
+                    '0' => ['name' => '员工姓名', 'field' => 'realname'],
79
+                    '1' => ['name' => '回访合同总数', 'field' => 'visit'],
80
+                    '2' => ['name' => '很满意', 'field' => 'satisfaction1'],
81
+                    '3' => ['name' => '满意', 'field' => 'satisfaction2'],
82
+                    '4' => ['name' => '一般', 'field' => 'satisfaction3'],
83
+                    '5' => ['name' => '不满意', 'field' => 'satisfaction4'],
84
+                    '6' => ['name' => '很不满意', 'field' => 'satisfaction5'],
85
+                ];
86
+                break;
87
+        }
88
+        return $excelModel->biExportExcel($file_name, $field_list, $type['type'], $param);
89
+    }
90
+
91
+    /**
92
+     * 员工业绩分析
93
+     * @param $type
94
+     * @param $param
95
+     * @return mixed
96
+     */
97
+    public function contractExcel($type, $param)
98
+    {
99
+
100
+        $excelModel = new \app\admin\model\Excel();
101
+        if($type['excel_types']=='analysis'){
102
+            $file_name = 'contractNumStats';
103
+            $field_list = [];
104
+            p($excelModel->template_download($file_name, $field_list, $type['type'], $param));
105
+            return $excelModel->template_download($file_name, $field_list, $type['type'], $param);
106
+        }elseif ($type['excel_types']=='summary'){
107
+            $file_name = 'totalContract';
108
+            $field_list = [
109
+                '0' => ['name' => '日期', 'field' => 'type'],
110
+                '1' => ['name' => '签约合同数(个)', 'field' => 'count'],
111
+                '2' => ['name' => '签约合同金额(元)', 'field' => 'money'],
112
+                '3' => ['name' => '回款金额(元)', 'field' => 'back'],
113
+            ];
114
+            return $excelModel->biExportExcel($file_name, $field_list, $type['type'], $param['items']);
115
+        }elseif ($type['excel_types']=='invoice'){
116
+            $file_name = 'invoiceStats';
117
+            $field_list = [
118
+                '0' => ['name' => '日期', 'field' => 'type'],
119
+                '1' => ['name' => '回款金额(元)', 'field' => 'receivables_money'],
120
+                '2' => ['name' => '开票金额(元)', 'field' => 'invoice_money'],
121
+                '3' => ['name' => '已回款未开票(元)', 'field' => 'not_invoice'],
122
+                '4' => ['name' => '已开票未回款(元)', 'field' => 'not_receivables'],
123
+            ];
124
+            return $excelModel->biExportExcel($file_name, $field_list, $type['type'], $param);
125
+        }
126
+//        switch ($type['excel_types']) {
127
+//            case 'analysis':
128
+//
129
+//
130
+//                break;
131
+//            case 'summary':
132
+//                $file_name = 'totalContract';
133
+//                $field_list = [
134
+//                    '0' => ['name' => '日期', 'field' => 'type'],
135
+//                    '1' => ['name' => '签约合同数(个)', 'field' => 'count'],
136
+//                    '2' => ['name' => '签约合同金额(元)', 'field' => 'money'],
137
+//                    '3' => ['name' => '回款金额(元)', 'field' => 'back'],
138
+//                ];
139
+//                return $excelModel->biExportExcel($file_name, $field_list, $type['type'], $param['items']);
140
+//                break;
141
+//            case 'invoice':
142
+//                $file_name = 'invoiceStats';
143
+//                $field_list = [
144
+//                    '0' => ['name' => '日期', 'field' => 'type'],
145
+//                    '1' => ['name' => '回款金额(元)', 'field' => 'receivables_money'],
146
+//                    '2' => ['name' => '开票金额(元)', 'field' => 'invoice_money'],
147
+//                    '3' => ['name' => '已回款未开票(元)', 'field' => 'not_invoice'],
148
+//                    '4' => ['name' => '已开票未回款(元)', 'field' => 'not_receivables'],
149
+//                ];
150
+//                return $excelModel->biExportExcel($file_name, $field_list, $type['type'], $param);
151
+//                break;
152
+//        }
153
+
154
+
155
+    }
156
+
157
+    /**
158
+     * 产品分析
159
+     * @param $type
160
+     * @param $param
161
+     * @return mixed
162
+     */
163
+    public function productExcel($type, $param)
164
+    {
165
+        $file_name = 'contractNumStats';
166
+        $field_list = [
167
+            '0' => ['name' => '日期', 'field' => 'type'],
168
+            '1' => ['name' => '产品分类', 'field' => 'category_id_info'],
169
+            '2' => ['name' => '产品名称', 'field' => 'product_name'],
170
+            '3' => ['name' => '合同编号', 'field' => 'contract_name'],
171
+            '4' => ['name' => '负责人', 'field' => 'realname'],
172
+            '5' => ['name' => '客户名称', 'field' => 'name'],
173
+            '6' => ['name' => '销售单价', 'field' => 'price'],
174
+            '7' => ['name' => '数量', 'field' => 'num'],
175
+            '8' => ['name' => '订单产品小计', 'field' => 'subtotal'],
176
+        ];
177
+        $type = '产品销售情况统计';
178
+        $excelModel = new \app\admin\model\Excel();
179
+        return $excelModel->biExportExcel($file_name, $field_list, $type, $param);
180
+    }
181
+
182
+    /**
183
+     * 排行榜
184
+     * @param $type
185
+     * @param $param
186
+     * @return mixed
187
+     */
188
+    public function rankingExcle($type, $param)
189
+    {
190
+
191
+        $excelModel = new \app\admin\model\Excel();
192
+        switch ($type['excel_types']) {
193
+            case 'contract':
194
+                $file_name = 'contractRanKing';
195
+                $field_list = [
196
+                    '0' => ['name' => '公司总排名', 'field' => 'id'],
197
+                    '1' => ['name' => '签订人', 'field' => 'user_name'],
198
+                    '2' => ['name' => '部门', 'field' => 'structure_name'],
199
+                    '3' => ['name' => '合同金额(元)', 'field' => 'money'],
200
+                ];
201
+                break;
202
+            case 'receivables':
203
+                $file_name = 'receivablesRanKing';
204
+                $field_list = [
205
+                    '0' => ['name' => '公司总排名', 'field' => 'id'],
206
+                    '1' => ['name' => '签订人', 'field' => 'user_name'],
207
+                    '2' => ['name' => '部门', 'field' => 'structure_name'],
208
+                    '3' => ['name' => '回款金额(元)', 'field' => 'money'],
209
+                ];
210
+                break;
211
+            case 'signing':
212
+                $file_name = 'signingRanKing';
213
+                $field_list = [
214
+                    '0' => ['name' => '公司总排名', 'field' => 'id'],
215
+                    '1' => ['name' => '签订人', 'field' => 'user_name'],
216
+                    '2' => ['name' => '部门', 'field' => 'structure_name'],
217
+                    '3' => ['name' => '签约合同', 'field' => 'count'],
218
+                ];
219
+                break;
220
+            case 'product':
221
+                $file_name = 'productCountRanKing';
222
+                $field_list = [
223
+                    '0' => ['name' => '公司总排名', 'field' => 'id'],
224
+                    '1' => ['name' => '签订人', 'field' => 'user_name'],
225
+                    '2' => ['name' => '部门', 'field' => 'structure_name'],
226
+                    '3' => ['name' => '产品销量', 'field' => 'num'],
227
+                ];
228
+                break;
229
+            case 'addCustomer':
230
+                $file_name = 'customerCountRanKing';
231
+                $field_list = [
232
+                    '0' => ['name' => '公司总排名', 'field' => 'id'],
233
+                    '1' => ['name' => '签订人', 'field' => 'user_name'],
234
+                    '2' => ['name' => '部门', 'field' => 'structure_name'],
235
+                    '3' => ['name' => '新增客户数(个)', 'field' => 'count'],
236
+                ];
237
+                break;
238
+            case 'addContacts':
239
+                $file_name = 'contactsCountRanKing';
240
+                $field_list = [
241
+                    '0' => ['name' => '公司总排名', 'field' => 'id'],
242
+                    '1' => ['name' => '签订人', 'field' => 'user_name'],
243
+                    '2' => ['name' => '部门', 'field' => 'structure_name'],
244
+                    '3' => ['name' => '新增联系人数(个)', 'field' => 'count'],
245
+                ];
246
+                break;
247
+            case 'recordNun':
248
+                $file_name = 'FollowupRecordCountRanKing';
249
+                $field_list = [
250
+                    '0' => ['name' => '公司总排名', 'field' => 'id'],
251
+                    '1' => ['name' => '签订人', 'field' => 'user_name'],
252
+                    '2' => ['name' => '部门', 'field' => 'structure_name'],
253
+                    '3' => ['name' => '跟进次数(个)', 'field' => 'count'],
254
+                ];
255
+                break;
256
+            case 'recordCustomer':
257
+                $file_name = 'customerFollowupCountRanKing';
258
+                $field_list = [
259
+                    '0' => ['name' => '公司总排名', 'field' => 'id'],
260
+                    '1' => ['name' => '签订人', 'field' => 'user_name'],
261
+                    '2' => ['name' => '部门', 'field' => 'structure_name'],
262
+                    '3' => ['name' => '跟进客户数(个)', 'field' => 'count'],
263
+                ];
264
+                break;
265
+            case 'examine':
266
+                $file_name = 'travelCountRanKing';
267
+                $field_list = [
268
+                    '0' => ['name' => '公司总排名', 'field' => 'id'],
269
+                    '1' => ['name' => '签订人', 'field' => 'user_name'],
270
+                    '2' => ['name' => '部门', 'field' => 'structure_name'],
271
+                    '3' => ['name' => '出差次数(次)', 'field' => 'count'],
272
+                ];
273
+                break;
274
+        }
275
+        return $excelModel->biExportExcel($file_name, $field_list, $type['type'], $param);
276
+    }
277
+
278
+    /**
279
+     * 业绩目标完成情况
280
+     * @param $type
281
+     * @param $param
282
+     * @return mixed
283
+     */
284
+    public function achienementExcel($type, $param)
285
+    {
286
+        $file_name = 'contractNumStats';
287
+        $field_list = [
288
+            '0' => ['name' => '名称', 'field' => 'name'],
289
+            '1' => ['name' => '月份', 'field' => 'month'],
290
+            '2' => ['name' => '目标', 'field' => 'achievement'],
291
+            '3' => ['name' => '完成', 'field' => 'money'],
292
+            '4' => ['name' => 'rate', 'field' => 'realname'],
293
+        ];
294
+        $type = '业绩目标完成情况';
295
+        $excelModel = new \app\admin\model\Excel();
296
+        return $excelModel->biExportExcel($file_name, $field_list, $type, $param);
297
+    }
298
+
299
+
300
+}

+ 32
- 0
application/bi/model/ActionRecord.php Целия файл

@@ -0,0 +1,32 @@
1
+<?php
2
+// +----------------------------------------------------------------------
3
+// | Description: 操作记录
4
+// +----------------------------------------------------------------------
5
+// | Author:  Michael_xu | gengxiaoxu@5kcrm.com 
6
+// +----------------------------------------------------------------------
7
+
8
+namespace app\bi\model;
9
+
10
+use think\Db;
11
+use app\admin\model\Common;
12
+use think\Request;
13
+use think\Validate;
14
+
15
+class ActionRecord extends Common 
16
+{
17
+    /**
18
+     * 为了数据库的整洁,同时又不影响Model和Controller的名称
19
+     * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
20
+     */
21
+	protected $name = 'admin_action_record';
22
+
23
+	/**
24
+	 * [getDataList 获取列表]
25
+	 * @return    [array]                         
26
+	 */
27
+	public function getDataCount($request)
28
+	{
29
+		$dataCount = db('admin_action_record')->where($request)->count();
30
+		return $dataCount;
31
+	}   	
32
+}

+ 0
- 0
application/bi/model/Business.php Целия файл


Някои файлове не бяха показани, защото твърде много файлове са промени