$account] 或 ['email' => $account] */ if (!function_exists('normalizeAccount')) { function normalizeAccount(string $account): array { // 使用FILTER_VALIDATE_EMAIL验证邮箱格式 if (filter_var($account, FILTER_VALIDATE_EMAIL)) { return ['email' => $account]; } // 清理手机号中的非数字字符 $cleanPhone = preg_replace('/[^0-9]/', '', $account); // 验证手机号格式(简单版:11位数字) if (preg_match('/^1[3-9]\d{9}$/', $cleanPhone)) { return ['phone' => $cleanPhone]; } // 如果既不是邮箱也不是手机号,根据业务需求处理 // 这里默认按手机号处理(可根据实际需求调整) return ['phone' => $cleanPhone]; } } /** * 公共html页面 */ if (!function_exists('htmlpage')) { function htmlpage() { static $html; if (!$html) { $html = file_get_contents(public_path('mzl.html')); } return $html; } } /** * 获取配置 */ if (!function_exists('getConfig')) { function getConfig($filePath = null) { // 构建文件路径 $config_file = app_path($filePath); // 检查文件是否存在 if (!file_exists($config_file)) { return []; } // 包含文件并获取返回的数组 $config = include $config_file; // 验证是否为数组 if (!is_array($config)) { return []; } return $config; } } /* * 询单号生成 */ if (!function_exists('orderNum')) { function orderNum() { return "SN".date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT); } } /* * 调试用(console) */ if (!function_exists('dpr')) { function dpr(\Throwable $e) { $contents = "=== === 报错打印 === ===\n"; $contents .= "文件:".$e->getFile()."\n"; $contents .= "行数:".$e->getLine()."\n"; $contents .= "详情:".$e->getMessage()."\n"; $contents .= "=== === 报错打印 === ===\n"; var_dump($contents); return $contents; } } /** * 调试用(file) */ if (!function_exists('flg')) { function flg($eventData = '', $isFs = true, $fileName = 'flg', $fileCatalog = 'flg') { if ($eventData == '') { return false; } if (is_array($eventData) || is_object($eventData)) { $eventData = json_encode($eventData); } $fileCatalog = substr(__FILE__, 0, strpos(__FILE__, 'app/')) . "runtime/" . $fileCatalog; if (!is_dir($fileCatalog)) { mkdir($fileCatalog, 0777, true); exec('chown -R nginx:nginx ' . $fileCatalog); } $fileName = $fileName . '-' . date('Ymd') . '.log'; if ($isFs) { $data = [ 'content' => $eventData, 'time' => date('Y-m-d H:i:s', time()) ]; RedisQueueRedis::send("server", $data); } return file_put_contents($fileCatalog . "/" . $fileName, date("Y-m-d H:i:s", time()) . "::" . $eventData . "\n", FILE_APPEND); } } /*** * 发送飞书文本消息 */ if (!function_exists('sendFeishuTextMessage')) { function sendFeishuTextMessage($webhookUrl, $message) { $data = [ 'msg_type' => 'text', 'content' => [ 'text' => $message ] ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $webhookUrl); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); return $response; } } /** * 替换模板 */ if (!function_exists('replaceTpl')) { function replaceTpl(array $data = [], string $tplKey = 'email') { if (!$data || !$tplKey) return ''; $templatePath = tplUrl($tplKey); $templatePath = app_path($templatePath); $content = file_get_contents($templatePath); foreach ($data as $key => $value) { $content = str_replace('{{'.$key.'}}', $value, $content); } return $content; } } /** * 模板路径 */ if (!function_exists('tplUrl')) { function tplUrl(string $tplKey = '') { $urlArray = [ 'email' => 'common/utils/scaffold/templates/Email.stub', 'work_order' => 'common/utils/scaffold/templates/workOrder.stub' ]; return $urlArray[$tplKey]; } } /** * 替换模板 */ if (!function_exists('InquiryFormat')) { function InquiryFormat(array $data = []) { if (!$data) return ''; $content = ''; // foreach ($data as $key => $value) { // $content .= $key . ':' . $value . "\r\n"; // } $content .= '编号:'.$data['order_no'] . "\r\n"; $content .= '询单质量:'.$data['quality'] . "\r\n"; $content .= '渠道:'.$data['channel'] . "\r\n"; $content .= '邮箱:'.$data['email'] . "\r\n"; $content .= '电话:'.$data['tel'] . "\r\n"; $content .= 'WhatsApp:'.$data['whatsapp'] . "\r\n"; $content .= '国家:'.$data['country'] . "\r\n"; $content .= '联系人:'.$data['contacts'] . "\r\n"; $content .= '录单人:'.$data['enter_user_id'] . "\r\n"; $content .= '录单时间:'.$data['r_time'] . "\r\n"; $content .= '内容:'.$data['content']; return $content; } } /** * 移除字符串中的括号及其内部内容(仅移除第一个匹配项) * * @param string $str 要处理的字符串 * @return string 处理后的字符串 */ if (!function_exists('removeParentheses')) { function removeParentheses(string $str): string { // 匹配模式:半角括号或全角括号及其内部内容 $pattern = '/ (?: # 非捕获分组开始 \( # 匹配半角左括号 [^)]* # 匹配除半角右括号外的任意字符 \) # 匹配半角右括号 )|(?: # 或 \( # 匹配全角左括号 [^)]* # 匹配除全角右括号外的任意字符 \) # 匹配全角右括号 ) # 非捕获分组结束 /xu'; // x: 忽略空白 u: Unicode模式 return trim(preg_replace($pattern, '', $str, 1)); } } /** * 规范hmtl富文本 */ if (!function_exists('normalizeRichText')) { function normalizeRichText(string $html): string { $dom = new DOMDocument(); // 处理UTF-8编码和HTML5标签 @$dom->loadHTML('' . $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); // 设置编码并规范化文档 $dom->encoding = 'UTF-8'; $dom->normalizeDocument(); // 统一处理空白字符 $xpath = new DOMXPath($dom); foreach ($xpath->query('//text()') as $node) { $normalized = preg_replace('/\s+/u', ' ', trim($node->nodeValue)); $node->nodeValue = $normalized; } // 标准化属性顺序(可选) foreach ($xpath->query('//*[@*]') as $element) { $attributes = $element->attributes; $sorted = []; foreach ($attributes as $attr) { $sorted[$attr->nodeName] = $attr->nodeValue; } ksort($sorted); // 移除所有属性后按排序后顺序重新添加 while ($attributes->length) { $element->removeAttributeNode($attributes->item(0)); } foreach ($sorted as $name => $value) { $element->setAttribute($name, $value); } } // 返回规范化后的HTML $result = trim($dom->saveHTML()); // 替换所有空白实体为普通空格 return preg_replace('/\s+/u', ' ', $result); } } /** * 生成消息编号(唯一业务标识) * 格式:年月日时分秒 + 微秒 + 随机数 * 例如:20250820175530987654321 * * @return string */ if (!function_exists('generateMsgId')) { function generateMsgId(): string { // 时间部分(精确到微秒) $time = microtime(true); $micro = sprintf("%06d", ($time - floor($time)) * 1e6); $date = date('YmdHis', (int)$time); // 随机部分(3位) $rand = mt_rand(100, 999); // 拼接:日期时间 + 微秒 + 随机数 return $date . $micro . $rand; } } /** * 生成sku_code * 格式:年月日时分秒 + 微秒 + 随机数 * 例如:20250820175530987654321 * * @return string */ if (!function_exists('skuCode')) { function skuCode(): string { // 时间部分(精确到微秒) $time = microtime(true); $micro = sprintf("%06d", ($time - floor($time)) * 1e6); $date = date('YmdHis', (int)$time); // 随机部分(3位) $rand = mt_rand(100, 999); // 拼接:日期时间 + 微秒 + 随机数 return $date . $micro . $rand; } } /** * 生成备货单编号(预占式,每天从1开始) * * @return string */ if (!function_exists('generateStockNo')) { function generateStockNo(string $prefix = 'BH', int $serialLength = 3): string { $date = date('Ymd'); $key = "stock:order:serial:{$date}"; // 原子递增获取当日流水号 $serial = \support\Redis::incr($key); // 首次创建时设置过期时间:到明天凌晨 + 1小时(容错) if ($serial === 1) { $tomorrow = strtotime(date('Y-m-d', strtotime('+1 day'))); $expireSeconds = $tomorrow - time() + 3600; // 多加1小时 \support\Redis::expire($key, $expireSeconds); } // 格式化流水号(补零) $paddedSerial = str_pad($serial, $serialLength, '0', STR_PAD_LEFT); return $prefix . $date . $paddedSerial; } }