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