diff --git a/app/admin/scheme/MallGoods.php b/app/admin/scheme/MallGoods.php index b21ab9a..8fdf352 100644 --- a/app/admin/scheme/MallGoods.php +++ b/app/admin/scheme/MallGoods.php @@ -40,10 +40,10 @@ class MallGoods extends BaseScheme #[Field(type: 'text', comment: '商品属性')] public $property; - #[Field(type: 'decimal', length: 8, precision: 8, scale: 2, default: '0.00', comment: '市场价')] + #[Field(type: 'decimal', length: 8, precision: 8, default: '0', comment: '市场价')] public $market_price; - #[Field(type: 'decimal', length: 8, precision: 8, scale: 2, default: '0.00', comment: '折扣价')] + #[Field(type: 'decimal', length: 8, precision: 8, default: '0', comment: '折扣价')] public $discount_price; #[Field(type: 'int', length: 11, default: '0', comment: '销量', unsigned: true)] diff --git a/extend/base/common/command/scheme/Sync.php b/extend/base/common/command/scheme/Sync.php index bb91533..ea544ac 100644 --- a/extend/base/common/command/scheme/Sync.php +++ b/extend/base/common/command/scheme/Sync.php @@ -7,7 +7,9 @@ use think\console\Input; use think\console\input\Option; use think\console\Output; use think\facade\Config; +use think\facade\Db; use app\common\service\scheme\SchemeToDbService; +use app\common\service\scheme\DbToSchemeService; use app\common\scheme\attribute\Table; use ReflectionClass; @@ -26,10 +28,12 @@ class Sync extends Command $skipData = $input->getOption('skip-data'); $service = new SchemeToDbService(); + $generator = new DbToSchemeService(); $schemeDir = app()->getAppPath() . 'admin/scheme/'; $ignoreTables = Config::get('scheme.ignore_tables', []); $connection = Config::get('database.default', 'mysql'); $prefix = Config::get('database.connections.' . $connection . '.prefix', ''); + $backupPrefix = Config::get('scheme.backup_prefix', 'backup'); if (!is_dir($schemeDir)) { $output->writeln("Scheme directory not found: $schemeDir"); @@ -43,11 +47,37 @@ class Sync extends Command if (class_exists($className)) { $tableName = $this->getTableNameFromScheme($className); - if (!empty($tableName) && $this->isIgnoredTable($tableName, $ignoreTables, $prefix)) { - $output->writeln("Skipping $className (ignored table: $tableName)"); + if (empty($tableName)) { + $output->writeln("Skipping $className (missing table name)"); continue; } + $fullTableName = $this->getFullTableName($tableName, $prefix); + if ($this->isBackupTable($fullTableName, $prefix, $backupPrefix)) { + $output->writeln("Skipping $className (backup table: $fullTableName)"); + continue; + } + + if ($this->isIgnoredTable($fullTableName, $ignoreTables, $prefix)) { + $output->writeln("Skipping $className (ignored table: $fullTableName)"); + continue; + } + + if ($this->checkTableExists($connection, $fullTableName)) { + try { + $expectedClass = basename($file, '.php'); + $generated = $generator->generate($fullTableName, $expectedClass); + $existing = (string)file_get_contents($file); + if ($this->normalizeCode($generated) === $this->normalizeCode($existing)) { + $output->writeln("Skipping $className (no schema changes)"); + continue; + } + } catch (\Exception $e) { + $output->writeln("Check failed for $className: " . $e->getMessage() . ""); + continue; + } + } + $output->writeln("Syncing $className..."); try { $backup = $service->sync($className, $skipData); @@ -91,4 +121,47 @@ class Sync extends Command return in_array($shortName, $ignoreTables, true) || in_array($tableName, $ignoreTables, true); } + + protected function normalizeCode(string $code): string + { + $code = str_replace(["\r\n", "\r"], "\n", $code); + $code = preg_replace('/[ \t]+$/m', '', $code); + return trim((string)$code); + } + + protected function checkTableExists(string $connection, string $tableName): bool + { + $database = (string)Config::get('database.connections.' . $connection . '.database', ''); + if ($database !== '') { + $rows = Db::connect($connection)->query( + 'SELECT 1 FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? LIMIT 1', + [$database, $tableName] + ); + return !empty($rows); + } + + $escaped = addcslashes($tableName, "\\_%"); + $tables = Db::connect($connection)->query("SHOW TABLES LIKE '$escaped'"); + return !empty($tables); + } + + protected function getFullTableName(string $tableName, string $prefix): string + { + if ($prefix && !str_starts_with($tableName, $prefix)) { + return $prefix . $tableName; + } + + return $tableName; + } + + protected function isBackupTable(string $tableName, string $prefix, string $backupPrefix): bool + { + $basePrefix = $prefix . $backupPrefix; + if ($basePrefix === '') { + return false; + } + + $pattern = '/^' . preg_quote($basePrefix, '/') . '_?\\d{14}(?:_.*)?$/'; + return preg_match($pattern, $tableName) === 1; + } }