Explorar o código

修改独立站的客户关联查询修改

lvhao hai 1 día
pai
achega
4149a7da98
Modificáronse 1 ficheiros con 318 adicións e 1 borrados
  1. 318 1
      core/CoreApp/controllers/Customer.php

+ 318 - 1
core/CoreApp/controllers/Customer.php

@@ -510,7 +510,7 @@ class Customer extends Start_Controller {
 	}
 	
 	
-	public function _dgso()
+	public function _dgso——tmp()
 	{
 		$user = $this->user->get_api($_SESSION['api']);
 		if($user)
@@ -2835,4 +2835,321 @@ class Customer extends Start_Controller {
 	    }
 		$this->_Template('customer_newold',$this->data);
 	}
+
+	/**
+	 * _dgsov1 - 优化版的_dgso方法
+	 * 改进点:
+	 * 1. 修复SQL注入漏洞,使用escape转义
+	 * 2. 修复$d[0]越界问题
+	 * 3. _dgcz改用BFS非递归算法,避免递归爆炸
+	 * 4. 批量预加载关联数据,解决N+1查询
+	 * 5. 修复特殊搜索路径的分页逻辑
+	 * 6. 使用map映射替代硬编码if-else
+	 * 7. 添加输入参数校验
+	 * 8. 未使用的筛选参数(shop/name/level/时间范围)添加为实际筛选条件
+	 */
+	public function _dgso()
+	{
+		$user = $this->user->get_api($_SESSION['api']);
+		if (!$user)
+		{
+			$vip = 0;
+			die("请先登录!!!");
+		}
+
+		$fgshop = "";
+		$sid = "";
+		$users = explode('|', trim($user['shop'], '|'));
+		foreach ($users as $value)
+		{
+			$fgshop .= " shop = " . intval($value) . " or";
+			$sid .= " id = " . intval($value) . " or";
+		}
+		$vip = ($user['vip'] == 1) ? 1 : 0;
+
+		$post = $this->input->post(NULL, TRUE);
+		if (!isset($post['page']))
+		{ 
+			$wlshop = $this->shop->find_all('1=1 and ' . rtrim($sid, 'or'));
+			$this->data['wlshop'] = $wlshop;
+			$this->data['vip'] = $vip;
+			$this->_Template('customer_dgso', $this->data);
+			return;
+		}
+
+		// 输入校验:page和perpage必须是正整数
+		$page = max(1, intval($this->input->post('page', true)));
+		$perpage = max(1, min(200, intval($this->input->post('perpage', true))));
+
+		// 获取搜索参数
+		$shop = intval($this->input->post('shop', true));
+		$numphone = $this->input->post('numphone', true);
+		$name = trim($this->input->post('name', true));
+		$email = trim($this->input->post('email', true));
+		$address = trim($this->input->post('address', true));
+		$level = intval($this->input->post('level', true));
+		$num = intval($this->input->post('num', true));
+		$timetk = $this->input->post('timetk', true);
+		$timetj = $this->input->post('timetj', true);
+		$timetk = strtotime($timetk);
+		$timetj = strtotime($timetj);
+
+		// 构建WHERE条件,使用escape防SQL注入
+		$where = "1=1 and (" . rtrim($fgshop, 'or') . ")";
+
+		if ($numphone)
+		{
+			$where .= " and numphone = " . $this->db->escape($numphone);
+		}
+		if ($email)
+		{
+			$where .= " and email like '%" . $this->db->escape_like_str($email) . "%'";
+		}
+		if ($address)
+		{
+			$where .= " and address like '%" . $this->db->escape_like_str($address) . "%'";
+		}
+		if ($shop)
+		{
+			$where .= " and shop = " . intval($shop);
+		}
+		if ($name)
+		{
+			$where .= " and name like '%" . $this->db->escape_like_str($name) . "%'";
+		}
+		if ($level)
+		{
+			$where .= " and level = " . intval($level);
+		}
+		if ($num)
+		{
+			$where .= " and num = " . intval($num);
+		}
+		if ($timetk && $timetj)
+		{
+			$where .= " and time >= " . intval($timetk) . " and time <= " . intval($timetj);
+		}
+
+		$fields = 'id,shop,source,name,email,country,level,money,num,time,type,numphone,address';
+
+		if ($numphone || $email || $address)
+		{
+			// 特殊搜索路径:通过地址/邮箱/电话查找关联客户
+			$d = $this->customer->find_all($where);
+
+			// 修复:判断$d是否为空,避免越界
+			if (empty($d))
+			{
+				echo json_encode(array('total' => 0, 'over' => 0, 'pagenum' => 0, 'rows' => array()));
+				exit;
+			}
+
+			// 使用BFS非递归算法查找所有关联客户
+			$cx = array();
+			$info_list = $this->_dgczv1($cx, $d);
+			$info_list = array_values($info_list);
+			$total = count($info_list);
+			$pagenum = ceil($total / $perpage);
+
+			// 修复:根据当前页码做切片分页
+			$start = ($page - 1) * $perpage;
+			$over = $total - ($start + $perpage);
+			$info_list = array_slice($info_list, $start, $perpage);
+		}
+		else
+		{
+			// 正常搜索路径
+			$order_str = "id desc";
+			$start = ($page - 1) * $perpage;
+
+			$info_list = $this->customer->find_all($where, 'id,shop,source,name,email,country,level,money,num,time,type', $order_str, $start, $perpage);
+			$total = $this->customer->find_count($where);
+			$pagenum = ceil($total / $perpage);
+			$over = $total - ($start + $perpage);
+		}
+
+		// 批量预加载关联数据,避免N+1查询
+		$shopIds = array();
+		$sourceIds = array();
+		$countryIds = array();
+		foreach ($info_list as $value)
+		{
+			if (!empty($value['shop'])) $shopIds[$value['shop']] = true;
+			if (!empty($value['source'])) $sourceIds[$value['source']] = true;
+			if (!empty($value['country'])) $countryIds[$value['country']] = true;
+		}
+
+		$shopMap = array();
+		if (!empty($shopIds))
+		{
+			$idList = implode(',', array_map('intval', array_keys($shopIds)));
+			$shopData = $this->shop->find_all("id in ($idList)", 'id,shopname');
+			foreach ($shopData as $row)
+			{
+				$shopMap[$row['id']] = $row['shopname'];
+			}
+		}
+
+		$sourceMap = array();
+		if (!empty($sourceIds))
+		{
+			$idList = implode(',', array_map('intval', array_keys($sourceIds)));
+			$sourceData = $this->typeclass->find_all("id in ($idList)", 'id,title');
+			foreach ($sourceData as $row)
+			{
+				$sourceMap[$row['id']] = $row['title'];
+			}
+		}
+
+		$countryMap = array();
+		if (!empty($countryIds))
+		{
+			$idList = implode(',', array_map('intval', array_keys($countryIds)));
+			$countryData = $this->country->find_all("id in ($idList)", 'id,name');
+			foreach ($countryData as $row)
+			{
+				$countryMap[$row['id']] = $row['name'];
+			}
+		}
+
+		// Level映射表
+		$levelMap = array(
+			1 => '网红',
+			2 => '批发',
+			3 => '店铺转线下',
+			4 => '线下其他',
+			5 => '店内客户',
+		);
+
+		// 数据后处理
+		foreach ($info_list as $key => $value)
+		{
+			// 使用预加载的map赋值,避免逐条查询
+			$info_list[$key]['shop'] = isset($shopMap[$value['shop']]) ? $shopMap[$value['shop']] : '';
+			$info_list[$key]['source'] = isset($sourceMap[$value['source']]) ? $sourceMap[$value['source']] : '';
+
+			if ($value['country'] != 0)
+			{
+				$info_list[$key]['country'] = isset($countryMap[$value['country']]) ? $countryMap[$value['country']] : '未知';
+			}
+			else
+			{
+				$info_list[$key]['country'] = '未知';
+			}
+
+			// 使用map映射替代if-else链
+			$info_list[$key]['level'] = isset($levelMap[$value['level']]) ? $levelMap[$value['level']] : '未知';
+
+			if ($value['time'] != 0)
+			{
+				$info_list[$key]['time'] = date('Y-m-d', $value['time']);
+			}
+			else
+			{
+				$info_list[$key]['time'] = '无';
+			}
+
+			if ($value['type'] != 2)
+			{
+				$info_list[$key]['type'] = "<a href='javascript:void(0);' class='window' data-h='/customer/mdedit/" . $value['id'] . "' data-t='客户下单'><b>下单</b></a>&nbsp;&nbsp;&nbsp;&nbsp;<a class='customer' data-type='2' data-t='yr' data-id='" . $value['id'] . "' href='javascript:void(0);'>移入黑名单</a>";
+			}
+			else
+			{
+				$info_list[$key]['type'] = '黑名单客户';
+			}
+
+			unset($info_list[$key]['numphone']);
+			unset($info_list[$key]['address']);
+		}
+
+		$rows = array('total' => $total, 'over' => $over, 'pagenum' => $pagenum, 'rows' => ($info_list));
+		echo json_encode($rows);
+		exit;
+	}
+
+	/**
+	 * _dgczv1 - 优化版的_dgcz方法
+	 * 使用BFS广度优先搜索替代递归,避免递归爆炸和栈溢出
+	 * 每一层合并所有搜索条件为一次查询,大幅减少数据库请求
+	 */
+	public function _dgczv1($child, $data)
+	{
+		// 初始化已处理集合
+		foreach ($data as $value)
+		{
+			if (!isset($child[$value['id']]))
+			{
+				$child[$value['id']] = $value;
+			}
+		}
+
+		$fields = 'id,shop,source,name,email,country,level,money,num,time,type,numphone,address';
+
+		// BFS广度优先搜索
+		$queue = $data;
+		$maxIterations = 50; // 安全上限,防止无限循环
+
+		while (!empty($queue) && $maxIterations > 0)
+		{
+			$maxIterations--;
+
+			// 收集当前层所有不重复的搜索词
+			$addressSet = array();
+			$emailSet = array();
+			$numphoneSet = array();
+
+			foreach ($queue as $row)
+			{
+				if (!empty($row['address']))
+				{
+					$addressSet[$row['address']] = true;
+				}
+				if (!empty($row['email']))
+				{
+					$emailSet[$row['email']] = true;
+				}
+				if (!empty($row['numphone']))
+				{
+					$numphoneSet[$row['numphone']] = true;
+				}
+			}
+
+			$queue = array(); // 清空当前层,准备下一层
+
+			// 构建合并后的查询条件
+			$conditions = array();
+			foreach (array_keys($addressSet) as $addr)
+			{
+				$conditions[] = "address like '%" . $this->db->escape_like_str($addr) . "%'";
+			}
+			foreach (array_keys($emailSet) as $em)
+			{
+				$conditions[] = "email like '%" . $this->db->escape_like_str($em) . "%'";
+			}
+			foreach (array_keys($numphoneSet) as $np)
+			{
+				$conditions[] = "numphone like '%" . $this->db->escape_like_str($np) . "%'";
+			}
+
+			if (empty($conditions))
+			{
+				break;
+			}
+
+			// 一次查询获取所有匹配记录
+			$where = implode(' or ', $conditions);
+			$rows = $this->customer->find_all($where, $fields);
+
+			foreach ($rows as $row)
+			{
+				if (!isset($child[$row['id']]))
+				{
+					$child[$row['id']] = $row;
+					$queue[] = $row; // 新发现的节点加入下一层搜索
+				}
+			}
+		}
+
+		return $child;
+	}
 }