展示名) */ const MODEL_NAME_FALLBACK = [ // 视频(Seedance 系列) 'doubao-seedance-1-5-pro-251215' => 'Seedance1.5pro', 'doubao-seedance-1-0-pro-250528' => 'Seedance1.0pro', 'doubao-seedance-1-0-pro-fast-251015' => 'Seedance1.0profast', 'doubao-seedance-2-0-260128' => 'Seedance2.0', 'doubao-seedance-2-0-fast-260128' => 'Seedance2.0fast', 'doubao-seedance-2.0' => 'Seedance2.0', 'baidu-doubao-seedance-2-0-260128' => 'Seedance2.0', 'baidu-doubao-seedance-2-0-fast-260128' => 'Seedance2.0fast', 'baidu-doubao-seedance-2-0-mini-260615' => 'Seedance2.0mini', 'baidu-doubao-seedance-2-5-260628' => 'Seedance2.5', 'baidu-dreamina-seedance-2-0-260128' => 'Seedance2.0(海外)', 'baidu-dreamina-seedance-2-0-fast-260128' => 'Seedance2.0fast(海外)', 'baidu-dreamina-seedance-2-0-mini-260615' => 'Seedance2.0mini(海外)', 'baidu-dreamina-seedance-2-5-260628' => 'Seedance2.5(海外)', 'zhizhen-20' => 'Seedance2.0', 'zhizhen-20-fast' => 'Seedance2.0fast', 'zhizhen-20-mini' => 'Seedance2.0mini', 'seed-2' => 'Seedance2.0', 'seed-2-fast' => 'Seedance2.0fast', 'seed-2-mini' => 'Seedance2.0mini', 'seed-2.5' => 'Seedance2.5', // 文本 'baidu-glm-5.2' => 'GLM-5.2', 'baidu-glm-5.3' => 'GLM-5.3', 'baidu-gpt-5.6-luna' => 'GPT-5.6-luna', 'baidu-gpt-5.6-sol' => 'GPT-5.6-sol', 'baidu-gpt-5.6-terra' => 'GPT-5.6-terra', 'baidu-gpt-6-astra' => 'GPT-6-astra', 'baidu-gpt-6-luna' => 'GPT-6-luna', 'baidu-gpt-6-sol' => 'GPT-6-sol', 'baidu-gpt-6.1-sol' => 'GPT-6.1-sol', ]; /** * 视频分辨率取值 => 展示文案 */ const VIDEO_RESOLUTION_LABELS = [ '480p' => '480p', '720p' => '720p', '1080p' => '1080p', '4k' => '4k', '2160p' => '4k', '4096x2160' => '4k', 'sr_720p' => '超分720p', 'sr720p' => '超分720p', '超分720p' => '超分720p', 'sr_1080p' => '超分1080p', 'sr1080p' => '超分1080p', '超分1080p' => '超分1080p', ]; /** * 配置表读取的模型展示名缓存(单次请求内只查一次) * * @var array|null */ private static $modelNameMap = null; /** * 获取模型对外展示名(隐藏百度/快快等供应商字样) * * @param string $model 模型ID(charge_info.model) * @return string */ public static function modelName(string $model = ''): string { $model = trim($model); if ($model === '' || $model === 'unknown') { return ''; } $map = self::modelNameMap(); $name = $map[$model] ?? self::MODEL_NAME_FALLBACK[$model] ?? ''; if ($name === '') { $name = $model; } return self::markReserveChannel($model, self::stripVendor($name)); } /** * 备渠道标记:命中备渠道前缀(seed-2 开头)的模型,展示名追加“(备)” * * @param string $model 模型ID * @param string $name 已剥离供应商字样的展示名 * @return string */ private static function markReserveChannel(string $model, string $name): string { if ($name === '' || mb_strpos($name, '(备用)') !== false) { return $name; } foreach (self::RESERVE_MODEL_PREFIXES as $prefix) { if ($prefix !== '' && stripos($model, $prefix) === 0) { return $name . '(备用)'; } } return $name; } /** * 获取明细的分辨率展示文案 * * - 视频:480p/720p/1080p/4k、超分720p、超分1080p(来自 charge_info.video_resolution) * - 图片:实际宽*高,如 1600*2848(来自 charge_info.width / height) * - 其他类型或无数据:空串 * * @param string $type 明细类型(video/image/chat/system/company) * @param array $chargeInfo 计费信息 * @return string */ public static function resolution(string $type, array $chargeInfo = []): string { if ($type === MpUserPointsDetail::TYPE_VIDEO) { $resolution = strtolower(trim((string)getProp($chargeInfo, 'video_resolution', ''))); if ($resolution === '') { return ''; } return self::VIDEO_RESOLUTION_LABELS[$resolution] ?? $resolution; } if ($type === MpUserPointsDetail::TYPE_IMAGE) { $width = (int)getProp($chargeInfo, 'width', 0); $height = (int)getProp($chargeInfo, 'height', 0); if ($width <= 0 || $height <= 0) { return ''; } return $width . '*' . $height; } return ''; } /** * 积分明细来源展示(charge_info.source_from → 中文) * * 规则: * - 1 → 资产 * - 2 → 画布 * - 0 / 缺失:有动漫或剧本归属时显示“动漫/剧本”,否则显示“默认” * * @param array $chargeInfo 明细计费信息 * @param int $animeId 明细归属的动漫ID(为 0 时回退 charge_info.anime_id) * @param int $scriptId 明细归属的剧本ID(为 0 时回退 charge_info.script_id) * @return string */ public static function sourceFrom(array $chargeInfo, $animeId = 0, $scriptId = 0): string { $sourceFrom = (int)getProp($chargeInfo, 'source_from', 0); if ($sourceFrom === 1) { return '资产'; } if ($sourceFrom === 2) { return '画布'; } $animeId = (int)$animeId ?: (int)getProp($chargeInfo, 'anime_id', 0); $scriptId = (int)$scriptId ?: (int)getProp($chargeInfo, 'script_id', 0); if ($animeId > 0 || $scriptId > 0) { return '动漫/剧本'; } return ''; } /** * 仅保留名称主体:剥离供应商字样前缀(百度Seedance2.0 → Seedance2.0,baidu-xxx → xxx) * * @param string $name * @return string */ private static function stripVendor(string $name): string { $name = trim($name); // 英文前缀(模型ID形态) foreach (self::VENDOR_PREFIXES as $prefix) { if (stripos($name, $prefix) === 0) { $name = trim(substr($name, strlen($prefix))); } } // 中文前缀(配置表 name 形态),可能连续出现(如“百度智帧xxx”) $changed = true; while ($changed) { $changed = false; foreach (self::VENDOR_WORDS as $word) { if (mb_strpos($name, $word) === 0) { $name = trim(mb_substr($name, mb_strlen($word))); $changed = true; break; } } } return $name; } /** * 模型ID => 配置表展示名(读取失败或未命中时返回空数组,由调用方走兜底映射) * * @return array */ private static function modelNameMap(): array { if (self::$modelNameMap !== null) { return self::$modelNameMap; } $map = []; foreach (['mp_video_models', 'mp_image_models', 'mp_text_models'] as $table) { try { $rows = DB::table($table)->select('model', 'name')->get(); } catch (\Throwable $e) { continue; } foreach ($rows as $row) { $model = trim((string)getProp($row, 'model', '')); $name = trim((string)getProp($row, 'name', '')); if ($model !== '' && $name !== '') { $map[$model] = $name; } } } self::$modelNameMap = $map; return self::$modelNameMap; } }