946684800) { return date('Y-m-d H:i:s', (int)$v); } return ProcuremenTime::formatDisplayDateTime($v); } /** 交货日期仅展示 YYYY-MM-DD */ public static function deliveryYmd($v): string { if ($v === null || $v === '') { return ''; } $s = trim((string)$v); if ($s === '' || preg_match('/^0000-00-00/i', $s)) { return ''; } if (preg_match('/^(\d{4}-\d{2}-\d{2})/', $s, $m)) { return $m[1]; } $ts = strtotime($s); return ($ts !== false && $ts > 0) ? date('Y-m-d', $ts) : $s; } /** 解析金额/数量(去千分位等非数字字符) */ public static function moneyNumber($value): ?float { if ($value === null || $value === '') { return null; } if (is_numeric($value)) { return (float)$value; } $v = preg_replace('/[^\d\.\-]/', '', (string)$value); return ($v !== '' && is_numeric($v)) ? (float)$v : null; } public static function moneyDisplay(?float $amount): string { if ($amount === null) { return ''; } $s = rtrim(rtrim(sprintf('%.5F', (float)$amount), '0'), '.'); return $s === '' ? '0' : $s; } /** 工作量为 0 时显示空 */ public static function workloadDisplay($value): string { if ($value === null || $value === '') { return ''; } $s = trim((string)$value); if ($s === '') { return ''; } if (is_numeric($s) && (float)$s == 0) { return ''; } return $s; } /** * @param string[] $names */ public static function notifySupplierDisplay(array $names): string { $names = array_values(array_unique(array_filter(array_map(function ($n) { return trim((string)$n); }, $names)))); if ($names === []) { return ''; } sort($names, SORT_STRING); return implode("\n", $names); } /** * @param array{all?: array, quoted?: array} $bucket */ public static function quotedSupplierLines(array $bucket): string { $all = array_keys($bucket['all'] ?? []); if ($all === []) { return ''; } sort($all, SORT_STRING); $lines = []; foreach ($all as $cn) { $status = !empty($bucket['quoted'][$cn]) ? '已报价' : '未报价'; $lines[] = $cn . '(' . $status . ')'; } return implode("\n", $lines); } /** @param int|null|string $days */ public static function leadDaysText($days): string { if ($days === null || $days === '') { return '未填写'; } if (!is_numeric($days)) { return '未填写'; } return ((int)$days) . '天'; } public static function deliveryDeadlineForInput($value): string { $s = trim((string)$value); if ($s === '' || stripos($s, '0000-00-00') === 0) { return ''; } if (preg_match('/^(\d{4}-\d{2}-\d{2})/', $s, $m)) { return $m[1]; } $ts = strtotime(str_replace('/', '-', $s)); return ($ts !== false && $ts > 0) ? date('Y-m-d', $ts) : ''; } public static function sysRqForInput($sysRq): string { $sr = trim((string)$sysRq); if ($sr === '' || stripos($sr, '0000-00-00') === 0) { return ''; } $ts = strtotime($sr); return ($ts !== false && $ts > 0) ? date('Y-m-d H:i:s', $ts) : $sr; } public static function sysRqForDisplay($sysRq): string { $sr = self::sysRqForInput($sysRq); if ($sr === '') { return '—'; } $ts = strtotime($sr); return ($ts !== false && $ts > 0) ? date('Y/m/d H:i', $ts) : $sr; } /** * @param array{quality_weight?:mixed,price_weight?:mixed,lead_weight?:mixed} $rule */ public static function scoreRuleWeightsText(array $rule): string { $parts = []; $qw = max(0, (float)($rule['quality_weight'] ?? 0)); $pw = max(0, (float)($rule['price_weight'] ?? 0)); $lw = max(0, (float)($rule['lead_weight'] ?? 0)); $fmt = static function ($n) { $s = rtrim(rtrim(sprintf('%.2F', (float)$n), '0'), '.'); return $s === '' ? '0' : $s; }; if ($qw > 0) { $parts[] = '质量' . $fmt($qw) . '%'; } if ($pw > 0) { $parts[] = '价格' . $fmt($pw) . '%'; } if ($lw > 0) { $parts[] = '交货' . $fmt($lw) . '%'; } return implode('、', $parts); } public static function mprocYmdForNotify($raw): string { $s = trim((string)$raw); if ($s === '' || preg_match('/^0000-00-00/i', $s)) { return ''; } $s = str_replace(['/', '.'], '-', $s); if (preg_match('/^(\d{4}-\d{2}-\d{2})/', $s, $m)) { return $m[1]; } $ts = strtotime(str_replace('T', ' ', $s)); if ($ts === false || $ts <= 0) { return ''; } return date('Y-m-d', $ts); } /** 导出用:工序列文案 */ public static function exportGxText(array $r): string { $a = trim((string)($r['CDXMC'] ?? '')); $b = trim((string)($r['CGYMC'] ?? '')); if ($a !== '' && $b !== '') { return $a . ':' . $b; } return $a !== '' ? $a : $b; } /** 导出用:加工金额 */ public static function exportAmount(array $r): float { foreach (['amount', 'jje', 'jgje', 'processing_amount'] as $k) { if (!array_key_exists($k, $r)) { continue; } $v = $r[$k]; if ($v === null || $v === '') { continue; } if (is_numeric($v)) { return (float)$v; } $v = preg_replace('/[^\d\.\-]/', '', (string)$v); if ($v !== '' && is_numeric($v)) { return (float)$v; } } return 0.0; } /** 订单号等用于 PDF 文件名片段 */ public static function sanitizePdfOrderKey(string $ccydh): string { $s = trim($ccydh); if ($s === '') { return 'ORDER'; } $s = preg_replace('@[\\\\/:*?"<>|\\s]+@u', '_', $s); $s = trim($s, '._-'); if ($s === '') { return 'ORDER'; } if (function_exists('mb_substr')) { return mb_substr($s, 0, 80, 'UTF-8'); } return strlen($s) <= 80 ? $s : substr($s, 0, 80); } /** * @return array{objectKey: string, webPath: string} */ public static function buildConfirmPdfPaths(int $scydgyId, string $ccydhRaw): array { $sid = (int)$scydgyId; $safeOrder = self::sanitizePdfOrderKey($ccydhRaw); $y = date('Y'); $m = date('m'); $d = date('d'); $basename = $safeOrder . '_' . $sid . '.pdf'; $objectKey = 'xinhua/' . $y . '/' . $m . '/' . $d . '/' . $sid . '/' . $basename; return [ 'objectKey' => $objectKey, 'webPath' => '/' . $objectKey, ]; } /** * @param array $vars * @return array */ public static function normalizeSmsTemplateVars(array $vars): array { $out = []; foreach ($vars as $k => $v) { $out[(string)$k] = trim((string)$v); } if (($out['contact_name'] ?? '') === '' && ($out['company_name'] ?? '') !== '') { $out['contact_name'] = $out['company_name']; } return $out; } /** * @return array */ public static function emailLogSceneLabelMap(): array { return [ 'pick_issue' => '初选下发', 'audit_resend' => '确认页重发', 'audit_append' => '确认页追加供应商', 'rfq_salesman' => '询价通知业务员', 'rfq_supplier' => '供应商询价通知', 'delivery_notify' => '交货情况通知生产部', 'confirm_result' => '确认结果通知', 'confirm_ok' => '确认已通过通知', 'confirm_fail' => '确认未通过通知', ]; } public static function normalizeEmailLogSceneForStore(string $scene): string { $scene = trim($scene); $map = self::emailLogSceneLabelMap(); if ($scene === '') { return $map['pick_issue']; } if (isset($map[$scene])) { return $map[$scene]; } if (in_array($scene, array_values($map), true)) { return $scene; } return $scene; } public static function emailLogSceneText(string $scene): string { return self::normalizeEmailLogSceneForStore($scene); } }