fix: 仓储图片上传支持 customerId,9610 明细补并发戳且主从安全
All checks were successful
Build and Deploy / deploy (push) Successful in 1m43s

上传接口接受 query customerId;ConcurrencyStamp 默认改为空串并用主键确定性回填,避免 Galera UUID unsafe。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zzh 2026-09-11 12:09:36 +08:00
parent d1e3672808
commit d1d31fee8a
5 changed files with 41 additions and 6 deletions

3
db.sql
View File

@ -1974,7 +1974,7 @@ CREATE TABLE `t_9610_order` (
`ManifestSyncTime` DATETIME NULL COMMENT '清单数据最近同步时间',
`FailReason` VARCHAR(512) NULL COMMENT '最近失败原因',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '' COMMENT '并发戳',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateUserId` INT NULL COMMENT '更新人',
@ -2008,6 +2008,7 @@ CREATE TABLE `t_9610_order_item` (
`Freight` DECIMAL(12,4) NULL COMMENT '行运费',
`SortNo` INT NOT NULL DEFAULT 0 COMMENT '排序',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '' COMMENT '并发戳',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateUserId` INT NULL COMMENT '更新人',

View File

@ -61,7 +61,7 @@ SET @sql := IF(
`ManifestSyncTime` DATETIME NULL COMMENT ''清单数据最近同步时间'',
`FailReason` VARCHAR(512) NULL COMMENT ''最近失败原因'',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT ''软删除'',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT ''并发戳'',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '''' COMMENT ''并发戳'',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT ''创建人'',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ''创建时间'',
`UpdateUserId` INT NULL COMMENT ''更新人'',
@ -108,6 +108,7 @@ SET @sql := IF(
`Freight` DECIMAL(12,4) NULL COMMENT ''行运费'',
`SortNo` INT NOT NULL DEFAULT 0 COMMENT ''排序'',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT ''软删除'',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '''' COMMENT ''并发戳'',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT ''创建人'',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ''创建时间'',
`UpdateUserId` INT NULL COMMENT ''更新人'',

View File

@ -0,0 +1,33 @@
-- t_9610_order_item 补齐 Fake AggregateRoot 并发戳(幂等)
-- 现象:详情/申报查明细时报 Unknown column 'ConcurrencyStamp' in 'field list'
-- 原因:实体继承 OmsAuditedAggregateRoot → AggregateRoot 含 ConcurrencyStamp,头表有、明细表缺
-- 注意:勿用 DEFAULT (UUID())——Galera/主从会报 Statement is unsafe(副本上 UUID 不一致)
SET @db := DATABASE();
SET @has := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_9610_order_item'
AND COLUMN_NAME = 'ConcurrencyStamp'
);
SET @sql := IF(
@has = 0,
'ALTER TABLE `t_9610_order_item` ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '''' COMMENT ''并发戳'' AFTER `IsDeleted`',
'SELECT ''skip t_9610_order_item.ConcurrencyStamp'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 已有行补确定性戳(基于主键,主从一致);新写入由 ORM 覆盖
UPDATE `t_9610_order_item`
SET `ConcurrencyStamp` = LOWER(CONCAT(
LPAD(HEX(`Id`), 8, '0'),
'-0000-4000-8000-',
LPAD(HEX(`Id`), 12, '0')
))
WHERE `ConcurrencyStamp` = '' OR `ConcurrencyStamp` IS NULL;

View File

@ -209,9 +209,9 @@ public partial class WarehouseService
/// </summary>
[HttpPost("/warehouse/parcel/upload-image")]
[Consumes("multipart/form-data")]
public async Task<object> UploadParcelImageAsync(IFormFile file)
public async Task<object> UploadParcelImageAsync(IFormFile file, [FromQuery] int? customerId = null)
{
await ResolveMutationCustomerIdAsync(null);
await ResolveMutationCustomerIdAsync(customerId);
var key = await OmsFileUploadHelper.SaveWarehouseParcelImageAsync(file, FileStorage);
var url = FileStorage.GetPublicUrl(key);
return new { key, url, fileUrl = key };

View File

@ -163,9 +163,9 @@ public partial class WarehouseService
/// </summary>
[HttpPost("/warehouse/sku/upload-image")]
[Consumes("multipart/form-data")]
public async Task<object> UploadSkuImageAsync(IFormFile file)
public async Task<object> UploadSkuImageAsync(IFormFile file, [FromQuery] int? customerId = null)
{
await ResolveMutationCustomerIdAsync(null);
await ResolveMutationCustomerIdAsync(customerId);
var key = await OmsFileUploadHelper.SaveWarehouseSkuImageAsync(file, FileStorage);
var url = FileStorage.GetPublicUrl(key);
return new { key, url, fileUrl = key };