【同步】BOOT 和 CLOUD 的功能

This commit is contained in:
YunaiV
2026-08-30 18:03:40 +08:00
parent d7a6df821c
commit bdcb27fc25
25 changed files with 652 additions and 318 deletions
+1
View File
@@ -716,6 +716,7 @@ INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_t
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (117, 11, '支付宝 Wap 网站支付', 'alipay_wap', 'pay_channel_code', 0, 'primary', '', '支付宝 Wap 网站支付', '1', '2021-12-03 10:42:26', '1', '2023-07-19 20:09:16', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (118, 12, '支付宝 App 支付', 'alipay_app', 'pay_channel_code', 0, 'primary', '', '支付宝 App 支付', '1', '2021-12-03 10:42:55', '1', '2023-07-19 20:09:20', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (119, 14, '支付宝扫码支付', 'alipay_qr', 'pay_channel_code', 0, 'primary', '', '支付宝扫码支付', '1', '2021-12-03 10:43:10', '1', '2023-07-19 20:09:28', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3449, 15, '支付宝小程序支付', 'alipay_lite', 'pay_channel_code', 0, 'primary', '', '支付宝小程序支付', '1', '2026-08-18 00:00:00', '1', '2026-08-18 00:00:00', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (120, 10, '通知成功', '10', 'pay_notify_status', 0, 'success', '', '通知成功', '1', '2021-12-03 11:02:41', '1', '2023-07-19 10:08:19', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (121, 20, '通知失败', '20', 'pay_notify_status', 0, 'danger', '', '通知失败', '1', '2021-12-03 11:02:59', '1', '2023-07-19 10:08:21', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (122, 0, '等待通知', '0', 'pay_notify_status', 0, 'info', '', '未通知', '1', '2021-12-03 11:03:10', '1', '2023-07-19 10:08:24', '0');
+1 -1
View File
@@ -817,6 +817,7 @@ INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_t
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (117, 11, '支付宝 Wap 网站支付', 'alipay_wap', 'pay_channel_code', 0, 'primary', '', '支付宝 Wap 网站支付', '1', '2021-12-03 10:42:26', '1', '2023-07-19 20:09:16', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (118, 12, '支付宝 App 支付', 'alipay_app', 'pay_channel_code', 0, 'primary', '', '支付宝 App 支付', '1', '2021-12-03 10:42:55', '1', '2023-07-19 20:09:20', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (119, 14, '支付宝扫码支付', 'alipay_qr', 'pay_channel_code', 0, 'primary', '', '支付宝扫码支付', '1', '2021-12-03 10:43:10', '1', '2023-07-19 20:09:28', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3449, 15, '支付宝小程序支付', 'alipay_lite', 'pay_channel_code', 0, 'primary', '', '支付宝小程序支付', '1', '2026-08-18 00:00:00', '1', '2026-08-18 00:00:00', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (120, 10, '通知成功', '10', 'pay_notify_status', 0, 'success', '', '通知成功', '1', '2021-12-03 11:02:41', '1', '2023-07-19 10:08:19', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (121, 20, '通知失败', '20', 'pay_notify_status', 0, 'danger', '', '通知失败', '1', '2021-12-03 11:02:59', '1', '2023-07-19 10:08:21', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (122, 0, '等待通知', '0', 'pay_notify_status', 0, 'info', '', '未通知', '1', '2021-12-03 11:03:10', '1', '2023-07-19 10:08:24', '0');
@@ -6195,4 +6196,3 @@ COMMIT;
DROP SEQUENCE IF EXISTS yudao_demo03_student_seq;
CREATE SEQUENCE yudao_demo03_student_seq
START 10;
+2 -1
View File
@@ -817,6 +817,7 @@ INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_t
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (117, 11, '支付宝 Wap 网站支付', 'alipay_wap', 'pay_channel_code', 0, 'primary', '', '支付宝 Wap 网站支付', '1', '2021-12-03 10:42:26', '1', '2023-07-19 20:09:16', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (118, 12, '支付宝 App 支付', 'alipay_app', 'pay_channel_code', 0, 'primary', '', '支付宝 App 支付', '1', '2021-12-03 10:42:55', '1', '2023-07-19 20:09:20', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (119, 14, '支付宝扫码支付', 'alipay_qr', 'pay_channel_code', 0, 'primary', '', '支付宝扫码支付', '1', '2021-12-03 10:43:10', '1', '2023-07-19 20:09:28', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3449, 15, '支付宝小程序支付', 'alipay_lite', 'pay_channel_code', 0, 'primary', '', '支付宝小程序支付', '1', '2026-08-18 00:00:00', '1', '2026-08-18 00:00:00', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (120, 10, '通知成功', '10', 'pay_notify_status', 0, 'success', '', '通知成功', '1', '2021-12-03 11:02:41', '1', '2023-07-19 10:08:19', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (121, 20, '通知失败', '20', 'pay_notify_status', 0, 'danger', '', '通知失败', '1', '2021-12-03 11:02:59', '1', '2023-07-19 10:08:21', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (122, 0, '等待通知', '0', 'pay_notify_status', 0, 'info', '', '未通知', '1', '2021-12-03 11:03:10', '1', '2023-07-19 10:08:24', '0');
@@ -1663,7 +1664,7 @@ COMMIT;
DROP SEQUENCE IF EXISTS system_dict_data_seq;
CREATE SEQUENCE system_dict_data_seq
START 3449;
START 3450;
-- ----------------------------
-- Table structure for system_dict_type
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -817,6 +817,7 @@ INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_t
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (117, 11, '支付宝 Wap 网站支付', 'alipay_wap', 'pay_channel_code', 0, 'primary', '', '支付宝 Wap 网站支付', '1', '2021-12-03 10:42:26', '1', '2023-07-19 20:09:16', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (118, 12, '支付宝 App 支付', 'alipay_app', 'pay_channel_code', 0, 'primary', '', '支付宝 App 支付', '1', '2021-12-03 10:42:55', '1', '2023-07-19 20:09:20', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (119, 14, '支付宝扫码支付', 'alipay_qr', 'pay_channel_code', 0, 'primary', '', '支付宝扫码支付', '1', '2021-12-03 10:43:10', '1', '2023-07-19 20:09:28', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3449, 15, '支付宝小程序支付', 'alipay_lite', 'pay_channel_code', 0, 'primary', '', '支付宝小程序支付', '1', '2026-08-18 00:00:00', '1', '2026-08-18 00:00:00', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (120, 10, '通知成功', '10', 'pay_notify_status', 0, 'success', '', '通知成功', '1', '2021-12-03 11:02:41', '1', '2023-07-19 10:08:19', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (121, 20, '通知失败', '20', 'pay_notify_status', 0, 'danger', '', '通知失败', '1', '2021-12-03 11:02:59', '1', '2023-07-19 10:08:21', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (122, 0, '等待通知', '0', 'pay_notify_status', 0, 'info', '', '未通知', '1', '2021-12-03 11:03:10', '1', '2023-07-19 10:08:24', '0');
@@ -1663,7 +1664,7 @@ COMMIT;
DROP SEQUENCE IF EXISTS system_dict_data_seq;
CREATE SEQUENCE system_dict_data_seq
START 3449;
START 3450;
-- ----------------------------
-- Table structure for system_dict_type
+2 -1
View File
@@ -769,6 +769,7 @@ INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_t
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (117, 11, '支付宝 Wap 网站支付', 'alipay_wap', 'pay_channel_code', 0, 'primary', '', '支付宝 Wap 网站支付', '1', to_date('2021-12-03 10:42:26', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2023-07-19 20:09:16', 'SYYYY-MM-DD HH24:MI:SS'), '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (118, 12, '支付宝 App 支付', 'alipay_app', 'pay_channel_code', 0, 'primary', '', '支付宝 App 支付', '1', to_date('2021-12-03 10:42:55', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2023-07-19 20:09:20', 'SYYYY-MM-DD HH24:MI:SS'), '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (119, 14, '支付宝扫码支付', 'alipay_qr', 'pay_channel_code', 0, 'primary', '', '支付宝扫码支付', '1', to_date('2021-12-03 10:43:10', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2023-07-19 20:09:28', 'SYYYY-MM-DD HH24:MI:SS'), '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3449, 15, '支付宝小程序支付', 'alipay_lite', 'pay_channel_code', 0, 'primary', '', '支付宝小程序支付', '1', to_date('2026-08-18 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2026-08-18 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'), '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (120, 10, '通知成功', '10', 'pay_notify_status', 0, 'success', '', '通知成功', '1', to_date('2021-12-03 11:02:41', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2023-07-19 10:08:19', 'SYYYY-MM-DD HH24:MI:SS'), '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (121, 20, '通知失败', '20', 'pay_notify_status', 0, 'danger', '', '通知失败', '1', to_date('2021-12-03 11:02:59', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2023-07-19 10:08:21', 'SYYYY-MM-DD HH24:MI:SS'), '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (122, 0, '等待通知', '0', 'pay_notify_status', 0, 'info', '', '未通知', '1', to_date('2021-12-03 11:03:10', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2023-07-19 10:08:24', 'SYYYY-MM-DD HH24:MI:SS'), '0');
@@ -1614,7 +1615,7 @@ COMMIT;
-- @formatter:on
CREATE SEQUENCE system_dict_data_seq
START WITH 3449;
START WITH 3450;
-- ----------------------------
-- Table structure for system_dict_type
+1
View File
@@ -817,6 +817,7 @@ INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_t
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (117, 11, '支付宝 Wap 网站支付', 'alipay_wap', 'pay_channel_code', 0, 'primary', '', '支付宝 Wap 网站支付', '1', '2021-12-03 10:42:26', '1', '2023-07-19 20:09:16', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (118, 12, '支付宝 App 支付', 'alipay_app', 'pay_channel_code', 0, 'primary', '', '支付宝 App 支付', '1', '2021-12-03 10:42:55', '1', '2023-07-19 20:09:20', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (119, 14, '支付宝扫码支付', 'alipay_qr', 'pay_channel_code', 0, 'primary', '', '支付宝扫码支付', '1', '2021-12-03 10:43:10', '1', '2023-07-19 20:09:28', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3449, 15, '支付宝小程序支付', 'alipay_lite', 'pay_channel_code', 0, 'primary', '', '支付宝小程序支付', '1', '2026-08-18 00:00:00', '1', '2026-08-18 00:00:00', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (120, 10, '通知成功', '10', 'pay_notify_status', 0, 'success', '', '通知成功', '1', '2021-12-03 11:02:41', '1', '2023-07-19 10:08:19', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (121, 20, '通知失败', '20', 'pay_notify_status', 0, 'danger', '', '通知失败', '1', '2021-12-03 11:02:59', '1', '2023-07-19 10:08:21', '0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (122, 0, '等待通知', '0', 'pay_notify_status', 0, 'info', '', '未通知', '1', '2021-12-03 11:03:10', '1', '2023-07-19 10:08:24', '0');
+1
View File
@@ -2258,6 +2258,7 @@ GO
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (118, 12, N'支付宝 App 支付', N'alipay_app', N'pay_channel_code', 0, N'primary', N'', N'支付宝 App 支付', N'1', N'2021-12-03 10:42:55', N'1', N'2023-07-19 20:09:20', N'0')
GO
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (119, 14, N'支付宝扫码支付', N'alipay_qr', N'pay_channel_code', 0, N'primary', N'', N'支付宝扫码支付', N'1', N'2021-12-03 10:43:10', N'1', N'2023-07-19 20:09:28', N'0')
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (3449, 15, N'支付宝小程序支付', N'alipay_lite', N'pay_channel_code', 0, N'primary', N'', N'支付宝小程序支付', N'1', N'2026-08-18 00:00:00', N'1', N'2026-08-18 00:00:00', N'0')
GO
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (120, 10, N'通知成功', N'10', N'pay_notify_status', 0, N'success', N'', N'通知成功', N'1', N'2021-12-03 11:02:41', N'1', N'2023-07-19 10:08:19', N'0')
GO
@@ -5,8 +5,6 @@ package cn.iocoder.yudao.framework.datasource.core.enums;
*
* 通过在方法上,使用 {@link com.baomidou.dynamic.datasource.annotation.DS} 注解,设置使用的数据源。
* 注意,默认是 {@link #MASTER} 数据源
*
* 对应官方文档为 http://dynamic-datasource.com/guide/customize/Annotation.html
*/
public interface DataSourceEnum {
@@ -35,7 +35,6 @@ public class AppFileController {
@Operation(summary = "上传文件")
@Parameter(name = "file", description = "文件附件", required = true,
schema = @Schema(type = "string", format = "binary"))
@PermitAll
public CommonResult<String> uploadFile(@Valid AppFileUploadReqVO uploadReqVO) throws Exception {
MultipartFile file = uploadReqVO.getFile();
byte[] content = IoUtil.readBytes(file.getInputStream());
@@ -57,7 +56,6 @@ public class AppFileController {
@PostMapping("/create")
@Operation(summary = "创建文件", description = "模式二:前端上传文件:配合 presigned-url 接口,记录上传了上传的文件")
@PermitAll
public CommonResult<Long> createFile(@Valid @RequestBody FileCreateReqVO createReqVO) {
return success(fileService.createFile(createReqVO));
}
@@ -173,6 +173,12 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
* @return 节点地址
*/
private String buildPresignerEndpoint() {
// 阿里云 OSS、七牛云的自定义域名仅用于文件访问,不能作为 S3 签名节点。
// Presigner 必须使用服务商提供的 endpoint,否则生成的签名无法用于直传。
if (StrUtil.contains(config.getEndpoint(), S3FileClientConfig.ENDPOINT_ALIYUN)
|| StrUtil.contains(config.getEndpoint(), S3FileClientConfig.ENDPOINT_QINIU)) {
return buildEndpoint();
}
// 补全 domain
if (StrUtil.isEmpty(config.getDomain())) {
config.setDomain(buildDomain());
@@ -69,6 +69,42 @@ public class S3FileClientTest {
assertFalse(result.contains("%25E4%25B8%25AD"));
}
@Test
public void testPresignPutUrl_aliyunUsesEndpointInsteadOfCustomDomain() {
S3FileClientConfig config = new S3FileClientConfig();
config.setAccessKey("access-key");
config.setAccessSecret("access-secret");
config.setBucket("test-bucket");
config.setDomain("https://custom.example.com");
config.setEndpoint("oss-cn-beijing.aliyuncs.com");
config.setEnablePathStyleAccess(false);
config.setEnablePublicAccess(false);
S3FileClient client = new S3FileClient(0L, config);
client.init();
String result = client.presignPutUrl("avatar.jpg");
assertTrue(result.startsWith("https://test-bucket.oss-cn-beijing.aliyuncs.com/"));
}
@Test
public void testPresignPutUrl_qiniuUsesEndpointInsteadOfCustomDomain() {
S3FileClientConfig config = new S3FileClientConfig();
config.setAccessKey("access-key");
config.setAccessSecret("access-secret");
config.setBucket("test-bucket");
config.setDomain("https://custom.example.com");
config.setEndpoint("s3-cn-south-1.qiniucs.com");
config.setEnablePathStyleAccess(false);
config.setEnablePublicAccess(false);
S3FileClient client = new S3FileClient(0L, config);
client.init();
String result = client.presignPutUrl("avatar.jpg");
assertTrue(result.startsWith("https://test-bucket.s3-cn-south-1.qiniucs.com/"));
}
@Test
@Disabled // MinIO,如果要集成测试,可以注释本行
public void testMinIO() throws Exception {
@@ -66,6 +66,8 @@ public interface ErrorCodeConstants {
ErrorCode OTA_FIRMWARE_NOT_EXISTS = new ErrorCode(1_050_008_000, "固件信息不存在");
ErrorCode OTA_FIRMWARE_PRODUCT_VERSION_DUPLICATE = new ErrorCode(1_050_008_001, "产品版本号重复");
ErrorCode OTA_FIRMWARE_DELETE_FAIL_TASK_IN_PROGRESS = new ErrorCode(1_050_008_002,
"删除 OTA 固件失败,原因:存在进行中的升级任务");
// ========== OTA 升级任务相关 1-050-008-100 ==========
@@ -105,4 +107,4 @@ public interface ErrorCodeConstants {
// ========== IoT 告警记录 1-050-014-000 ==========
ErrorCode ALERT_RECORD_NOT_EXISTS = new ErrorCode(1_050_014_000, "IoT 告警记录不存在");
}
}
@@ -83,10 +83,10 @@ public class IotDeviceMessageController {
@PostMapping("/send")
@Operation(summary = "发送消息", description = "可用于设备模拟")
@PreAuthorize("@ss.hasPermission('iot:device:message-end')")
@PreAuthorize("@ss.hasPermission('iot:device:message-send')")
public CommonResult<Boolean> sendDeviceMessage(@Valid @RequestBody IotDeviceMessageSendReqVO sendReqVO) {
deviceMessageService.sendDeviceMessage(BeanUtils.toBean(sendReqVO, IotDeviceMessage.class));
return success(true);
}
}
}
@@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
import cn.iocoder.yudao.module.iot.service.ota.IotOtaFirmwareService;
import cn.iocoder.yudao.module.iot.service.product.IotProductService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
@@ -47,6 +48,15 @@ public class IotOtaFirmwareController {
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除 OTA 固件")
@Parameter(name = "id", description = "固件编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('iot:ota-firmware:delete')")
public CommonResult<Boolean> deleteOtaFirmware(@RequestParam("id") Long id) {
otaFirmwareService.deleteOtaFirmware(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得 OTA 固件")
@PreAuthorize("@ss.hasPermission('iot:ota-firmware:query')")
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.task.IotOtaTaskPageReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaTaskDO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
@@ -16,6 +17,12 @@ public interface IotOtaTaskMapper extends BaseMapperX<IotOtaTaskDO> {
IotOtaTaskDO::getName, name);
}
default Long selectCountByFirmwareIdAndStatus(Long firmwareId, Integer status) {
return selectCount(new LambdaQueryWrapper<IotOtaTaskDO>()
.eq(IotOtaTaskDO::getFirmwareId, firmwareId)
.eq(IotOtaTaskDO::getStatus, status));
}
default PageResult<IotOtaTaskDO> selectPage(IotOtaTaskPageReqVO pageReqVO) {
return selectPage(pageReqVO, new LambdaQueryWrapperX<IotOtaTaskDO>()
.eqIfPresent(IotOtaTaskDO::getFirmwareId, pageReqVO.getFirmwareId())
@@ -35,6 +35,13 @@ public interface IotOtaFirmwareService {
*/
void updateOtaFirmware(@Valid IotOtaFirmwareUpdateReqVO updateReqVO);
/**
* 删除 OTA 固件信息
*
* @param id 固件编号
*/
void deleteOtaFirmware(Long id);
/**
* 获取 OTA 固件信息
*
@@ -10,6 +10,8 @@ import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.firmware.IotOtaFirmwa
import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.firmware.IotOtaFirmwareUpdateReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaFirmwareDO;
import cn.iocoder.yudao.module.iot.dal.mysql.ota.IotOtaFirmwareMapper;
import cn.iocoder.yudao.module.iot.dal.mysql.ota.IotOtaTaskMapper;
import cn.iocoder.yudao.module.iot.enums.ota.IotOtaTaskStatusEnum;
import cn.iocoder.yudao.module.iot.service.product.IotProductService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
@@ -23,6 +25,7 @@ import java.util.Collections;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.OTA_FIRMWARE_DELETE_FAIL_TASK_IN_PROGRESS;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.OTA_FIRMWARE_NOT_EXISTS;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.OTA_FIRMWARE_PRODUCT_VERSION_DUPLICATE;
@@ -38,6 +41,8 @@ public class IotOtaFirmwareServiceImpl implements IotOtaFirmwareService {
@Resource
private IotOtaFirmwareMapper otaFirmwareMapper;
@Resource
private IotOtaTaskMapper otaTaskMapper;
@Lazy
@Resource
private IotProductService productService;
@@ -74,6 +79,19 @@ public class IotOtaFirmwareServiceImpl implements IotOtaFirmwareService {
otaFirmwareMapper.updateById(updateObj);
}
@Override
public void deleteOtaFirmware(Long id) {
// 1.1 校验存在
validateFirmwareExists(id);
// 1.2 校验是否有进行中的升级任务
if (otaTaskMapper.selectCountByFirmwareIdAndStatus(id, IotOtaTaskStatusEnum.IN_PROGRESS.getStatus()) > 0) {
throw exception(OTA_FIRMWARE_DELETE_FAIL_TASK_IN_PROGRESS);
}
// 2. 删除
otaFirmwareMapper.deleteById(id);
}
@Override
public IotOtaFirmwareDO getOtaFirmware(Long id) {
return otaFirmwareMapper.selectById(id);
@@ -137,6 +137,8 @@ public interface ErrorCodeConstants {
ErrorCode CAL_TEAM_SHIFT_NOT_EXISTS = new ErrorCode(1_040_201_200, "班组排班记录不存在");
ErrorCode CAL_TEAM_SHIFT_GENERATE_TEAM_NOT_ENOUGH = new ErrorCode(1_040_201_201, "班组数量不满足轮班方式要求");
ErrorCode CAL_TEAM_SHIFT_GENERATE_SHIFT_NOT_ENOUGH = new ErrorCode(1_040_201_202, "班次数量不满足轮班方式要求");
ErrorCode CAL_TEAM_SHIFT_GENERATE_SHIFT_COUNT_INVALID = new ErrorCode(1_040_201_203, "按天倒班必须填写合法的倒班天数");
ErrorCode CAL_TEAM_SHIFT_GENERATE_SHIFT_METHOD_INVALID = new ErrorCode(1_040_201_204, "不支持的倒班方式:{}");
// ========== MES 日历排班-排班计划(1-040-202-000) ==========
ErrorCode CAL_PLAN_NOT_EXISTS = new ErrorCode(1_040_202_000, "排班计划不存在");
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanPageReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.ibatis.annotations.Mapper;
/**
@@ -31,4 +32,11 @@ public interface MesCalPlanMapper extends BaseMapperX<MesCalPlanDO> {
return selectOne(MesCalPlanDO::getCode, code);
}
default void updateWithShiftFieldCleanup(MesCalPlanDO plan, boolean clearShiftMethod, boolean clearShiftCount) {
update(plan, Wrappers.<MesCalPlanDO>lambdaUpdate()
.eq(MesCalPlanDO::getId, plan.getId())
.set(clearShiftMethod, MesCalPlanDO::getShiftMethod, null)
.set(clearShiftCount, MesCalPlanDO::getShiftCount, null));
}
}
@@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanSaveRe
import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO;
import cn.iocoder.yudao.module.mes.dal.mysql.cal.plan.MesCalPlanMapper;
import cn.iocoder.yudao.module.mes.enums.cal.MesCalPlanStatusEnum;
import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftMethodEnum;
import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftTypeEnum;
import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamShiftService;
import cn.hutool.core.util.ObjUtil;
@@ -35,6 +36,7 @@ public class MesCalPlanServiceImpl implements MesCalPlanService {
@Resource
private MesCalPlanMapper planMapper;
@Resource
@Lazy
private MesCalPlanShiftService planShiftService;
@@ -75,10 +77,20 @@ public class MesCalPlanServiceImpl implements MesCalPlanService {
// 1.3 校验编码唯一
validatePlanCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
// 2. 更新
// 2.1 倒班字段联动清理:单白班不倒班,倒班方式非按天时不需要倒班天数
updateReqVO.setStatus(null); // 不允许通过 update 修改状态,状态变更走专用接口
boolean clearShiftMethod = MesCalShiftTypeEnum.SINGLE.getType().equals(updateReqVO.getShiftType());
boolean clearShiftCount = clearShiftMethod || updateReqVO.getShiftMethod() == null
|| !MesCalShiftMethodEnum.DAY.getMethod().equals(updateReqVO.getShiftMethod());
if (clearShiftMethod) {
updateReqVO.setShiftMethod(null);
}
if (clearShiftCount) {
updateReqVO.setShiftCount(null);
}
// 2.2 更新
MesCalPlanDO updateObj = BeanUtils.toBean(updateReqVO, MesCalPlanDO.class);
planMapper.updateById(updateObj);
planMapper.updateWithShiftFieldCleanup(updateObj, clearShiftMethod, clearShiftCount);
}
@Override
@@ -25,6 +25,8 @@ import java.util.ArrayList;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_SHIFT_COUNT_INVALID;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_SHIFT_METHOD_INVALID;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_SHIFT_NOT_ENOUGH;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_TEAM_NOT_ENOUGH;
@@ -39,6 +41,7 @@ public class MesCalTeamShiftServiceImpl implements MesCalTeamShiftService {
@Resource
private MesCalTeamShiftMapper teamShiftMapper;
@Resource
@Lazy
private MesCalPlanService planService;
@@ -77,8 +80,10 @@ public class MesCalTeamShiftServiceImpl implements MesCalTeamShiftService {
for (int i = 0; i < days; i++) {
LocalDate currentDate = startDate.plusDays(i);
LocalDateTime currentDay = currentDate.atStartOfDay();
// 2.2.1 根据倒班方式计算 shiftIndex
shiftIndex = calculateShiftIndex(shiftIndex, i, currentDate, startDate, plan);
// 2.2.1 根据倒班方式计算 shiftIndex 单白班不倒班,跳过
if (!MesCalShiftTypeEnum.SINGLE.getType().equals(plan.getShiftType())) {
shiftIndex = calculateShiftIndex(shiftIndex, i, currentDate, startDate, plan);
}
// 2.2.2 根据轮班方式生成排班记录,收集到列表
buildRecordsForDay(allRecords, planId, currentDay, shiftIndex, plan.getShiftType(), teams, shifts);
}
@@ -118,11 +123,15 @@ public class MesCalTeamShiftServiceImpl implements MesCalTeamShiftService {
}
} else if (MesCalShiftMethodEnum.DAY.getMethod().equals(plan.getShiftMethod())) {
// 按天轮班:到了指定轮班天数的倍数
if (dayOffset % plan.getShiftCount() == 0) {
Integer shiftCount = plan.getShiftCount();
if (shiftCount == null || shiftCount <= 0) {
throw exception(CAL_TEAM_SHIFT_GENERATE_SHIFT_COUNT_INVALID);
}
if (dayOffset % shiftCount == 0) {
return shiftIndex + 1;
}
} else {
throw new IllegalArgumentException("不支持的倒班方式: " + plan.getShiftMethod());
throw exception(CAL_TEAM_SHIFT_GENERATE_SHIFT_METHOD_INVALID, plan.getShiftMethod());
}
return shiftIndex;
}
@@ -29,6 +29,7 @@ public enum PayChannelEnum implements ArrayValuable<String> {
ALIPAY_APP("alipay_app", "支付宝App 支付"),
ALIPAY_QR("alipay_qr", "支付宝扫码支付"),
ALIPAY_BAR("alipay_bar", "支付宝条码支付"),
ALIPAY_LITE("alipay_lite", "支付宝小程序支付"),
MOCK("mock", "模拟支付"),
@@ -6,7 +6,6 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.date.TemporalAccessorUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.io.FileUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
@@ -63,18 +62,17 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
WxPayConfig payConfig = new WxPayConfig();
BeanUtil.copyProperties(config, payConfig, "keyContent", "privateKeyContent", "publicKeyContent");
payConfig.setTradeType(tradeType);
// weixin-pay-java 无法设置内容,只允许读取文件,所以这里要创建临时文件来解决
if (Objects.equals(config.getApiVersion(), API_VERSION_V2)) {
payConfig.setKeyPath(FileUtils.createTempFile(Base64.decode(config.getKeyContent())).getPath());
payConfig.setKeyContent(Base64.decode(config.getKeyContent()));
} else if (Objects.equals(config.getApiVersion(), API_VERSION_V3)) {
payConfig.setPrivateKeyPath(FileUtils.createTempFile(config.getPrivateKeyContent()).getPath());
payConfig.setPrivateKeyContent(StrUtil.utf8Bytes(config.getPrivateKeyContent()));
// 参考 https://gitee.com/yudaocode/yudao-ui-admin-vue3/issues/ICUE53 和 https://t.zsxq.com/ODR5V
if (StrUtil.isNotBlank(config.getPublicKeyContent())) {
payConfig.setPublicKeyPath(FileUtils.createTempFile(config.getPublicKeyContent()).getPath());
payConfig.setPublicKeyContent(StrUtil.utf8Bytes(config.getPublicKeyContent()));
}
// 特殊:强制使用微信公钥模式,避免灰度期间的问题!!!
payConfig.setStrictlyNeedWechatPaySerial(true);
// 特殊:weixin-java-pay 只有配置 publicKeyPath 后,再开启 fullPublicKeyModel,才会使用 PublicCertificateVerifier
// 特殊:weixin-java-pay 只有配置 publicKeyContent 后,再开启 fullPublicKeyModel,才会使用 PublicCertificateVerifier
// 对应 https://t.zsxq.com/5Q9lO 帖子
payConfig.setFullPublicKeyModel(true);
}
@@ -166,7 +166,7 @@ public class MailTemplateServiceImpl implements MailTemplateService {
// 提取 <pre> 标签内的内容
String innerContent = matcher.group(1);
// 返回 div 标签包裹的内容
matcher.appendReplacement(sb, "<div>" + innerContent + "</div>");
matcher.appendReplacement(sb, Matcher.quoteReplacement("<div>" + innerContent + "</div>"));
}
matcher.appendTail(sb);
return sb.toString();
@@ -207,7 +207,8 @@ public class MailTemplateServiceImpl implements MailTemplateService {
String codeBlock = matcher.group(1);
// 为代码块添加样式
String replacement = "<pre style=\"background-color: #f5f5f5; padding: 10px; border-radius: 5px; overflow-x: auto;\"><code>" + codeBlock + "</code></pre>";
matcher.appendReplacement(sb, replacement);
// 代码块内容可能包含 $ 或 \\,需要 quoteReplacement,否则会抛 IllegalArgumentException: Illegal group reference
matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(sb);
return sb.toString();