Files
lgp-admin-plus-api/app/Service/business/SerialNoService.php
LQ bcf54c2727 初始化
缺陷:主题配色需要优化整体的同风格
2026-08-14 23:21:21 +08:00

62 lines
1.9 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Service\business;
use Illuminate\Support\Facades\DB;
/**
* 业务单号生成(清单 QD_ / 订单 DD_
*
* 随机串剔除 0/O/1/I/L 这些肉眼分不清的字符——单号会被打印在纸质报价单上人工抄录。
* 唯一索引兜底,撞号就重试;重试仍失败宁可报错,也不要为了成功而降级成可能重复的号。
*/
class SerialNoService
{
private static mixed $_instance;
private const ALPHABET = '23456789ABCDEFGHJKMNPQRSTUVWXYZ';
public const PREFIX_LIST = 'QD_';
public const PREFIX_ORDER = 'DD_';
public static function getInstance(): null|static
{
$name = get_called_class();
if (!isset(self::$_instance[$name])) {
self::$_instance[$name] = new static();
}
return self::$_instance[$name];
}
/**
* 生成一个库内不存在的单号
*
* @param string $prefix self::PREFIX_*
* @param string $table business 连接下的表名(不带前缀)
* @param string $column 单号字段
*/
public function generate(string $prefix, string $table, string $column, int $tries = 10): string
{
$day = date('Ymd');
for ($i = 0; $i < $tries; $i++) {
$no = $prefix . $day . $this->randomPart(6);
$exists = DB::connection('business')->table($table)->where($column, $no)->exists();
if (!$exists) {
return $no;
}
}
// 连续撞 10 次说明随机源或并发量出了问题,静默返回可能重复的号比抛错危险得多
throw new \RuntimeException('单号生成失败,请重试');
}
private function randomPart(int $length): string
{
$max = strlen(self::ALPHABET) - 1;
$out = '';
for ($i = 0; $i < $length; $i++) {
$out .= self::ALPHABET[random_int(0, $max)];
}
return $out;
}
}