添加:管理后台 - 代理中心 - 代理用户管理相关功能

This commit is contained in:
wuhui_zzw 2024-01-25 19:12:06 +08:00
parent a33b451285
commit 750966af78
8 changed files with 667 additions and 8 deletions

View File

@ -0,0 +1,83 @@
<?php
namespace app\common\dao\marketing;
use app\common\dao\BaseDao;
use app\common\model\marketing\Agent;
class AgentDao extends BaseDao{
protected function getModel(): string{
return Agent::class;
}
/**
* Common: 公共搜索查询
* Author: wu-hui
* Time: 2024/01/25 16:42
* @param array $params
* @return Agent
*/
public function searchList(array $params){
return (new Agent())
->where('is_del',0)
->when(isset($params['id']) && $params['id'] !== '',function($query) use ($params){
$query->where('id', (int)$params['id']);
})
->when(isset($params['uid']) && $params['uid'] !== '',function($query) use ($params){
$query->where('uid', (int)$params['uid']);
})
->when(isset($params['pid']) && $params['pid'] !== '',function($query) use ($params){
$query->where('pid', (int)$params['pid']);
})
->when(isset($params['contact_name']) && $params['contact_name'] !== '',function($query) use ($params){
$query->where('contact_name', 'like', "%{$params['contact_name']}%");
})
->when(isset($params['contact_phone']) && $params['contact_phone'] !== '',function($query) use ($params){
$query->where('contact_phone', $params['contact_phone']);
})
->when(isset($params['agent_type']) && $params['agent_type'] !== '',function($query) use ($params){
$query->where('agent_type', (int)$params['agent_type']);
})
->with([
'user' => function($query){
$query->field('uid,nickname,avatar');
},
'province' => function($query){
$query->field('id,name as province_name,code as province_code')->bind(['province_name', 'province_code']);
},
'city' => function($query){
$query->field('id,name as city_name,code as city_code')->bind(['city_name', 'city_code']);
},
'area' => function($query){
$query->field('id,name as area_name,code as area_code')->bind(['area_name', 'area_code']);
},
'street' => function($query){
$query->field('id,name as street_name,code as street_code')->bind(['street_name', 'street_code']);
},
'mer' => function($query){
$query->field('mer_id,mer_name,mer_avatar');
},
'merList' => function($query){
$query->field('agent_id,mer_name,mer_avatar');
},
'parent' => function($query){
$query->field('id,uid,agent_type')
->with([
'user' => function($query){
$query->field('uid,nickname,avatar')->bind(['nickname','avatar']);
}
]);
},
])
->order('create_time DESC,id DESC')
->append(['only_key','mer_id_list','children_count']);
}
}

View File

@ -71,6 +71,9 @@ class MerchantDao extends BaseDao
->when(isset($where['mer_id']) && $where['mer_id'] !== '', function ($query) use ($where) {
$query->where('mer_id', $where['mer_id']);
})
->when(isset($where['mer_id_list']) && $where['mer_id_list'] !== '', function ($query) use ($where) {
$query->whereIn('mer_id', $where['mer_id_list']);
})
->when(isset($where['category_id']) && $where['category_id'] !== '', function ($query) use ($where) {
$query->whereIn('category_id', is_array($where['category_id']) ? $where['category_id'] : explode(',', $where['category_id']));
})

View File

@ -7,6 +7,7 @@ namespace app\common\model;
use think\db\BaseQuery;
use think\facade\Db;
use think\Model;
/**
@ -63,4 +64,39 @@ abstract class BaseModel extends Model
return self::getInstance()->db($scope);
}
public static function batchUpdate(array $update, $whenField = 'id', $whereField = 'id', $raw = false){
$when = [];
$ids = [];
foreach ($update as $sets) {
# 跳过没有更新主键的数据
if (!isset($sets[$whenField])) {
continue;
}
$whenValue = $sets[$whenField];
foreach ($sets as $fieldName => $value) {
#主键不需要被更新
if ($fieldName == $whenField) {
array_push($ids, $value);
continue;
};
if ($raw) {
$when[$fieldName][] = "when {$whenValue} then {$value}";
} else {
$when[$fieldName][] = "when '{$whenValue}' then '{$value}'";
}
}
}
# 没有更新的条件id
if (!$when) return false;
$query = self::whereIn($whereField, $ids);
# 组织sql
foreach ($when as $fieldName => &$item) {
$item = Db::raw("case $whenField " . implode(' ', $item) . ' end ');
}
return $query->update($when);
}
}

View File

@ -0,0 +1,87 @@
<?php
namespace app\common\model\marketing;
use app\common\model\BaseModel;
use app\common\model\store\CityArea;
use app\common\model\system\merchant\Merchant;
use app\common\model\user\User;
/**
* Common: 代理中心
* Author: wu-hui
* Time: 2024/01/23 17:53
* Class Agent
* @package app\common\model\user
*/
class Agent extends BaseModel{
public static function tablePk(): string{
return 'id';
}
public static function tableName(): string{
return 'agent';
}
/**
* Common: 获取器 —— 信息唯一键(上级一致)
* Author: wu-hui
* Time: 2024/01/24 18:15
* @return string
*/
public function getOnlyKeyAttr():string{
return ($this->uid ?? '') . '_' . ($this->agent_type ?? '');
}
/**
* Common: 获取器 —— 获取配送商关联的商户
* Author: wu-hui
* Time: 2024/01/25 17:58
* @return array|string
*/
public function getMerIdListAttr(){
if(($this->agent_type ?? 0) == 8 && ($this->id ?? 0) > 0){
return Merchant::where('agent_id',$this->id)->column('mer_id');
}
return [];
}
/**
* Common: 获取器 —— 获取下级数量(直属)
* Author: wu-hui
* Time: 2024/01/25 19:06
* @return int
*/
public function getChildrenCountAttr():int{
if(($this->id ?? 0) > 0){
return self::where('pid',$this->id)->count();
}
return 0;
}
public function user(){
return $this->hasOne(User::class, 'uid', 'uid');
}
public function parent(){
return $this->hasOne(self::class, 'id', 'pid');
}
public function province(){
return $this->hasOne(CityArea::class, 'id', 'province_id');
}
public function city(){
return $this->hasOne(CityArea::class, 'id', 'city_id');
}
public function area(){
return $this->hasOne(CityArea::class, 'id', 'area_id');
}
public function street(){
return $this->hasOne(CityArea::class, 'id', 'street_id');
}
public function mer(){
return $this->hasOne(Merchant::class, 'mer_id', 'mer_id');
}
public function merList(){
return $this->hasMany(Merchant::class, 'agent_id', 'id');
}
}

View File

@ -0,0 +1,206 @@
<?php
namespace app\common\repositories\marketing;
use app\common\dao\marketing\AgentDao;
use app\common\model\marketing\Agent;
use app\common\model\system\merchant\Merchant;
use app\common\repositories\BaseRepository;
use think\facade\Db;
class AgentRepository extends BaseRepository{
protected $dao;
public function __construct(AgentDao $dao){
$this->dao = $dao;
}
/**
* Common: 获取信息列表
* Author: wu-hui
* Time: 2024/01/24 15:41
* @param array $params
* @param int $page
* @param int $limit
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getList(array $params,int $page,int $limit):array{
$query = $this->dao->searchList($params);
$count = $query->count();
$list = $query->page($page,$limit)->select();
return compact('count','list');
}
/**
* Common: 代理添加/编辑
* Author: wu-hui
* Time: 2024/01/25 9:03
* @param int $agentId
* @param array $data
* @param array $childrenList
* @return mixed
*/
public function editInfo(int $agentId, array $data, array $childrenList){
return Db::transaction(function() use ($agentId, $data, $childrenList){
// 处理当前角色用户信息
if($agentId > 0) $this->currentRoleHandle($agentId, $data);
// 处理子类信息
if(count($childrenList) > 0) $this->childrenListHandle($agentId, $childrenList);
});
}
/**
* Common: 代理添加/编辑 —— 处理当前角色信息
* Author: wu-hui
* Time: 2024/01/25 9:03
* @param int $agentId
* @param array $data
*/
private function currentRoleHandle(int $agentId,array $data){
// 修改基本信息
$keys = array_flip((array)[
"uid",
"pid",
"agent_type",
"agent_stock",
"contact_name",
"contact_phone",
"province_id",
"city_id",
"area_id",
"street_id",
"address",
"lat",
"lng",
"mer_id"
]);
$updateInfo = array_intersect_key($data, $keys);
Agent::update($updateInfo,['id'=>$agentId]);
// 修改配送商 - 商户关联信息
$merIdList = is_array($data['mer_id_list']) ? $data['mer_id_list'] : [];
if(count($merIdList) > 0){
// 删除已经存在的关联信息
Merchant::update(['agent_id' => null],['agent_id'=>$agentId]);
// 建立新的关联信息
Merchant::whereIn('mer_id',$data['mer_id_list'])->update(['agent_id' => $agentId]);
}
}
/**
* Common: 代理添加/编辑 —— 处理子类信息
* Author: wu-hui
* Time: 2024/01/25 17:45
* @param int $agentId
* @param array $childrenList
* @throws \think\db\exception\DbException
*/
private function childrenListHandle(int $agentId,array $childrenList){
$insertData = [];
$updateData = [];
$merUpdateData = [];
$keys = array_flip((array)[
"id",
"uid",
"pid",
"agent_type",
"agent_stock",
"contact_name",
"contact_phone",
"province_id",
"city_id",
"area_id",
"street_id",
"address",
"lat",
"lng",
"mer_id"
]);
// 循环:区分对应的操作
foreach($childrenList as $childrenItem){
unset($childrenItem['user']);
$childrenItemId = $childrenItem['id'] ?? 0;
$handleData = array_intersect_key($childrenItem, $keys);
$handleData['pid'] = $agentId;
// 判断:如果为配送商 处理商户关联信息
if($childrenItem['agent_type'] == 8){
// 判断:应该修改还是编辑
if((int)$childrenItemId > 0) $this->dao->update($childrenItemId,$handleData);
else $childrenItemId = Agent::insertGetId($handleData);
// 处理商户关联信息
foreach($childrenItem['mer_id_list'] as $merId){
$merUpdateData[] = [
'mer_id' => $merId,
'agent_id' => $childrenItemId
];
}
}else{
// 判断:应该修改还是编辑
if((int)$childrenItemId > 0) $updateData[] = $handleData;
else $insertData[] = $handleData;
}
}
// 获取需要删除的数据的id 删除思路:先获取总数据、对修改数据比较、删除缺少的项
$allIds = $this->dao->searchList([])->where('pid',$agentId)->column('id');
$updateIds = array_column($updateData,'id');
$delIds = array_diff($allIds,$updateIds);
// 处理结果 进行对应的操作;必须按照先删除、在修改、最后添加的顺序进行
if(count($delIds) > 0) Agent::whereIn('id',$delIds)->where('agent_type','<>',8)->update(['is_del'=>1]);
if(count($updateData) > 0) Agent::batchUpdate(array_values($updateData));
if(count($insertData) > 0) $this->dao->insertAll($insertData);
if(count($merUpdateData) > 0) {
// 删除已经存在的关联信息
Merchant::whereIn('agent_id',array_column($childrenList,'id'))->update(['agent_id' => null]);
// 建立新的关联信息
Merchant::batchUpdate(array_values($merUpdateData),'mer_id','mer_id');
}
}
/**
* Common: 代理添加/编辑 —— 获取需要编辑的信息
* Author: wu-hui
* Time: 2024/01/24 16:57
* @param $params
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getEditInfo($params){
// 获取当前信息 编辑类型0=发起人管理,1=发起人,2=省公司,3=省合伙人(外勤),4=省合伙人(内勤),5=区县运营商,6=区县合伙人,7=餐厅,8=配送商
if((int)$params['agent_id'] > 0) {
// 非发起人管理存在info及children_list
$info = $this->dao->searchList(['id' => $params['agent_id']])->findOrEmpty();
$childrenList = $this->dao
->searchList(['pid' => $params['agent_id']])
->select()
->toArray();
}
else{
// 发起人管理仅存在children_list
$childrenList = $this->dao
->searchList(['pid' => 0,'agent_type' => 1])
->select()
->toArray();
}
// 信息处理及返回
$childrenList = array_column($childrenList,null,'only_key');
return [
'info' => $info ?? [],
'children_list' => $childrenList
];
}
}

View File

@ -0,0 +1,219 @@
<?php
namespace app\controller\admin\marketing;
use app\common\repositories\marketing\AgentRepository;
use app\common\repositories\system\merchant\MerchantRepository;
use crmeb\basic\BaseController;
use think\exception\ValidateException;
class Agent extends BaseController{
/**
* Common: 代理列表
* Author: wu-hui
* Time: 2024/01/24 15:40
* @return mixed
*/
public function agentList(){
[$page, $limit] = $this->getPage();
$params = $this->request->params(['uid','agent_type','contact_name','contact_phone']);
$data = app()->make(AgentRepository::class)->getList((array)$params,(int)$page,(int)$limit);
return app('json')->success($data);
}
/**
* Common: 编辑信息
* Author: wu-hui
* Time: 2024/01/24 16:05
* @return mixed
*/
public function editInfo(){
// 参数获取
$params = $this->checkParams();
// 数据处理
app()->make(AgentRepository::class)->editInfo((int)$params['agentId'],(array)$params['data'],(array)$params['childrenList']);
return app('json')->success('操作成功');
}
/**
* Common: 编辑参数获取 & 参数校验
* Author: wu-hui
* Time: 2024/01/24 14:16
* @return array
*/
public function checkParams(){
// 参数获取
$data = $this->request->params([
['uid',0],
['pid',0],
['agent_type',0],
['agent_stock',0],
'contact_name',
'contact_phone',
['province_id',0],
['city_id', 0],
['area_id', 0],
['street_id', 0],
'address',
'lat',
'lng',
['mer_id', 0],
['mer_id_list', []],
]);
$agentId = (int)$this->request->param('id');
$childrenList = $this->request->param('children_list');
// 判断:如果$agentId 为空或者0则当前操作为编辑发起人至少有一个发起人信息
if($agentId <= 0){
if(count($childrenList) <= 0) throw new ValidateException('请至少添加一个发起人!');
$agentStock = (float)array_sum(array_column($childrenList,'agent_stock'));
if($agentStock != 100) throw new ValidateException('所有发起人的股份总和必须等于100');
}
// 循环判断:$childrenList 的数据是否完善 类型1=发起人,2=省公司,3=省合伙人(外勤),4=省合伙人(内勤),5=区县运营商,6=区县合伙人,7=餐厅,8=配送商
foreach($childrenList as $childrenItem){
if(empty($childrenItem['contact_name'])) throw new ValidateException('请输入联系人姓名!');
if(empty($childrenItem['contact_phone'])) throw new ValidateException('请输入联系人电话!');
if(isPhone($childrenItem['contact_phone'])) throw new ValidateException('请输入正确的联系人电话!');
// 判断:根据当前角色判断 数据
switch((int)$childrenItem['agent_type']){
case 1:
if((float)$childrenItem['agent_stock'] <= 0) throw new ValidateException('发起人的股份必须大于0');
break;
case 2:
case 3:
case 4:
if((float)$childrenItem['province_id'] <= 0) throw new ValidateException('请完善地区信息!');
break;
case 5:
case 6:
if((float)$childrenItem['province_id'] <= 0) throw new ValidateException('请完善地区信息!');
if((float)$childrenItem['city_id'] <= 0) throw new ValidateException('请完善地区信息!');
if((float)$childrenItem['area_id'] <= 0) throw new ValidateException('请完善地区信息!');
break;
case 7:
if((float)$childrenItem['province_id'] <= 0) throw new ValidateException('请完善地区信息!');
if((float)$childrenItem['city_id'] <= 0) throw new ValidateException('请完善地区信息!');
if((float)$childrenItem['area_id'] <= 0) throw new ValidateException('请完善地区信息!');
if((float)$childrenItem['street_id'] <= 0) throw new ValidateException('请完善地区信息!');
if(empty($childrenItem['address'])) throw new ValidateException('请完善地区信息!');
if((float)$childrenItem['lat'] <= 0 || (float)$childrenItem['lng'] <= 0) throw new ValidateException('请选择定位信息!');
if((float)$childrenItem['mer_id'] <= 0) throw new ValidateException('餐厅必须关联商户!');
break;
case 8:
if(count($childrenItem['mer_id_list']) <= 0) throw new ValidateException('配送商至少关联一个商户!');
break;
}
}
// 判断:餐厅关联的商户是否重复
$merIds = array_filter(array_column($childrenList,'mer_id'));
if(count($merIds) > 0){
// 判断:是否存在重复
if(count($merIds) != count(array_unique($merIds))) throw new ValidateException('每个商户只能关联一个餐厅,请勿重复关联!');
// 判断:当前关联商户中,是否存在其他已经被关联的商户
$ids = array_filter(array_column($childrenList,'id'));
$isHas = (int)app()->make(AgentRepository::class)
->getSearch([])
->whereNotIn('id',$ids)
->whereIn('mer_id',$merIds)
->count();
if($isHas > 0) throw new ValidateException('每个商户只能关联一个餐厅,请勿重复关联!');
}
// 判断:配送商关联的商户是否重复
$merIdList = array_filter(array_column($childrenList,'mer_id_list'));
if(count($merIdList) > 0){
// 判断:是否存在重复
$newMerIdList = call_user_func_array('array_merge', $merIdList);
if(count($newMerIdList) != count(array_unique($newMerIdList))) throw new ValidateException('每个商户只能关联一个配送商,请勿重复关联!');
// 判断:当前关联商户中,是否存在其他已经被关联的商户
$ids = array_filter(array_column($childrenList,'id'));
$isHas = (int)app()->make(MerchantRepository::class)
->getSearch([])
->whereNotIn('agent_id',$ids)
->whereIn('mer_id',$newMerIdList)
->count();
if($isHas > 0) throw new ValidateException('每个商户只能关联一个配送商,请勿重复关联!');
}
// 判断agentId 大于0验证data的信息
if($agentId > 0){
if(empty($data['contact_name'])) throw new ValidateException('请输入联系人姓名!');
if(empty($data['contact_phone'])) throw new ValidateException('请输入联系人电话!');
if(isPhone($data['contact_phone'])) throw new ValidateException('请输入正确的联系人电话!');
// 判断:根据当前角色判断 数据
switch((int)$data['agent_type']){
case 2:
case 3:
case 4:
if((float)$data['province_id'] <= 0) throw new ValidateException('请完善地区信息!');
break;
case 5:
case 6:
if((float)$data['province_id'] <= 0) throw new ValidateException('请完善地区信息!');
if((float)$data['city_id'] <= 0) throw new ValidateException('请完善地区信息!');
if((float)$data['area_id'] <= 0) throw new ValidateException('请完善地区信息!');
break;
case 7:
if((float)$data['province_id'] <= 0) throw new ValidateException('请完善地区信息!');
if((float)$data['city_id'] <= 0) throw new ValidateException('请完善地区信息!');
if((float)$data['area_id'] <= 0) throw new ValidateException('请完善地区信息!');
if((float)$data['street_id'] <= 0) throw new ValidateException('请完善地区信息!');
if(empty($data['address'])) throw new ValidateException('请完善地区信息!');
if((float)$data['lat'] <= 0 || (float)$data['lng'] <= 0) throw new ValidateException('请选择定位信息!');
if((float)$data['mer_id'] <= 0) throw new ValidateException('餐厅必须关联商户!');
break;
case 8:
if(count($data['mer_id_list']) <= 0) throw new ValidateException('配送商至少关联一个商户!');
break;
}
// 判断:餐厅关联的商户是否重复
if((int)$data['mer_id'] > 0){
// 判断:当前关联商户中,是否存在其他已经被关联的商户
$isHas = (int)app()->make(AgentRepository::class)
->getSearch([])
->where('id','<>',$agentId)
->where('mer_id',(int)$data['mer_id'])
->count();
if($isHas > 0) throw new ValidateException('每个商户只能关联一个餐厅,请勿重复关联!');
}
// 判断:配送商关联的商户是否重复
$merIdList = is_array($data['mer_id_list']) ? $data['mer_id_list'] : [];
if(count($merIdList) > 0){
// 判断:当前关联商户中,是否存在其他已经被关联的商户
$isHas = (int)app()->make(MerchantRepository::class)
->getSearch([])
->where('agent_id','<>',$agentId)
->whereIn('mer_id',$data['mer_id_list'])
->count();
if($isHas > 0) throw new ValidateException('每个商户只能关联一个配送商,请勿重复关联!');
}
}
return compact("data", "agentId", "childrenList");
}
/**
* Common: 获取编辑信息
* Author: wu-hui
* Time: 2024/01/24 18:25
* @return mixed
*/
public function getEditInfo(){
// 参数获取
$params = $this->request->params(['agent_id']);
$data = app()->make(AgentRepository::class)->getEditInfo((array)$params);
return app('json')->success($data);
}
}

View File

@ -65,7 +65,7 @@ class Merchant extends BaseController
public function lst()
{
[$page, $limit] = $this->getPage();
$where = $this->request->params(['keyword', 'date', 'status', 'statusTag', 'is_trader', 'category_id', 'type_id',['order','create_time'],'is_best']);
$where = $this->request->params(['mer_id_list','keyword','mer_id', 'date', 'status', 'statusTag', 'is_trader', 'category_id', 'type_id',['order','create_time'],'is_best']);
return app('json')->success($this->repository->lst($where, $page, $limit));
}

View File

@ -8,7 +8,6 @@ use app\common\middleware\AllowOriginMiddleware;
use app\common\middleware\LogMiddleware;
Route::group(function () {
//积分
Route::group('user/integral', function () {
Route::get('config', '.UserIntegral/getConfig')->name('systemUserIntegralConfig')->option([
@ -460,16 +459,42 @@ Route::group(function () {
Route::get('pickup_point_record', '.ExchangeQuota/pickupPointRecord')->name('systemUserExchangePickupPointRecord')->option([
'_alias' => '提货记录',
]);
})->prefix('admin.user')->option([
'_path' => '/marketing/integral/hold',
'_auth' => true,
]);
// 代理中心
Route::group('marketing/agent', function () {
// 代理商相关
Route::get('list','/agentList')->name('systemMarketingAgentList')->option([
'_alias' => '代理列表',
]);
Route::post('edit_info','/editInfo')->name('systemMarketingAgentEditInfo')->option([
'_alias' => '代理编辑',
]);
Route::get('get_edit_info','/getEditInfo')->name('systemMarketingAgentGetEditInfo')->option([
'_alias' => '获取编辑信息',
]);
})->prefix('admin.marketing.Agent')->option([
'_path' => '/marketing/agent/list',
'_auth' => true,
]);