feat: 用户资料支持企业微信客服接入链接

新增 user.WecomKfUrl 存取与迁移脚本,顾问接口同步返回该字段。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zzh 2026-09-01 19:09:34 +08:00
parent a70f6f2a87
commit 7e9a5d4ae0
9 changed files with 68 additions and 7 deletions

View File

@ -0,0 +1,20 @@
-- user 表:企业微信客服接入链接(幂等;列已存在则跳过)
-- MySQL 5.7+ / 8.0
SET @db := DATABASE();
SET @col := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 'user'
AND COLUMN_NAME = 'WecomKfUrl'
);
SET @sql := IF(
@col = 0,
'ALTER TABLE `user` ADD COLUMN `WecomKfUrl` VARCHAR(512) NULL COMMENT ''企业微信客服接入链接''',
'SELECT ''skip WecomKfUrl'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

View File

@ -19,4 +19,9 @@ public class CustomerServiceAdvisorOutput
/// 微信二维码(URL 或 Base64)。
/// </summary>
public string? WechatQrCode { get; set; }
/// <summary>
/// 企业微信客服接入链接。
/// </summary>
public string? WecomKfUrl { get; set; }
}

View File

@ -21,4 +21,9 @@ public class OrderUploadInput
/// 默认发件地址 ID(地址管理中的发件人地址)。
/// </summary>
public int? SenderAddressId { get; set; }
/// <summary>
/// 客户主键(管理端代客下单时必传)。
/// </summary>
public int? CustomerId { get; set; }
}

View File

@ -11,6 +11,11 @@ public class UserProfileData
public string? WechatId { get; set; }
public string? WechatQrCode { get; set; }
/// <summary>
/// 企业微信客服接入链接(微信外接入)。
/// </summary>
public string? WecomKfUrl { get; set; }
}
public class OmsUserCreateInput : UserCreateDto
@ -22,6 +27,8 @@ public class OmsUserCreateInput : UserCreateDto
public string? WechatId { get; set; }
public string? WechatQrCode { get; set; }
public string? WecomKfUrl { get; set; }
}
public class OmsUserUpdateInput : UserUpdateDto
@ -31,6 +38,8 @@ public class OmsUserUpdateInput : UserUpdateDto
public string? WechatId { get; set; }
public string? WechatQrCode { get; set; }
public string? WecomKfUrl { get; set; }
}
public class OmsUserDetailDto : UserDto
@ -42,4 +51,6 @@ public class OmsUserDetailDto : UserDto
public string? WechatId { get; set; }
public string? WechatQrCode { get; set; }
public string? WecomKfUrl { get; set; }
}

View File

@ -30,6 +30,7 @@ public class CustomerServiceAdvisorResolver(FakeRbacDbContext dbContext) : IScop
Name = row.Name,
WechatId = row.WechatId,
WechatQrCode = row.WechatQrCode,
WecomKfUrl = row.WecomKfUrl,
};
}
@ -44,7 +45,8 @@ public class CustomerServiceAdvisorResolver(FakeRbacDbContext dbContext) : IScop
SELECT
u.`Name` AS `Name`,
u.`WechatId` AS `WechatId`,
u.`WechatQrCode` AS `WechatQrCode`
u.`WechatQrCode` AS `WechatQrCode`,
u.`WecomKfUrl` AS `WecomKfUrl`
FROM `user` u
WHERE u.`IsDeleted` = 0
AND u.`userid` = {0}
@ -62,7 +64,8 @@ public class CustomerServiceAdvisorResolver(FakeRbacDbContext dbContext) : IScop
SELECT
u.`Name` AS `Name`,
u.`WechatId` AS `WechatId`,
u.`WechatQrCode` AS `WechatQrCode`
u.`WechatQrCode` AS `WechatQrCode`,
u.`WecomKfUrl` AS `WecomKfUrl`
FROM `user` u
WHERE u.`IsDeleted` = 0
AND (u.`Name` = {0} OR u.`Account` = {0})
@ -82,5 +85,7 @@ public class CustomerServiceAdvisorResolver(FakeRbacDbContext dbContext) : IScop
public string? WechatId { get; set; }
public string? WechatQrCode { get; set; }
public string? WecomKfUrl { get; set; }
}
}

View File

@ -32,6 +32,7 @@ internal static class OmsUserProfileMapper
detail.EmployeeNo = profile.EmployeeNo;
detail.WechatId = profile.WechatId;
detail.WechatQrCode = profile.WechatQrCode;
detail.WecomKfUrl = profile.WecomKfUrl;
return detail;
}
}

View File

@ -20,7 +20,8 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
u.`Phone` AS `Phone`,
u.`EmployeeNo` AS `EmployeeNo`,
u.`WechatId` AS `WechatId`,
u.`WechatQrCode` AS `WechatQrCode`
u.`WechatQrCode` AS `WechatQrCode`,
u.`WecomKfUrl` AS `WecomKfUrl`
FROM `user` u
WHERE u.`Id` = {0} AND u.`IsDeleted` = 0
LIMIT 1
@ -41,6 +42,7 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
EmployeeNo = row.EmployeeNo,
WechatId = row.WechatId,
WechatQrCode = row.WechatQrCode,
WecomKfUrl = row.WecomKfUrl,
};
}
@ -60,7 +62,8 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
u.`Phone` AS `Phone`,
u.`EmployeeNo` AS `EmployeeNo`,
u.`WechatId` AS `WechatId`,
u.`WechatQrCode` AS `WechatQrCode`
u.`WechatQrCode` AS `WechatQrCode`,
u.`WecomKfUrl` AS `WecomKfUrl`
FROM `user` u
WHERE u.`Id` IN ({inClause}) AND u.`IsDeleted` = 0
""";
@ -74,6 +77,7 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
EmployeeNo = x.EmployeeNo,
WechatId = x.WechatId,
WechatQrCode = x.WechatQrCode,
WecomKfUrl = x.WecomKfUrl,
});
}
@ -85,7 +89,8 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
`Phone` = {1},
`EmployeeNo` = {2},
`WechatId` = {3},
`WechatQrCode` = {4}
`WechatQrCode` = {4},
`WecomKfUrl` = {5}
WHERE `Id` = {0} AND `IsDeleted` = 0
""";
@ -98,6 +103,7 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
(object?)NormalizeOptional(profile.EmployeeNo),
(object?)NormalizeOptional(profile.WechatId),
(object?)NormalizeOptional(profile.WechatQrCode),
(object?)NormalizeOptional(profile.WecomKfUrl),
],
cancellationToken);
}
@ -112,7 +118,8 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
SET
`Phone` = {1},
`WechatId` = {2},
`WechatQrCode` = {3}
`WechatQrCode` = {3},
`WecomKfUrl` = {4}
WHERE `Id` = {0} AND `IsDeleted` = 0
""";
@ -123,6 +130,7 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
(object?)NormalizeOptional(profile.Phone),
(object?)NormalizeOptional(profile.WechatId),
(object?)NormalizeOptional(profile.WechatQrCode),
(object?)NormalizeOptional(profile.WecomKfUrl),
],
cancellationToken);
}
@ -208,6 +216,8 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
public string? WechatId { get; set; }
public string? WechatQrCode { get; set; }
public string? WecomKfUrl { get; set; }
}
private sealed class UserProfileListRow
@ -221,6 +231,8 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
public string? WechatId { get; set; }
public string? WechatQrCode { get; set; }
public string? WecomKfUrl { get; set; }
}
private sealed class EmployeeNoRow

View File

@ -543,7 +543,7 @@ public partial class OrderService
var template = await OrderTemplateRepository.FirstOrDefaultAsync(x => x.Id == input.TemplateId)
?? throw new BusinessException("模板不存在");
var effectiveCustomer = await ResolveEffectiveCustomerAsync();
var effectiveCustomer = await ResolveEffectiveCustomerAsync(input.CustomerId);
EnsureTemplateAccessible(template, effectiveCustomer.Id);
OrderTemplateImportMapping.EnsureTemplateReadyForImport(template);

View File

@ -109,6 +109,7 @@ public class OmsUserService(
EmployeeNo = employeeNo,
WechatId = input.WechatId,
WechatQrCode = input.WechatQrCode,
WecomKfUrl = input.WecomKfUrl,
},
cancellationToken);
@ -145,6 +146,7 @@ public class OmsUserService(
Phone = input.Phone,
WechatId = input.WechatId,
WechatQrCode = input.WechatQrCode,
WecomKfUrl = input.WecomKfUrl,
},
cancellationToken);