Index.php 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320
  1. <?php
  2. namespace app\sys\controller;
  3. use app\BaseController;
  4. use app\model\CompanyBossOpen;
  5. use app\model\Customer;
  6. use app\model\CustomerClue;
  7. use app\model\Employee;
  8. use app\model\Grant;
  9. use app\model\Org;
  10. use app\model\Permission;
  11. use app\model\User;
  12. use app\model\Company;
  13. use app\model\CustomerVisitLog;
  14. use think\facade\Db;
  15. use think\facade\View;
  16. use think\facade\Session;
  17. use wx\Oplatform;
  18. use app\model\SmartScreen;
  19. use app\model\Setting;
  20. class Index extends BaseController
  21. {
  22. /**
  23. * 面板
  24. */
  25. public function index()
  26. {
  27. $grant = Grant::where('id', $this->request->employee['grant_id'])->find();
  28. $permission = is_null($grant) ? [] : (array)$grant->permission;
  29. $company = Org::where('id', $this->request->employee['root_id'])->value('name');
  30. $companyInfo = Company::where('root_id', $this->request->employee['root_id'])->find();
  31. $menu = (new Permission())->getTree([['id', 'in', $permission], ['is_menu', '=', 1]], $this->request->employee['root_id']);
  32. //2022-12-29 智慧屏菜单和智慧屏首页绑定
  33. $smart = SmartScreen::where([['root_id', '=', $this->request->employee['root_id']], ['del', '=', 0]])->column('title', 'code');
  34. //智慧屏菜单排序
  35. $where = [
  36. ['name', '=', 'wisdomMenuOrder'],
  37. ['root_id', '=', $this->request->employee['root_id']]
  38. ];
  39. $order = Setting::where($where)->value('content');
  40. foreach ($menu as $k => $v) {
  41. if ($v['auth_name'] == '智慧屏设置') {
  42. foreach ($v['child'] as $k2 => $v2) {
  43. $arr = explode('?type=', $v2['uri']);
  44. if (count($arr) == 2 && isset($smart[$arr[1]])) {
  45. $menu[$k]['child'][$k2]['auth_name'] = $smart[$arr[1]];
  46. }
  47. }
  48. if ($order) {
  49. $ids = explode(',', $order);
  50. $nsortData = [];
  51. $sortData = [];
  52. foreach ($menu[$k]['child'] as $v4) {
  53. $sk = array_search($v4['id'], $ids);
  54. if ($sk === false) $nsortData[] = $v4;
  55. else $sortData[$sk] = $v4;
  56. }
  57. ksort($sortData);
  58. $new_order = array_merge($nsortData, $sortData);
  59. $menu[$k]['child'] = $new_order;
  60. }
  61. break;
  62. }
  63. }
  64. View::assign("menus", $menu);
  65. View::assign("company", $company);
  66. View::assign("company_info", $companyInfo);
  67. View::assign("employee", $this->request->employee);
  68. // 判断当前店面是否是集团
  69. if ($companyInfo->company_group === 0 && $this->request->employee['grant_id'] == 2) {
  70. //话术添加二级分类要打开新浏览器窗口判断
  71. $type = input('type', '');
  72. $id = input('id', 0);
  73. if ($type == 'talkskill') {
  74. View::assign("homePageUrl", url('talkskill/cate2_view', ['id' => $id]));
  75. } else {
  76. View::assign("homePageUrl", url('company/brand'));
  77. }
  78. } else {
  79. //话术添加二级分类要打开新浏览器窗口判断
  80. $type = input('type', '');
  81. $id = input('id', 0);
  82. if ($type == 'talkskill') {
  83. View::assign("homePageUrl", url('talkskill/cate2_view', ['id' => $id]));
  84. } else {
  85. View::assign("homePageUrl", url('index/welcome'));
  86. }
  87. //
  88. }
  89. // 判断当前是否绑定微信
  90. $domain = request()->domain();
  91. if (strpos($domain, "zqxg.cc") !== false) {
  92. $bind_field = 'xq_qrcode_show'; //薛鹊主体绑定
  93. $openid = $this->request->employee->xq_web_openid;
  94. $appid = config('app.xqweb_appid');
  95. $field = 'xq_unionid';
  96. } else {
  97. $bind_field = 'qrcode_show'; //原有主体绑定
  98. $openid = $this->request->employee->openid;
  99. $appid = config('app.kfweb_appid');
  100. $field = 'unionid';
  101. }
  102. if (!session($bind_field) && empty($openid)) { //第一次登陆 并且 openid为空 弹出否则不谈
  103. // $data->nickname = ' ';
  104. $state = rand(1000, 9999);
  105. View::assign('state', $state);
  106. View::assign('domain', $domain);
  107. View::assign('appid', $appid);
  108. session($bind_field, true);
  109. View::assign('qrcode_show', true);
  110. } else {
  111. View::assign('qrcode_show', false);
  112. }
  113. //切换店面查询手机号下其他店面
  114. $login_type = session('login_type');
  115. $w[] = ['root_id', '<>', $this->request->employee['root_id']];
  116. $w[] = ['grant_id', '>', 0];
  117. if ($login_type == 'phone_login') {
  118. $w[] = ['phone', '=', cypherphone($this->request->employee->phone)];
  119. } else {
  120. $w[] = [$field, '=', $this->request->employee->$field];
  121. }
  122. $root_ids = Employee::where($w)->column('phone', 'root_id');
  123. $w1[] = ['root_id', 'in', array_keys($root_ids)];
  124. $ydate = date('Y-m-d', strtotime('-1 day'));
  125. $w1[] = ['end_date', '>', $ydate . ' 23:59:59'];
  126. $w1[] = ['status', '=', 0]; //排除禁用
  127. // $w1[] = ['company_group','>',0];//排除集团账号
  128. $shop = Company::with(['brand'])->where($w1)->field('company_name,root_id,logo,company_brand')->select()->toArray();
  129. foreach ($shop as $key => $value) {
  130. $shop[$key]['phone'] = $root_ids[$value['root_id']];
  131. if ($value['brand'] && $value['brand']['logo'] && !$value['logo']) {
  132. $shop[$key]['logo'] = $value['brand']['logo'];
  133. }
  134. }
  135. View::assign('shop', $shop);
  136. return View::fetch();
  137. }
  138. /*
  139. * 首页数据中心
  140. */
  141. public function welcome()
  142. {
  143. $customerObj = new Customer();
  144. $customerClueObj = new CustomerClue();
  145. $request = request();
  146. // if ($request->employee->is_manager) {
  147. $customerObj = $customerObj->where([['org_id', 'in', $request->org]]);
  148. $customerClueObj = $customerClueObj->where([['org_id', 'in', $request->org]]);
  149. // } else {
  150. // $customerObj = $customerObj->where([['employee_id', '=', $request->employee->id]]);
  151. // $customerClueObj = $customerClueObj->where([['employee_id', '=', $request->employee->id]]);
  152. // }
  153. // 客户,定金,签单,线索
  154. $firstDay = date('Y-m-d 00:00:00', strtotime('first day of this month'));
  155. $lastDay = date('Y-m-d 00:00:00', strtotime('first day of next month'));
  156. // $prevFirstDay = date('Y-m-d 00:00:00', strtotime('first day of previous month'));
  157. // 客户
  158. $thisMonthCustomerNum = (clone $customerObj)->where([['addtime', 'between', [$firstDay, $lastDay]]])->count();
  159. // $prevMonthCustomerNum = (clone $customerObj)->where([['addtime', 'between', [$prevFirstDay, $firstDay]]])->count();
  160. $totalCustomerNum = (clone $customerObj)->where([['employee_id', 'not null', '']])->count();
  161. // 定金
  162. $thisMonthDingNum = (clone $customerObj)->where([['state', 'in', Customer::changeState('交定', 'chaos')], ['updatetime', 'between', [$firstDay, $lastDay]]])->count();
  163. // $prevMonthDingNum = (clone $customerObj)->where([['state', '=', '交定'], ['updatetime', 'between', [$prevFirstDay, $firstDay]]])->count();
  164. $totalDingNum = (clone $customerObj)->where([['state', 'in', Customer::changeState('交定', 'chaos')]])->count();
  165. // 签单
  166. $thisMonthSignNum = (clone $customerObj)->where([['state', 'in', Customer::changeState('签单', 'chaos')], ['updatetime', 'between', [$firstDay, $lastDay]]])->count();
  167. // $prevMonthSignNum = (clone $customerObj)->where([['state', '=', '签单'], ['updatetime', 'between', [$prevFirstDay, $firstDay]]])->count();
  168. $totalSignNum = (clone $customerObj)->where([['state', 'in', Customer::changeState('签单', 'chaos')]])->count();
  169. // 线索
  170. $thisMonthClueNum = (clone $customerClueObj)->where([['addtime', 'between', [$firstDay, $lastDay]]])->count();
  171. // $prevMonthClueNum = (clone $customerClueObj)->where([['addtime', 'between', [$prevFirstDay, $firstDay]]])->count();
  172. $totalClueNum = (clone $customerClueObj)->count();
  173. View::assign('thisMonthCustomerNum', $thisMonthCustomerNum);
  174. // View::assign('prevMonthCustomerNum', $prevMonthCustomerNum);
  175. View::assign('totalCustomerNum', $totalCustomerNum);
  176. View::assign('thisMonthDingNum', $thisMonthDingNum);
  177. // View::assign('prevMonthDingNum', $prevMonthDingNum);
  178. View::assign('totalDingNum', $totalDingNum);
  179. View::assign('thisMonthSignNum', $thisMonthSignNum);
  180. // View::assign('prevMonthSignNum', $prevMonthSignNum);
  181. View::assign('totalSignNum', $totalSignNum);
  182. View::assign('thisMonthClueNum', $thisMonthClueNum);
  183. // View::assign('prevMonthClueNum', $prevMonthClueNum);
  184. View::assign('totalClueNum', $totalClueNum);
  185. // 线性图取几个月
  186. $m = 5;
  187. $mMonthFirstDay = date('Y-m-1 00:00:00', strtotime('-' . ($m - 1) . ' month'));
  188. $now = date('Y-m-d H:i:s');
  189. // 数据统计
  190. $ding = (clone $customerObj)->where([['state', 'in', Customer::changeState('交定', 'chaos')], ['updatetime', 'between', [$mMonthFirstDay, $now]]])->group('month')->column("DATE_FORMAT(updatetime,'%c') as month,COUNT(id) as num");
  191. $sign = (clone $customerObj)->where([['state', 'in', Customer::changeState('签单', 'chaos')], ['updatetime', 'between', [$mMonthFirstDay, $now]]])->group('month')->column("DATE_FORMAT(updatetime,'%c') as month,COUNT(id) as num");
  192. $noVisit = (clone $customerObj)->where([['first_visit_date', 'null', ''], ['addtime', 'between', [$mMonthFirstDay, $now]]])->group('month')->column("DATE_FORMAT(addtime,'%c') as month,COUNT(id) as num");
  193. $valid = (clone $customerObj)->where([['state', 'in', Customer::changeState('无效', 'chaos')], ['updatetime', 'between', [$mMonthFirstDay, $now]]])->group('month')->column("DATE_FORMAT(addtime,'%c') as month,COUNT(id) as num");
  194. $wait = (clone $customerObj)->where([['state', 'in', Customer::changeState('待确认', 'chaos')], ['updatetime', 'between', [$mMonthFirstDay, $now]]])->group('month')->column("DATE_FORMAT(addtime,'%c') as month,COUNT(id) as num");
  195. $ding = array_combine(array_column($ding, 'month'), array_column($ding, 'num'));
  196. $sign = array_combine(array_column($sign, 'month'), array_column($sign, 'num'));
  197. $noVisit = array_combine(array_column($noVisit, 'month'), array_column($noVisit, 'num'));
  198. $valid = array_combine(array_column($valid, 'month'), array_column($valid, 'num'));
  199. $wait = array_combine(array_column($wait, 'month'), array_column($wait, 'num'));
  200. $thisMonth = date('n');
  201. $data = [
  202. 'month' => [],
  203. 'ding' => [],
  204. 'sign' => [],
  205. 'noVisit' => [],
  206. 'valid' => [],
  207. 'wait' => []
  208. ];
  209. for ($i = 0; $i < $m; $i++) {
  210. $month = ($thisMonth - $i) > 0 ? $thisMonth - $i : $thisMonth - $i + 12;
  211. array_unshift($data['month'], $month . '月');
  212. array_unshift($data['ding'], isset($ding[$month]) ? $ding[$month] : 0);
  213. array_unshift($data['sign'], isset($sign[$month]) ? $sign[$month] : 0);
  214. array_unshift($data['noVisit'], isset($noVisit[$month]) ? $noVisit[$month] : 0);
  215. array_unshift($data['valid'], isset($valid[$month]) ? $valid[$month] : 0);
  216. array_unshift($data['wait'], isset($wait[$month]) ? $wait[$month] : 0);
  217. }
  218. foreach ($data as $k => $val) {
  219. View::assign($k, json_encode($val));
  220. }
  221. // if (!$request->employee->is_manager) {
  222. // // 业绩排行(个人)
  223. // $dingTotalNum = Customer::where([['org_id', 'in', $request->org], ['state', '=', '交定'], ['updatetime', 'between', [$firstDay, $lastDay]]])->group('employee_id')->order('num desc')->column('count(id) num', 'employee_id');
  224. // $signTotalNum = Customer::where([['org_id', 'in', $request->org], ['state', '=', '签单'], ['updatetime', 'between', [$firstDay, $lastDay]]])->group('employee_id')->order('num desc')->column('count(id) num', 'employee_id');
  225. // $dingNum = $dingTotalNum[$request->employee->id] ?? 0;
  226. // sort($dingTotalNum);
  227. // $dingStage = array_search($dingNum, $dingTotalNum);
  228. // $dingStage != false ?: $dingStage = count($dingTotalNum);
  229. // $signNum = $signTotalNum[$request->employee->id] ?? 0;
  230. // sort($signTotalNum);
  231. // $signStage = array_search($signNum, $signTotalNum);
  232. // $signStage != false ?: $signStage = count($signTotalNum);
  233. // $totalDing = array_sum($dingTotalNum);
  234. // $totalSign = array_sum($signTotalNum);
  235. // View::assign('dingStage', $dingStage);
  236. // View::assign('dingNum', $dingNum);
  237. // View::assign('signStage', $signStage);
  238. // View::assign('signNum', $signNum);
  239. // View::assign('totalDing', $totalDing);
  240. // View::assign('totalSign', $totalSign);
  241. // } else {
  242. // 团队
  243. $dingTotalNum = Customer::where([['org_id', 'in', $request->org], ['state', '=', '交定'], ['updatetime', 'between', [$firstDay, $lastDay]]])->group('employee_id')->order('num desc')->column('employee_id, count(id) num');
  244. $signTotalNum = Customer::where([['org_id', 'in', $request->org], ['state', '=', '签单'], ['updatetime', 'between', [$firstDay, $lastDay]]])->group('employee_id')->order('num desc')->column('employee_id, count(id) num');
  245. $employeeIds = array_merge(array_column($dingTotalNum, 'employee_id'), array_column($signTotalNum, 'employee_id'));
  246. $employeeList = Employee::where([['id', 'in', $employeeIds]])->column('name,uid', 'id');
  247. foreach ($dingTotalNum as &$ding) {
  248. if (isset($employeeList[$ding['employee_id']])) {
  249. $ding['employee_name'] = $employeeList[$ding['employee_id']]['name'];
  250. } else {
  251. $ding['employee_name'] = '';
  252. }
  253. }
  254. foreach ($signTotalNum as &$sign) {
  255. if (isset($employeeList[$sign['employee_id']])) {
  256. $sign['employee_name'] = $employeeList[$sign['employee_id']]['name'];
  257. } else {
  258. $sign['employee_name'] = '';
  259. }
  260. }
  261. View::assign('dingStage', $dingTotalNum);
  262. View::assign('signStage', $signTotalNum);
  263. // }
  264. // View::assign('isManager', $request->employee->is_manager);
  265. $xinjushang = 0;
  266. View::assign('xinjushang', $xinjushang);
  267. return View::fetch();
  268. }
  269. /**
  270. * 退出登陆
  271. */
  272. public function logout()
  273. {
  274. //Session::clear();
  275. Session::delete('employee');
  276. Session::delete('login_type');
  277. $url = url('login/index');
  278. Session::delete('qrcode_show');
  279. $url = session('login_source')==1 ? $domain : $url;
  280. session::delete('login_source');
  281. return redirect($url);
  282. }
  283. /**
  284. * 个人资料
  285. */
  286. public function info()
  287. {
  288. $request = request();
  289. if (!$request->isAjax()) {
  290. $empid = $request->employee->id;
  291. $empobj = Employee::where('id', $empid)->find();
  292. View::assign('data', $empobj);
  293. // 微信登陆验证
  294. $state = rand(1000, 9999);
  295. View::assign('state', $state);
  296. $domain = request()->domain();
  297. View::assign('domain', $domain);
  298. $appid = strpos($domain, "zqxg.cc") !== false ? config('app.xqweb_appid') : config('app.kfweb_appid');
  299. View::assign('appid', $appid);
  300. return View::fetch();
  301. }
  302. }
  303. /**
  304. * 修改姓名
  305. */
  306. public function changename()
  307. {
  308. $request = request();
  309. $name = $request->param('name');
  310. $empid = $request->employee->id;
  311. if (Employee::update(['opt_name' => $name], ['id' => $empid])) {
  312. $this->request->employee['opt_name'] = $name;
  313. session('employee', $this->request->employee);
  314. return json(['code' => 0, 'msg' => '姓名更改成功']);
  315. } else {
  316. return json(['code' => 1, 'msg' => '姓名更改失败']);
  317. }
  318. }
  319. /**
  320. * 手机号修改
  321. */
  322. public function changephone()
  323. {
  324. $request = request();
  325. $phone = $request->param('phone');
  326. $empid = $request->employee->id;
  327. if (Employee::update(['phone' => $phone], ['id' => $empid])) {
  328. return json(['code' => 0, 'msg' => '手机号更换成功']);
  329. } else {
  330. return json(['code' => 1, 'msg' => '手机号已被绑定']);
  331. }
  332. }
  333. /**
  334. * 微信扫码换绑
  335. */
  336. public function wechat()
  337. {
  338. $request = request();
  339. $code = $request->param('code');
  340. View::assign('code', $code);
  341. return View::display("<script>parent.bind('" . $code . "');</script>");
  342. }
  343. public function wxBind($code)
  344. {
  345. $domain = request()->domain();
  346. if (strpos($domain, "zqxg.cc") !== false) {
  347. //薛鹊开放平台 web应用
  348. $appid = config('app.xqweb_appid');
  349. $secret = config('app.xqweb_secret');
  350. $field1 = 'xq_web_openid';
  351. $field2 = 'xq_unionid';
  352. } else {
  353. //原有主体开放平台 web应用
  354. $appid = config('app.kfweb_appid');
  355. $secret = config('app.kfweb_secret');
  356. $field1 = 'openid';
  357. $field2 = 'unionid';
  358. }
  359. // 授权获取accesstoken
  360. $tokendata = (new Oplatform())->getAccessToken($appid, $secret, $code);
  361. if (!$tokendata) {
  362. trace('授权获取用户信息', 'error');
  363. trace($tokendata, 'error');
  364. return json(['code' => 1, 'msg' => '请求失败,请刷新页面后重试!']);
  365. }
  366. if (isset($tokendata['errcode'])) { // code已经被使用
  367. if (in_array($tokendata['errcode'], [40029, 40163, 41008, 42003])) {
  368. return json(['code' => 1, 'msg' => '请求失败,请刷新页面后重试!']);
  369. } else {
  370. trace('授权获取用户信息', 'error');
  371. trace($tokendata, 'error');
  372. return json(['code' => 1, 'msg' => $tokendata['errmsg']]);
  373. }
  374. }
  375. // 拉取用户信息
  376. $getUserInfoUrl = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . $tokendata['access_token'] . '&openid=' . $tokendata['openid'] . '&lang=zh_CN';
  377. $data = curl($getUserInfoUrl);
  378. $data = json_decode($data, true);
  379. if (isset($data['errcode']) || empty($data['openid'])) {
  380. trace('拉取用户信息', 'error');
  381. trace($data, 'error');
  382. return json(['code' => 1, 'msg' => '请求失败']);
  383. }
  384. // 更新用户数据
  385. $empid = request()->employee->id;
  386. $empobj = Employee::where('id', $empid)->find();
  387. $empobj->save([
  388. $field1 => $data['openid'],
  389. $field2 => $data['unionid'],
  390. 'nickname' => $data['nickname'],
  391. 'headimgurl' => $data['headimgurl'],
  392. ]);
  393. if ($empobj->uid && $field1 == 'xq_web_openid') {
  394. User::where('id', $empobj->uid)->update([$field1 => $data['openid'], $field2 => $data['unionid']]);
  395. }
  396. return json(['code' => 0, 'msg' => '绑定成功!']);
  397. }
  398. /**
  399. * 多企业选择页面
  400. */
  401. public function company()
  402. {
  403. $request = request();
  404. $rootId = $request->param('rootid');
  405. $phone = session('employee');
  406. if (is_object($phone)) return redirect(url('index/index'));
  407. $domain = request()->domain();
  408. $field = strpos($domain, "zqxg.cc") !== false ? 'phone|xq_unionid' : 'phone|unionid';
  409. if ($rootId) {
  410. $employee = Employee::where([[$field, '=', $phone], ['root_id', '=', $rootId], ['grant_id', '<>', 0]])->find();
  411. if (!empty($employee)) {
  412. $company = Company::where('root_id', $employee['root_id'])->find();
  413. if ($company['status'] == 1) {
  414. return json(['code' => 1, 'msg' => '账号被禁用,请联系管理员']);
  415. } elseif ($company['end_date'] . ' 23:59:59' < date('Y-m-d H:i:s', time())) {
  416. return json(['code' => 1, 'msg' => '账号已过期,请联系管理员']);
  417. }
  418. session('employee', $employee);
  419. event('SysOperate', [$employee, '登录']);
  420. cache('employee_' . $employee['phone'], Session::getId());
  421. return redirect(url('index/index'));
  422. $session_field = strpos($domain, "zqxg.cc") !== false ? 'xq_qrcode_show' : 'qrcode_show';
  423. Session::delete($session_field);
  424. }
  425. }
  426. $companys = Employee::with(['company', 'companys'])->where($field, '=', $phone)->where('grant_id', '<>', 0)->select()->toArray();
  427. foreach ($companys as $k => $v) {
  428. if ($v['account_status'] == 1) {
  429. $companys[$k]['off'] = 1;
  430. $companys[$k]['off_remark'] = '账号被禁用';
  431. } elseif ($v['account_end_date'] . ' 23:59:59' < date('Y-m-d H:i:s', time())) {
  432. $companys[$k]['off'] = 1;
  433. $companys[$k]['off_remark'] = '账号已过期';
  434. } else {
  435. $companys[$k]['off'] = 0;
  436. $companys[$k]['off_remark'] = '账号正常';
  437. }
  438. }
  439. View::assign('companys', $companys);
  440. return View::fetch();
  441. }
  442. /**
  443. * 统计查询条件
  444. */
  445. public function getStatisticsCondition()
  446. {
  447. $param = $this->request->param();
  448. /* $startCondition = ['addtime', '>', date('Y-m-d H:i:s', 0)];
  449. $endCondition = ['addtime', '<', date('Y-m-d H:i:s')]; */
  450. $startCondition = [];
  451. $endCondition = [];
  452. if (!empty($param['start_date'])) {
  453. $startCondition = ['addtime', '>=', date('Y-m-d H:i:s', strtotime($param['start_date']))];
  454. }
  455. if (!empty($param['end_date'])) {
  456. $endCondition = ['addtime', '<=', date('Y-m-d', strtotime($param['end_date'])) . ' 23:59:59'];
  457. }
  458. if (empty($param['org_id'])) {
  459. $param['org_id'] = $this->request->employee['root_id'];
  460. }
  461. // 防止跨范围查询部门
  462. $path = Org::where([['id', '=', $param['org_id']], ['path', 'like', $this->request->employee['root_id'] . '-%']])->value('path');
  463. if (empty($path)) return [['1', '<>', '1'], ['1', '<>', '1'], ['1', '<>', '1'], ['1', '<>', '1'], $this->request->employee['root_id'] . '-'];
  464. $orgIdList = Org::where([['path', 'like', $path . '%']])->column('id');
  465. $orgCondition = ['org_id', 'in', $orgIdList];
  466. $employeeIdList = Employee::where([$orgCondition, ['state', '=', '在职'], ['uid', '<>', '']])->whereNotNull('uid')->column('id');
  467. $employeeCondition = ['employee_id', 'in', $employeeIdList];
  468. return [$startCondition, $endCondition, $employeeCondition, $orgCondition, $path];
  469. }
  470. /**
  471. * 部门列表获取
  472. */
  473. public function org()
  474. {
  475. $orgList = Org::where([['path', 'like', $this->request->employee['root_id'] . '-%'], ['pid', '<>', 0], ['org_type', 'in', [0, 1]]])->order('pid desc, id asc')->column('id,name,pid');
  476. $data = [];
  477. foreach ($orgList as $item) {
  478. if (isset($data[$item['id']])) {
  479. $item['child'] = $data[$item['id']];
  480. unset($data[$item['id']]);
  481. }
  482. $data[$item['pid']][] = $item;
  483. }
  484. return json(['code' => 0, 'data' => array_pop($data)]);
  485. }
  486. /**
  487. * 签单线型图
  488. */
  489. public function signLine()
  490. {
  491. $orgid = $this->request->param('org_id', $this->request->employee['root_id']);
  492. list($startDate, $endDate, $x, $mysqlDateFormat) = $this->getLineContition();
  493. $employeeCondition = $this->getEmployeeCondition($orgid);
  494. // Y轴数据
  495. $rs = CustomerVisitLog::where([CustomerVisitLog::changeState(['state', '=', '签单']), ['confirm_date', '>', $startDate . ' 00:00:00'], ['confirm_date', '<', $endDate . ' 23:59:59'], $employeeCondition])->column("customer_id, DATE_FORMAT(confirm_date, '$mysqlDateFormat') as d");
  496. $list = [];
  497. foreach ($rs as $k => $v) {
  498. $list[$v['d']][] = $v['customer_id'];
  499. }
  500. // 数据整合
  501. $y = [];
  502. $have_ids = []; // 已有的数据customer_id
  503. foreach ($x as $d) {
  504. if (isset($list[$d])) {
  505. $d_list = array_diff($list[$d], $have_ids);
  506. $y[] = count($d_list);
  507. $have_ids = array_merge($have_ids, $list[$d]);
  508. } else {
  509. $y[] = 0;
  510. }
  511. }
  512. return json(['code' => 0, 'data' => ['x' => $x, 'y' => $y]]);
  513. }
  514. /**
  515. * 签单数据统计
  516. */
  517. public function signData()
  518. {
  519. $param = $this->request->param();
  520. $start_time = date('Y-m-d H:i:s', 0);
  521. $end_time = date('Y-m-d H:i:s');
  522. if (!empty($param['start_date'])) {
  523. $start_time = date('Y-m-d H:i:s', strtotime($param['start_date']));
  524. }
  525. if (!empty($param['end_date'])) {
  526. $end_time = date('Y-m-d 23:59:59', strtotime($param['end_date']));
  527. }
  528. $token = request()->employee;
  529. $org_id = input('org_id', '', 'intval');
  530. $org_id = $org_id ? $org_id : $token['root_id'];
  531. $sub_orgs = orgSubIds($token['root_id']);
  532. if (!in_array($org_id, $sub_orgs)) {
  533. return json(['code' => 0, 'data' => []]);
  534. }
  535. $org_ids = orgSubIds($org_id);
  536. /* $wuxiao = Customer::changeState('无效', 'chaos');
  537. $c_where[] = ['org_id', 'in', $org_ids];
  538. $c_where[] = ['addtime|employee_time', 'between', [$start_time, $end_time]];
  539. $c_where[] = ['state', 'NOT NULL', null];
  540. $c_where[] = ['state', 'not in', $wuxiao];
  541. $c_where[] = ['died', '<>', 2];
  542. $customer_list = Customer::where($c_where)->where(function ($query) {
  543. $not_sure = Customer::changeState('待确认', 'chaos');
  544. $or1[] = ['crm_res_id', 'null', null];
  545. $or2[] = ['crm_res_id', 'not null', null];
  546. $or2[] = ['state', 'not in', $not_sure];
  547. $query->whereOr([$or1, $or2]);
  548. })->count(); */
  549. $state1 = CustomerVisitLog::changeState('已到店', 'chaos');
  550. $state2 = CustomerVisitLog::changeState('已到场', 'chaos');
  551. $state3 = CustomerVisitLog::changeState('已量房', 'chaos');
  552. $state4 = CustomerVisitLog::changeState('已交定', 'chaos');
  553. $state5 = CustomerVisitLog::changeState('已签单', 'chaos');
  554. $meet_state = array_merge($state1, $state2, $state3, $state4, $state5);
  555. /* $customer_list = CustomerVisitLog::where([['state', 'in', $meet_state], ['confirm_date', 'between', [$start_time, $end_time]], ['customer_org_id', 'in', $org_ids]])->group('customer_id')->count(); */
  556. $c_where[] = ['CustomerVisitLog.state', 'in', $meet_state];
  557. $c_where[] = ['Customer.org_id', 'in', $org_ids];
  558. $c_where[] = ['CustomerVisitLog.confirm_date', 'between', [$start_time, $end_time]];
  559. $customer_list = Db::view('Customer', 'id cid')
  560. ->view('CustomerVisitLog', 'id lid', 'Customer.id=CustomerVisitLog.customer_id')
  561. ->where($c_where)
  562. ->group('Customer.id')
  563. ->count();
  564. $data['num'] = $customer_list;
  565. // 签单数量获取
  566. $vis_where[] = ['is_merge', '=', 0];
  567. $vis_where[] = ['confirm_date', 'between', [$start_time, $end_time]];
  568. $vis_where[] = ['state', 'in', CustomerVisitLog::changeState('已签单', 'chaos')];
  569. $vis_where[] = ['org_id', 'in', $org_ids];
  570. $customerIdList = CustomerVisitLog::where($vis_where)->column('customer_id');
  571. $customerIdList = array_unique($customerIdList);
  572. $data['sign_num'] = count($customerIdList);
  573. $data['sign_money'] = Customer::where([['id', 'in', $customerIdList]])->sum('signed_money');
  574. // 本月数据获取
  575. $thisMonthCount = CustomerVisitLog::where([['org_id', 'in', $org_ids], CustomerVisitLog::changeState(['state', '=', '签单']), ['confirm_date', '>', date('Y-m') . '-01 00:00:00'], ['confirm_date', '<', date('Y-m-d 00:00:00', strtotime('next month'))]])->count();
  576. // 上月数据获取
  577. $prevMonthCount = CustomerVisitLog::where([['org_id', 'in', $org_ids], CustomerVisitLog::changeState(['state', '=', '签单']), ['confirm_date', '<', date('Y-m') . '-01 00:00:00'], ['confirm_date', '>', date('Y-m-d 00:00:00', strtotime('first day of previous month'))]])->count();
  578. $data['month_lv'] = $prevMonthCount == 0 ? ($thisMonthCount * 100) . '%' : round($thisMonthCount / $prevMonthCount * 100, 2) . '%';
  579. // 今日新增数量
  580. $data['today'] = CustomerVisitLog::where([['org_id', 'in', $org_ids], CustomerVisitLog::changeState(['state', '=', '签单']), ['confirm_date', 'like', date('Y-m-d') . '%']])->count();
  581. // 员工数量仅统计销售
  582. $path = Org::where('id', '=', $org_id)->value('path');
  583. $noDesignerOrgIdList = Org::where([['path', 'like', $path . '%'], ['org_type', 'in', [0, 1]]])->column('id');
  584. $data['employee_num'] = Employee::where([['org_id', 'in', $noDesignerOrgIdList], ['state', '=', '在职'], ['uid', '<>', '']])->count();
  585. $data['sign_lv'] = $data['num'] == 0 ? ($data['sign_num'] * 100) . '%' : round($data['sign_num'] / $data['num'] * 100, 2) . '%';
  586. $data['sign_avg'] = !empty($data['sign_money']) && !empty($data['sign_num']) ? round($data['sign_money'] / $data['sign_num'], 2) : 0;
  587. return json(['code' => 0, 'data' => $data]);
  588. }
  589. /**
  590. * 线型图条件获取
  591. */
  592. public function getLineContition()
  593. {
  594. $param = $this->request->only(['start_date' => date('Y-m-d', strtotime('first day of next month previous year')), 'end_date' => date('Y-m-d')]);
  595. $startDataTime = date_create($param['start_date']);
  596. $endDataTime = date_create($param['end_date']);
  597. $interval = date_diff($startDataTime, $endDataTime);
  598. // X轴数据
  599. $x = [];
  600. if ($interval->m > 1 || $interval->y > 0) {
  601. // 按月取数据,初始天按传的那天,结束天按传的那天
  602. $startDate = $param['start_date']; //date('Y-m-d', strtotime(date('Y-m-01', strtotime($param['start_date']))));
  603. $endDate = $param['end_date']; //date('Y-m-d');
  604. $sdate = date_create($startDate);
  605. $edate = date_create($endDate);
  606. while ($sdate->format('Y-m') <= $edate->format('Y-m')) {
  607. $x[] = $sdate->format('Y-m');
  608. date_add($sdate, date_interval_create_from_date_string('1 month'));
  609. }
  610. $mysqlDateFormat = "%Y-%m";
  611. } else {
  612. // 按天取数据
  613. $startDate = $param['start_date'];
  614. $endDate = $param['end_date'];
  615. $sdate = date_create($startDate);
  616. while ($sdate->format('Y-m-d') <= $endDate) {
  617. $x[] = $sdate->format('m-d');
  618. date_add($sdate, date_interval_create_from_date_string('1 days'));
  619. }
  620. $mysqlDateFormat = "%m-%d";
  621. }
  622. return [$startDate, $endDate, $x, $mysqlDateFormat];
  623. }
  624. /**
  625. * 获取员工查询范围
  626. */
  627. public function getEmployeeCondition($orgid)
  628. {
  629. if (empty($orgid)) $orgid = $this->request->employee['root_id'];
  630. $path = Org::where([['id', '=', $orgid], ['path', 'like', $this->request->employee['root_id'] . '-%']])->value('path');
  631. if (empty($path)) {
  632. $employeeCondition = ['employee_id', 'in', []];
  633. } else {
  634. $orgIdList = Org::where([['path', 'like', $path . '%']])->column('id');
  635. $orgCondition = ['org_id', 'in', $orgIdList];
  636. $employeeIdList = Employee::where([$orgCondition, ['state', '=', '在职'], ['uid', '<>', '']])->whereNotNull('uid')->column('id');
  637. $employeeCondition = ['employee_id', 'in', $employeeIdList];
  638. }
  639. return $employeeCondition;
  640. }
  641. /**
  642. * 收定线型图
  643. */
  644. public function depositLine()
  645. {
  646. $root_id = request()->employee['root_id'];
  647. $orgid = input('org_id', '', 'intval');
  648. $orgid = $orgid ? $orgid : $root_id;
  649. list($startDate, $endDate, $x, $mysqlDateFormat) = $this->getLineContition();
  650. $employeeCondition = $this->getEmployeeCondition($orgid);
  651. // Y轴数据
  652. $rs = CustomerVisitLog::where([CustomerVisitLog::changeState(['state', '=', '交定']), ['confirm_date', '>', $startDate . ' 00:00:00'], ['confirm_date', '<', $endDate . ' 23:59:59'], $employeeCondition])->column("customer_id, DATE_FORMAT(confirm_date, '$mysqlDateFormat') as d");
  653. $list = [];
  654. foreach ($rs as $k => $v) {
  655. $list[$v['d']][] = $v['customer_id'];
  656. }
  657. // 数据整合
  658. $y = [];
  659. $have_ids = []; // 已有的数据customer_id
  660. foreach ($x as $d) {
  661. if (isset($list[$d])) {
  662. $d_list = array_diff($list[$d], $have_ids);
  663. $y[] = count($d_list);
  664. $have_ids = array_merge($have_ids, $list[$d]);
  665. } else {
  666. $y[] = 0;
  667. }
  668. }
  669. return json(['code' => 0, 'data' => ['x' => $x, 'y' => $y]]);
  670. }
  671. /**
  672. * 收定数据统计
  673. */
  674. public function depositData()
  675. {
  676. $param = $this->request->param();
  677. $start_time = date('Y-m-d H:i:s', 0);
  678. $end_time = date('Y-m-d H:i:s');
  679. if (!empty($param['start_date'])) {
  680. $start_time = date('Y-m-d H:i:s', strtotime($param['start_date']));
  681. }
  682. if (!empty($param['end_date'])) {
  683. $end_time = date('Y-m-d 23:59:59', strtotime($param['end_date']));
  684. }
  685. $token = request()->employee;
  686. $org_id = input('org_id', '', 'intval');
  687. $org_id = $org_id ? $org_id : $token['root_id'];
  688. $sub_orgs = orgSubIds($token['root_id']);
  689. if (!in_array($org_id, $sub_orgs)) {
  690. return json(['code' => 0, 'data' => []]);
  691. }
  692. $org_ids = orgSubIds($org_id);
  693. /* $wuxiao = Customer::changeState('无效', 'chaos');
  694. $c_where[] = ['org_id', 'in', $org_ids];
  695. $c_where[] = ['addtime|employee_time', 'between', [$start_time, $end_time]];
  696. $c_where[] = ['state', 'NOT NULL', null];
  697. $c_where[] = ['state', 'not in', $wuxiao];
  698. $c_where[] = ['died', '<>', 2];
  699. $customer_list = Customer::where($c_where)->where(function ($query) {
  700. $not_sure = Customer::changeState('待确认', 'chaos');
  701. $or1[] = ['crm_res_id', 'null', null];
  702. $or2[] = ['crm_res_id', 'not null', null];
  703. $or2[] = ['state', 'not in', $not_sure];
  704. $query->whereOr([$or1, $or2]);
  705. })->count(); */
  706. $state1 = CustomerVisitLog::changeState('已到店', 'chaos');
  707. $state2 = CustomerVisitLog::changeState('已到场', 'chaos');
  708. $state3 = CustomerVisitLog::changeState('已量房', 'chaos');
  709. $state4 = CustomerVisitLog::changeState('已交定', 'chaos');
  710. $state5 = CustomerVisitLog::changeState('已签单', 'chaos');
  711. $meet_state = array_merge($state1, $state2, $state3, $state4, $state5);
  712. // $customer_list = CustomerVisitLog::where([['state', 'in', $meet_state], ['confirm_date', 'between', [$start_time, $end_time]], ['customer_org_id', 'in', $org_ids]])->group('customer_id')->count();
  713. $c_where[] = ['CustomerVisitLog.state', 'in', $meet_state];
  714. $c_where[] = ['Customer.org_id', 'in', $org_ids];
  715. $c_where[] = ['CustomerVisitLog.confirm_date', 'between', [$start_time, $end_time]];
  716. $customer_list = Db::view('Customer', 'id cid')
  717. ->view('CustomerVisitLog', 'id lid', 'Customer.id=CustomerVisitLog.customer_id')
  718. ->where($c_where)
  719. ->group('Customer.id')
  720. ->count();
  721. $data['num'] = $customer_list;
  722. // 数量获取
  723. $vis_where[] = ['is_merge', '=', 0];
  724. $vis_where[] = ['confirm_date', 'between', [$start_time, $end_time]];
  725. $vis_where[] = ['state', 'in', CustomerVisitLog::changeState('交定', 'chaos')];
  726. $vis_where[] = ['org_id', 'in', $org_ids];
  727. $customerIdList = CustomerVisitLog::where($vis_where)->column('customer_id');
  728. $customerIdList = array_unique($customerIdList);
  729. $data['deposit_num'] = count($customerIdList);
  730. $data['deposit_money'] = Customer::where([['id', 'in', $customerIdList]])->sum('deposit_money');
  731. // 今日新增数量
  732. $data['today'] = CustomerVisitLog::whereOr([
  733. [['org_id', 'in', $org_ids], CustomerVisitLog::changeState(['state', '=', '交定']), ['confirm_date', 'like', date('Y-m-d') . '%']]
  734. ])->count();
  735. $data['deposit_lv'] = $data['num'] == 0 ? ($data['deposit_num'] * 100) . '%' : round($data['deposit_num'] / $data['num'] * 100, 2) . '%';
  736. return json(['code' => 0, 'data' => $data]);
  737. }
  738. /**
  739. * 见面数据线型图
  740. */
  741. public function visitLine()
  742. {
  743. $token = request()->employee;
  744. $org_id = input('org_id', '', 'intval');
  745. $org_id = $org_id ? $org_id : $token['root_id'];
  746. $sub_orgs = orgSubIds($token['root_id']);
  747. if (!in_array($org_id, $sub_orgs)) {
  748. return json(['code' => 0, 'data' => []]);
  749. }
  750. $org_ids = orgSubIds($org_id);
  751. list($startDate, $endDate, $x, $mysqlDateFormat) = $this->getLineContition();
  752. // Y轴数据
  753. $shopState = CustomerVisitLog::changeState('确认到店', 'chaos');
  754. $presentState = CustomerVisitLog::changeState('确认到场', 'chaos');
  755. $measureState = CustomerVisitLog::changeState('确认量房', 'chaos');
  756. $rs = CustomerVisitLog::where([
  757. ['state', 'in', array_merge($shopState, $presentState, $measureState)],
  758. ['confirm_date', '>', $startDate . ' 00:00:00'],
  759. ['confirm_date', '<', $endDate . ' 23:59:59'],
  760. ['org_id', 'in', $org_ids]
  761. ])->field(
  762. "state,customer_id,
  763. DATE_FORMAT(confirm_date, '$mysqlDateFormat') as d"
  764. )->select()->toArray();
  765. $d = [];
  766. foreach ($rs as $r) {
  767. if (!isset($d[$r['d']])) {
  768. $d[$r['d']] = ['shop_num' => 0, 'present_num' => 0, 'measure_num' => 0, 'shop_customer_id' => [], 'present_customer_id' => [], 'measure_customer_id' => []];
  769. }
  770. if ($r['state'] == '已到店' && !in_array($r['customer_id'], $d[$r['d']]['shop_customer_id'])) {
  771. $d[$r['d']]['shop_customer_id'][] = $r['customer_id'];
  772. $d[$r['d']]['shop_num']++;
  773. }
  774. if ($r['state'] == '已到场' && !in_array($r['customer_id'], $d[$r['d']]['present_customer_id'])) {
  775. $d[$r['d']]['present_customer_id'][] = $r['customer_id'];
  776. $d[$r['d']]['present_num']++;
  777. }
  778. if ($r['state'] == '已量房' && !in_array($r['customer_id'], $d[$r['d']]['measure_customer_id'])) {
  779. $d[$r['d']]['measure_customer_id'][] = $r['customer_id'];
  780. $d[$r['d']]['measure_num']++;
  781. }
  782. }
  783. // 数据整合
  784. $yShop = [];
  785. $yPresent = [];
  786. $yMeasure = [];
  787. foreach ($x as $day) {
  788. $yShop[] = isset($d[$day]['shop_num']) ? $d[$day]['shop_num'] : 0;
  789. $yPresent[] = isset($d[$day]['present_num']) ? $d[$day]['present_num'] : 0;
  790. $yMeasure[] = isset($d[$day]['measure_num']) ? $d[$day]['measure_num'] : 0;
  791. }
  792. $y = [$yShop, $yPresent, $yMeasure];
  793. return json(['code' => 0, 'data' => ['x' => $x, 'y' => $y]]);
  794. }
  795. /**
  796. * 见面数据统计
  797. */
  798. public function visitData()
  799. {
  800. $param = $this->request->param();
  801. $start_time = date('Y-m-d H:i:s', 0);
  802. $end_time = date('Y-m-d H:i:s');
  803. if (!empty($param['start_date'])) {
  804. $start_time = date('Y-m-d H:i:s', strtotime($param['start_date']));
  805. }
  806. if (!empty($param['end_date'])) {
  807. $end_time = date('Y-m-d 23:59:59', strtotime($param['end_date']));
  808. }
  809. $token = request()->employee;
  810. $org_id = input('org_id', '', 'intval');
  811. $org_id = $org_id ? $org_id : $token['root_id'];
  812. $sub_orgs = orgSubIds($token['root_id']);
  813. if (!in_array($org_id, $sub_orgs)) {
  814. return json(['code' => 0, 'data' => []]);
  815. }
  816. $org_ids = orgSubIds($org_id);
  817. $shopState = CustomerVisitLog::changeState('确认到店', 'chaos');
  818. $presentState = CustomerVisitLog::changeState('确认到场', 'chaos');
  819. $measureState = CustomerVisitLog::changeState('确认量房', 'chaos');
  820. $qdState = CustomerVisitLog::changeState('已签单', 'chaos');
  821. $d = CustomerVisitLog::where([
  822. ['state', 'in', array_merge($shopState, $presentState, $measureState, $qdState)],
  823. ['confirm_date', 'between', [$start_time, $end_time]],
  824. ['org_id', 'in', $org_ids]
  825. ])->field('id,state,customer_id')->select()->toArray();
  826. $data = ['confirm_shop_num' => 0, 'confirm_present_num' => 0, 'confirm_measure_num' => 0];
  827. // 到店数组
  828. $confirm_shop_arr = [];
  829. // 到场数组
  830. $confirm_present_arr = [];
  831. // 量房数组
  832. $confirm_measure_arr = [];
  833. // 签单数组
  834. $qd_list = [];
  835. foreach ($d as $r) {
  836. if (in_array($r['state'], $shopState, true)) {
  837. $confirm_shop_arr[] = $r;
  838. }
  839. if (in_array($r['state'], $presentState, true)) {
  840. $confirm_present_arr[] = $r;
  841. }
  842. if (in_array($r['state'], $measureState, true)) {
  843. $confirm_measure_arr[] = $r;
  844. }
  845. if (in_array($r['state'], $qdState, true)) {
  846. $qd_list[] = $r;
  847. }
  848. }
  849. //签单数据
  850. $qd_customer_id = array_column($qd_list, 'customer_id');
  851. $qd_customer_id = array_values(array_unique(array_filter($qd_customer_id)));
  852. $data['num'] = count($qd_list);
  853. $qd_shop_num = 0; //到店签单数
  854. $qd_present_num = 0; //到场签单数
  855. $qd_measure_num = 0; //量房签单数
  856. $confirm_shop_customer_id = array_values(array_unique(array_filter(array_column($confirm_shop_arr, 'customer_id')))); // 到店客户id
  857. $confirm_present_customer_id = array_values(array_unique(array_filter(array_column($confirm_present_arr, 'customer_id')))); // 到场客户id
  858. $confirm_measure_customer_id = array_values(array_unique(array_filter(array_column($confirm_measure_arr, 'customer_id')))); // 量房客户id
  859. $data['confirm_shop_num'] = count($confirm_shop_customer_id);
  860. $data['confirm_present_num'] = count($confirm_present_customer_id);
  861. $data['confirm_measure_num'] = count($confirm_measure_customer_id);
  862. $qd_shop_num = count(array_intersect($confirm_shop_customer_id, $qd_customer_id));
  863. $qd_present_num = count(array_intersect($confirm_present_customer_id, $qd_customer_id));
  864. $qd_measure_num = count(array_intersect($confirm_measure_customer_id, $qd_customer_id));
  865. $data['confirm_shop_lv'] = $data['confirm_shop_num'] == 0 ? 0 : round($qd_shop_num / $data['confirm_shop_num'] * 100, 2);
  866. $data['confirm_present_lv'] = $data['confirm_present_num'] == 0 ? 0 : round($qd_present_num / $data['confirm_present_num'] * 100, 2);
  867. $data['confirm_measure_lv'] = $data['confirm_measure_num'] == 0 ? 0 : round($qd_measure_num / $data['confirm_measure_num'] * 100, 2);
  868. return json(['code' => 0, 'data' => $data]);
  869. }
  870. /**
  871. * 客户分类统计
  872. */
  873. public function customerLevelData()
  874. {
  875. list($startCondition, $endCondition,, $orgCondition) = $this->getStatisticsCondition();
  876. $where[] = $orgCondition;
  877. if (!empty($startCondition)) {
  878. $where[] = $startCondition;
  879. }
  880. if (!empty($endCondition)) {
  881. $where[] = $endCondition;
  882. }
  883. $state_wuxiao = Customer::changeState('无效', 'chaos');
  884. $data = Customer::field('
  885. count(id) as num,
  886. count(if(level="A",1,null)) as A_num,
  887. count(if(level="B",1,null)) as B_num,
  888. count(if(level="C",1,null)) as C_num,
  889. count(if(level="D",1,null)) as D_num
  890. ')->where($where)->where([['died', '<>', 2], ['state', 'not in', $state_wuxiao], ['employee_id', '>', 0]])->where(function($query){
  891. $state1 = Customer::changeState('待确认', 'chaos');
  892. $or1[] = ['crm_res_id', 'null', null];
  893. $or2[] = ['crm_res_id', 'not null', null];
  894. $or2[] = ['state', 'not in', $state1];
  895. $or3[] = ['valid_time','NOTNULL',NULL];
  896. $query->whereOr([$or1, $or2, $or3]);
  897. })->find();
  898. // A类客户签单数量
  899. $data['a_sign_num'] = Customer::where([['level', '=', 'A'], ['state', 'in', Customer::changeState('签单', 'chaos')]])->where($where)->count();
  900. $data['a_sign_lv'] = $data['A_num'] == 0 ? ($data['a_sign_num'] * 100) . '%' : round($data['a_sign_num'] / $data['A_num'] * 100, 2) . '%';
  901. return json(['code' => 0, 'data' => $data]);
  902. }
  903. /**
  904. * 线索线型图
  905. */
  906. public function clueLine()
  907. {
  908. $orgid = $this->request->param('org_id', $this->request->employee['root_id']);
  909. list($startDate, $endDate, $x, $mysqlDateFormat) = $this->getLineContition();
  910. $employeeCondition = $this->getEmployeeCondition($orgid);
  911. // Y轴数据
  912. $rs = CustomerClue::where([['addtime', '>', $startDate . ' 00:00:00'], ['addtime', '<', $endDate . ' 23:59:59'], $employeeCondition])->group('d')->field("count(id) as num,count(if(state=1,1,null)) as valid_num,DATE_FORMAT(addtime, '$mysqlDateFormat') as d")->select()->toArray();
  913. $rs = array_combine(array_column($rs, 'd'), $rs);
  914. // 数据整合
  915. $n = [];
  916. $valid = [];
  917. foreach ($x as $d) {
  918. if (isset($rs[$d])) {
  919. $n[] = $rs[$d]['num'];
  920. $valid[] = $rs[$d]['valid_num'];
  921. } else {
  922. $n[] = 0;
  923. $valid[] = 0;
  924. }
  925. }
  926. return json(['code' => 0, 'data' => ['x' => $x, 'y' => [$n, $valid]]]);
  927. }
  928. /**
  929. * 线索数据统计
  930. */
  931. public function clueData()
  932. {
  933. list($startCondition, $endCondition, $employeeCondition) = $this->getStatisticsCondition();
  934. $where[] = $employeeCondition;
  935. if (!empty($startCondition)) {
  936. $where[] = $startCondition;
  937. }
  938. if (!empty($endCondition)) {
  939. $where[] = $endCondition;
  940. }
  941. $data = CustomerClue::field('
  942. count(id) as num,
  943. count(if(state=1,1,null)) as valid_num,
  944. count(if(state=2,1,null)) as invalid_num
  945. ')->where($where)->find();
  946. $data['valid_lv'] = $data['num'] == 0 ? '0%' : round($data['valid_num'] / $data['num'], 2) * 100 . '%';
  947. // 今日新增数据
  948. $data['today'] = CustomerClue::where([$employeeCondition, ['addtime', 'like', date('Y-m-d') . '%']])->count();
  949. return json(['code' => 0, 'data' => $data]);
  950. }
  951. /**
  952. * 排行榜
  953. */
  954. public function signRank()
  955. {
  956. $param = $this->request->param();
  957. $start_time = date('Y-m-d H:i:s', 0);
  958. $end_time = date('Y-m-d H:i:s');
  959. if (!empty($param['start_date'])) {
  960. $start_time = date('Y-m-d H:i:s', strtotime($param['start_date']));
  961. }
  962. if (!empty($param['end_date'])) {
  963. $end_time = date('Y-m-d 23:59:59', strtotime($param['end_date']));
  964. }
  965. $token = request()->employee;
  966. $org_id = input('org_id', '', 'intval');
  967. $org_id = $org_id ? $org_id : $token['root_id'];
  968. $sub_orgs = orgSubIds($token['root_id']);
  969. if (!in_array($org_id, $sub_orgs)) {
  970. return json(['code' => 0, 'data' => []]);
  971. }
  972. $path = Org::where('id', '=', $org_id)->value('path');
  973. $orgIdList = Org::where([['path', 'like', $path . '%'], ['org_type', 'in', [0, 1]]])->column('id');
  974. // 签单数据
  975. $db_where[] = ['CustomerVisitLog.state', 'in', CustomerVisitLog::changeState('签单', 'chaos')];
  976. $db_where[] = ['Org.id', 'in', $orgIdList];
  977. $db_where[] = ['CustomerVisitLog.confirm_date', 'between', [$start_time, $end_time]];
  978. $db_where[] = ['Customer.state', 'NOT NULL', null];
  979. $visit_log_list = Db::view('CustomerVisitLog', 'id,customer_id')
  980. ->view('Customer', 'employee_id', 'Customer.id=CustomerVisitLog.customer_id')
  981. ->view('Org', [], 'Customer.org_id=Org.id')
  982. ->where($db_where)
  983. ->select()
  984. ->toArray();
  985. $emp_data = [];
  986. foreach ($visit_log_list as $k => $v) {
  987. if (empty($emp_data[$v['employee_id']])) {
  988. $emp_data[$v['employee_id']][] = $v['customer_id'];
  989. } elseif (!in_array($v['customer_id'], $emp_data[$v['employee_id']])) {
  990. $emp_data[$v['employee_id']][] = $v['customer_id'];
  991. }
  992. }
  993. $data = [];
  994. foreach ($emp_data as $k => $v) {
  995. $data[] = [
  996. 'employee_id' => $k,
  997. 'num' => count($v)
  998. ];
  999. }
  1000. // 员工编号
  1001. $employeeIdlist = array_column($data, 'employee_id');
  1002. // 总单数据
  1003. $not_sure = Customer::changeState('待确认', 'chaos');
  1004. $wuxiao = Customer::changeState('无效', 'chaos');
  1005. $c_where[] = ['addtime|employee_time', 'between', [$start_time, $end_time]];
  1006. $c_where[] = ['employee_id', 'in', $employeeIdlist];
  1007. $c_where[] = ['state', 'not in', array_merge($not_sure, $wuxiao)];
  1008. $c_where[] = ['died', '<>', 2];
  1009. $customerStatistics = Customer::where($c_where)->group('employee_id')->column('count(id) as num', 'employee_id');
  1010. // 员工数据获取
  1011. $employees = Employee::where([['id', 'in', $employeeIdlist]])->column('name,uid,org_id', 'id');
  1012. $userIdList = array_column($employees, 'uid');
  1013. $users = User::where([['id', 'in', $userIdList]])->column('headimgurl', 'id');
  1014. $orgs = Org::where([['id', 'in', array_column($employees, 'org_id')]])->column('name', 'id');
  1015. foreach ($data as &$item) {
  1016. $item['lv'] = (!isset($customerStatistics[$item['employee_id']]) || $customerStatistics[$item['employee_id']] == 0) ? ($item['num'] * 100) . '%' : round($item['num'] / $customerStatistics[$item['employee_id']] * 100, 2) . '%';
  1017. $item['name'] = $employees[$item['employee_id']]['name'];
  1018. $item['headimgurl'] = $users[$employees[$item['employee_id']]['uid']];
  1019. $item['org_name'] = $orgs[$employees[$item['employee_id']]['org_id']];
  1020. }
  1021. array_multisort(array_column($data, 'num'), SORT_DESC, $data);
  1022. return json(['code' => 0, 'data' => $data]);
  1023. }
  1024. public function depositRank()
  1025. {
  1026. $param = $this->request->param();
  1027. $start_time = date('Y-m-d H:i:s', 0);
  1028. $end_time = date('Y-m-d H:i:s');
  1029. if (!empty($param['start_date'])) {
  1030. $start_time = date('Y-m-d H:i:s', strtotime($param['start_date']));
  1031. }
  1032. if (!empty($param['end_date'])) {
  1033. $end_time = date('Y-m-d 23:59:59', strtotime($param['end_date']));
  1034. }
  1035. $token = request()->employee;
  1036. $org_id = input('org_id', '', 'intval');
  1037. $org_id = $org_id ? $org_id : $token['root_id'];
  1038. $sub_orgs = orgSubIds($token['root_id']);
  1039. if (!in_array($org_id, $sub_orgs)) {
  1040. return json(['code' => 0, 'data' => []]);
  1041. }
  1042. $path = Org::where('id', '=', $org_id)->value('path');
  1043. $orgIdList = Org::where([['path', 'like', $path . '%'], ['org_type', 'in', [0, 1]]])->column('id');
  1044. $db_where[] = ['CustomerVisitLog.state', 'in', CustomerVisitLog::changeState('交定', 'chaos')];
  1045. $db_where[] = ['Org.id', 'in', $orgIdList];
  1046. $db_where[] = ['CustomerVisitLog.confirm_date', 'between', [$start_time, $end_time]];
  1047. $db_where[] = ['Customer.state', 'NOT NULL', null];
  1048. $visit_log_list = Db::view('CustomerVisitLog', 'id,customer_id')
  1049. ->view('Customer', 'employee_id', 'Customer.id=CustomerVisitLog.customer_id')
  1050. ->view('Org', [], 'Customer.org_id=Org.id')
  1051. ->where($db_where)
  1052. ->select()
  1053. ->toArray();
  1054. $emp_data = [];
  1055. foreach ($visit_log_list as $k => $v) {
  1056. if (empty($v['employee_id'])) {
  1057. continue;
  1058. }
  1059. if (empty($emp_data[$v['employee_id']])) {
  1060. $emp_data[$v['employee_id']][] = $v['customer_id'];
  1061. } elseif (!in_array($v['customer_id'], $emp_data[$v['employee_id']])) {
  1062. $emp_data[$v['employee_id']][] = $v['customer_id'];
  1063. }
  1064. }
  1065. $data = [];
  1066. foreach ($emp_data as $k => $v) {
  1067. $data[] = [
  1068. 'employee_id' => $k,
  1069. 'num' => count($v)
  1070. ];
  1071. }
  1072. // 员工编号
  1073. $employeeIdlist = array_column($data, 'employee_id');
  1074. // 总单数据
  1075. $not_sure = Customer::changeState('待确认', 'chaos');
  1076. $wuxiao = Customer::changeState('无效', 'chaos');
  1077. $c_where[] = ['addtime|employee_time', 'between', [$start_time, $end_time]];
  1078. $c_where[] = ['employee_id', 'in', $employeeIdlist];
  1079. $c_where[] = ['state', 'not in', array_merge($not_sure, $wuxiao)];
  1080. $c_where[] = ['died', '<>', 2];
  1081. $customerStatistics = Customer::where($c_where)->group('employee_id')->column('count(id) as num', 'employee_id');
  1082. // 员工数据获取
  1083. $employees = Employee::where([['id', 'in', $employeeIdlist]])->column('name,uid,org_id', 'id');
  1084. $userIdList = array_column($employees, 'uid');
  1085. $users = User::where([['id', 'in', $userIdList]])->column('headimgurl', 'id');
  1086. $orgs = Org::where([['id', 'in', array_column($employees, 'org_id')]])->column('name', 'id');
  1087. foreach ($data as &$item) {
  1088. $item['lv'] = (!isset($customerStatistics[$item['employee_id']]) || $customerStatistics[$item['employee_id']] == 0) ? ($item['num'] * 100) . '%' : round($item['num'] / $customerStatistics[$item['employee_id']] * 100, 2) . '%';
  1089. $item['name'] = $employees[$item['employee_id']]['name'] ?? '';
  1090. $item['headimgurl'] = isset($employees[$item['employee_id']]) && isset($users[$employees[$item['employee_id']]['uid']]) ? $users[$employees[$item['employee_id']]['uid']] : '';
  1091. $item['org_name'] = isset($employees[$item['employee_id']]) && isset($orgs[$employees[$item['employee_id']]['org_id']]) ? $orgs[$employees[$item['employee_id']]['org_id']] : '';
  1092. }
  1093. array_multisort(array_column($data, 'num'), SORT_DESC, $data);
  1094. return json(['code' => 0, 'data' => $data]);
  1095. }
  1096. /**
  1097. * 跟进数据统计
  1098. */
  1099. public function followUpData()
  1100. {
  1101. $param = $this->request->param();
  1102. $start_time = date('Y-m-d H:i:s', 0);
  1103. $end_time = date('Y-m-d H:i:s');
  1104. if (!empty($param['start_date'])) {
  1105. $start_time = date('Y-m-d H:i:s', strtotime($param['start_date']));
  1106. }
  1107. if (!empty($param['end_date'])) {
  1108. $end_time = date('Y-m-d 23:59:59', strtotime($param['end_date']));
  1109. }
  1110. $token = request()->employee;
  1111. $org_id = input('org_id', '', 'intval');
  1112. $org_id = $org_id ? $org_id : $token['root_id'];
  1113. $sub_orgs = orgSubIds($token['root_id']);
  1114. if (!in_array($org_id, $sub_orgs)) {
  1115. return json(['code' => 0, 'data' => []]);
  1116. }
  1117. $org_ids = orgSubIds($org_id);
  1118. $shopState = CustomerVisitLog::changeState('确认到店', 'chaos');
  1119. $presentState = CustomerVisitLog::changeState('确认到场', 'chaos');
  1120. $measureState = CustomerVisitLog::changeState('确认量房', 'chaos');
  1121. $signState = CustomerVisitLog::changeState('签单', 'chaos');
  1122. $depositState = CustomerVisitLog::changeState('交定', 'chaos');
  1123. $dataAll = CustomerVisitLog::where([['state', 'in', array_merge($shopState, $presentState, $measureState, $signState, $depositState)], ['org_id', 'in', $org_ids], ['confirm_date', 'between', [$start_time, $end_time]]])->field('id,state')->select();
  1124. $data = ['shop_num' => 0, 'present_num' => 0, 'measure_num' => 0, 'deposit_num' => 0, 'sign_num' => 0];
  1125. foreach ($dataAll as $d) {
  1126. if ($d['state'] == '已到店') $data['shop_num']++;
  1127. if ($d['state'] == '已到场') $data['present_num']++;
  1128. if ($d['state'] == '已量房') $data['measure_num']++;
  1129. if ($d['state'] == '已交定') $data['deposit_num']++;
  1130. if ($d['state'] == '已签单') $data['sign_num']++;
  1131. }
  1132. $wuxiao = Customer::changeState('无效', 'chaos');
  1133. $c_where[] = ['org_id', 'in', $org_ids];
  1134. $c_where[] = ['addtime|employee_time', 'between', [$start_time, $end_time]];
  1135. $c_where[] = ['state', 'NOT NULL', null];
  1136. $c_where[] = ['state', 'not in', $wuxiao];
  1137. $c_where[] = ['died', '<>', 2];
  1138. $valid_num = Customer::where($c_where)->where(function ($query) {
  1139. $not_sure = Customer::changeState('待确认', 'chaos');
  1140. $or1[] = ['crm_res_id', 'null', null];
  1141. $or2[] = ['crm_res_id', 'not null', null];
  1142. $or2[] = ['state', 'not in', $not_sure];
  1143. $query->whereOr([$or1, $or2]);
  1144. })->count();
  1145. $data['valid_num'] = $valid_num;
  1146. return json(['code' => 0, 'data' => $data]);
  1147. }
  1148. /**
  1149. * 切换店面
  1150. */
  1151. public function switch_shop()
  1152. {
  1153. $request = request();
  1154. $rootId = $request->param('rootid');
  1155. $phone = $request->param('phone');
  1156. if ($rootId) {
  1157. $employee = Employee::where([['phone|openid', '=', $phone], ['root_id', '=', $rootId], ['grant_id', '<>', 0]])->find();
  1158. if (!empty($employee)) {
  1159. $company = Company::where('root_id', $employee['root_id'])->find();
  1160. if ($company['status'] == 1) {
  1161. return json(['code' => 1, 'msg' => '账号被禁用,请联系管理员']);
  1162. } elseif ($company['end_date'] . ' 23:59:59' < date('Y-m-d H:i:s', time())) {
  1163. return json(['code' => 1, 'msg' => '账号已过期,请联系管理员']);
  1164. }
  1165. session('employee', $employee);
  1166. event('SysOperate', [$employee, '登录']);
  1167. cache('employee_' . $employee['phone'], Session::getId());
  1168. $domain = request()->domain();
  1169. Session::delete(strpos($domain, "zqxg.cc") !== false ? 'xq_qrcode_show' : 'qrcode_show');
  1170. return json(['code' => 0, 'msg' => '切换店面成功']);
  1171. }
  1172. }
  1173. return json(['code' => 1, 'msg' => '切换失败']);
  1174. }
  1175. }