findById($id, [], function ($q) { return $q->with(['serviceList']); }); $statusList = [ Order::STATUS_SHIPPED, Order::STATUS_PAID, Order::STATUS_COMPLETED ]; $consumption = OrderRepository::getInstance()->userOrderList($id, [], 1, 0, $statusList); $orderNum = 0; $orderScoreNum = 0; $totalPrice = 0; $totalScore = 0; $totalCoin = 0; $consumption->each(function ($item) use (&$totalPrice, &$totalScore, &$totalCoin, &$orderScoreNum, &$orderNum) { if ($item->is_score == AccountModel::COMMON_ON) { $orderScoreNum += 1; } else { $orderNum += 1; } $totalPrice += $item->price; $totalScore += $item->score; $totalCoin += $item->coin; }); $item['total_price'] = Math::fen2Yuan($totalPrice); $item['total_score'] = $totalScore; $item['total_coin'] = $totalCoin; $item['order_num'] = $orderNum; $item['order_score_num'] = $orderScoreNum; $item['order_newest'] = $consumption->toArray()[0] ?? []; $item['customer_service'] = $item->serviceList->name ?? ''; $item['source_text'] = AccountRepository::getInstance()->getSourceDetail($id); $item['channel_text'] = AccountModel::channelTextList()[$item['channel']] ?? ''; $this->data['item'] = $item; return $this->view(); } /** * 编辑 * * @return Json|View * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException * @throws Exception */ public function edit() { $id = input('id/d', 0); if (!$info = AccountRepository::getInstance()->findById($id)) { if ($this->request->isPost()) { return $this->json(4000, '用户不存在'); } else { return $this->error('用户不存在'); } } if ($this->request->isPost()) { $item = input('post.'); $validate = $this->validateByApi($item, [ 'nickname' => 'require', ]); if ($validate !== true) { return $validate; } try { $info->save($item); return $this->json(); } catch (ValidateException $e) { return $this->json(4001, $e->getError()); } } $this->data['item'] = $info; return $this->view(); } /** * 单个字段编辑 * * @return Json * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException * @throws Exception */ public function modify(): Json { if ($this->request->isPost()) { $item = input('post.'); $validate = $this->validateByApi($item, [ 'field' => 'require', 'value' => 'require', ]); if ($validate !== true) { return $validate; } if (!$info = AccountModel::findById($item['id'])) { return $this->json(4001, '记录不存在'); } $update = [$item['field'] => $item['value']]; try { $info->save($update); return $this->json(); } catch (ValidateException $e) { return $this->json(4001, $e->getError()); } } return $this->json(4000, '非法请求'); } /** * 列表 * * @return View|Json * @throws Exception */ public function index() { if ($this->request->isPost()) { $page = input('page/d', 1); $size = input('size/d', 20); $searchParams = input('searchParams'); $search = []; $other = []; if ($searchParams) { foreach ($searchParams as $key => $param) { if ($key == 'tag' && !empty($param)) { $other['tag_id'] = $param; continue; } if ($param || $param == '0') { $search[] = [$key, 'like', '%'.$param.'%']; } } } $search[] = ['phone_active', '=', AccountModel::COMMON_ON]; // 后台绑定的账号 $accountId = $this->auth['account_id'] ?? 0; try { $items = AccountRepository::getInstance()->customerList($search, [], $accountId, $page, $size, function ($q) use ($other) { return $q->when(isset($other['tag_id']), function ($query) use ($other) { $query->leftJoin('account_tag_pivot atp', 'atp.account_id = id')->where('atp.tag_id', $other['tag_id']); }); }); return $this->json(0, '操作成功', $items); } catch (RepositoryException $e) { return $this->json(4001, $e->getMessage()); } catch (Exception $e) { return $this->json(5001, '获取用户列表失败'.$e->getMessage()); } } $this->data['channelList'] = AccountModel::channelTextList(); $this->data['customerList'] = Staff::getCustomerServiceList(); $this->data['tagList'] = AccountTag::getTags(); return $this->view(); } /** * 分配员工 * * @return View|Json * @throws Exception */ public function staff() { $id = input('id/s', ''); if ($this->request->isPost()) { $ids = input('ids/s'); $staffId = input('staff_id/d', 0); if (empty($ids)) { return $this->json(4001, '请选择要操作的用户'); } if (!$staffId) { return $this->json(4001, '请选择分配的员工'); } $ids = explode(',', $ids); try { CustomerReceive::allotServiceByBatch($ids, $staffId); return $this->json(0, '操作成功'); } catch (RepositoryException $e) { return $this->json(4001, $e->getMessage()); } catch (Exception $e) { Log::error('分配指定员工失败'.$e->getMessage()); return $this->json(5001, '分配指定员工失败'); } } $staffList = Staff::getCustomerServiceList(); // 分配的是客服分组下所有客服 $this->data['servicerList'] = json_encode($staffList, JSON_UNESCAPED_UNICODE); $this->data['id'] = $id; return $this->view(); } /** * 分配客户标签 * * @return View|Json * @throws Exception */ public function tag() { $id = input('id/s', ''); if ($this->request->isPost()) { $ids = input('ids/s'); $tagId = input('tag_id/s'); if (empty($ids)) { return $this->json(4001, '请选择要操作的用户'); } if (empty($tagId)) { return $this->json(4001, '请选择分配的标签'); } $ids = explode(',', $ids); $tags = explode(',', $tagId); Db::startTrans(); try { // 删除所有人标签 AccountTagPivot::whereIn('account_id', $ids)->delete(); // 新增标签 $insert = []; foreach ($ids as $id) { foreach ($tags as $tag) { $arr = []; $arr['account_id'] = $id; $arr['tag_id'] = $tag; $insert[] = $arr; } } (new AccountTagPivot())->saveAll($insert); Db::commit(); return $this->json(0, '操作成功'); } catch (RepositoryException $e) { Db::rollback(); return $this->json(4001, $e->getMessage()); } catch (Exception $e) { Db::rollback(); Log::error('分配客户标签失败'.$e->getMessage()); return $this->json(5001, '分配客户标签失败'); } } $tagList = AccountTag::order('sort', 'desc')->order('id', 'asc')->select()->toArray(); // 分配的是线上客服 $this->data['tagList'] = json_encode($tagList, JSON_UNESCAPED_UNICODE); $this->data['id'] = $id; return $this->view(); } /** * 分配客户来源 * * @return View|Json * @throws Exception */ public function source() { $id = input('id/s', ''); if ($this->request->isPost()) { $ids = input('ids/s'); $channel = input('channel/s'); if (empty($ids)) { return $this->json(4001, '请选择要操作的用户'); } if (empty($channel)) { return $this->json(4001, '请选择分配的客户来源'); } $value = $channel == AccountModel::CHANNEL_MEMBER ? input('type_staff') : input('type_'.$channel); $ids = explode(',', $ids); Db::startTrans(); try { $field = 'id,channel,inviter_account_id,inviter_parent_id,source_code'; $accountList = AccountModel::whereIn('id', $ids)->column($field, 'id'); $update = [];//更新account表 $insert = [];//插入account_operate_log表 switch ($channel) { case AccountModel::CHANNEL_NORMAL: // 设为自然流量 清空上级邀请人和上上级邀请人 $update = ['inviter_account_id' => 0, 'inviter_parent_id' => 0, 'channel' => $channel, 'source_code' => null]; break; case AccountModel::CHANNEL_CUSTOMER: case AccountModel::CHANNEL_MEMBER: // 客户分享或员工分享 修改上级邀请人ID $update = ['inviter_account_id' => $value, 'channel' => $channel, 'source_code' => null]; break; case AccountModel::CHANNEL_ACTIVITY: // 活码分享 $update = ['inviter_account_id' => 0, 'source_code' => $value, 'channel' => $channel]; break; } $now = date('Y-m-d H:i:s'); $createdBy = $this->auth['user_id'] ?? 0; foreach ($ids as $id) { $log = []; $originalSource = $accountList[$id] ?? []; switch ($channel) { case AccountModel::CHANNEL_NORMAL: $log['description'] = sprintf("从原始来源【channel=%s,inviter_account_id=%s,source_code=%s】变更为新来源【channel=%s,inviter_account_id=%s,source_code=%s】", $originalSource['channel'] ?? '', $originalSource['inviter_account_id'] ?? 0, $originalSource['source_code'] ?? '', $channel, 0, null); break; case AccountModel::CHANNEL_CUSTOMER: case AccountModel::CHANNEL_MEMBER: $log['description'] = sprintf("从原始来源【channel=%s,inviter_account_id=%s,source_code=%s】变更为新来源【channel=%s,inviter_account_id=%s,source_code=%s】", $originalSource['channel'] ?? '', $originalSource['inviter_account_id'] ?? 0, $originalSource['source_code'] ?? '', $channel, $value, null); break; case AccountModel::CHANNEL_ACTIVITY: $log['description'] = sprintf("从原始来源【channel=%s,inviter_account_id=%s,source_code=%s】变更为新来源【channel=%s,inviter_account_id=%s,source_code=%s】", $originalSource['channel'] ?? '', $originalSource['inviter_account_id'] ?? 0, $originalSource['source_code'] ?? '', $channel, 0, $value); break; } $log['type'] = AccountOperateLog::TYPE_CHANGE_SOURCE; $log['account_id'] = $id; $log['created_at'] = $now; $log['created_by'] = $createdBy; $insert[] = $log; } (new AccountOperateLog())->saveAll($insert); (new AccountModel())->whereIn('id', $ids)->save($update); Db::commit(); return $this->json(0, '操作成功'); } catch (RepositoryException $e) { Db::rollback(); return $this->json(4001, $e->getMessage()); } catch (Exception $e) { Db::rollback(); Log::error('分配客户标签失败'.$e->getMessage()); return $this->json(5001, '分配客户标签失败'); } } // 客服来源 $this->data['channelList'] = AccountModel::channelTextList(); $this->data['id'] = $id; return $this->view(); } /** * 到店设置 * * @return View|Json * @throws Exception */ public function sign() { $id = input('id/s', ''); if ($this->request->isPost()) { $ids = input('ids/s'); $sign = input('sign/d'); if (empty($ids)) { return $this->json(4001, '请选择要操作的用户'); } if (!in_array($sign, [AccountModel::COMMON_ON, AccountModel::COMMON_OFF])) { return $this->json(4001, '请选择是否到店'); } $ids = explode(',', $ids); Db::startTrans(); try { (new AccountModel())->whereIn('id', $ids)->save(['is_sign' => $sign]); Db::commit(); return $this->json(0, '操作成功'); } catch (Exception $e) { Db::rollback(); Log::error('是否到店操作失败'.$e->getMessage()); return $this->json(5001, '是否到店操作失败'); } } $this->data['id'] = $id; return $this->view(); } /** * 获取员工列表 * * @return Json * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException|Exception */ public function getStaffList(): Json { if ($this->request->isPost()) { $keyword = input('keyword/s', ''); $type = input('type/s', '');//员工类型标识 如在线客服=customer-online $page = input('page/d', 1); $size = input('size/d', 0); $id = input('id/d', 0); $relationIds = [];//已选记录 if ($id > 0 && $activity = Activity::findById($id)) { $relationIds = explode(',', $activity['account_id']); } $res = Staff::getStaff($type, $keyword, $page, $size); if ($res['total'] > 0) { $res['list'] = $res['list']->toArray(); foreach ($res['list'] as &$item) { if (count($relationIds) > 0 && in_array($item['id'], $relationIds)) { $item['selected'] = true; } } } return $this->json(0, '操作成功', $res); } return $this->json(4001, '非法请求'); } /** * 获取客户列表 * * @return Json * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException|Exception */ public function getAccountList(): Json { if ($this->request->isPost()) { $keyword = input('keyword/s', ''); $page = input('page/d', 1); $size = input('size/d', 10); $id = input('id', ''); $relationIds = explode(',', $id);//已选记录 $where = []; $where[] = ['is_staff', '=', AccountModel::COMMON_OFF]; if (!empty($keyword)) { $where[] = ['nickname|real_name|mobile', 'like', '%'.$keyword.'%']; } $res = AccountModel::findList($where, ['id', 'nickname', 'real_name', 'mobile'], $page, $size); if ($res['total'] > 0 && $relationIds) { $res['list'] = $res['list']->toArray(); foreach ($res['list'] as &$item) { $item['name_text'] = sprintf("昵称:%s;真实姓名:%s,手机号:%s", $item['nickname'], $item['real_name'], $item['mobile']); if (count($relationIds) > 0 && in_array($item['id'], $relationIds)) { $item['selected'] = true; } } } return $this->json(0, '操作成功', $res); } return $this->json(4001, '非法请求'); } /** * 充值孔雀币 * */ public function rechargeCoin() { $id = input('id/s'); if ($this->request->isPost()) { $ids = input('ids/s'); if (empty($ids)) { return $this->json("4003", "请选择用户"); } $ids = explode(",", $ids); if (count($ids) > 1000) { return $this->json("4003", "一次最多选择1000条"); } $coin = input("coin/d", 1, "abs"); $Account = AccountRepository::getInstance()->getModel() ->where("id", "in", $ids)->lock(true) ->select(); Db::startTrans(); try { AccountRepository::getInstance()->getModel()->where("id", "in", $ids)->inc("coin", $coin)->update(); $time = date("Y-m-d H:i:s"); $dataLog = []; $dataOperationLog = []; $Account->each(function ($item) use ($coin, $time, &$dataLog, &$dataOperationLog) { $dataLog[] = [ "account_id" => $item["id"], "operator" => ($this->auth['nickname'] ?? ""), "operator_id" => $this->auth['user_id'] ?? 0, "name" => "后台充值孔雀币", "num" => $coin, "type" => AccountDataLog::TYPE_COIN, "action" => AccountDataLog::ACTION_ADMIN_RECHARGE, "created_at" => $time, "surplus" => ($item["coin"] + $coin), ]; $dataOperationLog[] = [ "account_id" => $item["id"], "operator" => ($this->auth['nickname'] ?? ""), "num" => $coin, "remark" => "后台充值孔雀币", "type" => AccountDataLog::TYPE_COIN, "created_at" => $time, ]; }); AccountDataLog::insertAll($dataLog); AccountDataOperationLog::insertAll($dataOperationLog); Db::commit(); return $this->json(); } catch (Exception $e) { Db::rollback(); return $this->json("5003", "充值失败-1:".$e->getMessage()); } catch (RepositoryException $e) { Db::rollback(); return $this->json("5003", "充值失败-2:".$e->getMessage()); } } $this->data['id'] = $id; return $this->view(); } /** * 用户等级管理 * */ public function accountLevel() { if ($this->request->isPost()) { $page = input('page/d', 1); $limit = input('size/d', 10); $items = AccountLevel::findList([], [], $page, $limit, null, ["value" => "desc"]); $items["list"]->each(function (&$item) { if (empty($item["rights"])) { return; } $str = ""; foreach (explode(",", $item["rights"]) as $ritem) { foreach (AccountLevel::$rightsArray as $mitem) { if ($mitem["key"] == $ritem) { $str .= $mitem["title"]." "; } } } $item->rights = $str; }); return $this->json(0, '操作成功', $items); } return $this->view(); } /** * 添加用户等级管理 * */ public function addAccountLevel() { if ($this->request->isPost()) { $item = input('post.'); $rule = [ 'name|名称' => 'require', 'value|成长值' => 'require', ]; $validate = $this->validateByApi($item, $rule); if ($validate !== true) { return $validate; } try { AccountLevel::create($item); return $this->json(); } catch (ValidateException $e) { return $this->json(4001, $e->getError()); } } //权益列表 $rightsArray = AccountLevel::$rightsArray; $this->data['rightsJson'] = json_encode($rightsArray); return $this->view(); } /** * 添加用户等级管理 * */ public function delAccountLevel() { if ($this->request->isPost()) { $id = input('id/d'); $item = AccountLevel::findById($id); if (empty($item)) { return $this->json(4001, "信息不存在"); } AccountLevel::destroy($id); return $this->json(); } } /** * 编辑用户等级管理 * */ public function editAccountLevel() { $id = input("id/d"); $info = AccountLevel::findById($id); if ($this->request->isPost()) { if (empty($info)) { return $this->json(4001, "信息不存在"); } $item = $this->request->only(["name", "rights", "poster", "value", "content"]); $rule = [ 'name|名称' => 'require', 'value|成长值' => 'require', ]; $validate = $this->validateByApi($item, $rule); if ($validate !== true) { return $validate; } try { AccountLevel::updateById($id, $item); return $this->json(); } catch (ValidateException $e) { return $this->json(4001, $e->getError()); } } if (empty($info)) { return $this->error("信息不存在"); } $this->data['item'] = $info; //权益列表 $rightsArray = AccountLevel::$rightsArray; $selectd = []; if (!empty($info['rights'])) { $selectd = explode(",", $info['rights']); } $this->data['rightsJson'] = AccountLevel::xmSelectJson($selectd); return $this->view(); } }