Нет описания

TemplateController.php 45KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. <?php
  2. /**
  3. * Created by Sublime.
  4. * User: Williamslife Wang
  5. * Date: 17/10/18
  6. * Time: 上午11:20
  7. */
  8. namespace App\Http\Controllers\Admin;
  9. use App\Http\Controllers\Controller;
  10. use App\Admin;
  11. use Illuminate\Http\Request;
  12. use App\Templates;
  13. use App\TemplatesSalers;
  14. use App\TemplatesSource;
  15. use App\TemplatesSourceSalers;
  16. use App\AdminRole;
  17. use App\TemplatesLog;
  18. use App\TemplatesBackimg;
  19. use App\CustDetail;
  20. use App\Order;
  21. use App\RedisModel;
  22. use App\Services\OssServices as oss;
  23. use Illuminate\Support\Facades\DB;
  24. class TemplateController extends Controller
  25. {
  26. /**
  27. * @return \Illuminate\View\View
  28. */
  29. public function index(Request $request)
  30. {
  31. $page = (int)$request->input('page');
  32. $pageSize = 20;
  33. if($page<=0){
  34. $page = 1;
  35. }
  36. $offset = ($page-1) * $pageSize;
  37. $count = Templates::where('is_del',0)->count();
  38. if ($count > 1) {
  39. // 总页数
  40. $pages = ceil($count/$pageSize);
  41. }else{
  42. // 总页数
  43. $pages = 1;
  44. }
  45. $result = Templates::where('is_del',0)->orderBy('id', 'desc')->offset($offset)->limit($pageSize)->get();
  46. $result = json_decode(json_encode($result),true);
  47. foreach($result as $k=>&$v){
  48. # 获取销售
  49. $salers = TemplatesSalers::select('templates_salers.*', 'admin.realname as admin_name')->leftJoin('admin', 'admin.id', '=', 'templates_salers.admin_id')->where('templates_salers.t_id', $v['id'])->where('templates_salers.is_del', 0)->where('admin.is_use', 1)->get();
  50. $v['salers'] = $salers;
  51. $v['salers_k'] = count($salers);
  52. }
  53. return view('template/index', ['result' =>$result,
  54. 'page' =>$page,
  55. 'count' =>$count,
  56. 'pages' =>$pages,
  57. ]);
  58. }
  59. /**
  60. * @return \Illuminate\View\View
  61. */
  62. public function create()
  63. {
  64. return view('template/create');
  65. }
  66. /**
  67. * @param Request $request
  68. * @return \Illuminate\Http\RedirectResponse
  69. */
  70. public function store(Request $request)
  71. {
  72. $this->validate($request, [
  73. 'url' => 'required|unique:templates',
  74. ], [
  75. 'url.required' => '模板链接不能为空',
  76. 'url.unique' => '该模板链接已存在',
  77. ]);
  78. $template = new Templates();
  79. $template->url = trim($request->input('url'));
  80. $template->note = trim($request->input('note'));
  81. //图片上传 阿里云oss
  82. if ($request->hasFile('img') && $request->file('img')->isValid()) {
  83. $file = $request->file('img');
  84. $ossClient=new oss();
  85. // 上传阿里云
  86. $file = $ossClient->upload($file->getClientOriginalExtension(), $file->getRealPath(), 'upload/seafoodPic'.date("Y-m-d",time()).'/'.date('His'));
  87. $img=$file['oss-request-url'];
  88. $template->img=str_replace("kx-youhuiquan.oss-cn-beijing.aliyuncs.com","imgs.726p.com",$img);
  89. }
  90. $template->save();
  91. return redirect('/admin/template/index')->with('info', '添加模板成功');
  92. }
  93. /**
  94. * @param $id
  95. * @return \Illuminate\View\View
  96. */
  97. public function edit($id)
  98. {
  99. $template = Templates::findOrFail($id);
  100. return view('template/edit', ['template' => $template, 'id'=>$id]);
  101. }
  102. /**
  103. * @param Request $request
  104. * @return \Illuminate\Http\RedirectResponse
  105. */
  106. public function update(Request $request)
  107. {
  108. $id = (int)$request->input('id');
  109. $this->validate($request, [
  110. 'url' => 'required',
  111. ], [
  112. 'url.required' => '模板链接不能为空',
  113. 'url.unique' => '该模板链接已存在',
  114. ]);
  115. $template = Templates::findOrFail($id);
  116. $template->url = trim($request->input('url'));
  117. $template->note = trim($request->input('note'));
  118. //图片上传 阿里云oss
  119. if ($request->hasFile('img') && $request->file('img')->isValid()) {
  120. $file = $request->file('img');
  121. $ossClient=new oss();
  122. // 上传阿里云
  123. $file = $ossClient->upload($file->getClientOriginalExtension(), $file->getRealPath(), 'upload/seafoodPic'.date("Y-m-d",time()).'/'.date('His'));
  124. $img=$file['oss-request-url'];
  125. $template->img=str_replace("kx-youhuiquan.oss-cn-beijing.aliyuncs.com","imgs.726p.com",$img);
  126. }
  127. $template->save();
  128. return redirect('/admin/template/index')->with('info', '修改模板成功');
  129. }
  130. /**
  131. * @param $id
  132. * @return \Illuminate\Http\RedirectResponse
  133. */
  134. public function assignSalers(Request $request)
  135. {
  136. $s_id = (int)$request->input('id');
  137. $salers = $request->input('salers');
  138. $assign_type = (int)$request->input('assign_type');
  139. if( empty($salers) ){
  140. // exit('<script>parent.layer.msg("分配失败,未选择销售!",{icon:2,time:2000}); var index=parent.layer.getFrameIndex(window.name); parent.layer.close(index);</script>');
  141. echo '<script>parent.layer.msg("分配失败,未选择销售!",{icon:2,time:2000}); var index=parent.layer.getFrameIndex(window.name); parent.layer.close(index);</script>';die;
  142. }
  143. if($assign_type == 1){
  144. //平均分配
  145. $count = count($salers);
  146. $weight_avg = round(1000 / $count) / 10;
  147. }else{
  148. $weights = array();
  149. $total = 0;
  150. foreach( $salers as $k=>$id ){
  151. $weight_id = 'weight'.$id;
  152. $weights[$k] = trim( $request->input($weight_id) );
  153. if(!$weights[$k]){
  154. $weights[$k] = 0;
  155. }
  156. $total += $weights[$k];
  157. }
  158. if($total>100){
  159. // exit('<script>parent.layer.msg("分配权重之和不能超过100!",{icon:2,time:2000}); var index=parent.layer.getFrameIndex(window.name); parent.layer.close(index);</script>');
  160. echo '<script>parent.layer.msg("分配权重之和不能超过100!",{icon:2,time:2000}); var index=parent.layer.getFrameIndex(window.name); parent.layer.close(index);</script>';die;
  161. }
  162. }
  163. //如果已经有 ,删除未选中
  164. TemplatesSourceSalers::where('s_id', $s_id)->whereNotIn('admin_id',$salers)->update(['is_del'=>1]);
  165. foreach( $salers as $k=>$admin_id ){
  166. if($assign_type == 1){
  167. $weight = $weight_avg;
  168. }else{
  169. $weight = $weights[$k];
  170. }
  171. TemplatesSourceSalers::updateOrCreate( ['s_id'=>$s_id, 'admin_id'=>$admin_id], ['is_del'=>0, 'weight'=>$weight] );
  172. }
  173. // exit('<script>parent.layer.msg("操作成功!",{icon:1,time:1000}); var index=parent.layer.getFrameIndex(window.name); parent.location.href="/admin/template/sourceindex";parent.layer.close(index);</script>');
  174. echo '<script>parent.layer.msg("操作成功!",{icon:1,time:1000}); var index=parent.layer.getFrameIndex(window.name); parent.location.href="/admin/template/sourceindex";parent.layer.close(index);</script>';die;
  175. }
  176. /**
  177. * 获取分配销售
  178. * @return \Illuminate\View\View
  179. */
  180. public function getAssigns(Request $request){
  181. $id = $request->input('id');
  182. #销售筛选
  183. //$saler_ids = DB::table('admin_role')->where('role_name', '销售')->lists('user_id');
  184. $adminList = Admin::select('id', 'realname', 'username', 'team_id')->where('id','>', 1)->where('is_use', 1)->where(function ($query) {
  185. $query->whereNotNull('qrcode')->where('qrcode', '<>', '');
  186. })->get();
  187. $adminList = json_decode(json_encode($adminList), true);
  188. $assign_admin = TemplatesSourceSalers::where('s_id', $id)->where('is_del', 0)->lists('weight', 'admin_id');
  189. $team_info = DB::table('teams')->lists('name', 'id');
  190. foreach($adminList as &$admin){
  191. if( isset($assign_admin[$admin['id']]) ){
  192. $admin['weight'] = $assign_admin[$admin['id']];
  193. }else{
  194. $admin['weight'] = '';
  195. }
  196. if(isset($team_info[$admin['team_id']])){
  197. $admin['team_name'] = $team_info[$admin['team_id']];
  198. }else{
  199. $admin['team_name'] = '';
  200. }
  201. }
  202. return view('template/assign', [
  203. 'adminlist' =>$adminList,
  204. 'id' =>$id
  205. ]);
  206. }
  207. /**
  208. * @return \Illuminate\View\View
  209. */
  210. public function logindex(Request $request)
  211. {
  212. $page = (int)$request->input('page');
  213. $pageSize = 20;
  214. if($page<=0){
  215. $page = 1;
  216. }
  217. $offset = ($page-1) * $pageSize;
  218. $count = TemplatesLog::count();
  219. if ($count > 1) {
  220. // 总页数
  221. $pages = ceil($count/$pageSize);
  222. }else{
  223. // 总页数
  224. $pages = 1;
  225. }
  226. $result = TemplatesLog::orderBy('id', 'desc')->offset($offset)->limit($pageSize)->get();
  227. $result = json_decode(json_encode($result),true);
  228. foreach($result as $k=>&$v){
  229. # 获取销售名字
  230. $v['admin_name'] = Admin::where('id', $v['admin_id'])->pluck('realname');
  231. }
  232. return view('template/logindex', ['result' =>$result,
  233. 'page' =>$page,
  234. 'count' =>$count,
  235. 'pages' =>$pages,
  236. ]);
  237. }
  238. /**
  239. * 销售引流模板分配日志报表
  240. */
  241. public function templateLogReport(Request $request){
  242. $admin_id = (int)$request->input('admin_id');
  243. $team_id = (int)$request->input('team_id');
  244. $stime = $request->input('stime');
  245. $etime = $request->input('etime');
  246. $self_role = session('role_name');
  247. if($self_role == '销售' || $self_role == '分销销售'){
  248. $admin_id = session('admin_id');
  249. }
  250. if($self_role == '管理员'){
  251. //只能看自己团队的
  252. $self_id = session('admin_id');
  253. $team_id = DB::table('admin')->where('id', $self_id)->pluck('team_id');
  254. }
  255. //假如有团队筛选,检索销售队员
  256. $sale_ids = null;
  257. if($team_id>0){
  258. $sale_ids = DB::table('admin')->where('team_id', $team_id)->lists('id');
  259. }
  260. $page = (int)$request->input('page');
  261. $pageSize = 20;
  262. if($page<=0){
  263. $page = 1;
  264. }
  265. $offset = ($page-1) * $pageSize;
  266. $count = TemplatesLog::select('idate','admin_id')->where(function($query) use($admin_id, $stime, $etime, $sale_ids){
  267. if($admin_id>0) $query->where('admin_id', $admin_id);
  268. if($stime) $query->where('idate', '>=', $stime);
  269. if($etime) $query->where('idate', '<=', $etime);
  270. if($sale_ids !== null) $query->whereIn('admin_id', $sale_ids);
  271. })->groupBy('idate')->groupBy('admin_id')->get();
  272. $count = count($count);
  273. if ($count > 1) {
  274. // 总页数
  275. $pages = ceil($count/$pageSize);
  276. }else{
  277. // 总页数
  278. $pages = 1;
  279. }
  280. $result = TemplatesLog::select(DB::raw('idate,admin_id,count(1) as tcount'))->where(function($query) use($admin_id, $stime, $etime, $sale_ids){
  281. if($admin_id>0) $query->where('admin_id', $admin_id);
  282. if($stime) $query->where('idate', '>=', $stime);
  283. if($etime) $query->where('idate', '<=', $etime);
  284. if($sale_ids !== null) $query->whereIn('admin_id', $sale_ids);
  285. })->groupBy('idate')->groupBy('admin_id')->orderBy('idate', 'desc')->offset($offset)->limit($pageSize)->get();
  286. $result = json_decode(json_encode($result), true);
  287. foreach($result as $k=>&$v){
  288. //获取销售当天加粉情况
  289. $custDetail = CustDetail::select('fan_add', 'new_reply', 'new_consult', 'old_consult', 'admin_name')->where('dtime', $v['idate'])->where('admin_id', $v['admin_id'])->where('is_del', 0)->first();
  290. if(!empty($custDetail)){
  291. $v['fan_add'] = $custDetail->fan_add;
  292. $v['new_reply'] = $custDetail->new_reply;
  293. $v['old_consult'] = $custDetail->old_consult;
  294. $v['new_consult'] = $custDetail->new_consult;
  295. $v['admin_name'] = $custDetail->admin_name;
  296. }else{
  297. $v['fan_add'] = '';
  298. $v['new_reply'] = '';
  299. $v['old_consult'] = '';
  300. $v['new_consult'] = '';
  301. $v['admin_name'] = DB::table('admin')->where('id', $v['admin_id'])->pluck('realname');
  302. }
  303. //pv_count
  304. $pv_count = TemplatesLog::where('idate', $v['idate'])->where('admin_id', $v['admin_id'])->where('type', 1)->count();
  305. $v['pv_count'] = $pv_count;
  306. $v['long_count'] = $v['tcount'] - $v['pv_count'];
  307. //点击率
  308. $v['click_rate'] = $v['pv_count']>0 && $v['long_count']>0 ? round( $v['long_count'] / $v['pv_count'], 4 ) * 100 . '%' : '';
  309. $v['change_rate'] = $v['pv_count']>0 && $v['fan_add']>0 ? round( $v['fan_add'] / $v['pv_count'], 4 ) * 100 . '%' : '';
  310. }
  311. $teamList = DB::table('teams')->select('id', 'name')->where(function($query) use($team_id, $self_role){
  312. if($self_role == '管理员') $query->where('id', $team_id);
  313. })->where('type', 1)->get();
  314. $teamList = json_decode(json_encode($teamList), true);
  315. $adminList = DB::table('admin')->select('id', 'realname', 'username')->where(function($query) use($team_id, $self_role){
  316. if($self_role == '管理员') $query->where('team_id', $team_id);
  317. })->where('id','>', 1)->where('is_use', 1)->get();
  318. $adminList = json_decode(json_encode($adminList), true);
  319. return view('template/templateLogReport', ['result'=>$result,
  320. 'page' =>$page,
  321. 'count' =>$count,
  322. 'pages' =>$pages,
  323. 'teamlist' =>$teamList,
  324. 'adminlist' =>$adminList,
  325. 'team_id' =>$team_id,
  326. 'admin_id' =>$admin_id,
  327. 'stime' =>$stime,
  328. 'etime' =>$etime,
  329. 'self_role' =>$self_role,
  330. ]);
  331. }
  332. /**
  333. * 销售引流模板分配日志报表
  334. */
  335. public function templateLogReport_export(Request $request){
  336. $admin_id = (int)$request->input('admin_id');
  337. $team_id = (int)$request->input('team_id');
  338. $stime = $request->input('stime');
  339. $etime = $request->input('etime');
  340. $self_role = session('role_name');
  341. if($self_role == '销售' || $self_role == '分销销售'){
  342. $admin_id = session('admin_id');
  343. }
  344. if($self_role == '管理员'){
  345. //只能看自己团队的
  346. $self_id = session('admin_id');
  347. $team_id = DB::table('admin')->where('id', $self_id)->pluck('team_id');
  348. }
  349. //假如有团队筛选,检索销售队员
  350. $sale_ids = null;
  351. if($team_id>0){
  352. $sale_ids = DB::table('admin')->where('team_id', $team_id)->lists('id');
  353. }
  354. $result = TemplatesLog::select(DB::raw('idate,admin_id,count(1) as tcount'))->where(function($query) use($admin_id, $stime, $etime, $sale_ids){
  355. if($admin_id>0) $query->where('admin_id', $admin_id);
  356. if($stime) $query->where('idate', '>=', $stime);
  357. if($etime) $query->where('idate', '<=', $etime);
  358. if($sale_ids !== null) $query->whereIn('admin_id', $sale_ids);
  359. })->groupBy('idate')->groupBy('admin_id')->orderBy('idate', 'desc')->get();
  360. $result = json_decode(json_encode($result), true);
  361. foreach($result as $k=>&$v){
  362. //获取销售当天加粉情况
  363. $custDetail = CustDetail::select('fan_add', 'new_reply', 'new_consult', 'old_consult', 'admin_name')->where('dtime', $v['idate'])->where('admin_id', $v['admin_id'])->where('is_del', 0)->first();
  364. if(!empty($custDetail)){
  365. $v['fan_add'] = $custDetail->fan_add;
  366. $v['new_reply'] = $custDetail->new_reply;
  367. $v['old_consult'] = $custDetail->old_consult;
  368. $v['new_consult'] = $custDetail->new_consult;
  369. $v['admin_name'] = $custDetail->admin_name;
  370. }else{
  371. $v['fan_add'] = '';
  372. $v['new_reply'] = '';
  373. $v['old_consult'] = '';
  374. $v['new_consult'] = '';
  375. $v['admin_name'] = DB::table('admin')->where('id', $v['admin_id'])->pluck('realname');
  376. }
  377. //pv_count
  378. $pv_count = TemplatesLog::where('idate', $v['idate'])->where('admin_id', $v['admin_id'])->where('type', 1)->count();
  379. $v['pv_count'] = $pv_count;
  380. $v['long_count'] = $v['tcount'] - $v['pv_count'];
  381. //点击率
  382. $v['click_rate'] = $v['pv_count']>0 && $v['long_count']>0 ? round( $v['long_count'] / $v['pv_count'], 4 ) * 100 . '%' : '';
  383. $v['change_rate'] = $v['pv_count']>0 && $v['fan_add']>0 ? round( $v['fan_add'] / $v['pv_count'], 4 ) * 100 . '%' : '';
  384. }
  385. $indexKey = ['idate','admin_name','pv_count','long_count','fan_add','click_rate','change_rate','new_reply','new_consult','old_consult'];
  386. $title = ['日期', '销售名', 'PV量', '长按次数', '加粉数', '点击率', '转化率', '新粉回复数', '新粉询价数', '老粉询价数'];
  387. $filename = 'xiaoshoudaofen_'.date('Y-m-d_H').'.xlsx';
  388. return Order::export_excel($result, $filename, $indexKey, $title);
  389. }
  390. /*
  391. * @return \Illuminate\View\View
  392. */
  393. public function sourceindex(Request $request)
  394. {
  395. $page = (int)$request->input('page');
  396. $pageSize = 20;
  397. if($page<=0){
  398. $page = 1;
  399. }
  400. $offset = ($page-1) * $pageSize;
  401. $count = TemplatesSource::where('is_del',0)->count();
  402. if ($count > 1) {
  403. // 总页数
  404. $pages = ceil($count/$pageSize);
  405. }else{
  406. // 总页数
  407. $pages = 1;
  408. }
  409. $result = TemplatesSource::where('is_del',0)->orderBy('id', 'desc')->offset($offset)->limit($pageSize)->get();
  410. $result = json_decode(json_encode($result),true);
  411. foreach($result as $k=>&$v){
  412. # 获取销售
  413. $salers = TemplatesSourceSalers::select('templates_source_salers.*', 'admin.realname as admin_name')->leftJoin('admin', 'admin.id', '=', 'templates_source_salers.admin_id')->where('templates_source_salers.s_id', $v['id'])->where('templates_source_salers.is_del', 0)->where('admin.is_use', 1)->get();
  414. $v['salers'] = $salers;
  415. $v['salers_k'] = count($salers);
  416. # 获取模板图
  417. $v['img'] = Templates::where('id', $v['t_id'])->pluck('img');
  418. }
  419. return view('template/sourceindex', ['result' =>$result,
  420. 'page' =>$page,
  421. 'count' =>$count,
  422. 'pages' =>$pages,
  423. ]);
  424. }
  425. /**
  426. * @return \Illuminate\View\View
  427. */
  428. public function sourcecreate()
  429. {
  430. $templates = Templates::where('is_del', 0)->whereNotNull('url')->get();
  431. $back_imgs = TemplatesBackimg::where('is_del', 0)->whereNotNull('back_img')->where('t_id', 1)->lists('back_img');
  432. return view('template/sourcecreate', ['templates'=>$templates, 'back_imgs'=>$back_imgs]);
  433. }
  434. /**
  435. * @param Request $request
  436. * @return \Illuminate\Http\RedirectResponse
  437. */
  438. public function sourcestore(Request $request)
  439. {
  440. $t_id = intval($request->input('t_id'));
  441. #查次模板是否是html自定义
  442. $html_info = Templates::select('is_html')->where('id', $t_id)->first();
  443. $is_html = $html_info->is_html;
  444. $back_vali_str = '';
  445. if($t_id != 4 && $is_html != 1){
  446. $back_vali_str = 'required';
  447. }
  448. $this->validate($request, [
  449. 't_id' => 'required',
  450. 'back_img' => $back_vali_str,
  451. ], [
  452. 't_id.required' => '模板不能为空',
  453. 'back_img.required' => '背景图不能为空',
  454. ]);
  455. $template = new TemplatesSource();
  456. $template->t_id = $t_id;
  457. $template->note = trim($request->input('note'));
  458. $template->back_img = trim($request->input('back_img'));
  459. $template->is_html = $is_html;
  460. //图片上传 阿里云oss
  461. /*
  462. if ($request->hasFile('img') && $request->file('img')->isValid()) {
  463. $file = $request->file('img');
  464. $ossClient=new oss();
  465. // 上传阿里云
  466. $file = $ossClient->upload($file->getClientOriginalExtension(), $file->getRealPath(), 'upload/seafoodPic'.date("Y-m-d",time()).'/'.date('His'));
  467. $img=$file['oss-request-url'];
  468. $template->back_img=str_replace("kx-youhuiquan.oss-cn-beijing.aliyuncs.com","imgs.726p.com",$img);
  469. #保存背景图
  470. TemplatesBackimg::insert(['back_img'=>$template->back_img]);
  471. }
  472. */
  473. //新模板数据
  474. if($template->t_id == 4){
  475. $arr = array();
  476. $arr['title'] = trim($request->input('title'));
  477. $arr['text1'] = trim($request->input('text1'));
  478. $arr['text2'] = trim($request->input('text2'));
  479. $arr['text3'] = trim($request->input('text3'));
  480. $arr['img1'] = '';
  481. $arr['img2_1'] = '';
  482. $arr['img2_2'] = '';
  483. $arr['img3'] = '';
  484. if ($request->hasFile('img1') && $request->file('img1')->isValid()) {
  485. $file = $request->file('img1');
  486. $ossClient=new oss();
  487. // 上传阿里云
  488. $file = $ossClient->upload($file->getClientOriginalExtension(), $file->getRealPath(), 'upload/seafoodPic'.date("Y-m-d",time()).'/'.date('His'));
  489. $img=$file['oss-request-url'];
  490. $arr['img1']=str_replace("kx-youhuiquan.oss-cn-beijing.aliyuncs.com","imgs.726p.com",$img);
  491. }
  492. if ($request->hasFile('img2_1') && $request->file('img2_1')->isValid()) {
  493. $file = $request->file('img2_1');
  494. $ossClient=new oss();
  495. // 上传阿里云
  496. $file = $ossClient->upload($file->getClientOriginalExtension(), $file->getRealPath(), 'upload/seafoodPic'.date("Y-m-d",time()).'/'.date('His'));
  497. $img=$file['oss-request-url'];
  498. $arr['img2_1']=str_replace("kx-youhuiquan.oss-cn-beijing.aliyuncs.com","imgs.726p.com",$img);
  499. }
  500. if ($request->hasFile('img2_2') && $request->file('img2_2')->isValid()) {
  501. $file = $request->file('img2_2');
  502. $ossClient=new oss();
  503. // 上传阿里云
  504. $file = $ossClient->upload($file->getClientOriginalExtension(), $file->getRealPath(), 'upload/seafoodPic'.date("Y-m-d",time()).'/'.date('His'));
  505. $img=$file['oss-request-url'];
  506. $arr['img2_2']=str_replace("kx-youhuiquan.oss-cn-beijing.aliyuncs.com","imgs.726p.com",$img);
  507. }
  508. if ($request->hasFile('img3') && $request->file('img3')->isValid()) {
  509. $file = $request->file('img3');
  510. $ossClient=new oss();
  511. // 上传阿里云
  512. $file = $ossClient->upload($file->getClientOriginalExtension(), $file->getRealPath(), 'upload/seafoodPic'.date("Y-m-d",time()).'/'.date('His'));
  513. $img=$file['oss-request-url'];
  514. $arr['img3']=str_replace("kx-youhuiquan.oss-cn-beijing.aliyuncs.com","imgs.726p.com",$img);
  515. }
  516. $template->new_context = json_encode($arr);
  517. }
  518. if($template->save()){
  519. //生成连接
  520. $template->url = $this->createSourceUrl($template->t_id, $template->id);
  521. $template->save();
  522. }
  523. return redirect('/admin/template/sourceindex')->with('info', '添加模板成功');
  524. }
  525. /**
  526. * @param $id
  527. * @return \Illuminate\View\View
  528. */
  529. public function sourceedit($id)
  530. {
  531. $templates = Templates::where('is_del', 0)->whereNotNull('url')->get();
  532. $template = TemplatesSource::findOrFail($id);
  533. $back_imgs = TemplatesBackimg::where('is_del', 0)->whereNotNull('back_img')->where('t_id', $template->t_id)->lists('back_img');
  534. $new_context = array();
  535. if($template->t_id==4){
  536. $new_context = json_decode($template->new_context,true);
  537. }
  538. return view('template/sourceedit', ['template' => $template, 'id'=>$id, 'templates' => $templates, 'back_imgs'=>$back_imgs, 'new_context'=>$new_context]);
  539. }
  540. /**
  541. * @param Request $request
  542. * @return \Illuminate\Http\RedirectResponse
  543. */
  544. public function sourceupdate(Request $request)
  545. {
  546. $id = (int)$request->input('id');
  547. $template = TemplatesSource::findOrFail($id);
  548. $template->note = trim($request->input('note'));
  549. $template->back_img = trim($request->input('back_img'));
  550. //是否是新图文模板
  551. //新模板数据
  552. if($template->t_id == 4){
  553. $new_context = json_decode($template->new_context, true);
  554. $arr = $new_context;
  555. $arr['title'] = trim($request->input('title'));
  556. $arr['text1'] = trim($request->input('text1'));
  557. $arr['text2'] = trim($request->input('text2'));
  558. $arr['text3'] = trim($request->input('text3'));
  559. if ($request->hasFile('img1') && $request->file('img1')->isValid()) {
  560. $file = $request->file('img1');
  561. $ossClient=new oss();
  562. // 上传阿里云
  563. $file = $ossClient->upload($file->getClientOriginalExtension(), $file->getRealPath(), 'upload/seafoodPic'.date("Y-m-d",time()).'/'.date('His'));
  564. $img=$file['oss-request-url'];
  565. $arr['img1']=str_replace("kx-youhuiquan.oss-cn-beijing.aliyuncs.com","imgs.726p.com",$img);
  566. }
  567. if ($request->hasFile('img2_1') && $request->file('img2_1')->isValid()) {
  568. $file = $request->file('img2_1');
  569. $ossClient=new oss();
  570. // 上传阿里云
  571. $file = $ossClient->upload($file->getClientOriginalExtension(), $file->getRealPath(), 'upload/seafoodPic'.date("Y-m-d",time()).'/'.date('His'));
  572. $img=$file['oss-request-url'];
  573. $arr['img2_1']=str_replace("kx-youhuiquan.oss-cn-beijing.aliyuncs.com","imgs.726p.com",$img);
  574. }
  575. if ($request->hasFile('img2_2') && $request->file('img2_2')->isValid()) {
  576. $file = $request->file('img2_2');
  577. $ossClient=new oss();
  578. // 上传阿里云
  579. $file = $ossClient->upload($file->getClientOriginalExtension(), $file->getRealPath(), 'upload/seafoodPic'.date("Y-m-d",time()).'/'.date('His'));
  580. $img=$file['oss-request-url'];
  581. $arr['img2_2']=str_replace("kx-youhuiquan.oss-cn-beijing.aliyuncs.com","imgs.726p.com",$img);
  582. }
  583. if ($request->hasFile('img3') && $request->file('img3')->isValid()) {
  584. $file = $request->file('img3');
  585. $ossClient=new oss();
  586. // 上传阿里云
  587. $file = $ossClient->upload($file->getClientOriginalExtension(), $file->getRealPath(), 'upload/seafoodPic'.date("Y-m-d",time()).'/'.date('His'));
  588. $img=$file['oss-request-url'];
  589. $arr['img3']=str_replace("kx-youhuiquan.oss-cn-beijing.aliyuncs.com","imgs.726p.com",$img);
  590. }
  591. $template->new_context = json_encode($arr);
  592. }
  593. $template->save();
  594. return redirect('/admin/template/sourceindex')->with('info', '修改成功');
  595. }
  596. public function createSourceUrl($t_id, $id){
  597. $url = Templates::where('id', $t_id)->pluck('url');
  598. if($url){
  599. return $url . '?id='.$id;
  600. }
  601. return false;
  602. }
  603. public function uploadBack(Request $request){
  604. $img = $request->input('img');
  605. if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $img, $res)) {
  606. //获取图片类型
  607. $type = $res[2];
  608. // 临时文件
  609. $tmpfname = tempnam("/image/", "FOO");
  610. //保存图片
  611. $handle = fopen($tmpfname, "w");
  612. //阿里云oss上传的文件目录
  613. if (fwrite($handle, base64_decode(str_replace($res[1], '', $img))))
  614. {
  615. $ossClient=new oss();
  616. // 上传阿里云
  617. $file = $ossClient->upload($type, $tmpfname, 'upload/seafoodPic'.date("Y-m-d",time()).'/'.date('His'));
  618. fclose($handle);
  619. unlink($tmpfname);
  620. $img=$file['oss-request-url'];
  621. $back_img=str_replace("kx-youhuiquan.oss-cn-beijing.aliyuncs.com","imgs.726p.com",$img);
  622. #保存背景图
  623. $t_id = (int)$request->input('t_id');
  624. $res = TemplatesBackimg::insert(['back_img'=>$back_img, 't_id'=>$t_id]);
  625. // exit($back_img);
  626. echo (string)$back_img;die;
  627. }
  628. // exit('0');
  629. echo '0';die;
  630. }
  631. }
  632. public function getTempback($t_id){
  633. $result = TemplatesBackimg::where('t_id', $t_id)->lists('back_img');
  634. // exit(json_encode($result));
  635. echo json_encode($result);die;
  636. }
  637. /**
  638. * 销售引流模板分配月报
  639. */
  640. public function templateLogMonthReport(Request $request){
  641. $admin_id = (int)$request->input('admin_id');
  642. $team_id = (int)$request->input('team_id');
  643. $stime = $request->input('stime');
  644. $etime = $request->input('etime');
  645. $self_role = session('role_name');
  646. if($self_role == '销售' || $self_role == '分销销售'){
  647. $admin_id = session('admin_id');
  648. }
  649. if($self_role == '管理员'){
  650. //只能看自己团队的
  651. $self_id = session('admin_id');
  652. $team_id = DB::table('admin')->where('id', $self_id)->pluck('team_id');
  653. }
  654. //假如有团队筛选,检索销售队员
  655. $sale_ids = null;
  656. if($team_id>0){
  657. $sale_ids = DB::table('admin')->where('team_id', $team_id)->lists('id');
  658. }
  659. $page = (int)$request->input('page');
  660. $pageSize = 20;
  661. if($page<=0){
  662. $page = 1;
  663. }
  664. $offset = ($page-1) * $pageSize;
  665. $is_fx = env('IS_FX');
  666. $redisKey = "seafood.templateLogMonthReport".$is_fx.'_'.$team_id;
  667. if( empty($admin_id) && empty($stime) && empty($etime) ){
  668. $result = RedisModel::get($redisKey);
  669. if(!empty($result)){
  670. $result = json_decode($result, true);
  671. $count = count($result);
  672. if ($count > 1) {
  673. // 总页数
  674. $pages = ceil($count/$pageSize);
  675. }else{
  676. // 总页数
  677. $pages = 1;
  678. }
  679. $result = array_slice($result, $offset, $pageSize);
  680. $teamList = DB::table('teams')->select('id', 'name')->where('type', 1)->get();
  681. $teamList = json_decode(json_encode($teamList), true);
  682. $adminList = DB::table('admin')->select('id', 'realname', 'username')->where('id','>', 1)->where('is_use', 1)->get();
  683. $adminList = json_decode(json_encode($adminList), true);
  684. return view('template/templateLogMonthReport', ['result'=>$result,
  685. 'page' =>$page,
  686. 'count' =>$count,
  687. 'pages' =>$pages,
  688. 'teamlist' =>$teamList,
  689. 'adminlist' =>$adminList,
  690. 'team_id' =>$team_id,
  691. 'admin_id' =>$admin_id,
  692. 'stime' =>$stime,
  693. 'etime' =>$etime,
  694. 'self_role' =>$self_role,
  695. ]);
  696. }
  697. }
  698. $mstime = '';
  699. $metime = '';
  700. if($stime){
  701. $mstime = date('Y-m-1', strtotime($stime));
  702. }
  703. if($etime){
  704. $metime = date('Y-m-1', strtotime($etime.' +1 month'));
  705. }
  706. $_start = '2019-11-01';
  707. $count = TemplatesLog::select(DB::raw('mdate,admin_id'))->where('create_time', '>', $_start)->where(function($query) use($admin_id, $mstime, $metime, $sale_ids){
  708. if($admin_id>0) $query->where('admin_id', $admin_id);
  709. if($mstime) $query->where('create_time', '>=', $mstime);
  710. if($metime) $query->where('create_time', '<', $metime);
  711. if($sale_ids !== null) $query->whereIn('admin_id', $sale_ids);
  712. })->groupBy('mdate')->groupBy('admin_id')->get();
  713. $count = count($count);
  714. if ($count > 1) {
  715. // 总页数
  716. $pages = ceil($count/$pageSize);
  717. }else{
  718. // 总页数
  719. $pages = 1;
  720. }
  721. $result = TemplatesLog::select(DB::raw('mdate,admin_id,count(1) as tcount, count(if(type=1,true,null)) as pv_count'))->where('create_time', '>', $_start)->where(function($query) use($admin_id, $mstime, $metime, $sale_ids){
  722. if($admin_id>0) $query->where('admin_id', $admin_id);
  723. if($mstime) $query->where('create_time', '>=', $mstime);
  724. if($metime) $query->where('create_time', '<', $metime);
  725. if($sale_ids !== null) $query->whereIn('admin_id', $sale_ids);
  726. })->groupBy('mdate')->groupBy('admin_id')->orderBy('mdate', 'desc')->get();
  727. $result = json_decode(json_encode($result), true);
  728. foreach($result as $k=>&$v){
  729. //起止时间
  730. $s_time = date('Y-m-1', strtotime($v['mdate']));
  731. $e_time = date('Y-m-1', strtotime($v['mdate'].' +1 month'));
  732. //获取销售当月加粉情况
  733. $custDetail = CustDetail::select(DB::raw('sum(fan_add) as fan_add'))->whereRaw('left(dtime,7)="'.$v['mdate'].'"')->where('admin_id', $v['admin_id'])->where('is_del', 0)->first();
  734. if(!empty($custDetail)){
  735. $v['fan_add'] = $custDetail->fan_add;
  736. }else{
  737. $v['fan_add'] = '';
  738. }
  739. $v['admin_name'] = DB::table('admin')->where('id', $v['admin_id'])->pluck('realname');
  740. $v['long_count'] = $v['tcount'] - $v['pv_count'];
  741. //点击率
  742. //$v['click_rate'] = $v['pv_count']>0 && $v['long_count']>0 ? round( $v['long_count'] / $v['pv_count'], 4 ) * 100 . '%' : '';
  743. $v['change_rate'] = $v['pv_count']>0 && $v['fan_add']>0 ? round( $v['fan_add'] / $v['pv_count'], 4 ) * 100 . '%' : '';
  744. //1.获取当月新粉
  745. $phones = DB::table('customers')->whereRaw('left(fanTime,7)="'.$v['mdate'].'"')->lists('phone');
  746. $order = Order::select(DB::raw('count(1) as order_count, count(distinct(receiverMobile)) as cust_count, sum(receivedAmount) as order_amount'))->where('admin_id', $v['admin_id'])->whereIn('receiverMobile', $phones)->whereRaw('left(createTime,7)="'.$v['mdate'].'"')->where('is_del', 0)->first();
  747. //当月新粉下单单数
  748. $v['order_count'] = $order->order_count;
  749. //当月新粉下单人数
  750. $v['cust_count'] = $order->cust_count;
  751. //当月粉丝复购单数
  752. $v['fugou_order_count'] = $order->order_count - $order->cust_count;
  753. //当月粉丝总销售额
  754. $v['order_amount'] = $order->order_amount;
  755. //新粉下单率
  756. $v['new_order_rate'] = $v['fan_add']>0 ? round($v['cust_count'] / $v['fan_add'], 4) * 100 . '%' : '';
  757. //新粉复购率
  758. //复购用户数 = 下单超过一单的用户数
  759. $order_cust_fugou = Order::select(DB::raw('count(1) as counts,receiverMobile'))->where('admin_id', $v['admin_id'])->whereIn('receiverMobile', $phones)->where('is_del', 0)->whereRaw('left(createTime,7)="'.$v['mdate'].'"')->groupBy('receiverMobile')->having('counts', '>', 1)->get();
  760. $customer_fugou_count = count($order_cust_fugou);
  761. $v['cust_fugou_rate'] = $v['cust_count']>0 ? round($customer_fugou_count / $v['cust_count'], 4) * 100 . '%' : '';
  762. //新粉订单复购率
  763. $v['order_fugou_rate'] = $order->cust_count>0 ? round($v['fugou_order_count'] / $order->cust_count, 4) * 100 . '%' : '';
  764. //当月粉丝人均销售额
  765. $v['avg_amount'] = $v['fan_add']>0 ? round($order->order_amount / $v['fan_add'], 2) : '';
  766. }
  767. $sort_c = array_column($result, 'avg_amount');
  768. array_multisort($sort_c,SORT_DESC,$result);
  769. if( empty($admin_id) && empty($stime) && empty($etime) ){
  770. RedisModel::set($redisKey, json_encode($result));
  771. RedisModel::expire($redisKey, 36000);
  772. }
  773. $result = array_slice($result, $offset, $pageSize);
  774. $teamList = DB::table('teams')->select('id', 'name')->where(function($query) use($team_id, $self_role){
  775. if($self_role == '管理员') $query->where('id', $team_id);
  776. })->where('type', 1)->get();
  777. $teamList = json_decode(json_encode($teamList), true);
  778. $adminList = DB::table('admin')->select('id', 'realname', 'username')->where(function($query) use($team_id, $self_role){
  779. if($self_role == '管理员') $query->where('team_id', $team_id);
  780. })->where('id','>', 1)->where('is_use', 1)->get();
  781. $adminList = json_decode(json_encode($adminList), true);
  782. return view('template/templateLogMonthReport', ['result'=>$result,
  783. 'page' =>$page,
  784. 'count' =>$count,
  785. 'pages' =>$pages,
  786. 'teamlist' =>$teamList,
  787. 'adminlist' =>$adminList,
  788. 'team_id' =>$team_id,
  789. 'admin_id' =>$admin_id,
  790. 'stime' =>$stime,
  791. 'etime' =>$etime,
  792. 'self_role' =>$self_role,
  793. ]);
  794. }
  795. /**
  796. * 销售引流模板分配月报
  797. */
  798. public function templateLogMonthReport_export(Request $request){
  799. $admin_id = (int)$request->input('admin_id');
  800. $team_id = (int)$request->input('team_id');
  801. $stime = $request->input('stime');
  802. $etime = $request->input('etime');
  803. $self_role = session('role_name');
  804. if($self_role == '销售' || $self_role == '分销销售'){
  805. $admin_id = session('admin_id');
  806. }
  807. if($self_role == '管理员'){
  808. //只能看自己团队的
  809. $self_id = session('admin_id');
  810. $team_id = DB::table('admin')->where('id', $self_id)->pluck('team_id');
  811. }
  812. //假如有团队筛选,检索销售队员
  813. $sale_ids = null;
  814. if($team_id>0){
  815. $sale_ids = DB::table('admin')->where('team_id', $team_id)->lists('id');
  816. }
  817. $is_fx = env('IS_FX');
  818. $redisKey = "seafood.templateLogMonthReport".$is_fx.'_'.$team_id;
  819. if( empty($admin_id) && empty($stime) && empty($etime) ){
  820. $result = RedisModel::get($redisKey);
  821. if(!empty($result)){
  822. $result = json_decode($result, true);
  823. $indexKey = ['mdate','admin_name','pv_count','long_count','fan_add','cust_count','order_count','fugou_order_count','order_amount','change_rate','new_order_rate','cust_fugou_rate','order_fugou_rate','avg_amount'];
  824. $title = ['月份', '销售名', '当月PV量', '当月长按次数', '当月上报加粉数', '当月新粉下单人数', '新粉下单单数', '当月粉丝复购单数', '当月粉丝总销售额', '粉丝转化率', '新粉下单率', '新粉复购率', '新粉订单复购率', '当月粉丝人均销售额'];
  825. $filename = 'daofenyuebao_'.date('Y-m-d_H').'.xlsx';
  826. return Order::export_excel($result, $filename, $indexKey, $title);
  827. }
  828. }
  829. $mstime = '';
  830. $metime = '';
  831. if($stime){
  832. $mstime = date('Y-m-1', strtotime($stime));
  833. }
  834. if($etime){
  835. $metime = date('Y-m-1', strtotime($etime.' +1 month'));
  836. }
  837. $_start = '2019-11-01';
  838. $result = TemplatesLog::select(DB::raw('mdate,admin_id,count(1) as tcount, count(if(type=1,true,null)) as pv_count'))->where('create_time', '>', $_start)->where(function($query) use($admin_id, $mstime, $metime, $sale_ids){
  839. if($admin_id>0) $query->where('admin_id', $admin_id);
  840. if($mstime) $query->where('create_time', '>=', $mstime);
  841. if($metime) $query->where('create_time', '<', $metime);
  842. if($sale_ids !== null) $query->whereIn('admin_id', $sale_ids);
  843. })->groupBy('mdate')->groupBy('admin_id')->orderBy('mdate', 'desc')->get();
  844. $result = json_decode(json_encode($result), true);
  845. foreach($result as $k=>&$v){
  846. //获取销售当月加粉情况
  847. $custDetail = CustDetail::select(DB::raw('sum(fan_add) as fan_add'))->whereRaw('left(dtime,7)="'.$v['mdate'].'"')->where('admin_id', $v['admin_id'])->where('is_del', 0)->first();
  848. if(!empty($custDetail)){
  849. $v['fan_add'] = $custDetail->fan_add;
  850. }else{
  851. $v['fan_add'] = '';
  852. }
  853. $v['admin_name'] = DB::table('admin')->where('id', $v['admin_id'])->pluck('realname');
  854. $v['long_count'] = $v['tcount'] - $v['pv_count'];
  855. //点击率
  856. //$v['click_rate'] = $v['pv_count']>0 && $v['long_count']>0 ? round( $v['long_count'] / $v['pv_count'], 4 ) * 100 . '%' : '';
  857. $v['change_rate'] = $v['pv_count']>0 && $v['fan_add']>0 ? round( $v['fan_add'] / $v['pv_count'], 4 ) * 100 . '%' : '';
  858. //1.获取当月新粉
  859. $phones = DB::table('customers')->whereRaw('left(fanTime,7)="'.$v['mdate'].'"')->lists('phone');
  860. $order = Order::select(DB::raw('count(1) as order_count, count(distinct(receiverMobile)) as cust_count, sum(receivedAmount) as order_amount'))->where('admin_id', $v['admin_id'])->whereIn('receiverMobile', $phones)->whereRaw('left(createTime,7)="'.$v['mdate'].'"')->where('is_del', 0)->first();
  861. //当月新粉下单单数
  862. $v['order_count'] = $order->order_count;
  863. //当月新粉下单人数
  864. $v['cust_count'] = $order->cust_count;
  865. //当月粉丝复购单数
  866. $v['fugou_order_count'] = $order->order_count - $order->cust_count;
  867. //当月粉丝总销售额
  868. $v['order_amount'] = $order->order_amount;
  869. //新粉下单率
  870. $v['new_order_rate'] = $v['fan_add']>0 ? round($v['cust_count'] / $v['fan_add'], 4) * 100 . '%' : '';
  871. //新粉复购率
  872. //复购用户数 = 下单超过一单的用户数
  873. $order_cust_fugou = Order::select(DB::raw('count(1) as counts,receiverMobile'))->where('admin_id', $v['admin_id'])->whereIn('receiverMobile', $phones)->where('is_del', 0)->whereRaw('left(createTime,7)="'.$v['mdate'].'"')->groupBy('receiverMobile')->having('counts', '>', 1)->get();
  874. $customer_fugou_count = count($order_cust_fugou);
  875. $v['cust_fugou_rate'] = $v['cust_count']>0 ? round($customer_fugou_count / $v['cust_count'], 4) * 100 . '%' : '';
  876. //新粉订单复购率
  877. $v['order_fugou_rate'] = $order->cust_count>0 ? round($v['fugou_order_count'] / $order->cust_count, 4) * 100 . '%' : '';
  878. //当月粉丝人均销售额
  879. $v['avg_amount'] = $v['fan_add']>0 ? round($order->order_amount / $v['fan_add'], 2) : '';
  880. }
  881. $sort_c = array_column($result, 'avg_amount');
  882. array_multisort($sort_c,SORT_DESC,$result);
  883. if( empty($admin_id) && empty($stime) && empty($etime) ){
  884. RedisModel::set($redisKey, json_encode($result));
  885. RedisModel::expire($redisKey, 36000);
  886. }
  887. $indexKey = ['mdate','admin_name','pv_count','long_count','fan_add','cust_count','order_count','fugou_order_count','order_amount','change_rate','new_order_rate','cust_fugou_rate','order_fugou_rate','avg_amount'];
  888. $title = ['月份', '销售名', '当月PV量', '当月长按次数', '当月上报加粉数', '当月新粉下单人数', '新粉下单单数', '当月粉丝复购单数', '当月粉丝总销售额', '粉丝转化率', '新粉下单率', '新粉复购率', '新粉订单复购率', '当月粉丝人均销售额'];
  889. $filename = 'daofenyuebao_'.date('Y-m-d_H').'.xlsx';
  890. return Order::export_excel($result, $filename, $indexKey, $title);
  891. }
  892. }