Scene.php 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  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. if (!empty($v['start'])) $sceneData[$k]['start'] = $v['start'];
  56. if (!empty($v['end'])) $sceneData[$k]['end'] = $v['end'];
  57. }
  58. }
  59. if (!empty($sceneData)) $param['data'] = $sceneData;
  60. $max_order_id = $this->getMaxOrderid($types, $user_id);
  61. $param['order_id'] = $max_order_id ? $max_order_id+1 : 0;
  62. $param['update_time'] = time();
  63. $param['type'] = 0;
  64. $param['bydata'] = '';
  65. $res = $this->allowField(true)->save($param);
  66. if ($res) {
  67. //设置默认
  68. if ($param['is_default']) {
  69. $defaultData = [];
  70. $defaultData['types'] = $types;
  71. $defaultData['user_id'] = $user_id;
  72. $this->defaultDataById($defaultData, $this->scene_id);
  73. }
  74. return true;
  75. } else {
  76. $this->error = '添加失败';
  77. return false;
  78. }
  79. }
  80. /**
  81. * [getDataList 场景list]
  82. * @param types 分类
  83. * @author Michael_xu
  84. * @return [array]
  85. */
  86. public function getDataList($types, $user_id)
  87. {
  88. $fieldModel = new \app\admin\model\Field();
  89. $userModel = new \app\admin\model\User();
  90. if (!in_array($types, $this->types_arr)) {
  91. $this->error = '参数错误';
  92. return false;
  93. }
  94. $map['user_id'] = $user_id;
  95. $map['is_hide'] = 0;
  96. $map['types'] = $types;
  97. $list = db('admin_scene')
  98. ->where($map)
  99. ->whereOr(function ($query) use ($types) {
  100. $query->where(['types' => $types,'type' => 1]);
  101. })->order('order_id asc,scene_id asc')
  102. ->select();
  103. $defaultSceneId = db('admin_scene_default')->where(['types' => $types,'user_id' => $user_id])->value('scene_id');
  104. $fieldList = $fieldModel->getField(['types' => $types]);
  105. $newFieldList = [];
  106. foreach ($fieldList as $k=>$v) {
  107. $field = $v['field'];
  108. if ($v['field'] == 'customer_id') $field = 'customer_name';
  109. $newFieldList[$field] = $v;
  110. }
  111. foreach ($list as $k=>$v) {
  112. if ($v['scene_id'] == $defaultSceneId) {
  113. $list[$k]['is_default'] = 1;
  114. }
  115. $data = $v['data'] ? json_decode($v['data'],true) : [];
  116. if ($data) {
  117. foreach ($data as $key=>$val) {
  118. $setting = $newFieldList[$key]['setting'];
  119. $data[$key]['setting'] = $setting;
  120. if ($val['form_type'] == 'user' && !empty($val['value'][0])) {
  121. $userInfo = $userModel->getUserById($val['value'][0]);
  122. $data[$key]['setting']['realname'] = $userInfo['realname'];
  123. $data[$key]['setting']['id'] = $userInfo['id'];
  124. }
  125. }
  126. }
  127. $list[$k]['data'] = $data ? : [];
  128. }
  129. $map['is_hide'] = 1;
  130. $hideList = $this->where($map)->order('order_id asc')->select();
  131. $data = [];
  132. $data['list'] = $list;
  133. $data['hideList'] = $hideList;
  134. return $data;
  135. }
  136. /**
  137. * 根据主键获取详情
  138. * @param array $param [description]
  139. * @author Michael_xu
  140. */
  141. public function getDataById($id = '', $user_id = '', $types = '')
  142. {
  143. $where = [];
  144. $where['scene_id'] = $id;
  145. $data = db('admin_scene')->where($where)->find();
  146. if (!$types) {
  147. $types = $data['types'] ? : '';
  148. }
  149. //处理data
  150. if ($data['bydata'] && $types) {
  151. $data = $this->getByData($types, $data['bydata'], $user_id);
  152. } else {
  153. $data = json_decode($data['data'],true);
  154. if (is_array($data)) {
  155. foreach ($data as $k=>$v) {
  156. if ($v['form_type'] == 'business_type') {
  157. $data[$k]['value'] = $v['type_id'];
  158. }
  159. }
  160. }
  161. }
  162. return $data ? : [];
  163. }
  164. /**
  165. * 根据主键修改
  166. * @param array $param [description]
  167. * @author Michael_xu
  168. */
  169. public function updateDataById($param, $id)
  170. {
  171. $checkData = $this->get($id);
  172. $sceneInfo = $checkData->data;
  173. $user_id = $param['user_id'];
  174. if (!$sceneInfo) {
  175. $this->error = '暂无数据';
  176. return false;
  177. }
  178. //权限(只能编辑自己的)
  179. if ($sceneInfo['user_id'] !== $user_id) {
  180. $this->error = '参数错误';
  181. return false;
  182. }
  183. if (empty($param['name'])) {
  184. $this->error = '场景名称必填';
  185. return false;
  186. }
  187. if ($this->where(['scene_id' => ['neq', $id], 'types' => $param['types'], 'user_id' => $user_id,'name' => $param['name']])->find()) {
  188. $this->error = '场景名称已存在';
  189. return false;
  190. }
  191. # 转自定义场景结构
  192. $sceneData = [];
  193. foreach ($param['data'] AS $key => $value) {
  194. foreach ($value AS $k => $v) {
  195. $sceneData[$k] = [
  196. 'condition' => trim($v['condition']),
  197. 'value' => $v['value'],
  198. 'form_type' => $v['form_type'],
  199. 'name' => $v['name'],
  200. 'type' => $v['type']
  201. ];
  202. if (!empty($v['start'])) $sceneData[$k]['start'] = $v['start'];
  203. if (!empty($v['end'])) $sceneData[$k]['end'] = $v['end'];
  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. } else {
  214. db('admin_scene_default')->where(['user_id' => $user_id, 'types' => $param['types'], 'scene_id' => $id])->delete();
  215. }
  216. if ($res) {
  217. return true;
  218. } else {
  219. $this->error = '修改失败';
  220. return false;
  221. }
  222. }
  223. /**
  224. * 场景设置为默认
  225. * @param types 类型
  226. * @param user_id 人员ID
  227. * @param id 场景ID
  228. * @author Michael_xu
  229. */
  230. public function defaultDataById($param, $id)
  231. {
  232. if (!$param['types'] || !$id) {
  233. $this->error = '参数错误';
  234. return false;
  235. }
  236. $resInfo = db('admin_scene_default')->where(['types' => $param['types'],'user_id' => $param['user_id']])->find();
  237. if ($resInfo) {
  238. $res = db('admin_scene_default')->where(['types' => $param['types'],'user_id' => $param['user_id']])->update(['scene_id' => $id]);
  239. } else {
  240. $data = [];
  241. $data['types'] = $param['types'];
  242. $data['user_id'] = $param['user_id'];
  243. $data['scene_id'] = $id;
  244. $res = db('admin_scene_default')->insert($data);
  245. }
  246. if (!$res) {
  247. $this->error = '设置失败或数据无变化';
  248. return false;
  249. }
  250. return true;
  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. * @param
  306. * @author Michael_xu
  307. * @return
  308. */
  309. public function getMaxOrderid($types, $user_id)
  310. {
  311. $maxOrderid = $this->where(['types' => $types, 'user_id' => $user_id])->max('order_id');
  312. return $maxOrderid ? : 0;
  313. }
  314. /**
  315. * 场景数据(转数组格式),用于where条件
  316. * @param
  317. * @author Michael_xu
  318. * @return
  319. */
  320. public function dataChangeArray($string)
  321. {
  322. $data_arr = [];
  323. $where = [];
  324. eval('$data_arr = '.$string.';');
  325. foreach ($data_arr as $k=>$v) {
  326. if ($v['state']) {
  327. $address_where[] = '%'.$v['state'].'%';
  328. if ($v['city']) {
  329. $address_where[] = '%'.$v['city'].'%';
  330. if ($v['area']) {
  331. $address_where[] = '%'.$v['area'].'%';
  332. }
  333. }
  334. if ($v['condition'] == 'not_contain') {
  335. $where[$k] = ['notlike', $address_where, 'OR'];
  336. } else {
  337. $where[$k] = ['like', $address_where, 'AND'];
  338. }
  339. } elseif (!empty($v['start']) || !empty($v['end'])) {
  340. if ($v['start'] && $v['end']) {
  341. $where[$k] = ['between',[strtotime($v['start']),strtotime($v['end'])+86399]];
  342. } elseif ($v['start']) {
  343. $where[$k] = ['egt',strtotime($v['start'])];
  344. } else {
  345. $where[$k] = ['elt',strtotime($v['end'])+86399];
  346. }
  347. } elseif (!empty($v['value'])) {
  348. $where[$k] = field($v['value'],$v['condition']);
  349. }
  350. }
  351. return $where ? : [];
  352. }
  353. /**
  354. * 场景排序
  355. * @param ids 场景id数组
  356. * @param hide_ids 隐藏场景id数组
  357. * @author Michael_xu
  358. * @return
  359. */
  360. public function listOrder($param, $user_id)
  361. {
  362. $res = true;
  363. $resHide = true;
  364. //使用
  365. $data = [];
  366. foreach ($param['ids'] as $k=>$v) {
  367. $data[] = ['scene_id' => $v,'order_id' => $k,'update_time' => time(),'user_id' => $user_id,'is_hide' => 0];
  368. }
  369. if ($param['ids']) $res = $this->isUpdate()->saveAll($data);
  370. //隐藏
  371. $hideData = [];
  372. foreach ($param['hide_ids'] as $k=>$v) {
  373. $hideData[] = ['scene_id' => $v,'order_id' => $k,'update_time' => time(),'user_id' => $user_id,'is_hide' => 1];
  374. }
  375. if ($param['hide_ids']) $resHide = $this->isUpdate()->saveAll($hideData);
  376. if ($res == false || $resHide == false) {
  377. $this->error = '设置出错,请重试';
  378. return false;
  379. }
  380. return true;
  381. }
  382. /**
  383. * [getDefaultData 默认场景]
  384. * @param types 分类
  385. * @author Michael_xu
  386. * @return [array]
  387. */
  388. public function getDefaultData($types, $user_id)
  389. {
  390. $where = [];
  391. $where['types'] = $types;
  392. $where['user_id'] = $user_id;
  393. $scene_id = db('admin_scene_default')->where($where)->value('scene_id');
  394. if (!$scene_id && in_array($types,['crm_leads','crm_customer','crm_business','crm_contacts','crm_contract','crm_receivables','crm_visit','crm_invoice'])) {
  395. $resData['bydata'] = 'all';
  396. } else {
  397. $resData = db('admin_scene')->where(['scene_id' => $scene_id])->find();
  398. }
  399. if ($resData['bydata']) {
  400. $data = $this->getByData($types, $resData['bydata'], $user_id);
  401. } else {
  402. //处理data
  403. $data = $resData ? json_decode($resData,true) : [];
  404. }
  405. return $data;
  406. }
  407. /**
  408. * [getByData 系统场景数据]
  409. * @param types 分类
  410. * @author Michael_xu
  411. * @return [array]
  412. */
  413. public function getByData($types, $bydata, $user_id)
  414. {
  415. $map = [];
  416. $auth_user_ids = [];
  417. $part_user_ids = [];
  418. switch ($bydata) {
  419. case 'me' :
  420. # 我负责的
  421. $auth_user_ids[] = $user_id;
  422. break;
  423. case 'mePart' :
  424. # 我参与的(即相关团队)
  425. $part_user_ids = $user_id;
  426. break;
  427. case 'sub' :
  428. # 下属负责的
  429. $auth_user_ids = getSubUserId(false, 0, $user_id) ? : ['-1'];
  430. break;
  431. case 'all' :
  432. # 全部
  433. $auth_user_ids = '';
  434. break;
  435. case 'is_transform' :
  436. # 已转化线索
  437. $map['is_transform'] = ['condition' => 'is', 'value' => [1], 'form_type' => 'text', 'name' => ''];
  438. break;
  439. case 'pool' :
  440. # 今日进入公海的客户
  441. $customerModel = new \app\crm\model\Customer();
  442. $map = $customerModel->getWhereByToday();
  443. break;
  444. case 'win_business' :
  445. # 赢单的商机
  446. $map['is_end'] = ['condition' => 'is', 'value' => [1], 'form_type' => 'text'];
  447. break;
  448. case 'fail_business' :
  449. # 输单的商机
  450. $map['is_end'] = ['condition' => 'is', 'value' => [2], 'form_type' => 'text'];
  451. break;
  452. case 'star' :
  453. $where = $this->getStarParam($types, $user_id);
  454. if (!empty($where)) $map = $where;
  455. break;
  456. case 'go_business' :
  457. # 进行中的商机
  458. $map['is_end'] = ['condition' => 'is', 'value' => ['0'], 'form_type' => 'text'];
  459. break;
  460. case 'put_on_shelves' :
  461. # 上架的产品
  462. $map['status'] = ['condition' => 'is', 'value' => ['上架'], 'form_type' => 'select', 'name' => '是否上架', 'type' => 'status'];
  463. break;
  464. case 'pull_off_shelves' :
  465. # 下架的产品
  466. $map['status'] = ['condition' => 'is', 'value' => ['下架'], 'form_type' => 'select', 'name' => '是否上架', 'type' => 'status'];
  467. break;
  468. default :
  469. # 全部
  470. $auth_user_ids = '';
  471. }
  472. $auth_user_ids = $auth_user_ids ? : [];
  473. if ($auth_user_ids) {
  474. $map['owner_user_id'] = ['condition' => 'in', 'value' => $auth_user_ids, 'form_type' => 'user', 'name' => ''];
  475. }
  476. if ($part_user_ids) {
  477. $map['ro_user_id'] = $part_user_ids;
  478. $map['rw_user_id'] = $part_user_ids;
  479. }
  480. return $map;
  481. }
  482. /**
  483. * 获取我的关注条件
  484. *
  485. * @param $types
  486. * @return array
  487. * @throws \think\db\exception\DataNotFoundException
  488. * @throws \think\db\exception\ModelNotFoundException
  489. * @throws \think\exception\DbException
  490. */
  491. public function getStarParam($types, $user_id)
  492. {
  493. $primaryKey = getPrimaryKeyName('crm_' . $types);
  494. $targetIds = Db::name('crm_star')->where(['user_id' => $user_id, 'type' => 'crm_' . $types])->column('target_id');
  495. $where[$primaryKey] = ['condition' => 'in', 'value' => !empty($targetIds) ? $targetIds : [-1], 'form_type' => 'user'];
  496. return $where;
  497. }
  498. /**
  499. * [updateData 跳过验证的编辑]
  500. * @param types 分类
  501. * @author Michael_xu
  502. * @return [array]
  503. */
  504. public function updateData($data, $scene_id)
  505. {
  506. $param['data'] = is_array($data) ? $data : '';
  507. $param['update_time'] = time();
  508. $res = $this->allowField(true)->save($param, ['scene_id' => $scene_id]);
  509. if ($res) {
  510. return true;
  511. } else {
  512. $this->error = '修改失败';
  513. return false;
  514. }
  515. }
  516. }