diff --git a/application/admin/addresmart/Address.php b/application/admin/addresmart/Address.php index 7ecbfb4..385d78b 100644 --- a/application/admin/addresmart/Address.php +++ b/application/admin/addresmart/Address.php @@ -18,7 +18,11 @@ class Address $name_items [] = $item->title; $name_items_map [$item->title] = $item->id; } - $type = self::findMostSimilar($string,$name_items); + + $titles = Item::where('status',1)->column('title'); + $type = self::extractServiceTypes($string,$titles)[0] ?? ''; + + $type_arr = explode('__',$type); $type = $type_arr[0] ?? ''; $str = $type_arr[1] ?? ''; @@ -34,9 +38,9 @@ class Address $fuzz = self::fuzz($re['addr']); $parse = self::parse($fuzz['a1'], $fuzz['a2'], $fuzz['a3']); - $re['province'] = $parse['province']; - $re['city'] = $parse['city']; - $re['region'] = $parse['region']; + $re['province'] = $parse['province'] ?? ''; + $re['city'] = $parse['city'] ?? ''; + $re['region'] = $parse['region'] ?? ''; $re['item'] = [ 'id'=> $name_items_map[$type] ?? 0, 'item' => $type ?? '' @@ -305,4 +309,38 @@ class Address return $r; } + + + /** + * 从聊天内容中提取匹配的服务类型 + * + * @param string $chatText 聊天内容 + * @param array $serviceTypes 服务类型数组 + * @param bool $returnAll 是否返回全部匹配,false 时只返回第一个匹配 + * @return array|string|null 匹配的服务类型(数组或单个字符串) + */ + static function extractServiceTypes(string $chatText, array $serviceTypes, bool $returnAll = true): array|string|null + { + // 去重 + 去空 + $cleaned = array_filter(array_map('trim', $serviceTypes)); + + // 优先匹配更长的词 + usort($cleaned, fn($a, $b) => mb_strlen($b, 'UTF-8') - mb_strlen($a, 'UTF-8')); + + $matched = []; + + foreach ($cleaned as $service) { + if (mb_stripos($chatText, $service) !== false) { + if ($returnAll) { + $matched[] = $service; + } else { + return $service; + } + } + } + + return $returnAll ? $matched : null; + } + + } diff --git a/application/admin/command/Test.php b/application/admin/command/Test.php index ef5fc4e..f97508a 100644 --- a/application/admin/command/Test.php +++ b/application/admin/command/Test.php @@ -34,37 +34,12 @@ class Test extends Command protected function execute(Input $input, Output $output) { - dd(config('system_id')); - - $order = Order::where('id',140)->find(); - AutoDispatchLogic::autoDispatch($order); - - - $hookParams = [ - 'dispatch' => (new OrderDispatch())->where('id', 144)->find(), - 'remark' => '系统自动派单给师傅:'. '时间嗯' .'('.'12312'.')', + $dispatch = OrderDispatch::where('id',177)->get(); + $hookParams2 = [ + 'dispatch' => $dispatch, + 'remark' => '手动派单给师傅:' . '老师傅' .'(123)', ]; - - Lang::load(APP_PATH . 'admin/lang/zh-cn/orders/dispatch2.php'); - - $Model = new \app\admin\model\OrderDispatch(); - $statusList = $Model->getStatusList(); - $dispatch = $hookParams['dispatch']; //订单对象 - $remark = $hookParams['remark'] ?? ''; //备注 - $data = [ - 'dispatch_id' => $dispatch->id, - 'order_id' => $dispatch->order_id, - 'worker_id' => $dispatch->worker_id, - 'status' => $dispatch->status, - 'status_text' => $statusList[$dispatch->status], - 'remark' => $remark, - 'admin_user' => $dispatch->admin_user??'sys', - ]; - dd($data); - - - dd($res); - + Hook::listen('order_dispatch_change', $hookParams2); } diff --git a/application/admin/controller/CustomerInfoExtractor.php b/application/admin/controller/CustomerInfoExtractor.php new file mode 100644 index 0000000..3329cf1 --- /dev/null +++ b/application/admin/controller/CustomerInfoExtractor.php @@ -0,0 +1,91 @@ + $this->extractNickname($chatText), + 'city' => $this->extractCity($chatText), + 'district' => $this->extractDistrict($chatText), + 'address' => $this->extractAddress($chatText), + 'phone' => $this->extractPhone($chatText), + 'remark' => $this->extractRemark($chatText), + 'services' => $this->extractServices($chatText, $serviceTypes), + ]; + } + + protected function extractNickname(string $text): ?string + { + if (preg_match('/^(.*?)\s*-->/u', $text, $match)) { + return trim($match[1]); + } + return null; + } + + protected function extractCity(string $text): ?string + { + if (preg_match('/(北京|上海|广州|深圳|武汉|成都|重庆|杭州|南京|天津|西安|苏州|郑州|长沙|青岛|合肥|福州|厦门|南昌|昆明|大连|宁波|无锡|哈尔滨|长春|石家庄|南宁|贵阳|兰州|呼和浩特|乌鲁木齐)/u', $text, $match)) { + return $match[1]; + } + return null; + } + + protected function extractDistrict(string $text): ?string + { + if (preg_match('/([\p{Han}]{1,10}区)/u', $text, $match)) { + return $match[1]; + } + return null; + } + + protected function extractAddress(string $text): ?string + { + if (preg_match('/(湖北省|四川省|北京市|上海市|重庆市|[\p{Han}]+省)?[\p{Han}]+市\s*[\p{Han}]+区.*?(\d+栋.*?室)/u', $text, $match)) { + return $match[0]; + } + return null; + } + + protected function extractPhone(string $text): ?string + { + if (preg_match('/1[3-9]\d{9}/', $text, $match)) { + return $match[0]; + } + return null; + } + + protected function extractRemark(string $text): ?string + { + if (preg_match_all('/https?:\/\/[^\s]+/i', $text, $matches)) { + return implode(', ', $matches[0]); + } + + // 其他软件/售后/推广语也可加关键词检测 + if (str_contains($text, '软件下载') || str_contains($text, '自动发货')) { + return '可能包含软件下载或推广信息'; + } + + return null; + } + + protected function extractServices(string $text, array $serviceTypes): array + { + $cleaned = array_filter(array_map('trim', $serviceTypes)); + usort($cleaned, fn($a, $b) => mb_strlen($b, 'UTF-8') - mb_strlen($a, 'UTF-8')); + + $matched = []; + foreach ($cleaned as $service) { + if (mb_stripos($text, $service) !== false) { + $matched[] = $service; + } + } + return $matched; + } +} \ No newline at end of file diff --git a/application/admin/controller/Order.php b/application/admin/controller/Order.php index be5da90..7528246 100644 --- a/application/admin/controller/Order.php +++ b/application/admin/controller/Order.php @@ -5,6 +5,7 @@ namespace app\admin\controller; use app\admin\addresmart\Address; use app\admin\controller\orders\DispatchLogic; use app\admin\model\Admin; +use app\admin\model\Item; use app\admin\model\Message; use app\admin\model\order\Invoice; use app\admin\model\OrderDispatch; @@ -30,6 +31,7 @@ use function Symfony\Component\Clock\now; */ class Order extends Backend { + use CustomerInfoExtractor; /** * Order模型对象 * @var \app\admin\model\Order @@ -389,7 +391,11 @@ class Order extends Backend public function smart() { - $this->success(data: Address::smart(request()->get('str'))); +// $titles = Item::where('status',1)->column('title'); +// $res = $this->extractCustomerInfo(request()->post('str'),$titles); +// dd($res); + + $this->success(data: Address::smart(request()->post('str'))); } diff --git a/application/admin/validate/Order.php b/application/admin/validate/Order.php index 353541e..e4286fa 100644 --- a/application/admin/validate/Order.php +++ b/application/admin/validate/Order.php @@ -13,7 +13,7 @@ class Order extends Validate 'source' => 'require', 'item_id' => 'require', 'customer' => 'require|max:32', - 'tel' => 'require|number|max:32', + 'tel' => 'require|number|max:32|regex:/^1[3-9]\d{9}$/', 'area_id' => 'require', 'address' => 'require|max:255', 'lng' => 'require', @@ -32,6 +32,7 @@ class Order extends Validate 'customer.max' => '客户昵称不能超过 32 个字符', 'tel.require' => '请输入客户电话', + 'tel.regex' => '电话号码格式不正确', 'area_id.require' => '请选择地区', 'address.require' => '请选择详细地址', diff --git a/application/admin/view/order/add.html b/application/admin/view/order/add.html index 8ba7c27..23a4058 100644 --- a/application/admin/view/order/add.html +++ b/application/admin/view/order/add.html @@ -71,7 +71,7 @@