193 lines
6.2 KiB
PHP
193 lines
6.2 KiB
PHP
<?php
|
|
namespace app\models;
|
|
|
|
use core\base\Model;
|
|
|
|
/**
|
|
* 系统配置模型
|
|
*/
|
|
class SysConfig extends Model
|
|
{
|
|
protected $table = 'sys_config';
|
|
|
|
// 获取配置
|
|
public function getConfig()
|
|
{
|
|
return $this->where(['id = :id'], [':id' => 1])->fetch();
|
|
}
|
|
|
|
// 更新配置
|
|
public function updateConfig($data)
|
|
{
|
|
return $this->where(['id = :id'], [':id' => 1])->update($data);
|
|
}
|
|
|
|
/**
|
|
* 获取代码前缀规则
|
|
* 格式: ['成品' => 'CP', '电芯' => 'DX', 'PCBA' => 'XLB']
|
|
*/
|
|
public function getCodePrefixRules()
|
|
{
|
|
$config = $this->getConfig();
|
|
$raw = $config['code_prefix_rules'] ?? '';
|
|
if (empty($raw)) {
|
|
// 返回默认规则
|
|
$rules = $this->getDefaultCodePrefixRules();
|
|
} else {
|
|
$rules = json_decode($raw, true);
|
|
if (!is_array($rules)) {
|
|
$rules = $this->getDefaultCodePrefixRules();
|
|
}
|
|
}
|
|
|
|
// 产品类型别名对齐:确保同义类型能匹配到同一前缀规则
|
|
// 例如配置表中使用「电池」,而前缀规则可能使用旧名「电芯」
|
|
$aliases = [
|
|
'电池' => '电芯',
|
|
'电芯' => '电池',
|
|
'底壳' => '外壳',
|
|
'外壳' => '底壳',
|
|
'半成品' => '半成',
|
|
'半成' => '半成品',
|
|
];
|
|
foreach ($aliases as $from => $to) {
|
|
if (!isset($rules[$from]) && isset($rules[$to])) {
|
|
$rules[$from] = $rules[$to];
|
|
}
|
|
}
|
|
return $rules;
|
|
}
|
|
|
|
/**
|
|
* 获取默认代码前缀规则
|
|
*/
|
|
public function getDefaultCodePrefixRules()
|
|
{
|
|
return [
|
|
'成品' => 'CP',
|
|
'电池' => 'dc',
|
|
'PCBA' => 'xlb',
|
|
'半成品' => '',
|
|
'外壳' => '',
|
|
'包装' => '',
|
|
'配件' => '',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 根据产品类型获取代码前缀
|
|
* @param string $productType 产品类型(如:成品、电芯、PCBA)
|
|
* @return string 前缀,无规则返回空字符串
|
|
*/
|
|
public function getPrefixByType($productType)
|
|
{
|
|
$rules = $this->getCodePrefixRules();
|
|
$prefix = $rules[$productType] ?? '';
|
|
// 原则:所有工位序列号都受前缀管控。配置了该类型但前缀为空时,
|
|
// 自动回退为「产品类型名拼音首字母」,避免无前缀类型被放行或卡死。
|
|
if ($prefix === '' && isset($rules[$productType])) {
|
|
$prefix = $this->pinyinInitials($productType);
|
|
}
|
|
return $prefix;
|
|
}
|
|
|
|
/**
|
|
* 取得字符串的拼音首字母(中文取首字拼音首字母,英文/数字原样保留)。
|
|
* 兼容「外壳」「包装」「半成品」「配件」等常见类型,英文部分(如 PCBA)原样输出。
|
|
* @param string $str
|
|
* @return string
|
|
*/
|
|
public function pinyinInitials($str)
|
|
{
|
|
$str = trim($str);
|
|
if ($str === '') return '';
|
|
// 常见产品类型精确映射(避免多音字/误判)
|
|
$map = [
|
|
'外壳' => 'WK',
|
|
'底壳' => 'WK',
|
|
'包装' => 'BZ',
|
|
'半成品' => 'BCP',
|
|
'半成' => 'BCP',
|
|
'配件' => 'PJ',
|
|
'成品' => 'CP',
|
|
'电池' => 'DC',
|
|
'电芯' => 'DC',
|
|
'PCBA' => 'XLB',
|
|
];
|
|
if (isset($map[$str])) return $map[$str];
|
|
|
|
$first = mb_substr($str, 0, 1, 'UTF-8');
|
|
// 英文字母/数字:直接原样(大写)
|
|
if (preg_match('/^[A-Za-z0-9]$/', $first)) {
|
|
return strtoupper($first) . (mb_strlen($str, 'UTF-8') > 1 ? strtoupper(mb_substr($str, 1, 1, 'UTF-8')) : '');
|
|
}
|
|
// 中文:取首字拼音首字母
|
|
return $this->chineseInitial($first);
|
|
}
|
|
|
|
/**
|
|
* 单汉字 → 拼音首字母(GB2312 区位区间法,覆盖常用汉字)
|
|
*/
|
|
private function chineseInitial($char)
|
|
{
|
|
$py = 'A';
|
|
try {
|
|
$gbk = iconv('UTF-8', 'GB2312//IGNORE', $char);
|
|
} catch (\Throwable $e) {
|
|
$gbk = '';
|
|
}
|
|
if ($gbk === '' || strlen($gbk) < 2) {
|
|
return $py; // 生僻字/无法转换时回退
|
|
}
|
|
$hi = ord($gbk[0]);
|
|
$lo = ord($gbk[1]);
|
|
$code = $hi * 256 + $lo;
|
|
// GB2312 拼音首字母分区(常用字)
|
|
$ranges = [
|
|
[0xB0A1, 0xB0C4, 'A'], [0xB0C5, 0xB2C0, 'B'], [0xB2C1, 0xB4ED, 'C'],
|
|
[0xB4EE, 0xB6E9, 'D'], [0xB6EA, 0xB7A1, 'E'], [0xB7A2, 0xB8C0, 'F'],
|
|
[0xB8C1, 0xB9FD, 'G'], [0xB9FE, 0xBBF6, 'H'], [0xBBF7, 0xBFA5, 'J'],
|
|
[0xBFA6, 0xC0AB, 'K'], [0xC0AC, 0xC2E7, 'L'], [0xC2E8, 0xC4C2, 'M'],
|
|
[0xC4C3, 0xC5B5, 'N'], [0xC5B6, 0xC5BD, 'O'], [0xC5BE, 0xC6DA, 'P'],
|
|
[0xC6DB, 0xC8BA, 'Q'], [0xC8BB, 0xC8F5, 'R'], [0xC8F6, 0xCBF0, 'S'],
|
|
[0xCBF1, 0xCDDA, 'T'], [0xCDDB, 0xCEF3, 'W'], [0xCEF4, 0xD1B8, 'X'],
|
|
[0xD1B9, 0xD4D0, 'Y'], [0xD4D1, 0xD7F9, 'Z'],
|
|
];
|
|
foreach ($ranges as $r) {
|
|
if ($code >= $r[0] && $code <= $r[1]) { $py = $r[2]; break; }
|
|
}
|
|
return $py;
|
|
}
|
|
|
|
/**
|
|
* 获取所有已配置的非空前缀规则(用于验证)
|
|
* @return array [前缀 => 产品类型名]
|
|
*/
|
|
public function getActivePrefixMap()
|
|
{
|
|
$rules = $this->getCodePrefixRules();
|
|
$active = [];
|
|
foreach ($rules as $type => $prefix) {
|
|
if (!empty($prefix)) {
|
|
$active[$prefix] = $type;
|
|
}
|
|
}
|
|
return $active;
|
|
}
|
|
|
|
/**
|
|
* 更新代码前缀规则(JSON 存储)
|
|
* @param array $rules ['成品' => 'CP', '电池' => 'dc', ...]
|
|
*/
|
|
public function updateCodePrefixRules($rules)
|
|
{
|
|
$json = json_encode($rules, JSON_UNESCAPED_UNICODE);
|
|
// 使用原生 PDO 直写,避免 Model::update 链式调用在二次写入时的潜在问题
|
|
$pdo = \core\db\Db::pdo();
|
|
$table = $this->getTable();
|
|
$stmt = $pdo->prepare("UPDATE {$table} SET code_prefix_rules = :v WHERE id = 1");
|
|
$stmt->execute([':v' => $json]);
|
|
return true;
|
|
}
|
|
}
|