Files
anxinyan/server-api/app/support/ExpressCompanyService.php
2026-05-22 21:13:52 +08:00

209 lines
6.7 KiB
PHP

<?php
namespace app\support;
use support\think\Db;
class ExpressCompanyService
{
public function __construct()
{
$this->ensureTable();
$this->bootstrapDefaults();
}
public function list(bool $enabledOnly = false): array
{
$query = Db::name('express_companies')
->order('is_default', 'desc')
->order('sort_order', 'asc')
->order('id', 'asc');
if ($enabledOnly) {
$query->where('status', 'enabled');
}
return array_map(fn (array $item) => $this->format($item), $query->select()->toArray());
}
public function save(array $payload, int $id = 0): int
{
$now = date('Y-m-d H:i:s');
$companyName = trim((string)($payload['company_name'] ?? ''));
$companyCode = trim((string)($payload['company_code'] ?? ''));
$status = trim((string)($payload['status'] ?? 'enabled'));
$isDefault = !empty($payload['is_default']);
if ($companyName === '') {
throw new \RuntimeException('快递公司名称不能为空');
}
if (!in_array($status, ['enabled', 'disabled'], true)) {
throw new \RuntimeException('快递公司状态无效');
}
if ($isDefault && $status !== 'enabled') {
throw new \RuntimeException('默认快递公司必须保持启用');
}
if ($companyCode === '') {
$companyCode = $this->generateCompanyCode($companyName);
}
$existsByName = Db::name('express_companies')
->where('company_name', $companyName)
->when($id > 0, fn ($query) => $query->where('id', '<>', $id))
->find();
if ($existsByName) {
throw new \RuntimeException('快递公司名称已存在');
}
$existsByCode = Db::name('express_companies')
->where('company_code', $companyCode)
->when($id > 0, fn ($query) => $query->where('id', '<>', $id))
->find();
if ($existsByCode) {
throw new \RuntimeException('快递公司编码已存在');
}
$data = [
'company_name' => $companyName,
'company_code' => $companyCode,
'status' => $status,
'is_default' => $isDefault ? 1 : 0,
'sort_order' => (int)($payload['sort_order'] ?? 0),
'remark' => trim((string)($payload['remark'] ?? '')),
'updated_at' => $now,
];
Db::startTrans();
try {
if ($isDefault) {
Db::name('express_companies')->update([
'is_default' => 0,
'updated_at' => $now,
]);
}
if ($id > 0) {
Db::name('express_companies')->where('id', $id)->update($data);
$companyId = $id;
} else {
$data['created_at'] = $now;
$companyId = (int)Db::name('express_companies')->insertGetId($data);
}
$this->ensureEnabledDefault($now);
Db::commit();
} catch (\Throwable $e) {
Db::rollback();
throw $e;
}
return $companyId;
}
public function defaultName(): string
{
$row = Db::name('express_companies')
->where('status', 'enabled')
->where('is_default', 1)
->find();
if (!$row) {
$row = Db::name('express_companies')
->where('status', 'enabled')
->order('sort_order', 'asc')
->order('id', 'asc')
->find();
}
return trim((string)($row['company_name'] ?? ''));
}
private function format(array $item): array
{
$status = (string)($item['status'] ?? 'enabled');
return [
'id' => (int)$item['id'],
'company_name' => (string)$item['company_name'],
'company_code' => (string)$item['company_code'],
'status' => $status,
'status_text' => $status === 'enabled' ? '启用中' : '已停用',
'is_default' => (bool)$item['is_default'],
'sort_order' => (int)$item['sort_order'],
'remark' => (string)($item['remark'] ?? ''),
'created_at' => (string)($item['created_at'] ?? ''),
'updated_at' => (string)($item['updated_at'] ?? ''),
];
}
private function bootstrapDefaults(): void
{
$now = date('Y-m-d H:i:s');
$exists = Db::name('express_companies')->where('company_name', '顺丰速运')->find();
if (!$exists) {
Db::name('express_companies')->insert([
'company_name' => '顺丰速运',
'company_code' => 'sf_express',
'status' => 'enabled',
'is_default' => 1,
'sort_order' => 1,
'remark' => '系统默认快递公司',
'created_at' => $now,
'updated_at' => $now,
]);
}
$this->ensureEnabledDefault($now);
}
private function ensureEnabledDefault(string $now): void
{
$default = Db::name('express_companies')
->where('status', 'enabled')
->where('is_default', 1)
->find();
if ($default) {
return;
}
$firstEnabled = Db::name('express_companies')
->where('status', 'enabled')
->order('sort_order', 'asc')
->order('id', 'asc')
->find();
if ($firstEnabled) {
Db::name('express_companies')->where('id', $firstEnabled['id'])->update([
'is_default' => 1,
'updated_at' => $now,
]);
}
}
private function generateCompanyCode(string $companyName): string
{
return 'express_' . substr(hash('sha256', $companyName), 0, 12);
}
private function ensureTable(): void
{
Db::execute(<<<'SQL'
CREATE TABLE IF NOT EXISTS express_companies (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
company_name VARCHAR(64) NOT NULL DEFAULT '',
company_code VARCHAR(64) NOT NULL DEFAULT '',
status VARCHAR(32) NOT NULL DEFAULT 'enabled',
is_default TINYINT(1) NOT NULL DEFAULT 0,
sort_order INT NOT NULL DEFAULT 0,
remark VARCHAR(255) NOT NULL DEFAULT '',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY uk_express_companies_name (company_name),
UNIQUE KEY uk_express_companies_code (company_code),
KEY idx_express_companies_status (status),
KEY idx_express_companies_default (is_default)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='快递公司字典'
SQL);
}
}