Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/yudao-cloud
# Conflicts: # yudao-module-erp/yudao-module-erp-server/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java # yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DataSourceConfigController.java # yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileConfigController.java # yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileUploadReqVO.java # yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/AppFileUploadReqVO.java # yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java # yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigService.java # yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceImpl.java # yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java # yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java # yudao-module-mall/yudao-module-product-server/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java # yudao-module-mall/yudao-module-promotion-server/src/main/java/cn/iocoder/yudao/module/promotion/service/diy/DiyPageServiceImpl.java # yudao-module-mall/yudao-module-promotion-server/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillConfigServiceImpl.java # yudao-module-mp/yudao-module-mp-server/src/main/java/cn/iocoder/yudao/module/mp/service/handler/user/SubscribeHandler.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailAccountController.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailTemplateController.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/NoticeController.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyTemplateController.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2ClientController.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2TokenController.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuController.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsChannelController.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialClientController.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantPackageController.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/dept/PostServiceImpl.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImpl.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountService.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImpl.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateService.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImpl.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImpl.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateService.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateServiceImpl.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientService.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateService.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageService.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImpl.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java # yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.javapull/198/head
commit
91614e9898
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,253 +1,208 @@
|
||||||
-- ----------------------------
|
-- https://github.com/quartz-scheduler/quartz/blob/main/quartz/src/main/resources/org/quartz/impl/jdbcjobstore/tables_postgres.sql
|
||||||
-- qrtz_blob_triggers
|
-- Thanks to Patrick Lightbody for submitting this...
|
||||||
-- ----------------------------
|
--
|
||||||
CREATE TABLE qrtz_blob_triggers
|
-- In your Quartz properties file, you'll need to set
|
||||||
|
-- org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
|
||||||
|
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
|
||||||
|
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
|
||||||
|
DROP TABLE IF EXISTS QRTZ_LOCKS;
|
||||||
|
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
|
||||||
|
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
|
||||||
|
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
|
||||||
|
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
|
||||||
|
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
|
||||||
|
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
|
||||||
|
DROP TABLE IF EXISTS QRTZ_CALENDARS;
|
||||||
|
|
||||||
|
CREATE TABLE QRTZ_JOB_DETAILS
|
||||||
(
|
(
|
||||||
sched_name varchar(120) NOT NULL,
|
SCHED_NAME VARCHAR(120) NOT NULL,
|
||||||
trigger_name varchar(190) NOT NULL,
|
JOB_NAME VARCHAR(200) NOT NULL,
|
||||||
trigger_group varchar(190) NOT NULL,
|
JOB_GROUP VARCHAR(200) NOT NULL,
|
||||||
blob_data bytea NULL,
|
DESCRIPTION VARCHAR(250) NULL,
|
||||||
PRIMARY KEY (sched_name, trigger_name, trigger_group)
|
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
|
||||||
|
IS_DURABLE BOOL NOT NULL,
|
||||||
|
IS_NONCONCURRENT BOOL NOT NULL,
|
||||||
|
IS_UPDATE_DATA BOOL NOT NULL,
|
||||||
|
REQUESTS_RECOVERY BOOL NOT NULL,
|
||||||
|
JOB_DATA BYTEA NULL,
|
||||||
|
PRIMARY KEY (SCHED_NAME, JOB_NAME, JOB_GROUP)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX idx_qrtz_blob_triggers_sched_name ON qrtz_blob_triggers (sched_name, trigger_name, trigger_group);
|
CREATE TABLE QRTZ_TRIGGERS
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- qrtz_calendars
|
|
||||||
-- ----------------------------
|
|
||||||
CREATE TABLE qrtz_calendars
|
|
||||||
(
|
(
|
||||||
sched_name varchar(120) NOT NULL,
|
SCHED_NAME VARCHAR(120) NOT NULL,
|
||||||
calendar_name varchar(190) NOT NULL,
|
TRIGGER_NAME VARCHAR(200) NOT NULL,
|
||||||
calendar bytea NOT NULL,
|
TRIGGER_GROUP VARCHAR(200) NOT NULL,
|
||||||
PRIMARY KEY (sched_name, calendar_name)
|
JOB_NAME VARCHAR(200) NOT NULL,
|
||||||
|
JOB_GROUP VARCHAR(200) NOT NULL,
|
||||||
|
DESCRIPTION VARCHAR(250) NULL,
|
||||||
|
NEXT_FIRE_TIME BIGINT NULL,
|
||||||
|
PREV_FIRE_TIME BIGINT NULL,
|
||||||
|
PRIORITY INTEGER NULL,
|
||||||
|
TRIGGER_STATE VARCHAR(16) NOT NULL,
|
||||||
|
TRIGGER_TYPE VARCHAR(8) NOT NULL,
|
||||||
|
START_TIME BIGINT NOT NULL,
|
||||||
|
END_TIME BIGINT NULL,
|
||||||
|
CALENDAR_NAME VARCHAR(200) NULL,
|
||||||
|
MISFIRE_INSTR SMALLINT NULL,
|
||||||
|
JOB_DATA BYTEA NULL,
|
||||||
|
PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP),
|
||||||
|
FOREIGN KEY (SCHED_NAME, JOB_NAME, JOB_GROUP)
|
||||||
|
REFERENCES QRTZ_JOB_DETAILS (SCHED_NAME, JOB_NAME, JOB_GROUP)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE QRTZ_SIMPLE_TRIGGERS
|
||||||
|
(
|
||||||
|
SCHED_NAME VARCHAR(120) NOT NULL,
|
||||||
|
TRIGGER_NAME VARCHAR(200) NOT NULL,
|
||||||
|
TRIGGER_GROUP VARCHAR(200) NOT NULL,
|
||||||
|
REPEAT_COUNT BIGINT NOT NULL,
|
||||||
|
REPEAT_INTERVAL BIGINT NOT NULL,
|
||||||
|
TIMES_TRIGGERED BIGINT NOT NULL,
|
||||||
|
PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP),
|
||||||
|
FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
|
||||||
|
REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE QRTZ_CRON_TRIGGERS
|
||||||
|
(
|
||||||
|
SCHED_NAME VARCHAR(120) NOT NULL,
|
||||||
|
TRIGGER_NAME VARCHAR(200) NOT NULL,
|
||||||
|
TRIGGER_GROUP VARCHAR(200) NOT NULL,
|
||||||
|
CRON_EXPRESSION VARCHAR(120) NOT NULL,
|
||||||
|
TIME_ZONE_ID VARCHAR(80),
|
||||||
|
PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP),
|
||||||
|
FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
|
||||||
|
REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE QRTZ_SIMPROP_TRIGGERS
|
||||||
|
(
|
||||||
|
SCHED_NAME VARCHAR(120) NOT NULL,
|
||||||
|
TRIGGER_NAME VARCHAR(200) NOT NULL,
|
||||||
|
TRIGGER_GROUP VARCHAR(200) NOT NULL,
|
||||||
|
STR_PROP_1 VARCHAR(512) NULL,
|
||||||
|
STR_PROP_2 VARCHAR(512) NULL,
|
||||||
|
STR_PROP_3 VARCHAR(512) NULL,
|
||||||
|
INT_PROP_1 INT NULL,
|
||||||
|
INT_PROP_2 INT NULL,
|
||||||
|
LONG_PROP_1 BIGINT NULL,
|
||||||
|
LONG_PROP_2 BIGINT NULL,
|
||||||
|
DEC_PROP_1 NUMERIC(13, 4) NULL,
|
||||||
|
DEC_PROP_2 NUMERIC(13, 4) NULL,
|
||||||
|
BOOL_PROP_1 BOOL NULL,
|
||||||
|
BOOL_PROP_2 BOOL NULL,
|
||||||
|
PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP),
|
||||||
|
FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
|
||||||
|
REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE QRTZ_BLOB_TRIGGERS
|
||||||
|
(
|
||||||
|
SCHED_NAME VARCHAR(120) NOT NULL,
|
||||||
|
TRIGGER_NAME VARCHAR(200) NOT NULL,
|
||||||
|
TRIGGER_GROUP VARCHAR(200) NOT NULL,
|
||||||
|
BLOB_DATA BYTEA NULL,
|
||||||
|
PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP),
|
||||||
|
FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
|
||||||
|
REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE QRTZ_CALENDARS
|
||||||
|
(
|
||||||
|
SCHED_NAME VARCHAR(120) NOT NULL,
|
||||||
|
CALENDAR_NAME VARCHAR(200) NOT NULL,
|
||||||
|
CALENDAR BYTEA NOT NULL,
|
||||||
|
PRIMARY KEY (SCHED_NAME, CALENDAR_NAME)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
-- ----------------------------
|
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
|
||||||
-- qrtz_cron_triggers
|
|
||||||
-- ----------------------------
|
|
||||||
CREATE TABLE qrtz_cron_triggers
|
|
||||||
(
|
(
|
||||||
sched_name varchar(120) NOT NULL,
|
SCHED_NAME VARCHAR(120) NOT NULL,
|
||||||
trigger_name varchar(190) NOT NULL,
|
TRIGGER_GROUP VARCHAR(200) NOT NULL,
|
||||||
trigger_group varchar(190) NOT NULL,
|
PRIMARY KEY (SCHED_NAME, TRIGGER_GROUP)
|
||||||
cron_expression varchar(120) NOT NULL,
|
|
||||||
time_zone_id varchar(80) NULL DEFAULT NULL,
|
|
||||||
PRIMARY KEY (sched_name, trigger_name, trigger_group)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
-- @formatter:off
|
CREATE TABLE QRTZ_FIRED_TRIGGERS
|
||||||
BEGIN;
|
|
||||||
COMMIT;
|
|
||||||
-- @formatter:on
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- qrtz_fired_triggers
|
|
||||||
-- ----------------------------
|
|
||||||
CREATE TABLE qrtz_fired_triggers
|
|
||||||
(
|
(
|
||||||
sched_name varchar(120) NOT NULL,
|
SCHED_NAME VARCHAR(120) NOT NULL,
|
||||||
entry_id varchar(95) NOT NULL,
|
ENTRY_ID VARCHAR(95) NOT NULL,
|
||||||
trigger_name varchar(190) NOT NULL,
|
TRIGGER_NAME VARCHAR(200) NOT NULL,
|
||||||
trigger_group varchar(190) NOT NULL,
|
TRIGGER_GROUP VARCHAR(200) NOT NULL,
|
||||||
instance_name varchar(190) NOT NULL,
|
INSTANCE_NAME VARCHAR(200) NOT NULL,
|
||||||
fired_time int8 NOT NULL,
|
FIRED_TIME BIGINT NOT NULL,
|
||||||
sched_time int8 NOT NULL,
|
SCHED_TIME BIGINT NOT NULL,
|
||||||
priority int4 NOT NULL,
|
PRIORITY INTEGER NOT NULL,
|
||||||
state varchar(16) NOT NULL,
|
STATE VARCHAR(16) NOT NULL,
|
||||||
job_name varchar(190) NULL DEFAULT NULL,
|
JOB_NAME VARCHAR(200) NULL,
|
||||||
job_group varchar(190) NULL DEFAULT NULL,
|
JOB_GROUP VARCHAR(200) NULL,
|
||||||
is_nonconcurrent varchar(1) NULL DEFAULT NULL,
|
IS_NONCONCURRENT BOOL NULL,
|
||||||
requests_recovery varchar(1) NULL DEFAULT NULL,
|
REQUESTS_RECOVERY BOOL NULL,
|
||||||
PRIMARY KEY (sched_name, entry_id)
|
PRIMARY KEY (SCHED_NAME, ENTRY_ID)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX idx_qrtz_ft_trig_inst_name ON qrtz_fired_triggers (sched_name, instance_name);
|
CREATE TABLE QRTZ_SCHEDULER_STATE
|
||||||
CREATE INDEX idx_qrtz_ft_inst_job_req_rcvry ON qrtz_fired_triggers (sched_name, instance_name, requests_recovery);
|
|
||||||
CREATE INDEX idx_qrtz_ft_j_g ON qrtz_fired_triggers (sched_name, job_name, job_group);
|
|
||||||
CREATE INDEX idx_qrtz_ft_jg ON qrtz_fired_triggers (sched_name, job_group);
|
|
||||||
CREATE INDEX idx_qrtz_ft_t_g ON qrtz_fired_triggers (sched_name, trigger_name, trigger_group);
|
|
||||||
CREATE INDEX idx_qrtz_ft_tg ON qrtz_fired_triggers (sched_name, trigger_group);
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- qrtz_job_details
|
|
||||||
-- ----------------------------
|
|
||||||
CREATE TABLE qrtz_job_details
|
|
||||||
(
|
(
|
||||||
sched_name varchar(120) NOT NULL,
|
SCHED_NAME VARCHAR(120) NOT NULL,
|
||||||
job_name varchar(190) NOT NULL,
|
INSTANCE_NAME VARCHAR(200) NOT NULL,
|
||||||
job_group varchar(190) NOT NULL,
|
LAST_CHECKIN_TIME BIGINT NOT NULL,
|
||||||
description varchar(250) NULL DEFAULT NULL,
|
CHECKIN_INTERVAL BIGINT NOT NULL,
|
||||||
job_class_name varchar(250) NOT NULL,
|
PRIMARY KEY (SCHED_NAME, INSTANCE_NAME)
|
||||||
is_durable varchar(1) NOT NULL,
|
|
||||||
is_nonconcurrent varchar(1) NOT NULL,
|
|
||||||
is_update_data varchar(1) NOT NULL,
|
|
||||||
requests_recovery varchar(1) NOT NULL,
|
|
||||||
job_data bytea NULL,
|
|
||||||
PRIMARY KEY (sched_name, job_name, job_group)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX idx_qrtz_j_req_recovery ON qrtz_job_details (sched_name, requests_recovery);
|
CREATE TABLE QRTZ_LOCKS
|
||||||
CREATE INDEX idx_qrtz_j_grp ON qrtz_job_details (sched_name, job_group);
|
|
||||||
|
|
||||||
-- @formatter:off
|
|
||||||
BEGIN;
|
|
||||||
COMMIT;
|
|
||||||
-- @formatter:on
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- qrtz_locks
|
|
||||||
-- ----------------------------
|
|
||||||
CREATE TABLE qrtz_locks
|
|
||||||
(
|
(
|
||||||
sched_name varchar(120) NOT NULL,
|
SCHED_NAME VARCHAR(120) NOT NULL,
|
||||||
lock_name varchar(40) NOT NULL,
|
LOCK_NAME VARCHAR(40) NOT NULL,
|
||||||
PRIMARY KEY (sched_name, lock_name)
|
PRIMARY KEY (SCHED_NAME, LOCK_NAME)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- @formatter:off
|
CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY
|
||||||
BEGIN;
|
ON QRTZ_JOB_DETAILS (SCHED_NAME, REQUESTS_RECOVERY);
|
||||||
COMMIT;
|
CREATE INDEX IDX_QRTZ_J_GRP
|
||||||
-- @formatter:on
|
ON QRTZ_JOB_DETAILS (SCHED_NAME, JOB_GROUP);
|
||||||
|
|
||||||
-- ----------------------------
|
CREATE INDEX IDX_QRTZ_T_J
|
||||||
-- qrtz_paused_trigger_grps
|
ON QRTZ_TRIGGERS (SCHED_NAME, JOB_NAME, JOB_GROUP);
|
||||||
-- ----------------------------
|
CREATE INDEX IDX_QRTZ_T_JG
|
||||||
CREATE TABLE qrtz_paused_trigger_grps
|
ON QRTZ_TRIGGERS (SCHED_NAME, JOB_GROUP);
|
||||||
(
|
CREATE INDEX IDX_QRTZ_T_C
|
||||||
sched_name varchar(120) NOT NULL,
|
ON QRTZ_TRIGGERS (SCHED_NAME, CALENDAR_NAME);
|
||||||
trigger_group varchar(190) NOT NULL,
|
CREATE INDEX IDX_QRTZ_T_G
|
||||||
PRIMARY KEY (sched_name, trigger_group)
|
ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_GROUP);
|
||||||
);
|
CREATE INDEX IDX_QRTZ_T_STATE
|
||||||
|
ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_STATE);
|
||||||
|
CREATE INDEX IDX_QRTZ_T_N_STATE
|
||||||
|
ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP, TRIGGER_STATE);
|
||||||
|
CREATE INDEX IDX_QRTZ_T_N_G_STATE
|
||||||
|
ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_GROUP, TRIGGER_STATE);
|
||||||
|
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME
|
||||||
|
ON QRTZ_TRIGGERS (SCHED_NAME, NEXT_FIRE_TIME);
|
||||||
|
CREATE INDEX IDX_QRTZ_T_NFT_ST
|
||||||
|
ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_STATE, NEXT_FIRE_TIME);
|
||||||
|
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE
|
||||||
|
ON QRTZ_TRIGGERS (SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME);
|
||||||
|
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE
|
||||||
|
ON QRTZ_TRIGGERS (SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME, TRIGGER_STATE);
|
||||||
|
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP
|
||||||
|
ON QRTZ_TRIGGERS (SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME, TRIGGER_GROUP, TRIGGER_STATE);
|
||||||
|
|
||||||
-- ----------------------------
|
CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME
|
||||||
-- qrtz_scheduler_state
|
ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, INSTANCE_NAME);
|
||||||
-- ----------------------------
|
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY
|
||||||
CREATE TABLE qrtz_scheduler_state
|
ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, INSTANCE_NAME, REQUESTS_RECOVERY);
|
||||||
(
|
CREATE INDEX IDX_QRTZ_FT_J_G
|
||||||
sched_name varchar(120) NOT NULL,
|
ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, JOB_NAME, JOB_GROUP);
|
||||||
instance_name varchar(190) NOT NULL,
|
CREATE INDEX IDX_QRTZ_FT_JG
|
||||||
last_checkin_time int8 NOT NULL,
|
ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, JOB_GROUP);
|
||||||
checkin_interval int8 NOT NULL,
|
CREATE INDEX IDX_QRTZ_FT_T_G
|
||||||
PRIMARY KEY (sched_name, instance_name)
|
ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP);
|
||||||
);
|
CREATE INDEX IDX_QRTZ_FT_TG
|
||||||
|
ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, TRIGGER_GROUP);
|
||||||
-- @formatter:off
|
|
||||||
BEGIN;
|
|
||||||
COMMIT;
|
|
||||||
-- @formatter:on
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- qrtz_simple_triggers
|
|
||||||
-- ----------------------------
|
|
||||||
CREATE TABLE qrtz_simple_triggers
|
|
||||||
(
|
|
||||||
sched_name varchar(120) NOT NULL,
|
|
||||||
trigger_name varchar(190) NOT NULL,
|
|
||||||
trigger_group varchar(190) NOT NULL,
|
|
||||||
repeat_count int8 NOT NULL,
|
|
||||||
repeat_interval int8 NOT NULL,
|
|
||||||
times_triggered int8 NOT NULL,
|
|
||||||
PRIMARY KEY (sched_name, trigger_name, trigger_group)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- qrtz_simprop_triggers
|
|
||||||
-- ----------------------------
|
|
||||||
CREATE TABLE qrtz_simprop_triggers
|
|
||||||
(
|
|
||||||
sched_name varchar(120) NOT NULL,
|
|
||||||
trigger_name varchar(190) NOT NULL,
|
|
||||||
trigger_group varchar(190) NOT NULL,
|
|
||||||
str_prop_1 varchar(512) NULL DEFAULT NULL,
|
|
||||||
str_prop_2 varchar(512) NULL DEFAULT NULL,
|
|
||||||
str_prop_3 varchar(512) NULL DEFAULT NULL,
|
|
||||||
int_prop_1 int4 NULL DEFAULT NULL,
|
|
||||||
int_prop_2 int4 NULL DEFAULT NULL,
|
|
||||||
long_prop_1 int8 NULL DEFAULT NULL,
|
|
||||||
long_prop_2 int8 NULL DEFAULT NULL,
|
|
||||||
dec_prop_1 numeric(13, 4) NULL DEFAULT NULL,
|
|
||||||
dec_prop_2 numeric(13, 4) NULL DEFAULT NULL,
|
|
||||||
bool_prop_1 varchar(1) NULL DEFAULT NULL,
|
|
||||||
bool_prop_2 varchar(1) NULL DEFAULT NULL,
|
|
||||||
PRIMARY KEY (sched_name, trigger_name, trigger_group)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- qrtz_triggers
|
|
||||||
-- ----------------------------
|
|
||||||
CREATE TABLE qrtz_triggers
|
|
||||||
(
|
|
||||||
sched_name varchar(120) NOT NULL,
|
|
||||||
trigger_name varchar(190) NOT NULL,
|
|
||||||
trigger_group varchar(190) NOT NULL,
|
|
||||||
job_name varchar(190) NOT NULL,
|
|
||||||
job_group varchar(190) NOT NULL,
|
|
||||||
description varchar(250) NULL DEFAULT NULL,
|
|
||||||
next_fire_time int8 NULL DEFAULT NULL,
|
|
||||||
prev_fire_time int8 NULL DEFAULT NULL,
|
|
||||||
priority int4 NULL DEFAULT NULL,
|
|
||||||
trigger_state varchar(16) NOT NULL,
|
|
||||||
trigger_type varchar(8) NOT NULL,
|
|
||||||
start_time int8 NOT NULL,
|
|
||||||
end_time int8 NULL DEFAULT NULL,
|
|
||||||
calendar_name varchar(190) NULL DEFAULT NULL,
|
|
||||||
misfire_instr int2 NULL DEFAULT NULL,
|
|
||||||
job_data bytea NULL,
|
|
||||||
PRIMARY KEY (sched_name, trigger_name, trigger_group)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX idx_qrtz_t_j ON qrtz_triggers (sched_name, job_name, job_group);
|
|
||||||
CREATE INDEX idx_qrtz_t_jg ON qrtz_triggers (sched_name, job_group);
|
|
||||||
CREATE INDEX idx_qrtz_t_c ON qrtz_triggers (sched_name, calendar_name);
|
|
||||||
CREATE INDEX idx_qrtz_t_g ON qrtz_triggers (sched_name, trigger_group);
|
|
||||||
CREATE INDEX idx_qrtz_t_state ON qrtz_triggers (sched_name, trigger_state);
|
|
||||||
CREATE INDEX idx_qrtz_t_n_state ON qrtz_triggers (sched_name, trigger_name, trigger_group, trigger_state);
|
|
||||||
CREATE INDEX idx_qrtz_t_n_g_state ON qrtz_triggers (sched_name, trigger_group, trigger_state);
|
|
||||||
CREATE INDEX idx_qrtz_t_next_fire_time ON qrtz_triggers (sched_name, next_fire_time);
|
|
||||||
CREATE INDEX idx_qrtz_t_nft_st ON qrtz_triggers (sched_name, trigger_state, next_fire_time);
|
|
||||||
CREATE INDEX idx_qrtz_t_nft_misfire ON qrtz_triggers (sched_name, misfire_instr, next_fire_time);
|
|
||||||
CREATE INDEX idx_qrtz_t_nft_st_misfire ON qrtz_triggers (sched_name, misfire_instr, next_fire_time, trigger_state);
|
|
||||||
CREATE INDEX idx_qrtz_t_nft_st_misfire_grp ON qrtz_triggers (sched_name, misfire_instr, next_fire_time, trigger_group,
|
|
||||||
trigger_state);
|
|
||||||
|
|
||||||
-- @formatter:off
|
|
||||||
BEGIN;
|
|
||||||
COMMIT;
|
|
||||||
-- @formatter:on
|
|
||||||
|
|
||||||
|
|
||||||
-- ----------------------------
|
COMMIT;
|
||||||
-- FK: qrtz_blob_triggers
|
|
||||||
-- ----------------------------
|
|
||||||
ALTER TABLE qrtz_blob_triggers
|
|
||||||
ADD CONSTRAINT qrtz_blob_triggers_ibfk_1 FOREIGN KEY (sched_name, trigger_name, trigger_group) REFERENCES qrtz_triggers (sched_name,
|
|
||||||
trigger_name,
|
|
||||||
trigger_group);
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- FK: qrtz_cron_triggers
|
|
||||||
-- ----------------------------
|
|
||||||
ALTER TABLE qrtz_cron_triggers
|
|
||||||
ADD CONSTRAINT qrtz_cron_triggers_ibfk_1 FOREIGN KEY (sched_name, trigger_name, trigger_group) REFERENCES qrtz_triggers (sched_name, trigger_name, trigger_group);
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- FK: qrtz_simple_triggers
|
|
||||||
-- ----------------------------
|
|
||||||
ALTER TABLE qrtz_simple_triggers
|
|
||||||
ADD CONSTRAINT qrtz_simple_triggers_ibfk_1 FOREIGN KEY (sched_name, trigger_name, trigger_group) REFERENCES qrtz_triggers (sched_name,
|
|
||||||
trigger_name,
|
|
||||||
trigger_group);
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- FK: qrtz_simprop_triggers
|
|
||||||
-- ----------------------------
|
|
||||||
ALTER TABLE qrtz_simprop_triggers
|
|
||||||
ADD CONSTRAINT qrtz_simprop_triggers_ibfk_1 FOREIGN KEY (sched_name, trigger_name, trigger_group) REFERENCES qrtz_triggers (sched_name, trigger_name, trigger_group);
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- FK: qrtz_triggers
|
|
||||||
-- ----------------------------
|
|
||||||
ALTER TABLE qrtz_triggers
|
|
||||||
ADD CONSTRAINT qrtz_triggers_ibfk_1 FOREIGN KEY (sched_name, job_name, job_group) REFERENCES qrtz_job_details (sched_name, job_name, job_group);
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -4,6 +4,14 @@
|
||||||
Author: dhb52 (https://gitee.com/dhb52)
|
Author: dhb52 (https://gitee.com/dhb52)
|
||||||
|
|
||||||
pip install simple-ddl-parser
|
pip install simple-ddl-parser
|
||||||
|
|
||||||
|
or with uv
|
||||||
|
uv run --with simple-ddl-parser convertor.py postgres > ../postgresql/ruoyi-vue-pro.sql 239ms 四 5/22 21:03:16 2025
|
||||||
|
uv run --with simple-ddl-parser convertor.py sqlserver > ../sqlserver/ruoyi-vue-pro.sql
|
||||||
|
uv run --with simple-ddl-parser convertor.py kingbase > ../kingbase/ruoyi-vue-pro.sql
|
||||||
|
uv run --with simple-ddl-parser convertor.py opengauss > ../opengauss/ruoyi-vue-pro.sql
|
||||||
|
uv run --with simple-ddl-parser convertor.py oracle > ../oracle/ruoyi-vue-pro.sql
|
||||||
|
uv run --with simple-ddl-parser convertor.py dm8 > ../dm/ruoyi-vue-pro-dm8.sql
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
@ -38,6 +46,7 @@ def load_and_clean(sql_file: str) -> str:
|
||||||
str: 清理后的sql文件内容
|
str: 清理后的sql文件内容
|
||||||
"""
|
"""
|
||||||
REPLACE_PAIR_LIST = (
|
REPLACE_PAIR_LIST = (
|
||||||
|
(")\nVALUES ", ") VALUES "),
|
||||||
(" CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ", " "),
|
(" CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ", " "),
|
||||||
(" KEY `", " INDEX `"),
|
(" KEY `", " INDEX `"),
|
||||||
("UNIQUE INDEX", "UNIQUE KEY"),
|
("UNIQUE INDEX", "UNIQUE KEY"),
|
||||||
|
|
@ -45,7 +54,7 @@ def load_and_clean(sql_file: str) -> str:
|
||||||
("b'1'", "'1'"),
|
("b'1'", "'1'"),
|
||||||
)
|
)
|
||||||
|
|
||||||
content = open(sql_file).read()
|
content = open(sql_file, encoding="utf-8").read()
|
||||||
for replace_pair in REPLACE_PAIR_LIST:
|
for replace_pair in REPLACE_PAIR_LIST:
|
||||||
content = content.replace(*replace_pair)
|
content = content.replace(*replace_pair)
|
||||||
content = re.sub(r"ENGINE.*COMMENT", "COMMENT", content)
|
content = re.sub(r"ENGINE.*COMMENT", "COMMENT", content)
|
||||||
|
|
@ -110,18 +119,28 @@ class Convertor(ABC):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def gen_comment(self, table_sql: str, table_name: str) -> str:
|
def gen_comment(self, table_ddl: Dict) -> str:
|
||||||
"""生成字段/表注释
|
"""生成字段/表注释
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
table_sql (str): 原始表SQL
|
table_ddl (Dict): 表DDL
|
||||||
table_name (str): 表名
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: 生成脚本
|
str: 生成脚本
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def gen_uk(self, table_ddl: Dict) -> str:
|
||||||
|
"""生成
|
||||||
|
|
||||||
|
Args:
|
||||||
|
table_ddl (Dict): 表DDL
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: 生成脚本
|
||||||
|
"""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def gen_insert(self, table_name: str) -> str:
|
def gen_insert(self, table_name: str) -> str:
|
||||||
"""生成 insert 语句块
|
"""生成 insert 语句块
|
||||||
|
|
@ -178,6 +197,16 @@ class Convertor(ABC):
|
||||||
table_name = ddl["table_name"].lower()
|
table_name = ddl["table_name"].lower()
|
||||||
yield f"CREATE INDEX idx_{table_name}_{no:02d} ON {table_name} ({columns})"
|
yield f"CREATE INDEX idx_{table_name}_{no:02d} ON {table_name} ({columns})"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def unique_index(ddl: Dict) -> Generator:
|
||||||
|
if "constraints" in ddl and "uniques" in ddl["constraints"]:
|
||||||
|
uk_list = ddl["constraints"]["uniques"]
|
||||||
|
for uk in uk_list:
|
||||||
|
table_name = ddl["table_name"]
|
||||||
|
uk_name = uk["constraint_name"]
|
||||||
|
uk_columns = uk["columns"]
|
||||||
|
yield table_name, uk_name, uk_columns
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def filed_comments(table_sql: str) -> Generator:
|
def filed_comments(table_sql: str) -> Generator:
|
||||||
for line in table_sql.split("\n"):
|
for line in table_sql.split("\n"):
|
||||||
|
|
@ -188,7 +217,7 @@ class Convertor(ABC):
|
||||||
yield field, comment_string
|
yield field, comment_string
|
||||||
|
|
||||||
def table_comment(self, table_sql: str) -> str:
|
def table_comment(self, table_sql: str) -> str:
|
||||||
match = re.search(r"COMMENT \= '([^']+)';", table_sql)
|
match = re.search(r"COMMENT \='([^']+)';", table_sql)
|
||||||
return match.group(1) if match else None
|
return match.group(1) if match else None
|
||||||
|
|
||||||
def print(self):
|
def print(self):
|
||||||
|
|
@ -226,11 +255,21 @@ class Convertor(ABC):
|
||||||
if table_name.lower().startswith("qrtz"):
|
if table_name.lower().startswith("qrtz"):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# 为每个表生成个5个基本部分
|
# 解析注释
|
||||||
|
for column in table_ddl["columns"]:
|
||||||
|
column["comment"] = bytes(column["comment"], "utf-8").decode(
|
||||||
|
"unicode_escape"
|
||||||
|
)[1:-1]
|
||||||
|
table_ddl["comment"] = bytes(table_ddl["comment"], "utf-8").decode(
|
||||||
|
"unicode_escape"
|
||||||
|
)[1:-1]
|
||||||
|
|
||||||
|
# 为每个表生成个6个基本部分
|
||||||
create = self.gen_create(table_ddl)
|
create = self.gen_create(table_ddl)
|
||||||
pk = self.gen_pk(table_name)
|
pk = self.gen_pk(table_name)
|
||||||
|
uk = self.gen_uk(table_ddl)
|
||||||
index = self.gen_index(table_ddl)
|
index = self.gen_index(table_ddl)
|
||||||
comment = self.gen_comment(table_sql, table_name)
|
comment = self.gen_comment(table_ddl)
|
||||||
inserts = self.gen_insert(table_name)
|
inserts = self.gen_insert(table_name)
|
||||||
|
|
||||||
# 组合当前表的DDL脚本
|
# 组合当前表的DDL脚本
|
||||||
|
|
@ -238,6 +277,8 @@ class Convertor(ABC):
|
||||||
|
|
||||||
{pk}
|
{pk}
|
||||||
|
|
||||||
|
{uk}
|
||||||
|
|
||||||
{index}
|
{index}
|
||||||
|
|
||||||
{comment}
|
{comment}
|
||||||
|
|
@ -267,17 +308,19 @@ class PostgreSQLConvertor(Convertor):
|
||||||
|
|
||||||
if type == "varchar":
|
if type == "varchar":
|
||||||
return f"varchar({size})"
|
return f"varchar({size})"
|
||||||
if type == "int":
|
if type in ("int", "int unsigned"):
|
||||||
return "int4"
|
return "int4"
|
||||||
if type == "bigint" or type == "bigint unsigned":
|
if type in ("bigint", "bigint unsigned"):
|
||||||
return "int8"
|
return "int8"
|
||||||
if type == "datetime":
|
if type == "datetime":
|
||||||
return "timestamp"
|
return "timestamp"
|
||||||
|
if type == "timestamp":
|
||||||
|
return f"timestamp({size})"
|
||||||
if type == "bit":
|
if type == "bit":
|
||||||
return "bool"
|
return "bool"
|
||||||
if type in ("tinyint", "smallint"):
|
if type in ("tinyint", "smallint"):
|
||||||
return "int2"
|
return "int2"
|
||||||
if type == "text":
|
if type in ("text", "longtext"):
|
||||||
return "text"
|
return "text"
|
||||||
if type in ("blob", "mediumblob"):
|
if type in ("blob", "mediumblob"):
|
||||||
return "bytea"
|
return "bytea"
|
||||||
|
|
@ -316,18 +359,22 @@ CREATE TABLE {table_name} (
|
||||||
def gen_index(self, ddl: Dict) -> str:
|
def gen_index(self, ddl: Dict) -> str:
|
||||||
return "\n".join(f"{script};" for script in self.index(ddl))
|
return "\n".join(f"{script};" for script in self.index(ddl))
|
||||||
|
|
||||||
def gen_comment(self, table_sql: str, table_name: str) -> str:
|
def gen_comment(self, table_ddl: Dict) -> str:
|
||||||
"""生成字段及表的注释"""
|
"""生成字段及表的注释"""
|
||||||
|
|
||||||
script = ""
|
script = ""
|
||||||
for field, comment_string in self.filed_comments(table_sql):
|
for column in table_ddl["columns"]:
|
||||||
|
table_comment = column["comment"]
|
||||||
script += (
|
script += (
|
||||||
f"COMMENT ON COLUMN {table_name}.{field} IS '{comment_string}';" + "\n"
|
f"COMMENT ON COLUMN {table_ddl['table_name']}.{column['name']} IS '{table_comment}';"
|
||||||
|
+ "\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
table_comment = self.table_comment(table_sql)
|
table_comment = table_ddl["comment"]
|
||||||
if table_comment:
|
if table_comment:
|
||||||
script += f"COMMENT ON TABLE {table_name} IS '{table_comment}';\n"
|
script += (
|
||||||
|
f"COMMENT ON TABLE {table_ddl['table_name']} IS '{table_comment}';\n"
|
||||||
|
)
|
||||||
|
|
||||||
return script
|
return script
|
||||||
|
|
||||||
|
|
@ -335,6 +382,15 @@ CREATE TABLE {table_name} (
|
||||||
"""生成主键定义"""
|
"""生成主键定义"""
|
||||||
return f"ALTER TABLE {table_name} ADD CONSTRAINT pk_{table_name} PRIMARY KEY (id);\n"
|
return f"ALTER TABLE {table_name} ADD CONSTRAINT pk_{table_name} PRIMARY KEY (id);\n"
|
||||||
|
|
||||||
|
def gen_uk(self, table_ddl: Dict) -> str:
|
||||||
|
script = ""
|
||||||
|
uk_list = list(Convertor.unique_index(table_ddl))
|
||||||
|
for idx, (table_name, _, uk_columns) in enumerate(uk_list, 1):
|
||||||
|
uk_name = f"uk_{table_name}_{idx:02d}"
|
||||||
|
script += f"CREATE UNIQUE INDEX {uk_name} ON {table_name} ({', '.join(uk_columns)});\n"
|
||||||
|
|
||||||
|
return script
|
||||||
|
|
||||||
def gen_insert(self, table_name: str) -> str:
|
def gen_insert(self, table_name: str) -> str:
|
||||||
"""生成 insert 语句,以及根据最后的 insert id+1 生成 Sequence"""
|
"""生成 insert 语句,以及根据最后的 insert id+1 生成 Sequence"""
|
||||||
|
|
||||||
|
|
@ -393,17 +449,19 @@ class OracleConvertor(Convertor):
|
||||||
|
|
||||||
if type == "varchar":
|
if type == "varchar":
|
||||||
return f"varchar2({size if size < 4000 else 4000})"
|
return f"varchar2({size if size < 4000 else 4000})"
|
||||||
if type == "int":
|
if type in ("int", "int unsigned"):
|
||||||
return "number"
|
return "number"
|
||||||
if type == "bigint" or type == "bigint unsigned":
|
if type == "bigint" or type == "bigint unsigned":
|
||||||
return "number"
|
return "number"
|
||||||
if type == "datetime":
|
if type == "datetime":
|
||||||
return "date"
|
return "date"
|
||||||
|
if type == "timestamp":
|
||||||
|
return f"timestamp({size})"
|
||||||
if type == "bit":
|
if type == "bit":
|
||||||
return "number(1,0)"
|
return "number(1,0)"
|
||||||
if type in ("tinyint", "smallint"):
|
if type in ("tinyint", "smallint"):
|
||||||
return "smallint"
|
return "smallint"
|
||||||
if type == "text":
|
if type in ("text", "longtext"):
|
||||||
return "clob"
|
return "clob"
|
||||||
if type in ("blob", "mediumblob"):
|
if type in ("blob", "mediumblob"):
|
||||||
return "blob"
|
return "blob"
|
||||||
|
|
@ -423,6 +481,8 @@ class OracleConvertor(Convertor):
|
||||||
type = col["type"].lower()
|
type = col["type"].lower()
|
||||||
full_type = self.translate_type(type, col["size"])
|
full_type = self.translate_type(type, col["size"])
|
||||||
nullable = "NULL" if col["nullable"] else "NOT NULL"
|
nullable = "NULL" if col["nullable"] else "NOT NULL"
|
||||||
|
# Oracle的 INSERT '' 不能通过NOT NULL校验,因此对文字类型字段覆写为 NULL
|
||||||
|
nullable = "NULL" if type in ("varchar", "text", "longtext") else nullable
|
||||||
default = f"DEFAULT {col['default']}" if col["default"] is not None else ""
|
default = f"DEFAULT {col['default']}" if col["default"] is not None else ""
|
||||||
# Oracle 中 size 不能作为字段名
|
# Oracle 中 size 不能作为字段名
|
||||||
field_name = '"size"' if name == "size" else name
|
field_name = '"size"' if name == "size" else name
|
||||||
|
|
@ -447,16 +507,20 @@ CREATE TABLE {table_name} (
|
||||||
def gen_index(self, ddl: Dict) -> str:
|
def gen_index(self, ddl: Dict) -> str:
|
||||||
return "\n".join(f"{script};" for script in self.index(ddl))
|
return "\n".join(f"{script};" for script in self.index(ddl))
|
||||||
|
|
||||||
def gen_comment(self, table_sql: str, table_name: str) -> str:
|
def gen_comment(self, table_ddl: Dict) -> str:
|
||||||
script = ""
|
script = ""
|
||||||
for field, comment_string in self.filed_comments(table_sql):
|
for column in table_ddl["columns"]:
|
||||||
|
table_comment = column["comment"]
|
||||||
script += (
|
script += (
|
||||||
f"COMMENT ON COLUMN {table_name}.{field} IS '{comment_string}';" + "\n"
|
f"COMMENT ON COLUMN {table_ddl['table_name']}.{column['name']} IS '{table_comment}';"
|
||||||
|
+ "\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
table_comment = self.table_comment(table_sql)
|
table_comment = table_ddl["comment"]
|
||||||
if table_comment:
|
if table_comment:
|
||||||
script += f"COMMENT ON TABLE {table_name} IS '{table_comment}';\n"
|
script += (
|
||||||
|
f"COMMENT ON TABLE {table_ddl['table_name']} IS '{table_comment}';\n"
|
||||||
|
)
|
||||||
|
|
||||||
return script
|
return script
|
||||||
|
|
||||||
|
|
@ -464,6 +528,15 @@ CREATE TABLE {table_name} (
|
||||||
"""生成主键定义"""
|
"""生成主键定义"""
|
||||||
return f"ALTER TABLE {table_name} ADD CONSTRAINT pk_{table_name} PRIMARY KEY (id);\n"
|
return f"ALTER TABLE {table_name} ADD CONSTRAINT pk_{table_name} PRIMARY KEY (id);\n"
|
||||||
|
|
||||||
|
def gen_uk(self, table_ddl: Dict) -> str:
|
||||||
|
script = ""
|
||||||
|
uk_list = list(Convertor.unique_index(table_ddl))
|
||||||
|
for idx, (table_name, _, uk_columns) in enumerate(uk_list, 1):
|
||||||
|
uk_name = f"uk_{table_name}_{idx:02d}"
|
||||||
|
script += f"CREATE UNIQUE INDEX {uk_name} ON {table_name} ({', '.join(uk_columns)});\n"
|
||||||
|
|
||||||
|
return script
|
||||||
|
|
||||||
def gen_index(self, ddl: Dict) -> str:
|
def gen_index(self, ddl: Dict) -> str:
|
||||||
return "\n".join(f"{script};" for script in self.index(ddl))
|
return "\n".join(f"{script};" for script in self.index(ddl))
|
||||||
|
|
||||||
|
|
@ -521,17 +594,17 @@ class SQLServerConvertor(Convertor):
|
||||||
|
|
||||||
if type == "varchar":
|
if type == "varchar":
|
||||||
return f"nvarchar({size if size < 4000 else 4000})"
|
return f"nvarchar({size if size < 4000 else 4000})"
|
||||||
if type == "int":
|
if type in ("int", "int unsigned"):
|
||||||
return "int"
|
return "int"
|
||||||
if type == "bigint" or type == "bigint unsigned":
|
if type in ("bigint", "bigint unsigned"):
|
||||||
return "bigint"
|
return "bigint"
|
||||||
if type == "datetime":
|
if type in ("datetime", "timestamp"):
|
||||||
return "datetime2"
|
return "datetime2"
|
||||||
if type == "bit":
|
if type == "bit":
|
||||||
return "varchar(1)"
|
return "varchar(1)"
|
||||||
if type in ("tinyint", "smallint"):
|
if type in ("tinyint", "smallint"):
|
||||||
return "tinyint"
|
return "tinyint"
|
||||||
if type == "text":
|
if type in ("text", "longtext"):
|
||||||
return "nvarchar(max)"
|
return "nvarchar(max)"
|
||||||
if type in ("blob", "mediumblob"):
|
if type in ("blob", "mediumblob"):
|
||||||
return "varbinary(max)"
|
return "varbinary(max)"
|
||||||
|
|
@ -571,14 +644,18 @@ GO"""
|
||||||
|
|
||||||
return script
|
return script
|
||||||
|
|
||||||
def gen_comment(self, table_sql: str, table_name: str) -> str:
|
def gen_comment(self, table_ddl: Dict) -> str:
|
||||||
"""生成字段及表的注释"""
|
"""生成字段及表的注释"""
|
||||||
|
|
||||||
script = ""
|
script = ""
|
||||||
|
table_name = table_ddl["table_name"]
|
||||||
|
|
||||||
|
for column in table_ddl["columns"]:
|
||||||
|
column_comment = column["comment"]
|
||||||
|
field = column["name"]
|
||||||
|
|
||||||
for field, comment_string in self.filed_comments(table_sql):
|
|
||||||
script += f"""EXEC sp_addextendedproperty
|
script += f"""EXEC sp_addextendedproperty
|
||||||
'MS_Description', N'{comment_string}',
|
'MS_Description', N'{column_comment}',
|
||||||
'SCHEMA', N'dbo',
|
'SCHEMA', N'dbo',
|
||||||
'TABLE', N'{table_name}',
|
'TABLE', N'{table_name}',
|
||||||
'COLUMN', N'{field}'
|
'COLUMN', N'{field}'
|
||||||
|
|
@ -586,7 +663,7 @@ GO
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
table_comment = self.table_comment(table_sql)
|
table_comment = table_ddl["comment"]
|
||||||
if table_comment:
|
if table_comment:
|
||||||
script += f"""EXEC sp_addextendedproperty
|
script += f"""EXEC sp_addextendedproperty
|
||||||
'MS_Description', N'{table_comment}',
|
'MS_Description', N'{table_comment}',
|
||||||
|
|
@ -601,6 +678,15 @@ GO
|
||||||
"""生成主键定义"""
|
"""生成主键定义"""
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
def gen_uk(self, table_ddl: Dict) -> str:
|
||||||
|
script = ""
|
||||||
|
uk_list = list(Convertor.unique_index(table_ddl))
|
||||||
|
for idx, (table_name, _, uk_columns) in enumerate(uk_list, 1):
|
||||||
|
uk_name = f"uk_{table_name}_{idx:02d}"
|
||||||
|
script += f"CREATE UNIQUE INDEX {uk_name} ON {table_name} ({', '.join(uk_columns)})\nGO"
|
||||||
|
|
||||||
|
return script
|
||||||
|
|
||||||
def gen_index(self, ddl: Dict) -> str:
|
def gen_index(self, ddl: Dict) -> str:
|
||||||
"""生成 index"""
|
"""生成 index"""
|
||||||
return "\n".join(f"{script}\nGO" for script in self.index(ddl))
|
return "\n".join(f"{script}\nGO" for script in self.index(ddl))
|
||||||
|
|
@ -674,22 +760,22 @@ class DM8Convertor(Convertor):
|
||||||
|
|
||||||
if type == "varchar":
|
if type == "varchar":
|
||||||
return f"varchar({size})"
|
return f"varchar({size})"
|
||||||
if type == "int":
|
if type in ("int", "int unsigned"):
|
||||||
return "int"
|
return "int"
|
||||||
if type == "bigint" or type == "bigint unsigned":
|
if type in ("bigint", "bigint unsigned"):
|
||||||
return "bigint"
|
return "bigint"
|
||||||
if type == "datetime":
|
if type == "datetime":
|
||||||
return "datetime"
|
return "datetime"
|
||||||
|
if type == "timestamp":
|
||||||
|
return f"timestamp({size})"
|
||||||
if type == "bit":
|
if type == "bit":
|
||||||
return "bit"
|
return "bit"
|
||||||
if type in ("tinyint", "smallint"):
|
if type in ("tinyint", "smallint"):
|
||||||
return "smallint"
|
return "smallint"
|
||||||
if type == "text":
|
if type in ("text", "longtext"):
|
||||||
return "text"
|
return "text"
|
||||||
if type == "blob":
|
if type in ("blob", "mediumblob"):
|
||||||
return "blob"
|
return "blob"
|
||||||
if type == "mediumblob":
|
|
||||||
return "varchar(10240)"
|
|
||||||
if type == "decimal":
|
if type == "decimal":
|
||||||
return (
|
return (
|
||||||
f"decimal({','.join(str(s) for s in size)})" if len(size) else "decimal"
|
f"decimal({','.join(str(s) for s in size)})" if len(size) else "decimal"
|
||||||
|
|
@ -724,19 +810,20 @@ CREATE TABLE {table_name} (
|
||||||
|
|
||||||
return script
|
return script
|
||||||
|
|
||||||
def gen_index(self, ddl: Dict) -> str:
|
def gen_comment(self, table_ddl: Dict) -> str:
|
||||||
return "\n".join(f"{script};" for script in self.index(ddl))
|
|
||||||
|
|
||||||
def gen_comment(self, table_sql: str, table_name: str) -> str:
|
|
||||||
script = ""
|
script = ""
|
||||||
for field, comment_string in self.filed_comments(table_sql):
|
for column in table_ddl["columns"]:
|
||||||
|
table_comment = column["comment"]
|
||||||
script += (
|
script += (
|
||||||
f"COMMENT ON COLUMN {table_name}.{field} IS '{comment_string}';" + "\n"
|
f"COMMENT ON COLUMN {table_ddl['table_name']}.{column['name']} IS '{table_comment}';"
|
||||||
|
+ "\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
table_comment = self.table_comment(table_sql)
|
table_comment = table_ddl["comment"]
|
||||||
if table_comment:
|
if table_comment:
|
||||||
script += f"COMMENT ON TABLE {table_name} IS '{table_comment}';\n"
|
script += (
|
||||||
|
f"COMMENT ON TABLE {table_ddl['table_name']} IS '{table_comment}';\n"
|
||||||
|
)
|
||||||
|
|
||||||
return script
|
return script
|
||||||
|
|
||||||
|
|
@ -744,6 +831,15 @@ CREATE TABLE {table_name} (
|
||||||
"""生成主键定义"""
|
"""生成主键定义"""
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
def gen_uk(self, table_ddl: Dict) -> str:
|
||||||
|
script = ""
|
||||||
|
uk_list = list(Convertor.unique_index(table_ddl))
|
||||||
|
for idx, (table_name, _, uk_columns) in enumerate(uk_list, 1):
|
||||||
|
uk_name = f"uk_{table_name}_{idx:02d}"
|
||||||
|
script += f"CREATE UNIQUE INDEX {uk_name} ON {table_name} ({', '.join(uk_columns)});\n"
|
||||||
|
|
||||||
|
return script
|
||||||
|
|
||||||
def gen_index(self, ddl: Dict) -> str:
|
def gen_index(self, ddl: Dict) -> str:
|
||||||
return "\n".join(f"{script};" for script in self.index(ddl))
|
return "\n".join(f"{script};" for script in self.index(ddl))
|
||||||
|
|
||||||
|
|
@ -784,6 +880,8 @@ class KingbaseConvertor(PostgreSQLConvertor):
|
||||||
type = col["type"].lower()
|
type = col["type"].lower()
|
||||||
full_type = self.translate_type(type, col["size"])
|
full_type = self.translate_type(type, col["size"])
|
||||||
nullable = "NULL" if col["nullable"] else "NOT NULL"
|
nullable = "NULL" if col["nullable"] else "NOT NULL"
|
||||||
|
if full_type == "text":
|
||||||
|
nullable = "NULL"
|
||||||
default = f"DEFAULT {col['default']}" if col["default"] is not None else ""
|
default = f"DEFAULT {col['default']}" if col["default"] is not None else ""
|
||||||
return f"{name} {full_type} {nullable} {default}"
|
return f"{name} {full_type} {nullable} {default}"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.date;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.date.DatePattern;
|
import cn.hutool.core.date.DatePattern;
|
||||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||||
|
import cn.hutool.core.date.TemporalAccessorUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.enums.DateIntervalEnum;
|
import cn.iocoder.yudao.framework.common.enums.DateIntervalEnum;
|
||||||
|
|
@ -19,7 +20,7 @@ import static cn.hutool.core.date.DatePattern.UTC_MS_WITH_XXX_OFFSET_PATTERN;
|
||||||
import static cn.hutool.core.date.DatePattern.createFormatter;
|
import static cn.hutool.core.date.DatePattern.createFormatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 时间工具类,用于 {@link java.time.LocalDateTime}
|
* 时间工具类,用于 {@link LocalDateTime}
|
||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
|
|
@ -312,4 +313,16 @@ public class LocalDateTimeUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将给定的 {@link LocalDateTime} 转换为自 Unix 纪元时间(1970-01-01T00:00:00Z)以来的秒数。
|
||||||
|
*
|
||||||
|
* @param sourceDateTime 需要转换的本地日期时间,不能为空
|
||||||
|
* @return 自 1970-01-01T00:00:00Z 起的秒数(epoch second)
|
||||||
|
* @throws NullPointerException 如果 {@code sourceDateTime} 为 {@code null}
|
||||||
|
* @throws DateTimeException 如果转换过程中发生时间超出范围或其他时间处理异常
|
||||||
|
*/
|
||||||
|
public static Long toEpochSecond(LocalDateTime sourceDateTime) {
|
||||||
|
return TemporalAccessorUtil.toInstant(sourceDateTime).getEpochSecond();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,15 +49,17 @@ public class EnvLoadBalancerClient implements ReactorServiceInstanceLoadBalancer
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Response<ServiceInstance>> choose(Request request) {
|
public Mono<Response<ServiceInstance>> choose(Request request) {
|
||||||
// 情况一,没有 tag 时,使用默认的 reactiveLoadBalancer 实现负载均衡
|
|
||||||
String tag = EnvContextHolder.getTag();
|
|
||||||
if (StrUtil.isEmpty(tag)) {
|
|
||||||
return Mono.from(reactiveLoadBalancer.choose(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 情况二,有 tag 时,使用 tag 匹配服务实例
|
|
||||||
ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);
|
ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);
|
||||||
return supplier.get(request).next().map(list -> getInstanceResponse(list, tag));
|
return supplier.get(request).next().map(list -> {
|
||||||
|
// 情况一,没有 tag 时,过滤掉有 tag 的节点。目的:避免 test 环境,打到本地有 tag 的实例
|
||||||
|
String tag = EnvContextHolder.getTag();
|
||||||
|
if (StrUtil.isEmpty(tag)) {
|
||||||
|
return getInstanceResponseWithoutTag(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 情况二,有 tag 时,使用 tag 匹配服务实例
|
||||||
|
return getInstanceResponse(list, tag);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances, String tag) {
|
private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances, String tag) {
|
||||||
|
|
@ -74,10 +76,32 @@ public class EnvLoadBalancerClient implements ReactorServiceInstanceLoadBalancer
|
||||||
chooseInstances = instances;
|
chooseInstances = instances;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 芋艿:https://juejin.cn/post/7056770721858469896 想通网段
|
// TODO 芋艿:https://juejin.cn/post/7056770721858469896 相同网段
|
||||||
|
|
||||||
// 随机 + 权重获取实例列表 TODO 芋艿:目前直接使用 Nacos 提供的方法,如果替换注册中心,需要重新失败该方法
|
// 随机 + 权重获取实例列表 TODO 芋艿:目前直接使用 Nacos 提供的方法,如果替换注册中心,需要重新失败该方法
|
||||||
return new DefaultResponse(NacosBalancer.getHostByRandomWeight3(chooseInstances));
|
return new DefaultResponse(NacosBalancer.getHostByRandomWeight3(chooseInstances));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当没有 tag 时,过滤掉有 tag 的实例列表
|
||||||
|
*/
|
||||||
|
private Response<ServiceInstance> getInstanceResponseWithoutTag(List<ServiceInstance> instances) {
|
||||||
|
// 如果服务实例为空,则直接返回
|
||||||
|
if (CollUtil.isEmpty(instances)) {
|
||||||
|
log.warn("[getInstanceResponseWithoutTag][serviceId({}) 服务实例列表为空]", serviceId);
|
||||||
|
return new EmptyResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 筛选没有 tag 的实例列表
|
||||||
|
List<ServiceInstance> chooseInstances = CollectionUtils.filterList(instances, instance -> StrUtil.isEmpty(EnvUtils.getTag(instance)));
|
||||||
|
// 【重要】补充说明:如果希望在 chooseInstances 为空时,不允许打到有 tag 的实例,可以取消注释下面的代码
|
||||||
|
if (CollUtil.isEmpty(chooseInstances)) {
|
||||||
|
log.warn("[getInstanceResponseWithoutTag][serviceId({}) 没有不带 tag 的服务实例列表,直接使用所有服务实例列表]", serviceId);
|
||||||
|
chooseInstances = instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 随机 + 权重获取实例列表
|
||||||
|
return new DefaultResponse(NacosBalancer.getHostByRandomWeight3(chooseInstances));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.excel.core.handler;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.extra.spring.SpringUtil;
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
import cn.hutool.poi.excel.ExcelUtil;
|
import cn.hutool.poi.excel.ExcelUtil;
|
||||||
|
|
@ -10,6 +11,8 @@ import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||||
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
|
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
|
||||||
import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect;
|
import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect;
|
||||||
import cn.iocoder.yudao.framework.excel.core.function.ExcelColumnSelectFunction;
|
import cn.iocoder.yudao.framework.excel.core.function.ExcelColumnSelectFunction;
|
||||||
|
import com.alibaba.excel.annotation.ExcelIgnore;
|
||||||
|
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||||
import com.alibaba.excel.annotation.ExcelProperty;
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
import com.alibaba.excel.write.handler.SheetWriteHandler;
|
import com.alibaba.excel.write.handler.SheetWriteHandler;
|
||||||
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
|
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
|
||||||
|
|
@ -20,6 +23,7 @@ import org.apache.poi.ss.usermodel.*;
|
||||||
import org.apache.poi.ss.util.CellRangeAddressList;
|
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -56,7 +60,20 @@ public class SelectSheetWriteHandler implements SheetWriteHandler {
|
||||||
public SelectSheetWriteHandler(Class<?> head) {
|
public SelectSheetWriteHandler(Class<?> head) {
|
||||||
// 解析下拉数据
|
// 解析下拉数据
|
||||||
int colIndex = 0;
|
int colIndex = 0;
|
||||||
|
boolean ignoreUnannotated = head.isAnnotationPresent(ExcelIgnoreUnannotated.class);
|
||||||
for (Field field : head.getDeclaredFields()) {
|
for (Field field : head.getDeclaredFields()) {
|
||||||
|
// 关联 https://github.com/YunaiV/ruoyi-vue-pro/pull/853
|
||||||
|
// 1.1 忽略 static final 或 transient 的字段
|
||||||
|
if (isStaticFinalOrTransient(field) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 1.2 忽略的字段跳过
|
||||||
|
if ((ignoreUnannotated && !field.isAnnotationPresent(ExcelProperty.class))
|
||||||
|
|| field.isAnnotationPresent(ExcelIgnore.class)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 核心:处理有 ExcelColumnSelect 注解的字段
|
||||||
if (field.isAnnotationPresent(ExcelColumnSelect.class)) {
|
if (field.isAnnotationPresent(ExcelColumnSelect.class)) {
|
||||||
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
|
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
|
||||||
if (excelProperty != null && excelProperty.index() != -1) {
|
if (excelProperty != null && excelProperty.index() != -1) {
|
||||||
|
|
@ -68,6 +85,19 @@ public class SelectSheetWriteHandler implements SheetWriteHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断字段是否是静态的、最终的、 transient 的
|
||||||
|
* 原因:EasyExcel 默认是忽略 static final 或 transient 的字段,所以需要判断
|
||||||
|
*
|
||||||
|
* @param field 字段
|
||||||
|
* @return 是否是静态的、最终的、transient 的
|
||||||
|
*/
|
||||||
|
private boolean isStaticFinalOrTransient(Field field) {
|
||||||
|
return (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()))
|
||||||
|
|| Modifier.isTransient(field.getModifiers());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得下拉数据,并添加到 {@link #selectMap} 中
|
* 获得下拉数据,并添加到 {@link #selectMap} 中
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.scheduling.annotation.EnableAsync;
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 异步任务 Configuration
|
* 异步任务 Configuration
|
||||||
|
|
@ -22,13 +22,20 @@ public class YudaoAsyncAutoConfiguration {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||||
if (!(bean instanceof ThreadPoolTaskExecutor)) {
|
// 处理 ThreadPoolTaskExecutor
|
||||||
return bean;
|
if (bean instanceof ThreadPoolTaskExecutor) {
|
||||||
|
ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) bean;
|
||||||
|
executor.setTaskDecorator(TtlRunnable::get);
|
||||||
|
return executor;
|
||||||
}
|
}
|
||||||
// 修改提交的任务,接入 TransmittableThreadLocal
|
// 处理 SimpleAsyncTaskExecutor
|
||||||
ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) bean;
|
// 参考 https://t.zsxq.com/CBoks 增加
|
||||||
executor.setTaskDecorator(TtlRunnable::get);
|
if (bean instanceof SimpleAsyncTaskExecutor) {
|
||||||
return executor;
|
SimpleAsyncTaskExecutor executor = (SimpleAsyncTaskExecutor) bean;
|
||||||
|
executor.setTaskDecorator(TtlRunnable::get);
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
return bean;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
|
||||||
default PageResult<T> selectPage(PageParam pageParam, Collection<SortingField> sortingFields, @Param("ew") Wrapper<T> queryWrapper) {
|
default PageResult<T> selectPage(PageParam pageParam, Collection<SortingField> sortingFields, @Param("ew") Wrapper<T> queryWrapper) {
|
||||||
// 特殊:不分页,直接查询全部
|
// 特殊:不分页,直接查询全部
|
||||||
if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) {
|
if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) {
|
||||||
|
MyBatisUtils.addOrder(queryWrapper, sortingFields);
|
||||||
List<T> list = selectList(queryWrapper);
|
List<T> list = selectList(queryWrapper);
|
||||||
return new PageResult<>(list, (long) list.size());
|
return new PageResult<>(list, (long) list.size());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
package cn.iocoder.yudao.framework.mybatis.core.util;
|
package cn.iocoder.yudao.framework.mybatis.core.util;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.lang.func.Func1;
|
||||||
|
import cn.hutool.core.lang.func.LambdaUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.SortingField;
|
import cn.iocoder.yudao.framework.common.pojo.SortingField;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.enums.DbTypeEnum;
|
import cn.iocoder.yudao.framework.mybatis.core.enums.DbTypeEnum;
|
||||||
import com.baomidou.mybatisplus.annotation.DbType;
|
import com.baomidou.mybatisplus.annotation.DbType;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||||
|
|
@ -18,7 +22,6 @@ import net.sf.jsqlparser.schema.Table;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MyBatis 工具类
|
* MyBatis 工具类
|
||||||
|
|
@ -35,15 +38,27 @@ public class MyBatisUtils {
|
||||||
// 页码 + 数量
|
// 页码 + 数量
|
||||||
Page<T> page = new Page<>(pageParam.getPageNo(), pageParam.getPageSize());
|
Page<T> page = new Page<>(pageParam.getPageNo(), pageParam.getPageSize());
|
||||||
// 排序字段
|
// 排序字段
|
||||||
if (!CollectionUtil.isEmpty(sortingFields)) {
|
if (CollUtil.isNotEmpty(sortingFields)) {
|
||||||
page.addOrder(sortingFields.stream().map(sortingField -> SortingField.ORDER_ASC.equals(sortingField.getOrder())
|
for (SortingField sortingField : sortingFields) {
|
||||||
? OrderItem.asc(StrUtil.toUnderlineCase(sortingField.getField()))
|
page.addOrder(new OrderItem().setAsc(SortingField.ORDER_ASC.equals(sortingField.getOrder()))
|
||||||
: OrderItem.desc(StrUtil.toUnderlineCase(sortingField.getField())))
|
.setColumn(StrUtil.toUnderlineCase(sortingField.getField())));
|
||||||
.collect(Collectors.toList()));
|
}
|
||||||
}
|
}
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> void addOrder(Wrapper<T> wrapper, Collection<SortingField> sortingFields) {
|
||||||
|
if (CollUtil.isEmpty(sortingFields)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QueryWrapper<T> query = (QueryWrapper<T>) wrapper;
|
||||||
|
for (SortingField sortingField : sortingFields) {
|
||||||
|
query.orderBy(true,
|
||||||
|
SortingField.ORDER_ASC.equals(sortingField.getOrder()),
|
||||||
|
StrUtil.toUnderlineCase(sortingField.getField()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将拦截器添加到链中
|
* 将拦截器添加到链中
|
||||||
* 由于 MybatisPlusInterceptor 不支持添加拦截器,所以只能全量设置
|
* 由于 MybatisPlusInterceptor 不支持添加拦截器,所以只能全量设置
|
||||||
|
|
@ -103,4 +118,18 @@ public class MyBatisUtils {
|
||||||
.replace("#{value}", StrUtil.toString(value));
|
.replace("#{value}", StrUtil.toString(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将驼峰命名转换为下划线命名
|
||||||
|
*
|
||||||
|
* 使用场景:
|
||||||
|
* 1. <a href="https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1357/files">fix:修复"商品统计聚合函数的别名与排序字段不符"导致的 SQL 异常</a>
|
||||||
|
*
|
||||||
|
* @param func 字段名函数(驼峰命名)
|
||||||
|
* @return 字段名(下划线命名)
|
||||||
|
*/
|
||||||
|
public static <T> String toUnderlineCase(Func1<T, ?> func) {
|
||||||
|
String fieldName = LambdaUtil.getFieldName(func);
|
||||||
|
return StrUtil.toUnderlineCase(fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -128,8 +128,10 @@ public class SecurityFrameworkUtils {
|
||||||
|
|
||||||
// 额外设置到 request 中,用于 ApiAccessLogFilter 可以获取到用户编号;
|
// 额外设置到 request 中,用于 ApiAccessLogFilter 可以获取到用户编号;
|
||||||
// 原因是,Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息
|
// 原因是,Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息
|
||||||
WebFrameworkUtils.setLoginUserId(request, loginUser.getId());
|
if (request != null) {
|
||||||
WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType());
|
WebFrameworkUtils.setLoginUserId(request, loginUser.getId());
|
||||||
|
WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Authentication buildAuthentication(LoginUser loginUser, HttpServletRequest request) {
|
private static Authentication buildAuthentication(LoginUser loginUser, HttpServletRequest request) {
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ public class StringDesensitizeSerializer extends StdSerializer<String> implement
|
||||||
*/
|
*/
|
||||||
private Field getField(JsonGenerator generator) {
|
private Field getField(JsonGenerator generator) {
|
||||||
String currentName = generator.getOutputContext().getCurrentName();
|
String currentName = generator.getOutputContext().getCurrentName();
|
||||||
Object currentValue = generator.getCurrentValue();
|
Object currentValue = generator.currentValue();
|
||||||
Class<?> currentValueClass = currentValue.getClass();
|
Class<?> currentValueClass = currentValue.getClass();
|
||||||
return ReflectUtil.getField(currentValueClass, currentName);
|
return ReflectUtil.getField(currentValueClass, currentName);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,10 +93,16 @@ public class GrayLoadBalancer implements ReactorServiceInstanceLoadBalancer {
|
||||||
* @return 服务实例列表
|
* @return 服务实例列表
|
||||||
*/
|
*/
|
||||||
private List<ServiceInstance> filterTagServiceInstances(List<ServiceInstance> instances, HttpHeaders headers) {
|
private List<ServiceInstance> filterTagServiceInstances(List<ServiceInstance> instances, HttpHeaders headers) {
|
||||||
// 情况一,没有 tag 时,直接返回
|
// 情况一,没有 tag 时,过滤掉有 tag 的节点。目的:避免 test 环境,打到本地有 tag 的实例
|
||||||
String tag = EnvUtils.getTag(headers);
|
String tag = EnvUtils.getTag(headers);
|
||||||
if (StrUtil.isEmpty(tag)) {
|
if (StrUtil.isEmpty(tag)) {
|
||||||
return instances;
|
List<ServiceInstance> chooseInstances = CollectionUtils.filterList(instances, instance -> StrUtil.isEmpty(EnvUtils.getTag(instance)));
|
||||||
|
// 【重要】补充说明:如果希望在 chooseInstances 为空时,不允许打到有 tag 的实例,可以取消注释下面的代码
|
||||||
|
if (CollUtil.isEmpty(chooseInstances)) {
|
||||||
|
log.warn("[filterTagServiceInstances][serviceId({}) 没有不带 tag 的服务实例列表,直接使用所有服务实例列表]", serviceId);
|
||||||
|
chooseInstances = instances;
|
||||||
|
}
|
||||||
|
return chooseInstances;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 情况二,有 tag 时,使用 tag 匹配服务实例
|
// 情况二,有 tag 时,使用 tag 匹配服务实例
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,12 @@
|
||||||
<description>
|
<description>
|
||||||
ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维导图等功能。
|
ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维导图等功能。
|
||||||
目前已接入各种模型,不限于:
|
目前已接入各种模型,不限于:
|
||||||
国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek
|
国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek
|
||||||
国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno
|
国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno
|
||||||
</description>
|
</description>
|
||||||
<properties>
|
<properties>
|
||||||
<spring-ai.version>1.0.0-M6</spring-ai.version>
|
<spring-ai.version>1.0.0</spring-ai.version>
|
||||||
|
<alibaba-ai.version>1.0.0.2</alibaba-ai.version>
|
||||||
<tinyflow.version>1.0.2</tinyflow.version>
|
<tinyflow.version>1.0.2</tinyflow.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
@ -110,65 +111,73 @@
|
||||||
<!-- Spring AI Model 模型接入 -->
|
<!-- Spring AI Model 模型接入 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
|
<artifactId>spring-ai-starter-model-openai</artifactId>
|
||||||
<version>${spring-ai.version}</version>
|
<version>${spring-ai.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-azure-openai-spring-boot-starter</artifactId>
|
<artifactId>spring-ai-starter-model-azure-openai</artifactId>
|
||||||
<version>${spring-ai.version}</version>
|
<version>${spring-ai.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
|
<artifactId>spring-ai-starter-model-deepseek</artifactId>
|
||||||
<version>${spring-ai.version}</version>
|
<version>${spring-ai.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-stability-ai-spring-boot-starter</artifactId>
|
<artifactId>spring-ai-starter-model-ollama</artifactId>
|
||||||
<version>${spring-ai.version}</version>
|
<version>${spring-ai.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<!-- 通义千问 -->
|
|
||||||
<groupId>com.alibaba.cloud.ai</groupId>
|
|
||||||
<artifactId>spring-ai-alibaba-starter</artifactId>
|
|
||||||
<version>${spring-ai.version}.1</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<!-- 文心一言 -->
|
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-qianfan-spring-boot-starter</artifactId>
|
<artifactId>spring-ai-starter-model-stability-ai</artifactId>
|
||||||
<version>${spring-ai.version}</version>
|
<version>${spring-ai.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<!-- 智谱 GLM -->
|
<!-- 智谱 GLM -->
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-zhipuai-spring-boot-starter</artifactId>
|
<artifactId>spring-ai-starter-model-zhipuai</artifactId>
|
||||||
<version>${spring-ai.version}</version>
|
<version>${spring-ai.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-minimax-spring-boot-starter</artifactId>
|
<artifactId>spring-ai-starter-model-minimax</artifactId>
|
||||||
<version>${spring-ai.version}</version>
|
<version>${spring-ai.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<!-- 通义千问 -->
|
||||||
<artifactId>spring-ai-moonshot-spring-boot-starter</artifactId>
|
<groupId>com.alibaba.cloud.ai</groupId>
|
||||||
<version>${spring-ai.version}</version>
|
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
|
||||||
|
<version>${alibaba-ai.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<!-- 文心一言 -->
|
||||||
|
<groupId>org.springaicommunity</groupId>
|
||||||
|
<artifactId>qianfan-spring-boot-starter</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<!-- 月之暗灭 -->
|
||||||
|
<groupId>org.springaicommunity</groupId>
|
||||||
|
<artifactId>moonshot-spring-boot-starter</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 向量存储:https://db-engines.com/en/ranking/vector+dbms -->
|
<!-- 向量存储:https://db-engines.com/en/ranking/vector+dbms -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<!-- Qdrant:https://qdrant.tech/ -->
|
<!-- Qdrant:https://qdrant.tech/ -->
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-qdrant-store</artifactId>
|
<artifactId>spring-ai-starter-vector-store-qdrant</artifactId>
|
||||||
<version>${spring-ai.version}</version>
|
<version>${spring-ai.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<!-- Redis:https://redis.io/docs/latest/develop/get-started/vector-database/ -->
|
<!-- Redis:https://redis.io/docs/latest/develop/get-started/vector-database/ -->
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-redis-store</artifactId>
|
<artifactId>spring-ai-starter-vector-store-redis</artifactId>
|
||||||
<version>${spring-ai.version}</version>
|
<version>${spring-ai.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
@ -179,7 +188,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<!-- Milvus:https://milvus.io/ -->
|
<!-- Milvus:https://milvus.io/ -->
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-milvus-store</artifactId>
|
<artifactId>spring-ai-starter-vector-store-milvus</artifactId>
|
||||||
<version>${spring-ai.version}</version>
|
<version>${spring-ai.version}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<!-- 解决和 logback 的日志冲突 -->
|
<!-- 解决和 logback 的日志冲突 -->
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@SpringBootApplication(exclude = {
|
@SpringBootApplication(exclude = {
|
||||||
org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration.class,
|
org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration.class,
|
||||||
org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration.class,
|
org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration.class,
|
||||||
}) // 解决 application-${profile}.yaml 配置文件下,通过 spring.autoconfigure.exclude 无法排除的问题
|
}) // 解决 application-${profile}.yaml 配置文件下,通过 spring.autoconfigure.exclude 无法排除的问题
|
||||||
public class AiServerApplication {
|
public class AiServerApplication {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import cn.hutool.extra.spring.SpringUtil;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.AiModelFactory;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.AiModelFactory;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.AiModelFactoryImpl;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.AiModelFactoryImpl;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel;
|
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi;
|
||||||
|
|
@ -14,10 +13,6 @@ import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlo
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientProperties;
|
|
||||||
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreProperties;
|
|
||||||
import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties;
|
|
||||||
import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties;
|
|
||||||
import org.springframework.ai.embedding.BatchingStrategy;
|
import org.springframework.ai.embedding.BatchingStrategy;
|
||||||
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
|
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
|
||||||
import org.springframework.ai.model.tool.ToolCallingManager;
|
import org.springframework.ai.model.tool.ToolCallingManager;
|
||||||
|
|
@ -26,6 +21,10 @@ import org.springframework.ai.openai.OpenAiChatOptions;
|
||||||
import org.springframework.ai.openai.api.OpenAiApi;
|
import org.springframework.ai.openai.api.OpenAiApi;
|
||||||
import org.springframework.ai.tokenizer.JTokkitTokenCountEstimator;
|
import org.springframework.ai.tokenizer.JTokkitTokenCountEstimator;
|
||||||
import org.springframework.ai.tokenizer.TokenCountEstimator;
|
import org.springframework.ai.tokenizer.TokenCountEstimator;
|
||||||
|
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientProperties;
|
||||||
|
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreProperties;
|
||||||
|
import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreProperties;
|
||||||
|
import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreProperties;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
@ -52,33 +51,6 @@ public class AiAutoConfiguration {
|
||||||
|
|
||||||
// ========== 各种 AI Client 创建 ==========
|
// ========== 各种 AI Client 创建 ==========
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnProperty(value = "yudao.ai.deepseek.enable", havingValue = "true")
|
|
||||||
public DeepSeekChatModel deepSeekChatModel(YudaoAiProperties yudaoAiProperties) {
|
|
||||||
YudaoAiProperties.DeepSeekProperties properties = yudaoAiProperties.getDeepseek();
|
|
||||||
return buildDeepSeekChatModel(properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeepSeekChatModel buildDeepSeekChatModel(YudaoAiProperties.DeepSeekProperties properties) {
|
|
||||||
if (StrUtil.isEmpty(properties.getModel())) {
|
|
||||||
properties.setModel(DeepSeekChatModel.MODEL_DEFAULT);
|
|
||||||
}
|
|
||||||
OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
|
|
||||||
.openAiApi(OpenAiApi.builder()
|
|
||||||
.baseUrl(DeepSeekChatModel.BASE_URL)
|
|
||||||
.apiKey(properties.getApiKey())
|
|
||||||
.build())
|
|
||||||
.defaultOptions(OpenAiChatOptions.builder()
|
|
||||||
.model(properties.getModel())
|
|
||||||
.temperature(properties.getTemperature())
|
|
||||||
.maxTokens(properties.getMaxTokens())
|
|
||||||
.topP(properties.getTopP())
|
|
||||||
.build())
|
|
||||||
.toolCallingManager(getToolCallingManager())
|
|
||||||
.build();
|
|
||||||
return new DeepSeekChatModel(openAiChatModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(value = "yudao.ai.doubao.enable", havingValue = "true")
|
@ConditionalOnProperty(value = "yudao.ai.doubao.enable", havingValue = "true")
|
||||||
public DouBaoChatModel douBaoChatClient(YudaoAiProperties yudaoAiProperties) {
|
public DouBaoChatModel douBaoChatClient(YudaoAiProperties yudaoAiProperties) {
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
@Data
|
@Data
|
||||||
public class YudaoAiProperties {
|
public class YudaoAiProperties {
|
||||||
|
|
||||||
/**
|
|
||||||
* DeepSeek
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
|
||||||
private DeepSeekProperties deepseek;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 字节豆包
|
* 字节豆包
|
||||||
*/
|
*/
|
||||||
|
|
@ -60,19 +54,6 @@ public class YudaoAiProperties {
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
@SuppressWarnings("SpellCheckingInspection")
|
||||||
private SunoProperties suno;
|
private SunoProperties suno;
|
||||||
|
|
||||||
@Data
|
|
||||||
public static class DeepSeekProperties {
|
|
||||||
|
|
||||||
private String enable;
|
|
||||||
private String apiKey;
|
|
||||||
|
|
||||||
private String model;
|
|
||||||
private Double temperature;
|
|
||||||
private Integer maxTokens;
|
|
||||||
private Double topP;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class DouBaoProperties {
|
public static class DouBaoProperties {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,11 @@ import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.hutool.core.util.RuntimeUtil;
|
import cn.hutool.core.util.RuntimeUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.extra.spring.SpringUtil;
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
|
||||||
|
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.config.AiAutoConfiguration;
|
import cn.iocoder.yudao.module.ai.framework.ai.config.AiAutoConfiguration;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.config.YudaoAiProperties;
|
import cn.iocoder.yudao.module.ai.framework.ai.config.YudaoAiProperties;
|
||||||
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
|
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel;
|
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi;
|
||||||
|
|
@ -22,8 +22,9 @@ import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlo
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageModel;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageModel;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel;
|
||||||
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
|
import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeChatAutoConfiguration;
|
||||||
import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeAutoConfiguration;
|
import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeEmbeddingAutoConfiguration;
|
||||||
|
import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeImageAutoConfiguration;
|
||||||
import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
|
import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
|
||||||
import com.alibaba.cloud.ai.dashscope.api.DashScopeImageApi;
|
import com.alibaba.cloud.ai.dashscope.api.DashScopeImageApi;
|
||||||
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
|
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
|
||||||
|
|
@ -32,47 +33,55 @@ import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingModel;
|
||||||
import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions;
|
import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions;
|
||||||
import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel;
|
import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel;
|
||||||
import com.azure.ai.openai.OpenAIClientBuilder;
|
import com.azure.ai.openai.OpenAIClientBuilder;
|
||||||
|
import com.azure.core.credential.KeyCredential;
|
||||||
import io.micrometer.observation.ObservationRegistry;
|
import io.micrometer.observation.ObservationRegistry;
|
||||||
import io.milvus.client.MilvusServiceClient;
|
import io.milvus.client.MilvusServiceClient;
|
||||||
import io.qdrant.client.QdrantClient;
|
import io.qdrant.client.QdrantClient;
|
||||||
import io.qdrant.client.QdrantGrpcClient;
|
import io.qdrant.client.QdrantGrpcClient;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration;
|
import org.springaicommunity.moonshot.MoonshotChatModel;
|
||||||
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties;
|
import org.springaicommunity.moonshot.MoonshotChatOptions;
|
||||||
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiConnectionProperties;
|
import org.springaicommunity.moonshot.api.MoonshotApi;
|
||||||
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiEmbeddingProperties;
|
import org.springaicommunity.moonshot.autoconfigure.MoonshotChatAutoConfiguration;
|
||||||
import org.springframework.ai.autoconfigure.minimax.MiniMaxAutoConfiguration;
|
import org.springaicommunity.qianfan.QianFanChatModel;
|
||||||
import org.springframework.ai.autoconfigure.moonshot.MoonshotAutoConfiguration;
|
import org.springaicommunity.qianfan.QianFanEmbeddingModel;
|
||||||
import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration;
|
import org.springaicommunity.qianfan.QianFanEmbeddingOptions;
|
||||||
import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration;
|
import org.springaicommunity.qianfan.QianFanImageModel;
|
||||||
import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration;
|
import org.springaicommunity.qianfan.api.QianFanApi;
|
||||||
import org.springframework.ai.autoconfigure.stabilityai.StabilityAiImageAutoConfiguration;
|
import org.springaicommunity.qianfan.api.QianFanImageApi;
|
||||||
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientConnectionDetails;
|
import org.springaicommunity.qianfan.autoconfigure.QianFanChatAutoConfiguration;
|
||||||
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientProperties;
|
import org.springaicommunity.qianfan.autoconfigure.QianFanEmbeddingAutoConfiguration;
|
||||||
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration;
|
|
||||||
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreProperties;
|
|
||||||
import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration;
|
|
||||||
import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties;
|
|
||||||
import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreAutoConfiguration;
|
|
||||||
import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties;
|
|
||||||
import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration;
|
|
||||||
import org.springframework.ai.azure.openai.AzureOpenAiChatModel;
|
import org.springframework.ai.azure.openai.AzureOpenAiChatModel;
|
||||||
import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingModel;
|
import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingModel;
|
||||||
import org.springframework.ai.chat.model.ChatModel;
|
import org.springframework.ai.chat.model.ChatModel;
|
||||||
|
import org.springframework.ai.deepseek.DeepSeekChatModel;
|
||||||
|
import org.springframework.ai.deepseek.DeepSeekChatOptions;
|
||||||
|
import org.springframework.ai.deepseek.api.DeepSeekApi;
|
||||||
import org.springframework.ai.document.MetadataMode;
|
import org.springframework.ai.document.MetadataMode;
|
||||||
import org.springframework.ai.embedding.BatchingStrategy;
|
import org.springframework.ai.embedding.BatchingStrategy;
|
||||||
import org.springframework.ai.embedding.EmbeddingModel;
|
import org.springframework.ai.embedding.EmbeddingModel;
|
||||||
|
import org.springframework.ai.embedding.observation.EmbeddingModelObservationConvention;
|
||||||
import org.springframework.ai.image.ImageModel;
|
import org.springframework.ai.image.ImageModel;
|
||||||
import org.springframework.ai.minimax.MiniMaxChatModel;
|
import org.springframework.ai.minimax.MiniMaxChatModel;
|
||||||
import org.springframework.ai.minimax.MiniMaxChatOptions;
|
import org.springframework.ai.minimax.MiniMaxChatOptions;
|
||||||
import org.springframework.ai.minimax.MiniMaxEmbeddingModel;
|
import org.springframework.ai.minimax.MiniMaxEmbeddingModel;
|
||||||
import org.springframework.ai.minimax.MiniMaxEmbeddingOptions;
|
import org.springframework.ai.minimax.MiniMaxEmbeddingOptions;
|
||||||
import org.springframework.ai.minimax.api.MiniMaxApi;
|
import org.springframework.ai.minimax.api.MiniMaxApi;
|
||||||
import org.springframework.ai.model.function.FunctionCallbackResolver;
|
import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatAutoConfiguration;
|
||||||
|
import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingAutoConfiguration;
|
||||||
|
import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingProperties;
|
||||||
|
import org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration;
|
||||||
|
import org.springframework.ai.model.minimax.autoconfigure.MiniMaxChatAutoConfiguration;
|
||||||
|
import org.springframework.ai.model.minimax.autoconfigure.MiniMaxEmbeddingAutoConfiguration;
|
||||||
|
import org.springframework.ai.model.ollama.autoconfigure.OllamaChatAutoConfiguration;
|
||||||
|
import org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration;
|
||||||
|
import org.springframework.ai.model.openai.autoconfigure.OpenAiEmbeddingAutoConfiguration;
|
||||||
|
import org.springframework.ai.model.openai.autoconfigure.OpenAiImageAutoConfiguration;
|
||||||
|
import org.springframework.ai.model.stabilityai.autoconfigure.StabilityAiImageAutoConfiguration;
|
||||||
import org.springframework.ai.model.tool.ToolCallingManager;
|
import org.springframework.ai.model.tool.ToolCallingManager;
|
||||||
import org.springframework.ai.moonshot.MoonshotChatModel;
|
import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiChatAutoConfiguration;
|
||||||
import org.springframework.ai.moonshot.MoonshotChatOptions;
|
import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiEmbeddingAutoConfiguration;
|
||||||
import org.springframework.ai.moonshot.api.MoonshotApi;
|
import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiImageAutoConfiguration;
|
||||||
import org.springframework.ai.ollama.OllamaChatModel;
|
import org.springframework.ai.ollama.OllamaChatModel;
|
||||||
import org.springframework.ai.ollama.OllamaEmbeddingModel;
|
import org.springframework.ai.ollama.OllamaEmbeddingModel;
|
||||||
import org.springframework.ai.ollama.api.OllamaApi;
|
import org.springframework.ai.ollama.api.OllamaApi;
|
||||||
|
|
@ -84,21 +93,23 @@ import org.springframework.ai.openai.OpenAiImageModel;
|
||||||
import org.springframework.ai.openai.api.OpenAiApi;
|
import org.springframework.ai.openai.api.OpenAiApi;
|
||||||
import org.springframework.ai.openai.api.OpenAiImageApi;
|
import org.springframework.ai.openai.api.OpenAiImageApi;
|
||||||
import org.springframework.ai.openai.api.common.OpenAiApiConstants;
|
import org.springframework.ai.openai.api.common.OpenAiApiConstants;
|
||||||
import org.springframework.ai.qianfan.QianFanChatModel;
|
|
||||||
import org.springframework.ai.qianfan.QianFanEmbeddingModel;
|
|
||||||
import org.springframework.ai.qianfan.QianFanEmbeddingOptions;
|
|
||||||
import org.springframework.ai.qianfan.QianFanImageModel;
|
|
||||||
import org.springframework.ai.qianfan.api.QianFanApi;
|
|
||||||
import org.springframework.ai.qianfan.api.QianFanImageApi;
|
|
||||||
import org.springframework.ai.stabilityai.StabilityAiImageModel;
|
import org.springframework.ai.stabilityai.StabilityAiImageModel;
|
||||||
import org.springframework.ai.stabilityai.api.StabilityAiApi;
|
import org.springframework.ai.stabilityai.api.StabilityAiApi;
|
||||||
import org.springframework.ai.vectorstore.SimpleVectorStore;
|
import org.springframework.ai.vectorstore.SimpleVectorStore;
|
||||||
import org.springframework.ai.vectorstore.VectorStore;
|
import org.springframework.ai.vectorstore.VectorStore;
|
||||||
import org.springframework.ai.vectorstore.milvus.MilvusVectorStore;
|
import org.springframework.ai.vectorstore.milvus.MilvusVectorStore;
|
||||||
|
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientConnectionDetails;
|
||||||
|
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientProperties;
|
||||||
|
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration;
|
||||||
|
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreProperties;
|
||||||
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
|
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
|
||||||
import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention;
|
import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention;
|
||||||
import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore;
|
import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore;
|
||||||
|
import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration;
|
||||||
|
import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreProperties;
|
||||||
import org.springframework.ai.vectorstore.redis.RedisVectorStore;
|
import org.springframework.ai.vectorstore.redis.RedisVectorStore;
|
||||||
|
import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreAutoConfiguration;
|
||||||
|
import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreProperties;
|
||||||
import org.springframework.ai.zhipuai.*;
|
import org.springframework.ai.zhipuai.*;
|
||||||
import org.springframework.ai.zhipuai.api.ZhiPuAiApi;
|
import org.springframework.ai.zhipuai.api.ZhiPuAiApi;
|
||||||
import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi;
|
import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi;
|
||||||
|
|
@ -190,7 +201,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
case XING_HUO:
|
case XING_HUO:
|
||||||
return SpringUtil.getBean(XingHuoChatModel.class);
|
return SpringUtil.getBean(XingHuoChatModel.class);
|
||||||
case BAI_CHUAN:
|
case BAI_CHUAN:
|
||||||
return SpringUtil.getBean(AzureOpenAiChatModel.class);
|
return SpringUtil.getBean(BaiChuanChatModel.class);
|
||||||
case OPENAI:
|
case OPENAI:
|
||||||
return SpringUtil.getBean(OpenAiChatModel.class);
|
return SpringUtil.getBean(OpenAiChatModel.class);
|
||||||
case AZURE_OPENAI:
|
case AZURE_OPENAI:
|
||||||
|
|
@ -319,27 +330,34 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
// ========== 各种创建 spring-ai 客户端的方法 ==========
|
// ========== 各种创建 spring-ai 客户端的方法 ==========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link DashScopeAutoConfiguration} 的 dashscopeChatModel 方法
|
* 可参考 {@link DashScopeChatAutoConfiguration} 的 dashscopeChatModel 方法
|
||||||
*/
|
*/
|
||||||
private static DashScopeChatModel buildTongYiChatModel(String key) {
|
private static DashScopeChatModel buildTongYiChatModel(String key) {
|
||||||
DashScopeApi dashScopeApi = new DashScopeApi(key);
|
DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(key).build();
|
||||||
DashScopeChatOptions options = DashScopeChatOptions.builder().withModel(DashScopeApi.DEFAULT_CHAT_MODEL)
|
DashScopeChatOptions options = DashScopeChatOptions.builder().withModel(DashScopeApi.DEFAULT_CHAT_MODEL)
|
||||||
.withTemperature(0.7).build();
|
.withTemperature(0.7).build();
|
||||||
return new DashScopeChatModel(dashScopeApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE);
|
return DashScopeChatModel.builder()
|
||||||
|
.dashScopeApi(dashScopeApi)
|
||||||
|
.defaultOptions(options)
|
||||||
|
.toolCallingManager(getToolCallingManager())
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link DashScopeAutoConfiguration} 的 dashScopeImageModel 方法
|
* 可参考 {@link DashScopeImageAutoConfiguration} 的 dashScopeImageModel 方法
|
||||||
*/
|
*/
|
||||||
private static DashScopeImageModel buildTongYiImagesModel(String key) {
|
private static DashScopeImageModel buildTongYiImagesModel(String key) {
|
||||||
DashScopeImageApi dashScopeImageApi = new DashScopeImageApi(key);
|
DashScopeImageApi dashScopeImageApi = new DashScopeImageApi(key);
|
||||||
return new DashScopeImageModel(dashScopeImageApi);
|
return DashScopeImageModel.builder()
|
||||||
|
.dashScopeApi(dashScopeImageApi)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link QianFanAutoConfiguration} 的 qianFanChatModel 方法
|
* 可参考 {@link QianFanChatAutoConfiguration} 的 qianFanChatModel 方法
|
||||||
*/
|
*/
|
||||||
private static QianFanChatModel buildYiYanChatModel(String key) {
|
private static QianFanChatModel buildYiYanChatModel(String key) {
|
||||||
|
// TODO spring ai qianfan 有 bug,无法使用 https://github.com/spring-ai-community/qianfan/issues/6
|
||||||
List<String> keys = StrUtil.split(key, '|');
|
List<String> keys = StrUtil.split(key, '|');
|
||||||
Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式");
|
Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式");
|
||||||
String appKey = keys.get(0);
|
String appKey = keys.get(0);
|
||||||
|
|
@ -349,9 +367,10 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link QianFanAutoConfiguration} 的 qianFanImageModel 方法
|
* 可参考 {@link QianFanEmbeddingAutoConfiguration} 的 qianFanImageModel 方法
|
||||||
*/
|
*/
|
||||||
private QianFanImageModel buildQianFanImageModel(String key) {
|
private QianFanImageModel buildQianFanImageModel(String key) {
|
||||||
|
// TODO spring ai qianfan 有 bug,无法使用 https://github.com/spring-ai-community/qianfan/issues/6
|
||||||
List<String> keys = StrUtil.split(key, '|');
|
List<String> keys = StrUtil.split(key, '|');
|
||||||
Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式");
|
Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式");
|
||||||
String appKey = keys.get(0);
|
String appKey = keys.get(0);
|
||||||
|
|
@ -361,12 +380,17 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link AiAutoConfiguration#deepSeekChatModel(YudaoAiProperties)}
|
* 可参考 {@link DeepSeekChatAutoConfiguration} 的 deepSeekChatModel 方法
|
||||||
*/
|
*/
|
||||||
private static DeepSeekChatModel buildDeepSeekChatModel(String apiKey) {
|
private static DeepSeekChatModel buildDeepSeekChatModel(String apiKey) {
|
||||||
YudaoAiProperties.DeepSeekProperties properties = new YudaoAiProperties.DeepSeekProperties()
|
DeepSeekApi deepSeekApi = DeepSeekApi.builder().apiKey(apiKey).build();
|
||||||
.setApiKey(apiKey);
|
DeepSeekChatOptions options = DeepSeekChatOptions.builder().model(DeepSeekApi.DEFAULT_CHAT_MODEL)
|
||||||
return new AiAutoConfiguration().buildDeepSeekChatModel(properties);
|
.temperature(0.7).build();
|
||||||
|
return DeepSeekChatModel.builder()
|
||||||
|
.deepSeekApi(deepSeekApi)
|
||||||
|
.defaultOptions(options)
|
||||||
|
.toolCallingManager(getToolCallingManager())
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -397,17 +421,18 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiChatModel 方法
|
* 可参考 {@link ZhiPuAiChatAutoConfiguration} 的 zhiPuAiChatModel 方法
|
||||||
*/
|
*/
|
||||||
private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) {
|
private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) {
|
||||||
ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey)
|
ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey)
|
||||||
: new ZhiPuAiApi(url, apiKey);
|
: new ZhiPuAiApi(url, apiKey);
|
||||||
ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder().model(ZhiPuAiApi.DEFAULT_CHAT_MODEL).temperature(0.7).build();
|
ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder().model(ZhiPuAiApi.DEFAULT_CHAT_MODEL).temperature(0.7).build();
|
||||||
return new ZhiPuAiChatModel(zhiPuAiApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE);
|
return new ZhiPuAiChatModel(zhiPuAiApi, options, getToolCallingManager(), DEFAULT_RETRY_TEMPLATE,
|
||||||
|
getObservationRegistry().getIfAvailable());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiImageModel 方法
|
* 可参考 {@link ZhiPuAiImageAutoConfiguration} 的 zhiPuAiImageModel 方法
|
||||||
*/
|
*/
|
||||||
private ZhiPuAiImageModel buildZhiPuAiImageModel(String apiKey, String url) {
|
private ZhiPuAiImageModel buildZhiPuAiImageModel(String apiKey, String url) {
|
||||||
ZhiPuAiImageApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiImageApi(apiKey)
|
ZhiPuAiImageApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiImageApi(apiKey)
|
||||||
|
|
@ -416,23 +441,30 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link MiniMaxAutoConfiguration} 的 miniMaxChatModel 方法
|
* 可参考 {@link MiniMaxChatAutoConfiguration} 的 miniMaxChatModel 方法
|
||||||
*/
|
*/
|
||||||
private MiniMaxChatModel buildMiniMaxChatModel(String apiKey, String url) {
|
private MiniMaxChatModel buildMiniMaxChatModel(String apiKey, String url) {
|
||||||
MiniMaxApi miniMaxApi = StrUtil.isEmpty(url) ? new MiniMaxApi(apiKey)
|
MiniMaxApi miniMaxApi = StrUtil.isEmpty(url) ? new MiniMaxApi(apiKey)
|
||||||
: new MiniMaxApi(url, apiKey);
|
: new MiniMaxApi(url, apiKey);
|
||||||
MiniMaxChatOptions options = MiniMaxChatOptions.builder().model(MiniMaxApi.DEFAULT_CHAT_MODEL).temperature(0.7).build();
|
MiniMaxChatOptions options = MiniMaxChatOptions.builder().model(MiniMaxApi.DEFAULT_CHAT_MODEL).temperature(0.7).build();
|
||||||
return new MiniMaxChatModel(miniMaxApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE);
|
return new MiniMaxChatModel(miniMaxApi, options, getToolCallingManager(), DEFAULT_RETRY_TEMPLATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link MoonshotAutoConfiguration} 的 moonshotChatModel 方法
|
* 可参考 {@link MoonshotChatAutoConfiguration} 的 moonshotChatModel 方法
|
||||||
*/
|
*/
|
||||||
private MoonshotChatModel buildMoonshotChatModel(String apiKey, String url) {
|
private MoonshotChatModel buildMoonshotChatModel(String apiKey, String url) {
|
||||||
MoonshotApi moonshotApi = StrUtil.isEmpty(url)? new MoonshotApi(apiKey)
|
MoonshotApi.Builder moonshotApiBuilder = MoonshotApi.builder()
|
||||||
: new MoonshotApi(url, apiKey);
|
.apiKey(apiKey);
|
||||||
|
if (StrUtil.isNotEmpty(url)) {
|
||||||
|
moonshotApiBuilder.baseUrl(url);
|
||||||
|
}
|
||||||
MoonshotChatOptions options = MoonshotChatOptions.builder().model(MoonshotApi.DEFAULT_CHAT_MODEL).build();
|
MoonshotChatOptions options = MoonshotChatOptions.builder().model(MoonshotApi.DEFAULT_CHAT_MODEL).build();
|
||||||
return new MoonshotChatModel(moonshotApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE);
|
return MoonshotChatModel.builder()
|
||||||
|
.moonshotApi(moonshotApiBuilder.build())
|
||||||
|
.defaultOptions(options)
|
||||||
|
.toolCallingManager(getToolCallingManager())
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -456,33 +488,32 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link OpenAiAutoConfiguration} 的 openAiChatModel 方法
|
* 可参考 {@link OpenAiChatAutoConfiguration} 的 openAiChatModel 方法
|
||||||
*/
|
*/
|
||||||
private static OpenAiChatModel buildOpenAiChatModel(String openAiToken, String url) {
|
private static OpenAiChatModel buildOpenAiChatModel(String openAiToken, String url) {
|
||||||
url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL);
|
url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL);
|
||||||
OpenAiApi openAiApi = OpenAiApi.builder().baseUrl(url).apiKey(openAiToken).build();
|
OpenAiApi openAiApi = OpenAiApi.builder().baseUrl(url).apiKey(openAiToken).build();
|
||||||
return OpenAiChatModel.builder().openAiApi(openAiApi).toolCallingManager(getToolCallingManager()).build();
|
return OpenAiChatModel.builder()
|
||||||
|
.openAiApi(openAiApi)
|
||||||
|
.toolCallingManager(getToolCallingManager())
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @芋艿:手头暂时没密钥,使用建议再测试下
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link AzureOpenAiAutoConfiguration}
|
* 可参考 {@link AzureOpenAiChatAutoConfiguration}
|
||||||
*/
|
*/
|
||||||
private static AzureOpenAiChatModel buildAzureOpenAiChatModel(String apiKey, String url) {
|
private static AzureOpenAiChatModel buildAzureOpenAiChatModel(String apiKey, String url) {
|
||||||
AzureOpenAiAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiAutoConfiguration();
|
// TODO @芋艿:使用前,请测试,暂时没密钥!!!
|
||||||
// 创建 OpenAIClient 对象
|
OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder()
|
||||||
AzureOpenAiConnectionProperties connectionProperties = new AzureOpenAiConnectionProperties();
|
.endpoint(url).credential(new KeyCredential(apiKey));
|
||||||
connectionProperties.setApiKey(apiKey);
|
return AzureOpenAiChatModel.builder()
|
||||||
connectionProperties.setEndpoint(url);
|
.openAIClientBuilder(openAIClientBuilder)
|
||||||
OpenAIClientBuilder openAIClient = azureOpenAiAutoConfiguration.openAIClientBuilder(connectionProperties, null);
|
.toolCallingManager(getToolCallingManager())
|
||||||
// 获取 AzureOpenAiChatProperties 对象
|
.build();
|
||||||
AzureOpenAiChatProperties chatProperties = SpringUtil.getBean(AzureOpenAiChatProperties.class);
|
|
||||||
return azureOpenAiAutoConfiguration.azureOpenAiChatModel(openAIClient, chatProperties,
|
|
||||||
getToolCallingManager(), null, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link OpenAiAutoConfiguration} 的 openAiImageModel 方法
|
* 可参考 {@link OpenAiImageAutoConfiguration} 的 openAiImageModel 方法
|
||||||
*/
|
*/
|
||||||
private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) {
|
private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) {
|
||||||
url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL);
|
url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL);
|
||||||
|
|
@ -500,11 +531,14 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link OllamaAutoConfiguration} 的 ollamaApi 方法
|
* 可参考 {@link OllamaChatAutoConfiguration} 的 ollamaChatModel 方法
|
||||||
*/
|
*/
|
||||||
private static OllamaChatModel buildOllamaChatModel(String url) {
|
private static OllamaChatModel buildOllamaChatModel(String url) {
|
||||||
OllamaApi ollamaApi = new OllamaApi(url);
|
OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build();
|
||||||
return OllamaChatModel.builder().ollamaApi(ollamaApi).toolCallingManager(getToolCallingManager()).build();
|
return OllamaChatModel.builder()
|
||||||
|
.ollamaApi(ollamaApi)
|
||||||
|
.toolCallingManager(getToolCallingManager())
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -519,16 +553,16 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
// ========== 各种创建 EmbeddingModel 的方法 ==========
|
// ========== 各种创建 EmbeddingModel 的方法 ==========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link DashScopeAutoConfiguration} 的 dashscopeEmbeddingModel 方法
|
* 可参考 {@link DashScopeEmbeddingAutoConfiguration} 的 dashscopeEmbeddingModel 方法
|
||||||
*/
|
*/
|
||||||
private DashScopeEmbeddingModel buildTongYiEmbeddingModel(String apiKey, String model) {
|
private DashScopeEmbeddingModel buildTongYiEmbeddingModel(String apiKey, String model) {
|
||||||
DashScopeApi dashScopeApi = new DashScopeApi(apiKey);
|
DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(apiKey).build();
|
||||||
DashScopeEmbeddingOptions dashScopeEmbeddingOptions = DashScopeEmbeddingOptions.builder().withModel(model).build();
|
DashScopeEmbeddingOptions dashScopeEmbeddingOptions = DashScopeEmbeddingOptions.builder().withModel(model).build();
|
||||||
return new DashScopeEmbeddingModel(dashScopeApi, MetadataMode.EMBED, dashScopeEmbeddingOptions);
|
return new DashScopeEmbeddingModel(dashScopeApi, MetadataMode.EMBED, dashScopeEmbeddingOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiEmbeddingModel 方法
|
* 可参考 {@link ZhiPuAiEmbeddingAutoConfiguration} 的 zhiPuAiEmbeddingModel 方法
|
||||||
*/
|
*/
|
||||||
private ZhiPuAiEmbeddingModel buildZhiPuEmbeddingModel(String apiKey, String url, String model) {
|
private ZhiPuAiEmbeddingModel buildZhiPuEmbeddingModel(String apiKey, String url, String model) {
|
||||||
ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey)
|
ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey)
|
||||||
|
|
@ -538,7 +572,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link MiniMaxAutoConfiguration} 的 miniMaxEmbeddingModel 方法
|
* 可参考 {@link MiniMaxEmbeddingAutoConfiguration} 的 miniMaxEmbeddingModel 方法
|
||||||
*/
|
*/
|
||||||
private EmbeddingModel buildMiniMaxEmbeddingModel(String apiKey, String url, String model) {
|
private EmbeddingModel buildMiniMaxEmbeddingModel(String apiKey, String url, String model) {
|
||||||
MiniMaxApi miniMaxApi = StrUtil.isEmpty(url)? new MiniMaxApi(apiKey)
|
MiniMaxApi miniMaxApi = StrUtil.isEmpty(url)? new MiniMaxApi(apiKey)
|
||||||
|
|
@ -548,7 +582,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link QianFanAutoConfiguration} 的 qianFanEmbeddingModel 方法
|
* 可参考 {@link QianFanEmbeddingAutoConfiguration} 的 qianFanEmbeddingModel 方法
|
||||||
*/
|
*/
|
||||||
private QianFanEmbeddingModel buildYiYanEmbeddingModel(String key, String model) {
|
private QianFanEmbeddingModel buildYiYanEmbeddingModel(String key, String model) {
|
||||||
List<String> keys = StrUtil.split(key, '|');
|
List<String> keys = StrUtil.split(key, '|');
|
||||||
|
|
@ -561,13 +595,16 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
private OllamaEmbeddingModel buildOllamaEmbeddingModel(String url, String model) {
|
private OllamaEmbeddingModel buildOllamaEmbeddingModel(String url, String model) {
|
||||||
OllamaApi ollamaApi = new OllamaApi(url);
|
OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build();
|
||||||
OllamaOptions ollamaOptions = OllamaOptions.builder().model(model).build();
|
OllamaOptions ollamaOptions = OllamaOptions.builder().model(model).build();
|
||||||
return OllamaEmbeddingModel.builder().ollamaApi(ollamaApi).defaultOptions(ollamaOptions).build();
|
return OllamaEmbeddingModel.builder()
|
||||||
|
.ollamaApi(ollamaApi)
|
||||||
|
.defaultOptions(ollamaOptions)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link OpenAiAutoConfiguration} 的 openAiEmbeddingModel 方法
|
* 可参考 {@link OpenAiEmbeddingAutoConfiguration} 的 openAiEmbeddingModel 方法
|
||||||
*/
|
*/
|
||||||
private OpenAiEmbeddingModel buildOpenAiEmbeddingModel(String openAiToken, String url, String model) {
|
private OpenAiEmbeddingModel buildOpenAiEmbeddingModel(String openAiToken, String url, String model) {
|
||||||
url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL);
|
url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL);
|
||||||
|
|
@ -576,21 +613,19 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
return new OpenAiEmbeddingModel(openAiApi, MetadataMode.EMBED, openAiEmbeddingProperties);
|
return new OpenAiEmbeddingModel(openAiApi, MetadataMode.EMBED, openAiEmbeddingProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @芋艿:手头暂时没密钥,使用建议再测试下
|
|
||||||
/**
|
/**
|
||||||
* 可参考 {@link AzureOpenAiAutoConfiguration} 的 azureOpenAiEmbeddingModel 方法
|
* 可参考 {@link AzureOpenAiEmbeddingAutoConfiguration} 的 azureOpenAiEmbeddingModel 方法
|
||||||
*/
|
*/
|
||||||
private AzureOpenAiEmbeddingModel buildAzureOpenAiEmbeddingModel(String apiKey, String url, String model) {
|
private AzureOpenAiEmbeddingModel buildAzureOpenAiEmbeddingModel(String apiKey, String url, String model) {
|
||||||
AzureOpenAiAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiAutoConfiguration();
|
// TODO @芋艿:手头暂时没密钥,使用建议再测试下
|
||||||
// 创建 OpenAIClient 对象
|
AzureOpenAiEmbeddingAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiEmbeddingAutoConfiguration();
|
||||||
AzureOpenAiConnectionProperties connectionProperties = new AzureOpenAiConnectionProperties();
|
// 创建 OpenAIClientBuilder 对象
|
||||||
connectionProperties.setApiKey(apiKey);
|
OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder()
|
||||||
connectionProperties.setEndpoint(url);
|
.endpoint(url).credential(new KeyCredential(apiKey));
|
||||||
OpenAIClientBuilder openAIClient = azureOpenAiAutoConfiguration.openAIClientBuilder(connectionProperties, null);
|
|
||||||
// 获取 AzureOpenAiChatProperties 对象
|
// 获取 AzureOpenAiChatProperties 对象
|
||||||
AzureOpenAiEmbeddingProperties embeddingProperties = SpringUtil.getBean(AzureOpenAiEmbeddingProperties.class);
|
AzureOpenAiEmbeddingProperties embeddingProperties = SpringUtil.getBean(AzureOpenAiEmbeddingProperties.class);
|
||||||
return azureOpenAiAutoConfiguration.azureOpenAiEmbeddingModel(openAIClient, embeddingProperties,
|
return azureOpenAiAutoConfiguration.azureOpenAiEmbeddingModel(openAIClientBuilder, embeddingProperties,
|
||||||
null, null);
|
getObservationRegistry(), getEmbeddingModelObservationConvention());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 各种创建 VectorStore 的方法 ==========
|
// ========== 各种创建 VectorStore 的方法 ==========
|
||||||
|
|
@ -655,12 +690,12 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
Map<String, Class<?>> metadataFields) {
|
Map<String, Class<?>> metadataFields) {
|
||||||
// 创建 JedisPooled 对象
|
// 创建 JedisPooled 对象
|
||||||
RedisProperties redisProperties = SpringUtils.getBean(RedisProperties.class);
|
RedisProperties redisProperties = SpringUtils.getBean(RedisProperties.class);
|
||||||
JedisPooled jedisPooled = new JedisPooled(redisProperties.getHost(), redisProperties.getPort());
|
JedisPooled jedisPooled = new JedisPooled(redisProperties.getHost(), redisProperties.getPort(),
|
||||||
|
redisProperties.getUsername(), redisProperties.getPassword());
|
||||||
// 创建 RedisVectorStoreProperties 对象
|
// 创建 RedisVectorStoreProperties 对象
|
||||||
RedisVectorStoreAutoConfiguration configuration = new RedisVectorStoreAutoConfiguration();
|
|
||||||
RedisVectorStoreProperties properties = SpringUtil.getBean(RedisVectorStoreProperties.class);
|
RedisVectorStoreProperties properties = SpringUtil.getBean(RedisVectorStoreProperties.class);
|
||||||
RedisVectorStore redisVectorStore = RedisVectorStore.builder(jedisPooled, embeddingModel)
|
RedisVectorStore redisVectorStore = RedisVectorStore.builder(jedisPooled, embeddingModel)
|
||||||
.indexName(properties.getIndex()).prefix(properties.getPrefix())
|
.indexName(properties.getIndexName()).prefix(properties.getPrefix())
|
||||||
.initializeSchema(properties.isInitializeSchema())
|
.initializeSchema(properties.isInitializeSchema())
|
||||||
.metadataFields(convertList(metadataFields.entrySet(), entry -> {
|
.metadataFields(convertList(metadataFields.entrySet(), entry -> {
|
||||||
String fieldName = entry.getKey();
|
String fieldName = entry.getKey();
|
||||||
|
|
@ -730,10 +765,12 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
|
|
||||||
private static ObjectProvider<VectorStoreObservationConvention> getCustomObservationConvention() {
|
private static ObjectProvider<VectorStoreObservationConvention> getCustomObservationConvention() {
|
||||||
return new ObjectProvider<>() {
|
return new ObjectProvider<>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VectorStoreObservationConvention getObject() throws BeansException {
|
public VectorStoreObservationConvention getObject() throws BeansException {
|
||||||
return new DefaultVectorStoreObservationConvention();
|
return new DefaultVectorStoreObservationConvention();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -745,8 +782,15 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
||||||
return SpringUtil.getBean(ToolCallingManager.class);
|
return SpringUtil.getBean(ToolCallingManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FunctionCallbackResolver getFunctionCallbackResolver() {
|
private static ObjectProvider<EmbeddingModelObservationConvention> getEmbeddingModelObservationConvention() {
|
||||||
return SpringUtil.getBean(FunctionCallbackResolver.class);
|
return new ObjectProvider<>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EmbeddingModelObservationConvention getObject() throws BeansException {
|
||||||
|
return SpringUtil.getBean(EmbeddingModelObservationConvention.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
package cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.ai.chat.model.ChatModel;
|
|
||||||
import org.springframework.ai.chat.model.ChatResponse;
|
|
||||||
import org.springframework.ai.chat.prompt.ChatOptions;
|
|
||||||
import org.springframework.ai.chat.prompt.Prompt;
|
|
||||||
import org.springframework.ai.openai.OpenAiChatModel;
|
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DeepSeek {@link ChatModel} 实现类
|
|
||||||
*
|
|
||||||
* @author fansili
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class DeepSeekChatModel implements ChatModel {
|
|
||||||
|
|
||||||
public static final String BASE_URL = "https://api.deepseek.com";
|
|
||||||
|
|
||||||
public static final String MODEL_DEFAULT = "deepseek-chat";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 兼容 OpenAI 接口,进行复用
|
|
||||||
*/
|
|
||||||
private final OpenAiChatModel openAiChatModel;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ChatResponse call(Prompt prompt) {
|
|
||||||
return openAiChatModel.call(prompt);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Flux<ChatResponse> stream(Prompt prompt) {
|
|
||||||
return openAiChatModel.stream(prompt);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ChatOptions getDefaultOptions() {
|
|
||||||
return openAiChatModel.getDefaultOptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -46,94 +46,94 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class SiliconFlowImageModel implements ImageModel {
|
public class SiliconFlowImageModel implements ImageModel {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(SiliconFlowImageModel.class);
|
private static final Logger logger = LoggerFactory.getLogger(SiliconFlowImageModel.class);
|
||||||
|
|
||||||
private static final ImageModelObservationConvention DEFAULT_OBSERVATION_CONVENTION = new DefaultImageModelObservationConvention();
|
private static final ImageModelObservationConvention DEFAULT_OBSERVATION_CONVENTION = new DefaultImageModelObservationConvention();
|
||||||
|
|
||||||
private final SiliconFlowImageOptions defaultOptions;
|
private final SiliconFlowImageOptions defaultOptions;
|
||||||
|
|
||||||
private final RetryTemplate retryTemplate;
|
private final RetryTemplate retryTemplate;
|
||||||
|
|
||||||
private final SiliconFlowImageApi siliconFlowImageApi;
|
private final SiliconFlowImageApi siliconFlowImageApi;
|
||||||
|
|
||||||
private final ObservationRegistry observationRegistry;
|
private final ObservationRegistry observationRegistry;
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
private ImageModelObservationConvention observationConvention = DEFAULT_OBSERVATION_CONVENTION;
|
private ImageModelObservationConvention observationConvention = DEFAULT_OBSERVATION_CONVENTION;
|
||||||
|
|
||||||
public SiliconFlowImageModel(SiliconFlowImageApi siliconFlowImageApi) {
|
public SiliconFlowImageModel(SiliconFlowImageApi siliconFlowImageApi) {
|
||||||
this(siliconFlowImageApi, SiliconFlowImageOptions.builder().build(), RetryUtils.DEFAULT_RETRY_TEMPLATE);
|
this(siliconFlowImageApi, SiliconFlowImageOptions.builder().build(), RetryUtils.DEFAULT_RETRY_TEMPLATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SiliconFlowImageModel(SiliconFlowImageApi siliconFlowImageApi, SiliconFlowImageOptions options, RetryTemplate retryTemplate) {
|
public SiliconFlowImageModel(SiliconFlowImageApi siliconFlowImageApi, SiliconFlowImageOptions options, RetryTemplate retryTemplate) {
|
||||||
this(siliconFlowImageApi, options, retryTemplate, ObservationRegistry.NOOP);
|
this(siliconFlowImageApi, options, retryTemplate, ObservationRegistry.NOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SiliconFlowImageModel(SiliconFlowImageApi siliconFlowImageApi, SiliconFlowImageOptions options, RetryTemplate retryTemplate,
|
public SiliconFlowImageModel(SiliconFlowImageApi siliconFlowImageApi, SiliconFlowImageOptions options, RetryTemplate retryTemplate,
|
||||||
ObservationRegistry observationRegistry) {
|
ObservationRegistry observationRegistry) {
|
||||||
Assert.notNull(siliconFlowImageApi, "OpenAiImageApi must not be null");
|
Assert.notNull(siliconFlowImageApi, "OpenAiImageApi must not be null");
|
||||||
Assert.notNull(options, "options must not be null");
|
Assert.notNull(options, "options must not be null");
|
||||||
Assert.notNull(retryTemplate, "retryTemplate must not be null");
|
Assert.notNull(retryTemplate, "retryTemplate must not be null");
|
||||||
Assert.notNull(observationRegistry, "observationRegistry must not be null");
|
Assert.notNull(observationRegistry, "observationRegistry must not be null");
|
||||||
this.siliconFlowImageApi = siliconFlowImageApi;
|
this.siliconFlowImageApi = siliconFlowImageApi;
|
||||||
this.defaultOptions = options;
|
this.defaultOptions = options;
|
||||||
this.retryTemplate = retryTemplate;
|
this.retryTemplate = retryTemplate;
|
||||||
this.observationRegistry = observationRegistry;
|
this.observationRegistry = observationRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImageResponse call(ImagePrompt imagePrompt) {
|
public ImageResponse call(ImagePrompt imagePrompt) {
|
||||||
SiliconFlowImageOptions requestImageOptions = mergeOptions(imagePrompt.getOptions(), this.defaultOptions);
|
SiliconFlowImageOptions requestImageOptions = mergeOptions(imagePrompt.getOptions(), this.defaultOptions);
|
||||||
SiliconFlowImageApi.SiliconflowImageRequest imageRequest = createRequest(imagePrompt, requestImageOptions);
|
SiliconFlowImageApi.SiliconflowImageRequest imageRequest = createRequest(imagePrompt, requestImageOptions);
|
||||||
|
|
||||||
var observationContext = ImageModelObservationContext.builder()
|
var observationContext = ImageModelObservationContext.builder()
|
||||||
.imagePrompt(imagePrompt)
|
.imagePrompt(imagePrompt)
|
||||||
.provider(SiliconFlowApiConstants.PROVIDER_NAME)
|
.provider(SiliconFlowApiConstants.PROVIDER_NAME)
|
||||||
.requestOptions(imagePrompt.getOptions())
|
.imagePrompt(imagePrompt)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
return ImageModelObservationDocumentation.IMAGE_MODEL_OPERATION
|
return ImageModelObservationDocumentation.IMAGE_MODEL_OPERATION
|
||||||
.observation(this.observationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,
|
.observation(this.observationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,
|
||||||
this.observationRegistry)
|
this.observationRegistry)
|
||||||
.observe(() -> {
|
.observe(() -> {
|
||||||
ResponseEntity<OpenAiImageApi.OpenAiImageResponse> imageResponseEntity = this.retryTemplate
|
ResponseEntity<OpenAiImageApi.OpenAiImageResponse> imageResponseEntity = this.retryTemplate
|
||||||
.execute(ctx -> this.siliconFlowImageApi.createImage(imageRequest));
|
.execute(ctx -> this.siliconFlowImageApi.createImage(imageRequest));
|
||||||
|
|
||||||
ImageResponse imageResponse = convertResponse(imageResponseEntity, imageRequest);
|
ImageResponse imageResponse = convertResponse(imageResponseEntity, imageRequest);
|
||||||
|
|
||||||
observationContext.setResponse(imageResponse);
|
observationContext.setResponse(imageResponse);
|
||||||
|
|
||||||
return imageResponse;
|
return imageResponse;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private SiliconFlowImageApi.SiliconflowImageRequest createRequest(ImagePrompt imagePrompt,
|
private SiliconFlowImageApi.SiliconflowImageRequest createRequest(ImagePrompt imagePrompt,
|
||||||
SiliconFlowImageOptions requestImageOptions) {
|
SiliconFlowImageOptions requestImageOptions) {
|
||||||
String instructions = imagePrompt.getInstructions().get(0).getText();
|
String instructions = imagePrompt.getInstructions().get(0).getText();
|
||||||
|
|
||||||
SiliconFlowImageApi.SiliconflowImageRequest imageRequest = new SiliconFlowImageApi.SiliconflowImageRequest(instructions,
|
SiliconFlowImageApi.SiliconflowImageRequest imageRequest = new SiliconFlowImageApi.SiliconflowImageRequest(instructions,
|
||||||
SiliconFlowApiConstants.DEFAULT_IMAGE_MODEL);
|
SiliconFlowApiConstants.DEFAULT_IMAGE_MODEL);
|
||||||
|
|
||||||
return ModelOptionsUtils.merge(requestImageOptions, imageRequest, SiliconFlowImageApi.SiliconflowImageRequest.class);
|
return ModelOptionsUtils.merge(requestImageOptions, imageRequest, SiliconFlowImageApi.SiliconflowImageRequest.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImageResponse convertResponse(ResponseEntity<OpenAiImageApi.OpenAiImageResponse> imageResponseEntity,
|
private ImageResponse convertResponse(ResponseEntity<OpenAiImageApi.OpenAiImageResponse> imageResponseEntity,
|
||||||
SiliconFlowImageApi.SiliconflowImageRequest siliconflowImageRequest) {
|
SiliconFlowImageApi.SiliconflowImageRequest siliconflowImageRequest) {
|
||||||
OpenAiImageApi.OpenAiImageResponse imageApiResponse = imageResponseEntity.getBody();
|
OpenAiImageApi.OpenAiImageResponse imageApiResponse = imageResponseEntity.getBody();
|
||||||
if (imageApiResponse == null) {
|
if (imageApiResponse == null) {
|
||||||
logger.warn("No image response returned for request: {}", siliconflowImageRequest);
|
logger.warn("No image response returned for request: {}", siliconflowImageRequest);
|
||||||
return new ImageResponse(List.of());
|
return new ImageResponse(List.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ImageGeneration> imageGenerationList = imageApiResponse.data()
|
List<ImageGeneration> imageGenerationList = imageApiResponse.data()
|
||||||
.stream()
|
.stream()
|
||||||
.map(entry -> new ImageGeneration(new Image(entry.url(), entry.b64Json()),
|
.map(entry -> new ImageGeneration(new Image(entry.url(), entry.b64Json()),
|
||||||
new OpenAiImageGenerationMetadata(entry.revisedPrompt())))
|
new OpenAiImageGenerationMetadata(entry.revisedPrompt())))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
ImageResponseMetadata openAiImageResponseMetadata = new ImageResponseMetadata(imageApiResponse.created());
|
ImageResponseMetadata openAiImageResponseMetadata = new ImageResponseMetadata(imageApiResponse.created());
|
||||||
return new ImageResponse(imageGenerationList, openAiImageResponseMetadata);
|
return new ImageResponse(imageGenerationList, openAiImageResponseMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SiliconFlowImageOptions mergeOptions(@Nullable ImageOptions runtimeOptions, SiliconFlowImageOptions defaultOptions) {
|
private SiliconFlowImageOptions mergeOptions(@Nullable ImageOptions runtimeOptions, SiliconFlowImageOptions defaultOptions) {
|
||||||
var runtimeOptionsForProvider = ModelOptionsUtils.copyToTarget(runtimeOptions, ImageOptions.class,
|
var runtimeOptionsForProvider = ModelOptionsUtils.copyToTarget(runtimeOptions, ImageOptions.class,
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService
|
||||||
if (CollUtil.isEmpty(list)) {
|
if (CollUtil.isEmpty(list)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
chatConversationMapper.deleteBatchIds(convertList(list, AiChatConversationDO::getId));
|
chatConversationMapper.deleteByIds(convertList(list, AiChatConversationDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -339,7 +339,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
||||||
throw exception(CHAT_MESSAGE_NOT_EXIST);
|
throw exception(CHAT_MESSAGE_NOT_EXIST);
|
||||||
}
|
}
|
||||||
// 2. 执行删除
|
// 2. 执行删除
|
||||||
chatMessageMapper.deleteBatchIds(convertList(messages, AiChatMessageDO::getId));
|
chatMessageMapper.deleteByIds(convertList(messages, AiChatMessageDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,12 @@ import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
||||||
import com.alibaba.cloud.ai.dashscope.image.DashScopeImageOptions;
|
import com.alibaba.cloud.ai.dashscope.image.DashScopeImageOptions;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springaicommunity.qianfan.QianFanImageOptions;
|
||||||
import org.springframework.ai.image.ImageModel;
|
import org.springframework.ai.image.ImageModel;
|
||||||
import org.springframework.ai.image.ImageOptions;
|
import org.springframework.ai.image.ImageOptions;
|
||||||
import org.springframework.ai.image.ImagePrompt;
|
import org.springframework.ai.image.ImagePrompt;
|
||||||
import org.springframework.ai.image.ImageResponse;
|
import org.springframework.ai.image.ImageResponse;
|
||||||
import org.springframework.ai.openai.OpenAiImageOptions;
|
import org.springframework.ai.openai.OpenAiImageOptions;
|
||||||
import org.springframework.ai.qianfan.QianFanImageOptions;
|
|
||||||
import org.springframework.ai.stabilityai.api.StabilityAiImageOptions;
|
import org.springframework.ai.stabilityai.api.StabilityAiImageOptions;
|
||||||
import org.springframework.ai.zhipuai.ZhiPuAiImageOptions;
|
import org.springframework.ai.zhipuai.ZhiPuAiImageOptions;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
|
@ -140,10 +140,10 @@ public class AiImageServiceImpl implements AiImageService {
|
||||||
private static ImageOptions buildImageOptions(AiImageDrawReqVO draw, AiModelDO model) {
|
private static ImageOptions buildImageOptions(AiImageDrawReqVO draw, AiModelDO model) {
|
||||||
if (ObjUtil.equal(model.getPlatform(), AiPlatformEnum.OPENAI.getPlatform())) {
|
if (ObjUtil.equal(model.getPlatform(), AiPlatformEnum.OPENAI.getPlatform())) {
|
||||||
// https://platform.openai.com/docs/api-reference/images/create
|
// https://platform.openai.com/docs/api-reference/images/create
|
||||||
return OpenAiImageOptions.builder().withModel(model.getModel())
|
return OpenAiImageOptions.builder().model(model.getModel())
|
||||||
.withHeight(draw.getHeight()).withWidth(draw.getWidth())
|
.height(draw.getHeight()).width(draw.getWidth())
|
||||||
.withStyle(MapUtil.getStr(draw.getOptions(), "style")) // 风格
|
.style(MapUtil.getStr(draw.getOptions(), "style")) // 风格
|
||||||
.withResponseFormat("b64_json")
|
.responseFormat("b64_json")
|
||||||
.build();
|
.build();
|
||||||
} else if (ObjUtil.equal(model.getPlatform(), AiPlatformEnum.SILICON_FLOW.getPlatform())) {
|
} else if (ObjUtil.equal(model.getPlatform(), AiPlatformEnum.SILICON_FLOW.getPlatform())) {
|
||||||
// https://docs.siliconflow.cn/cn/api-reference/images/images-generations
|
// https://docs.siliconflow.cn/cn/api-reference/images/images-generations
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,7 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return knowledgeDocumentMapper.selectBatchIds(ids);
|
return knowledgeDocumentMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -351,7 +351,7 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return segmentMapper.selectBatchIds(ids);
|
return segmentMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ public class AiChatRoleServiceImpl implements AiChatRoleService {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return chatRoleMapper.selectBatchIds(ids);
|
return chatRoleMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ public class AiToolServiceImpl implements AiToolService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AiToolDO> getToolList(Collection<Long> ids) {
|
public List<AiToolDO> getToolList(Collection<Long> ids) {
|
||||||
return toolMapper.selectBatchIds(ids);
|
return toolMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -97,4 +97,4 @@ public class AiToolServiceImpl implements AiToolService {
|
||||||
return toolMapper.selectListByStatus(status);
|
return toolMapper.selectListByStatus(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
||||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||||
import com.fasterxml.jackson.annotation.JsonClassDescription;
|
import com.fasterxml.jackson.annotation.JsonClassDescription;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
@ -17,7 +19,7 @@ import org.springframework.stereotype.Component;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 工具:当前用户信息查询
|
* 工具:用户信息查询
|
||||||
*
|
*
|
||||||
* 同时,也是展示 ToolContext 上下文的使用
|
* 同时,也是展示 ToolContext 上下文的使用
|
||||||
*
|
*
|
||||||
|
|
@ -31,8 +33,17 @@ public class UserProfileQueryToolFunction
|
||||||
private AdminUserApi adminUserApi;
|
private AdminUserApi adminUserApi;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@JsonClassDescription("当前用户信息查询")
|
@JsonClassDescription("用户信息查询")
|
||||||
public static class Request { }
|
public static class Request {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户编号
|
||||||
|
*/
|
||||||
|
@JsonProperty(value = "id")
|
||||||
|
@JsonPropertyDescription("用户编号,例如说:1。如果查询自己,则 id 为空")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
|
@ -61,13 +72,19 @@ public class UserProfileQueryToolFunction
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response apply(Request request, ToolContext toolContext) {
|
public Response apply(Request request, ToolContext toolContext) {
|
||||||
LoginUser loginUser = (LoginUser) toolContext.getContext().get(AiUtils.TOOL_CONTEXT_LOGIN_USER);
|
|
||||||
Long tenantId = (Long) toolContext.getContext().get(AiUtils.TOOL_CONTEXT_TENANT_ID);
|
Long tenantId = (Long) toolContext.getContext().get(AiUtils.TOOL_CONTEXT_TENANT_ID);
|
||||||
if (loginUser == null | tenantId == null) {
|
if (tenantId == null) {
|
||||||
return null;
|
return new Response();
|
||||||
|
}
|
||||||
|
if (request.getId() == null) {
|
||||||
|
LoginUser loginUser = (LoginUser) toolContext.getContext().get(AiUtils.TOOL_CONTEXT_LOGIN_USER);
|
||||||
|
if (loginUser == null) {
|
||||||
|
return new Response();
|
||||||
|
}
|
||||||
|
request.setId(loginUser.getId());
|
||||||
}
|
}
|
||||||
return TenantUtils.execute(tenantId, () -> {
|
return TenantUtils.execute(tenantId, () -> {
|
||||||
AdminUserRespDTO user = adminUserApi.getUser(loginUser.getId()).getCheckedData();
|
AdminUserRespDTO user = adminUserApi.getUser(request.getId()).getCheckedData();
|
||||||
return BeanUtils.toBean(user, Response.class);
|
return BeanUtils.toBean(user, Response.class);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,18 @@ package cn.iocoder.yudao.module.ai.util;
|
||||||
|
|
||||||
import cn.hutool.core.util.ObjUtil;
|
import cn.hutool.core.util.ObjUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
|
|
||||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||||
|
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
|
||||||
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
|
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
|
||||||
|
import org.springaicommunity.moonshot.MoonshotChatOptions;
|
||||||
|
import org.springaicommunity.qianfan.QianFanChatOptions;
|
||||||
import org.springframework.ai.azure.openai.AzureOpenAiChatOptions;
|
import org.springframework.ai.azure.openai.AzureOpenAiChatOptions;
|
||||||
import org.springframework.ai.chat.messages.*;
|
import org.springframework.ai.chat.messages.*;
|
||||||
import org.springframework.ai.chat.prompt.ChatOptions;
|
import org.springframework.ai.chat.prompt.ChatOptions;
|
||||||
import org.springframework.ai.minimax.MiniMaxChatOptions;
|
import org.springframework.ai.minimax.MiniMaxChatOptions;
|
||||||
import org.springframework.ai.moonshot.MoonshotChatOptions;
|
|
||||||
import org.springframework.ai.ollama.api.OllamaOptions;
|
import org.springframework.ai.ollama.api.OllamaOptions;
|
||||||
import org.springframework.ai.openai.OpenAiChatOptions;
|
import org.springframework.ai.openai.OpenAiChatOptions;
|
||||||
import org.springframework.ai.qianfan.QianFanChatOptions;
|
|
||||||
import org.springframework.ai.zhipuai.ZhiPuAiChatOptions;
|
import org.springframework.ai.zhipuai.ZhiPuAiChatOptions;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
@ -43,18 +43,18 @@ public class AiUtils {
|
||||||
switch (platform) {
|
switch (platform) {
|
||||||
case TONG_YI:
|
case TONG_YI:
|
||||||
return DashScopeChatOptions.builder().withModel(model).withTemperature(temperature).withMaxToken(maxTokens)
|
return DashScopeChatOptions.builder().withModel(model).withTemperature(temperature).withMaxToken(maxTokens)
|
||||||
.withFunctions(toolNames).withToolContext(toolContext).build();
|
.withToolNames(toolNames).withToolContext(toolContext).build();
|
||||||
case YI_YAN:
|
case YI_YAN:
|
||||||
return QianFanChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens).build();
|
return QianFanChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens).build();
|
||||||
case ZHI_PU:
|
case ZHI_PU:
|
||||||
return ZhiPuAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens)
|
return ZhiPuAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens)
|
||||||
.functions(toolNames).toolContext(toolContext).build();
|
.toolNames(toolNames).toolContext(toolContext).build();
|
||||||
case MINI_MAX:
|
case MINI_MAX:
|
||||||
return MiniMaxChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens)
|
return MiniMaxChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens)
|
||||||
.functions(toolNames).toolContext(toolContext).build();
|
.toolNames(toolNames).toolContext(toolContext).build();
|
||||||
case MOONSHOT:
|
case MOONSHOT:
|
||||||
return MoonshotChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens)
|
return MoonshotChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens)
|
||||||
.functions(toolNames).toolContext(toolContext).build();
|
.toolNames(toolNames).toolContext(toolContext).build();
|
||||||
case OPENAI:
|
case OPENAI:
|
||||||
case DEEP_SEEK: // 复用 OpenAI 客户端
|
case DEEP_SEEK: // 复用 OpenAI 客户端
|
||||||
case DOU_BAO: // 复用 OpenAI 客户端
|
case DOU_BAO: // 复用 OpenAI 客户端
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ spring:
|
||||||
# 数据源配置项
|
# 数据源配置项
|
||||||
autoconfigure:
|
autoconfigure:
|
||||||
exclude:
|
exclude:
|
||||||
- org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建
|
- org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建
|
||||||
- org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建
|
- org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建
|
||||||
datasource:
|
datasource:
|
||||||
druid: # Druid 【监控】相关的全局配置
|
druid: # Druid 【监控】相关的全局配置
|
||||||
web-stat-filter:
|
web-stat-filter:
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@ spring:
|
||||||
autoconfigure:
|
autoconfigure:
|
||||||
exclude:
|
exclude:
|
||||||
- de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置
|
- de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置
|
||||||
- org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建
|
- org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建
|
||||||
- org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建
|
- org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建
|
||||||
datasource:
|
datasource:
|
||||||
druid: # Druid 【监控】相关的全局配置
|
druid: # Druid 【监控】相关的全局配置
|
||||||
web-stat-filter:
|
web-stat-filter:
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ spring:
|
||||||
vectorstore: # 向量存储
|
vectorstore: # 向量存储
|
||||||
redis:
|
redis:
|
||||||
initialize-schema: true
|
initialize-schema: true
|
||||||
index: knowledge_index # Redis 中向量索引的名称:用于存储和检索向量数据的索引标识符,所有相关的向量搜索操作都会基于这个索引进行
|
index-name: knowledge_index # Redis 中向量索引的名称:用于存储和检索向量数据的索引标识符,所有相关的向量搜索操作都会基于这个索引进行
|
||||||
prefix: "knowledge_segment:" # Redis 中存储向量数据的键名前缀:这个前缀会添加到每个存储在 Redis 中的向量数据键名前,每个 document 都是一个 hash 结构
|
prefix: "knowledge_segment:" # Redis 中存储向量数据的键名前缀:这个前缀会添加到每个存储在 Redis 中的向量数据键名前,每个 document 都是一个 hash 结构
|
||||||
qdrant:
|
qdrant:
|
||||||
initialize-schema: true
|
initialize-schema: true
|
||||||
|
|
@ -145,13 +145,14 @@ spring:
|
||||||
api-key: xxxx
|
api-key: xxxx
|
||||||
moonshot: # 月之暗灭(KIMI)
|
moonshot: # 月之暗灭(KIMI)
|
||||||
api-key: sk-abc
|
api-key: sk-abc
|
||||||
|
deepseek: # DeepSeek
|
||||||
|
api-key: sk-e94db327cc7d457d99a8de8810fc6b12
|
||||||
|
chat:
|
||||||
|
options:
|
||||||
|
model: deepseek-chat
|
||||||
|
|
||||||
yudao:
|
yudao:
|
||||||
ai:
|
ai:
|
||||||
deep-seek: # DeepSeek
|
|
||||||
enable: true
|
|
||||||
api-key: sk-e94db327cc7d457d99a8de8810fc6b12
|
|
||||||
model: deepseek-chat
|
|
||||||
doubao: # 字节豆包
|
doubao: # 字节豆包
|
||||||
enable: true
|
enable: true
|
||||||
api-key: 5c1b5747-26d2-4ebd-a4e0-dd0e8d8b4272
|
api-key: 5c1b5747-26d2-4ebd-a4e0-dd0e8d8b4272
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
|
||||||
|
|
||||||
import com.azure.ai.openai.OpenAIClientBuilder;
|
import com.azure.ai.openai.OpenAIClientBuilder;
|
||||||
import com.azure.core.credential.AzureKeyCredential;
|
import com.azure.core.credential.AzureKeyCredential;
|
||||||
import com.azure.core.util.ClientOptions;
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.ai.azure.openai.AzureOpenAiChatModel;
|
import org.springframework.ai.azure.openai.AzureOpenAiChatModel;
|
||||||
|
|
@ -17,7 +16,7 @@ import reactor.core.publisher.Flux;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties.DEFAULT_DEPLOYMENT_NAME;
|
import static org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatProperties.DEFAULT_DEPLOYMENT_NAME;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link AzureOpenAiChatModel} 集成测试
|
* {@link AzureOpenAiChatModel} 集成测试
|
||||||
|
|
@ -29,10 +28,13 @@ public class AzureOpenAIChatModelTests {
|
||||||
// TODO @芋艿:晚点在调整
|
// TODO @芋艿:晚点在调整
|
||||||
private final OpenAIClientBuilder openAiApi = new OpenAIClientBuilder()
|
private final OpenAIClientBuilder openAiApi = new OpenAIClientBuilder()
|
||||||
.endpoint("https://eastusprejade.openai.azure.com")
|
.endpoint("https://eastusprejade.openai.azure.com")
|
||||||
.credential(new AzureKeyCredential("xxx"))
|
.credential(new AzureKeyCredential("xxx"));
|
||||||
.clientOptions((new ClientOptions()).setApplicationId("spring-ai"));
|
private final AzureOpenAiChatModel chatModel = AzureOpenAiChatModel.builder()
|
||||||
private final AzureOpenAiChatModel chatModel = new AzureOpenAiChatModel(openAiApi,
|
.openAIClientBuilder(openAiApi)
|
||||||
AzureOpenAiChatOptions.builder().deploymentName(DEFAULT_DEPLOYMENT_NAME).build());
|
.defaultOptions(AzureOpenAiChatOptions.builder()
|
||||||
|
.deploymentName(DEFAULT_DEPLOYMENT_NAME)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled
|
@Disabled
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
|
package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel;
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel;
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.ai.chat.messages.Message;
|
import org.springframework.ai.chat.messages.Message;
|
||||||
|
|
@ -35,7 +34,7 @@ public class BaiChuanChatModelTests {
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private final DeepSeekChatModel chatModel = new DeepSeekChatModel(openAiChatModel);
|
private final BaiChuanChatModel chatModel = new BaiChuanChatModel(openAiChatModel);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled
|
@Disabled
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
|
package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel;
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.ai.chat.messages.Message;
|
import org.springframework.ai.chat.messages.Message;
|
||||||
|
|
@ -8,9 +7,9 @@ import org.springframework.ai.chat.messages.SystemMessage;
|
||||||
import org.springframework.ai.chat.messages.UserMessage;
|
import org.springframework.ai.chat.messages.UserMessage;
|
||||||
import org.springframework.ai.chat.model.ChatResponse;
|
import org.springframework.ai.chat.model.ChatResponse;
|
||||||
import org.springframework.ai.chat.prompt.Prompt;
|
import org.springframework.ai.chat.prompt.Prompt;
|
||||||
import org.springframework.ai.openai.OpenAiChatModel;
|
import org.springframework.ai.deepseek.DeepSeekChatModel;
|
||||||
import org.springframework.ai.openai.OpenAiChatOptions;
|
import org.springframework.ai.deepseek.DeepSeekChatOptions;
|
||||||
import org.springframework.ai.openai.api.OpenAiApi;
|
import org.springframework.ai.deepseek.api.DeepSeekApi;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -23,19 +22,16 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class DeepSeekChatModelTests {
|
public class DeepSeekChatModelTests {
|
||||||
|
|
||||||
private final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
|
private final DeepSeekChatModel chatModel = DeepSeekChatModel.builder()
|
||||||
.openAiApi(OpenAiApi.builder()
|
.deepSeekApi(DeepSeekApi.builder()
|
||||||
.baseUrl(DeepSeekChatModel.BASE_URL)
|
.apiKey("sk-eaf4172a057344dd9bc64b1f806b6axx") // apiKey
|
||||||
.apiKey("sk-e52047409b144d97b791a6a46a2d") // apiKey
|
|
||||||
.build())
|
.build())
|
||||||
.defaultOptions(OpenAiChatOptions.builder()
|
.defaultOptions(DeepSeekChatOptions.builder()
|
||||||
.model("deepseek-chat") // 模型
|
.model("deepseek-chat") // 模型
|
||||||
.temperature(0.7)
|
.temperature(0.7)
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private final DeepSeekChatModel chatModel = new DeepSeekChatModel(openAiChatModel);
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled
|
@Disabled
|
||||||
public void testCall() {
|
public void testCall() {
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
|
package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.ai.chat.messages.Message;
|
|
||||||
import org.springframework.ai.chat.messages.SystemMessage;
|
|
||||||
import org.springframework.ai.chat.messages.UserMessage;
|
|
||||||
import org.springframework.ai.chat.model.ChatResponse;
|
|
||||||
import org.springframework.ai.chat.prompt.Prompt;
|
|
||||||
import org.springframework.ai.ollama.OllamaChatModel;
|
import org.springframework.ai.ollama.OllamaChatModel;
|
||||||
import org.springframework.ai.ollama.api.OllamaApi;
|
|
||||||
import org.springframework.ai.ollama.api.OllamaModel;
|
|
||||||
import org.springframework.ai.ollama.api.OllamaOptions;
|
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link OllamaChatModel} 集成测试
|
* {@link OllamaChatModel} 集成测试
|
||||||
|
|
@ -23,43 +9,43 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class LlamaChatModelTests {
|
public class LlamaChatModelTests {
|
||||||
|
|
||||||
private final OllamaChatModel chatModel = OllamaChatModel.builder()
|
// private final OllamaChatModel chatModel = OllamaChatModel.builder()
|
||||||
.ollamaApi(new OllamaApi("http://127.0.0.1:11434")) // Ollama 服务地址
|
// .ollamaApi(new OllamaApi("http://127.0.0.1:11434")) // Ollama 服务地址
|
||||||
.defaultOptions(OllamaOptions.builder()
|
// .defaultOptions(OllamaOptions.builder()
|
||||||
.model(OllamaModel.LLAMA3.getName()) // 模型
|
// .model(OllamaModel.LLAMA3.getName()) // 模型
|
||||||
.build())
|
// .build())
|
||||||
.build();
|
// .build();
|
||||||
|
//
|
||||||
@Test
|
// @Test
|
||||||
@Disabled
|
// @Disabled
|
||||||
public void testCall() {
|
// public void testCall() {
|
||||||
// 准备参数
|
// // 准备参数
|
||||||
List<Message> messages = new ArrayList<>();
|
// List<Message> messages = new ArrayList<>();
|
||||||
messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。"));
|
// messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。"));
|
||||||
messages.add(new UserMessage("1 + 1 = ?"));
|
// messages.add(new UserMessage("1 + 1 = ?"));
|
||||||
|
//
|
||||||
// 调用
|
// // 调用
|
||||||
ChatResponse response = chatModel.call(new Prompt(messages));
|
// ChatResponse response = chatModel.call(new Prompt(messages));
|
||||||
// 打印结果
|
// // 打印结果
|
||||||
System.out.println(response);
|
// System.out.println(response);
|
||||||
System.out.println(response.getResult().getOutput());
|
// System.out.println(response.getResult().getOutput());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Test
|
// @Test
|
||||||
@Disabled
|
// @Disabled
|
||||||
public void testStream() {
|
// public void testStream() {
|
||||||
// 准备参数
|
// // 准备参数
|
||||||
List<Message> messages = new ArrayList<>();
|
// List<Message> messages = new ArrayList<>();
|
||||||
messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。"));
|
// messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。"));
|
||||||
messages.add(new UserMessage("1 + 1 = ?"));
|
// messages.add(new UserMessage("1 + 1 = ?"));
|
||||||
|
//
|
||||||
// 调用
|
// // 调用
|
||||||
Flux<ChatResponse> flux = chatModel.stream(new Prompt(messages));
|
// Flux<ChatResponse> flux = chatModel.stream(new Prompt(messages));
|
||||||
// 打印结果
|
// // 打印结果
|
||||||
flux.doOnNext(response -> {
|
// flux.doOnNext(response -> {
|
||||||
// System.out.println(response);
|
//// System.out.println(response);
|
||||||
System.out.println(response.getResult().getOutput());
|
// System.out.println(response.getResult().getOutput());
|
||||||
}).then().block();
|
// }).then().block();
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springaicommunity.moonshot.MoonshotChatModel;
|
||||||
|
import org.springaicommunity.moonshot.MoonshotChatOptions;
|
||||||
|
import org.springaicommunity.moonshot.api.MoonshotApi;
|
||||||
import org.springframework.ai.chat.messages.Message;
|
import org.springframework.ai.chat.messages.Message;
|
||||||
import org.springframework.ai.chat.messages.SystemMessage;
|
import org.springframework.ai.chat.messages.SystemMessage;
|
||||||
import org.springframework.ai.chat.messages.UserMessage;
|
import org.springframework.ai.chat.messages.UserMessage;
|
||||||
import org.springframework.ai.chat.model.ChatResponse;
|
import org.springframework.ai.chat.model.ChatResponse;
|
||||||
import org.springframework.ai.chat.prompt.Prompt;
|
import org.springframework.ai.chat.prompt.Prompt;
|
||||||
import org.springframework.ai.moonshot.MoonshotChatModel;
|
|
||||||
import org.springframework.ai.moonshot.MoonshotChatOptions;
|
|
||||||
import org.springframework.ai.moonshot.api.MoonshotApi;
|
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -22,11 +22,15 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class MoonshotChatModelTests {
|
public class MoonshotChatModelTests {
|
||||||
|
|
||||||
private final MoonshotChatModel chatModel = new MoonshotChatModel(
|
private final MoonshotChatModel chatModel = MoonshotChatModel.builder()
|
||||||
new MoonshotApi("sk-aHYYV1SARscItye5QQRRNbXij4fy65Ee7pNZlC9gsSQnUKXA"), // 密钥
|
.moonshotApi(MoonshotApi.builder()
|
||||||
MoonshotChatOptions.builder()
|
.apiKey("sk-aHYYV1SARscItye5QQRRNbXij4fy65Ee7pNZlC9gsSQnUKXA") // 密钥
|
||||||
.model("moonshot-v1-8k") // 模型
|
.build())
|
||||||
.build());
|
.defaultOptions(MoonshotChatOptions.builder()
|
||||||
|
.model("kimi-k2-0711-preview") // 模型
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled
|
@Disabled
|
||||||
public void testCall() {
|
public void testCall() {
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@ import java.util.List;
|
||||||
public class OllamaChatModelTests {
|
public class OllamaChatModelTests {
|
||||||
|
|
||||||
private final OllamaChatModel chatModel = OllamaChatModel.builder()
|
private final OllamaChatModel chatModel = OllamaChatModel.builder()
|
||||||
.ollamaApi(new OllamaApi("http://127.0.0.1:11434")) // Ollama 服务地址
|
.ollamaApi(OllamaApi.builder()
|
||||||
|
.baseUrl("http://127.0.0.1:11434") // Ollama 服务地址
|
||||||
|
.build())
|
||||||
.defaultOptions(OllamaOptions.builder()
|
.defaultOptions(OllamaOptions.builder()
|
||||||
// .model("qwen") // 模型(https://ollama.com/library/qwen)
|
// .model("qwen") // 模型(https://ollama.com/library/qwen)
|
||||||
.model("deepseek-r1") // 模型(https://ollama.com/library/deepseek-r1)
|
.model("deepseek-r1") // 模型(https://ollama.com/library/deepseek-r1)
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,10 @@ public class OpenAIChatModelTests {
|
||||||
private final OpenAiChatModel chatModel = OpenAiChatModel.builder()
|
private final OpenAiChatModel chatModel = OpenAiChatModel.builder()
|
||||||
.openAiApi(OpenAiApi.builder()
|
.openAiApi(OpenAiApi.builder()
|
||||||
.baseUrl("https://api.holdai.top")
|
.baseUrl("https://api.holdai.top")
|
||||||
.apiKey("sk-aN6nWn3fILjrgLFT0fC4Aa60B72e4253826c77B29dC94f17") // apiKey
|
.apiKey("sk-PytRecQlmjEteoa2RRN6cGnwslo72UUPLQVNEMS6K9yjbmpD") // apiKey
|
||||||
.build())
|
.build())
|
||||||
.defaultOptions(OpenAiChatOptions.builder()
|
.defaultOptions(OpenAiChatOptions.builder()
|
||||||
.model(OpenAiApi.ChatModel.GPT_4_O) // 模型
|
.model(OpenAiApi.ChatModel.GPT_4_1_NANO) // 模型
|
||||||
.temperature(0.7)
|
.temperature(0.7)
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,17 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class TongYiChatModelTests {
|
public class TongYiChatModelTests {
|
||||||
|
|
||||||
private final DashScopeChatModel chatModel = new DashScopeChatModel(
|
private final DashScopeChatModel chatModel = DashScopeChatModel.builder()
|
||||||
new DashScopeApi("sk-7d903764249848cfa912733146da12d1"),
|
.dashScopeApi(DashScopeApi.builder()
|
||||||
DashScopeChatOptions.builder()
|
.apiKey("sk-47aa124781be4bfb95244cc62f63f7d0")
|
||||||
|
.build())
|
||||||
|
.defaultOptions( DashScopeChatOptions.builder()
|
||||||
.withModel("qwen1.5-72b-chat") // 模型
|
.withModel("qwen1.5-72b-chat") // 模型
|
||||||
// .withModel("deepseek-r1") // 模型(deepseek-r1)
|
// .withModel("deepseek-r1") // 模型(deepseek-r1)
|
||||||
// .withModel("deepseek-v3") // 模型(deepseek-v3)
|
// .withModel("deepseek-v3") // 模型(deepseek-v3)
|
||||||
// .withModel("deepseek-r1-distill-qwen-1.5b") // 模型(deepseek-r1-distill-qwen-1.5b)
|
// .withModel("deepseek-r1-distill-qwen-1.5b") // 模型(deepseek-r1-distill-qwen-1.5b)
|
||||||
.build());
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled
|
@Disabled
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springaicommunity.qianfan.QianFanChatModel;
|
||||||
|
import org.springaicommunity.qianfan.QianFanChatOptions;
|
||||||
|
import org.springaicommunity.qianfan.api.QianFanApi;
|
||||||
import org.springframework.ai.chat.messages.Message;
|
import org.springframework.ai.chat.messages.Message;
|
||||||
import org.springframework.ai.chat.messages.UserMessage;
|
import org.springframework.ai.chat.messages.UserMessage;
|
||||||
import org.springframework.ai.chat.model.ChatResponse;
|
import org.springframework.ai.chat.model.ChatResponse;
|
||||||
import org.springframework.ai.chat.prompt.Prompt;
|
import org.springframework.ai.chat.prompt.Prompt;
|
||||||
import org.springframework.ai.qianfan.QianFanChatModel;
|
|
||||||
import org.springframework.ai.qianfan.QianFanChatOptions;
|
|
||||||
import org.springframework.ai.qianfan.api.QianFanApi;
|
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -23,9 +23,9 @@ import java.util.List;
|
||||||
public class YiYanChatModelTests {
|
public class YiYanChatModelTests {
|
||||||
|
|
||||||
private final QianFanChatModel chatModel = new QianFanChatModel(
|
private final QianFanChatModel chatModel = new QianFanChatModel(
|
||||||
new QianFanApi("qS8k8dYr2nXunagK4SSU8Xjj", "pHGbx51ql2f0hOyabQvSZezahVC3hh3e"), // 密钥
|
new QianFanApi("DGnyzREuaY7av7c38bOM9Ji2", "9aR8myflEOPDrEeLhoXv0FdqANOAyIZW"), // 密钥
|
||||||
QianFanChatOptions.builder()
|
QianFanChatOptions.builder()
|
||||||
.model(QianFanApi.ChatModel.ERNIE_4_0_8K_Preview.getValue())
|
.model("ERNIE-4.5-8K-Preview")
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ public class OpenAiImageModelTests {
|
||||||
|
|
||||||
private final OpenAiImageModel imageModel = new OpenAiImageModel(OpenAiImageApi.builder()
|
private final OpenAiImageModel imageModel = new OpenAiImageModel(OpenAiImageApi.builder()
|
||||||
.baseUrl("https://api.holdai.top") // apiKey
|
.baseUrl("https://api.holdai.top") // apiKey
|
||||||
.apiKey("sk-aN6nWn3fILjrgLFT0fC4Aa60B72e4253826c77B29dC94f17")
|
.apiKey("sk-PytRecQlmjEteoa2RRN6cGnwslo72UUPLQVNEMS6K9yjbmpD")
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -26,8 +26,8 @@ public class OpenAiImageModelTests {
|
||||||
public void testCall() {
|
public void testCall() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
ImageOptions options = OpenAiImageOptions.builder()
|
ImageOptions options = OpenAiImageOptions.builder()
|
||||||
.withModel(OpenAiImageApi.ImageModel.DALL_E_2.getValue()) // 这个模型比较便宜
|
.model(OpenAiImageApi.ImageModel.DALL_E_2.getValue()) // 这个模型比较便宜
|
||||||
.withHeight(256).withWidth(256)
|
.height(256).width(256)
|
||||||
.build();
|
.build();
|
||||||
ImagePrompt prompt = new ImagePrompt("中国长城!", options);
|
ImagePrompt prompt = new ImagePrompt("中国长城!", options);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.image;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springaicommunity.qianfan.QianFanImageModel;
|
||||||
|
import org.springaicommunity.qianfan.QianFanImageOptions;
|
||||||
|
import org.springaicommunity.qianfan.api.QianFanImageApi;
|
||||||
import org.springframework.ai.image.ImagePrompt;
|
import org.springframework.ai.image.ImagePrompt;
|
||||||
import org.springframework.ai.image.ImageResponse;
|
import org.springframework.ai.image.ImageResponse;
|
||||||
import org.springframework.ai.qianfan.QianFanImageModel;
|
|
||||||
import org.springframework.ai.qianfan.QianFanImageOptions;
|
|
||||||
import org.springframework.ai.qianfan.api.QianFanImageApi;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.module.ai.framework.ai.core.model.image.StabilityAiImageModelTests.viewImage;
|
import static cn.iocoder.yudao.module.ai.framework.ai.core.model.image.StabilityAiImageModelTests.viewImage;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,8 @@ public class StabilityAiImageModelTests {
|
||||||
public void testCall() {
|
public void testCall() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
ImageOptions options = OpenAiImageOptions.builder()
|
ImageOptions options = OpenAiImageOptions.builder()
|
||||||
.withModel("stable-diffusion-v1-6")
|
.model("stable-diffusion-v1-6")
|
||||||
.withHeight(320).withWidth(320)
|
.height(320).width(320)
|
||||||
.build();
|
.build();
|
||||||
ImagePrompt prompt = new ImagePrompt("great wall", options);
|
ImagePrompt prompt = new ImagePrompt("great wall", options);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.ai.framework.ai.core.model.ppt.wdd;
|
package cn.iocoder.yudao.module.ai.framework.ai.core.model.ppt.wdd;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.wenduoduo.api.WenDuoDuoPptApi;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.wenduoduo.api.WenDuoDuoPptApi;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package cn.iocoder.yudao.module.ai.framework.ai.core.model.ppt.xunfei;
|
package cn.iocoder.yudao.module.ai.framework.ai.core.model.ppt.xunfei;
|
||||||
|
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.api.XunFeiPptApi;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
|
import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.api.XunFeiPptApi;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.mock.web.MockMultipartFile;
|
import org.springframework.mock.web.MockMultipartFile;
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ public class BpmFormServiceImpl implements BpmFormService {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return formMapper.selectBatchIds(ids);
|
return formMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ public class BpmUserGroupServiceImpl implements BpmUserGroupService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<BpmUserGroupDO> getUserGroupList(Collection<Long> ids) {
|
public List<BpmUserGroupDO> getUserGroupList(Collection<Long> ids) {
|
||||||
return userGroupMapper.selectBatchIds(ids);
|
return userGroupMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@ public class BpmUserGroupServiceImpl implements BpmUserGroupService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 获得用户组信息
|
// 获得用户组信息
|
||||||
List<BpmUserGroupDO> userGroups = userGroupMapper.selectBatchIds(ids);
|
List<BpmUserGroupDO> userGroups = userGroupMapper.selectByIds(ids);
|
||||||
Map<Long, BpmUserGroupDO> userGroupMap = convertMap(userGroups, BpmUserGroupDO::getId);
|
Map<Long, BpmUserGroupDO> userGroupMap = convertMap(userGroups, BpmUserGroupDO::getId);
|
||||||
// 校验
|
// 校验
|
||||||
ids.forEach(id -> {
|
ids.forEach(id -> {
|
||||||
|
|
|
||||||
|
|
@ -270,7 +270,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||||
.setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(node))
|
.setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(node))
|
||||||
.setCandidateUserIds(getTaskCandidateUserList(bpmnModel, node.getId(),
|
.setCandidateUserIds(getTaskCandidateUserList(bpmnModel, node.getId(),
|
||||||
loginUserId, historicProcessInstance.getProcessDefinitionId(), processVariables)));
|
loginUserId, historicProcessInstance.getProcessDefinitionId(), processVariables)));
|
||||||
if (CollUtil.isNotEmpty(nextActivityNodes)) {
|
if (CollUtil.isEmpty(nextActivityNodes)) {
|
||||||
return nextActivityNodes;
|
return nextActivityNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -142,12 +142,13 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||||
updateBusinessProduct(updateObj.getId(), businessProducts);
|
updateBusinessProduct(updateObj.getId(), businessProducts);
|
||||||
|
|
||||||
// 3. 记录操作日志上下文
|
// 3. 记录操作日志上下文
|
||||||
|
updateReqVO.setOwnerUserId(oldBusiness.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况
|
||||||
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldBusiness, CrmBusinessSaveReqVO.class));
|
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldBusiness, CrmBusinessSaveReqVO.class));
|
||||||
LogRecordContext.putVariable("businessName", oldBusiness.getName());
|
LogRecordContext.putVariable("businessName", oldBusiness.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}",
|
@LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}}",
|
||||||
success = CRM_BUSINESS_FOLLOW_UP_SUCCESS)
|
success = CRM_BUSINESS_FOLLOW_UP_SUCCESS)
|
||||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.WRITE)
|
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.WRITE)
|
||||||
public void updateBusinessFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) {
|
public void updateBusinessFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) {
|
||||||
|
|
@ -180,7 +181,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||||
businessProductMapper.updateBatch(diffList.get(1));
|
businessProductMapper.updateBatch(diffList.get(1));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||||
businessProductMapper.deleteBatchIds(convertSet(diffList.get(2), CrmBusinessProductDO::getId));
|
businessProductMapper.deleteByIds(convertSet(diffList.get(2), CrmBusinessProductDO::getId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -328,7 +329,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return ListUtil.empty();
|
return ListUtil.empty();
|
||||||
}
|
}
|
||||||
return businessMapper.selectBatchIds(ids);
|
return businessMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService {
|
||||||
businessStatusMapper.updateBatch(diffList.get(1));
|
businessStatusMapper.updateBatch(diffList.get(1));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||||
businessStatusMapper.deleteBatchIds(convertSet(diffList.get(2), CrmBusinessStatusDO::getId));
|
businessStatusMapper.deleteByIds(convertSet(diffList.get(2), CrmBusinessStatusDO::getId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,7 +160,7 @@ public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return businessStatusTypeMapper.selectBatchIds(ids);
|
return businessStatusTypeMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -175,7 +175,7 @@ public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return businessStatusMapper.selectBatchIds(ids);
|
return businessStatusMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -92,19 +92,20 @@ public class CrmClueServiceImpl implements CrmClueService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@LogRecord(type = CRM_CLUE_TYPE, subType = CRM_CLUE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
|
@LogRecord(type = CRM_CLUE_TYPE, subType = CRM_CLUE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
|
||||||
success = CRM_CLUE_UPDATE_SUCCESS)
|
success = CRM_CLUE_UPDATE_SUCCESS)
|
||||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#updateReq.id", level = CrmPermissionLevelEnum.OWNER)
|
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.OWNER)
|
||||||
public void updateClue(CrmClueSaveReqVO updateReq) {
|
public void updateClue(CrmClueSaveReqVO updateReqVO) {
|
||||||
Assert.notNull(updateReq.getId(), "线索编号不能为空");
|
Assert.notNull(updateReqVO.getId(), "线索编号不能为空");
|
||||||
// 1.1 校验线索是否存在
|
// 1.1 校验线索是否存在
|
||||||
CrmClueDO oldClue = validateClueExists(updateReq.getId());
|
CrmClueDO oldClue = validateClueExists(updateReqVO.getId());
|
||||||
// 1.2 校验关联数据
|
// 1.2 校验关联数据
|
||||||
validateRelationDataExists(updateReq);
|
validateRelationDataExists(updateReqVO);
|
||||||
|
|
||||||
// 2. 更新线索
|
// 2. 更新线索
|
||||||
CrmClueDO updateObj = BeanUtils.toBean(updateReq, CrmClueDO.class);
|
CrmClueDO updateObj = BeanUtils.toBean(updateReqVO, CrmClueDO.class);
|
||||||
clueMapper.updateById(updateObj);
|
clueMapper.updateById(updateObj);
|
||||||
|
|
||||||
// 3. 记录操作日志上下文
|
// 3. 记录操作日志上下文
|
||||||
|
updateReqVO.setOwnerUserId(oldClue.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况
|
||||||
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmCustomerSaveReqVO.class));
|
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmCustomerSaveReqVO.class));
|
||||||
LogRecordContext.putVariable("clueName", oldClue.getName());
|
LogRecordContext.putVariable("clueName", oldClue.getName());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,7 @@ public class CrmContactServiceImpl implements CrmContactService {
|
||||||
contactMapper.updateById(updateObj);
|
contactMapper.updateById(updateObj);
|
||||||
|
|
||||||
// 3. 记录操作日志
|
// 3. 记录操作日志
|
||||||
|
updateReqVO.setOwnerUserId(oldContact.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况
|
||||||
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContact, CrmContactSaveReqVO.class));
|
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContact, CrmContactSaveReqVO.class));
|
||||||
LogRecordContext.putVariable("contactName", oldContact.getName());
|
LogRecordContext.putVariable("contactName", oldContact.getName());
|
||||||
}
|
}
|
||||||
|
|
@ -262,7 +263,7 @@ public class CrmContactServiceImpl implements CrmContactService {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return ListUtil.empty();
|
return ListUtil.empty();
|
||||||
}
|
}
|
||||||
return contactMapper.selectBatchIds(ids);
|
return contactMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -303,4 +304,4 @@ public class CrmContactServiceImpl implements CrmContactService {
|
||||||
return contactMapper.selectListByCustomerIdOwnerUserId(customerId, ownerUserId);
|
return contactMapper.selectListByCustomerIdOwnerUserId(customerId, ownerUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -140,9 +140,9 @@ public class CrmContractServiceImpl implements CrmContractService {
|
||||||
Assert.notNull(updateReqVO.getId(), "合同编号不能为空");
|
Assert.notNull(updateReqVO.getId(), "合同编号不能为空");
|
||||||
updateReqVO.setOwnerUserId(null); // 不允许更新的字段
|
updateReqVO.setOwnerUserId(null); // 不允许更新的字段
|
||||||
// 1.1 校验存在
|
// 1.1 校验存在
|
||||||
CrmContractDO contract = validateContractExists(updateReqVO.getId());
|
CrmContractDO oldContract = validateContractExists(updateReqVO.getId());
|
||||||
// 1.2 只有草稿、审批中,可以编辑;
|
// 1.2 只有草稿、审批中,可以编辑;
|
||||||
if (!ObjectUtils.equalsAny(contract.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(),
|
if (!ObjectUtils.equalsAny(oldContract.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(),
|
||||||
CrmAuditStatusEnum.PROCESS.getStatus())) {
|
CrmAuditStatusEnum.PROCESS.getStatus())) {
|
||||||
throw exception(CONTRACT_UPDATE_FAIL_NOT_DRAFT);
|
throw exception(CONTRACT_UPDATE_FAIL_NOT_DRAFT);
|
||||||
}
|
}
|
||||||
|
|
@ -159,8 +159,9 @@ public class CrmContractServiceImpl implements CrmContractService {
|
||||||
updateContractProduct(updateReqVO.getId(), contractProducts);
|
updateContractProduct(updateReqVO.getId(), contractProducts);
|
||||||
|
|
||||||
// 3. 记录操作日志上下文
|
// 3. 记录操作日志上下文
|
||||||
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(contract, CrmContractSaveReqVO.class));
|
updateReqVO.setOwnerUserId(oldContract.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况
|
||||||
LogRecordContext.putVariable("contractName", contract.getName());
|
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContract, CrmContractSaveReqVO.class));
|
||||||
|
LogRecordContext.putVariable("contractName", oldContract.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateContractProduct(Long id, List<CrmContractProductDO> newList) {
|
private void updateContractProduct(Long id, List<CrmContractProductDO> newList) {
|
||||||
|
|
@ -175,7 +176,7 @@ public class CrmContractServiceImpl implements CrmContractService {
|
||||||
contractProductMapper.updateBatch(diffList.get(1));
|
contractProductMapper.updateBatch(diffList.get(1));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||||
contractProductMapper.deleteBatchIds(convertSet(diffList.get(2), CrmContractProductDO::getId));
|
contractProductMapper.deleteByIds(convertSet(diffList.get(2), CrmContractProductDO::getId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -341,7 +342,7 @@ public class CrmContractServiceImpl implements CrmContractService {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return ListUtil.empty();
|
return ListUtil.empty();
|
||||||
}
|
}
|
||||||
return contractMapper.selectBatchIds(ids);
|
return contractMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
||||||
customerMapper.updateById(updateObj);
|
customerMapper.updateById(updateObj);
|
||||||
|
|
||||||
// 3. 记录操作日志上下文
|
// 3. 记录操作日志上下文
|
||||||
|
updateReqVO.setOwnerUserId(oldCustomer.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况
|
||||||
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomer, CrmCustomerSaveReqVO.class));
|
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomer, CrmCustomerSaveReqVO.class));
|
||||||
LogRecordContext.putVariable("customerName", oldCustomer.getName());
|
LogRecordContext.putVariable("customerName", oldCustomer.getName());
|
||||||
}
|
}
|
||||||
|
|
@ -162,7 +163,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}",
|
@LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}}",
|
||||||
success = CRM_CUSTOMER_FOLLOW_UP_SUCCESS)
|
success = CRM_CUSTOMER_FOLLOW_UP_SUCCESS)
|
||||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.WRITE)
|
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.WRITE)
|
||||||
public void updateCustomerFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) {
|
public void updateCustomerFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) {
|
||||||
|
|
@ -232,24 +233,18 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
||||||
private void transfer(CrmCustomerTransferReqVO reqVO, Long userId) {
|
private void transfer(CrmCustomerTransferReqVO reqVO, Long userId) {
|
||||||
if (reqVO.getToBizTypes().contains(CrmBizTypeEnum.CRM_CONTACT.getType())) {
|
if (reqVO.getToBizTypes().contains(CrmBizTypeEnum.CRM_CONTACT.getType())) {
|
||||||
List<CrmContactDO> contactList = contactService.getContactListByCustomerIdOwnerUserId(reqVO.getId(), userId);
|
List<CrmContactDO> contactList = contactService.getContactListByCustomerIdOwnerUserId(reqVO.getId(), userId);
|
||||||
contactList.forEach(item -> {
|
contactList.forEach(item -> contactService.transferContact(new CrmContactTransferReqVO(item.getId(), reqVO.getNewOwnerUserId(),
|
||||||
contactService.transferContact(new CrmContactTransferReqVO(item.getId(), reqVO.getNewOwnerUserId(),
|
reqVO.getOldOwnerPermissionLevel()), userId));
|
||||||
reqVO.getOldOwnerPermissionLevel()), userId);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if (reqVO.getToBizTypes().contains(CrmBizTypeEnum.CRM_BUSINESS.getType())) {
|
if (reqVO.getToBizTypes().contains(CrmBizTypeEnum.CRM_BUSINESS.getType())) {
|
||||||
List<CrmBusinessDO> businessList = businessService.getBusinessListByCustomerIdOwnerUserId(reqVO.getId(), userId);
|
List<CrmBusinessDO> businessList = businessService.getBusinessListByCustomerIdOwnerUserId(reqVO.getId(), userId);
|
||||||
businessList.forEach(item -> {
|
businessList.forEach(item -> businessService.transferBusiness(new CrmBusinessTransferReqVO(item.getId(), reqVO.getNewOwnerUserId(),
|
||||||
businessService.transferBusiness(new CrmBusinessTransferReqVO(item.getId(), reqVO.getNewOwnerUserId(),
|
reqVO.getOldOwnerPermissionLevel()), userId));
|
||||||
reqVO.getOldOwnerPermissionLevel()), userId);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if (reqVO.getToBizTypes().contains(CrmBizTypeEnum.CRM_CONTRACT.getType())) {
|
if (reqVO.getToBizTypes().contains(CrmBizTypeEnum.CRM_CONTRACT.getType())) {
|
||||||
List<CrmContractDO> contractList = contractService.getContractListByCustomerIdOwnerUserId(reqVO.getId(), userId);
|
List<CrmContractDO> contractList = contractService.getContractListByCustomerIdOwnerUserId(reqVO.getId(), userId);
|
||||||
contractList.forEach(item -> {
|
contractList.forEach(item -> contractService.transferContract(new CrmContractTransferReqVO(item.getId(), reqVO.getNewOwnerUserId(),
|
||||||
contractService.transferContract(new CrmContractTransferReqVO(item.getId(), reqVO.getNewOwnerUserId(),
|
reqVO.getOldOwnerPermissionLevel()), userId));
|
||||||
reqVO.getOldOwnerPermissionLevel()), userId);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -391,7 +386,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void receiveCustomer(List<Long> ids, Long ownerUserId, Boolean isReceive) {
|
public void receiveCustomer(List<Long> ids, Long ownerUserId, Boolean isReceive) {
|
||||||
// 1.1 校验存在
|
// 1.1 校验存在
|
||||||
List<CrmCustomerDO> customers = customerMapper.selectBatchIds(ids);
|
List<CrmCustomerDO> customers = customerMapper.selectByIds(ids);
|
||||||
if (customers.size() != ids.size()) {
|
if (customers.size() != ids.size()) {
|
||||||
throw exception(CUSTOMER_NOT_EXISTS);
|
throw exception(CUSTOMER_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
|
|
@ -495,7 +490,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return customerMapper.selectBatchIds(ids);
|
return customerMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validatePermissionExists(Collection<Long> ids) {
|
private void validatePermissionExists(Collection<Long> ids) {
|
||||||
List<CrmPermissionDO> permissionList = permissionMapper.selectBatchIds(ids);
|
List<CrmPermissionDO> permissionList = permissionMapper.selectByIds(ids);
|
||||||
if (ObjUtil.notEqual(permissionList.size(), ids.size())) {
|
if (ObjUtil.notEqual(permissionList.size(), ids.size())) {
|
||||||
throw exception(CRM_PERMISSION_NOT_EXISTS);
|
throw exception(CRM_PERMISSION_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
|
|
@ -210,12 +210,12 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
|
||||||
CrmPermissionDO oldPermission = permissionMapper.selectByBizTypeAndBizIdByUserId(
|
CrmPermissionDO oldPermission = permissionMapper.selectByBizTypeAndBizIdByUserId(
|
||||||
transferReqBO.getBizType(), transferReqBO.getBizId(), transferReqBO.getUserId());
|
transferReqBO.getBizType(), transferReqBO.getBizId(), transferReqBO.getUserId());
|
||||||
String bizTypeName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType());
|
String bizTypeName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType());
|
||||||
if (oldPermission == null // 不是拥有者,并且不是超管
|
if ((oldPermission == null || !isOwner(oldPermission.getLevel()))
|
||||||
|| (!isOwner(oldPermission.getLevel()) && !CrmPermissionUtils.isCrmAdmin())) {
|
&& !CrmPermissionUtils.isCrmAdmin()) { // 并且不是超管
|
||||||
throw exception(CRM_PERMISSION_DENIED, bizTypeName);
|
throw exception(CRM_PERMISSION_DENIED, bizTypeName);
|
||||||
}
|
}
|
||||||
// 1.1 校验转移对象是否已经是该负责人
|
// 1.1 校验转移对象是否已经是该负责人
|
||||||
if (ObjUtil.equal(transferReqBO.getNewOwnerUserId(), oldPermission.getUserId())) {
|
if (oldPermission != null && ObjUtil.equal(transferReqBO.getNewOwnerUserId(), oldPermission.getUserId())) {
|
||||||
throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, bizTypeName);
|
throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, bizTypeName);
|
||||||
}
|
}
|
||||||
// 1.2 校验新负责人是否存在
|
// 1.2 校验新负责人是否存在
|
||||||
|
|
@ -255,7 +255,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除数据权限
|
// 删除数据权限
|
||||||
permissionMapper.deleteBatchIds(convertSet(permissions, CrmPermissionDO::getId));
|
permissionMapper.deleteByIds(convertSet(permissions, CrmPermissionDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -268,7 +268,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deletePermissionBatch(Collection<Long> ids, Long userId) {
|
public void deletePermissionBatch(Collection<Long> ids, Long userId) {
|
||||||
List<CrmPermissionDO> permissions = permissionMapper.selectBatchIds(ids);
|
List<CrmPermissionDO> permissions = permissionMapper.selectByIds(ids);
|
||||||
if (CollUtil.isEmpty(permissions)) {
|
if (CollUtil.isEmpty(permissions)) {
|
||||||
throw exception(CRM_PERMISSION_NOT_EXISTS);
|
throw exception(CRM_PERMISSION_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
|
|
@ -286,7 +286,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除数据权限
|
// 删除数据权限
|
||||||
permissionMapper.deleteBatchIds(ids);
|
permissionMapper.deleteByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CrmProductCategoryDO> getProductCategoryList(Collection<Long> ids) {
|
public List<CrmProductCategoryDO> getProductCategoryList(Collection<Long> ids) {
|
||||||
return productCategoryMapper.selectBatchIds(ids);
|
return productCategoryMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ public class CrmProductServiceImpl implements CrmProductService {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
List<CrmProductDO> list = productMapper.selectBatchIds(ids);
|
List<CrmProductDO> list = productMapper.selectByIds(ids);
|
||||||
Map<Long, CrmProductDO> productMap = convertMap(list, CrmProductDO::getId);
|
Map<Long, CrmProductDO> productMap = convertMap(list, CrmProductDO::getId);
|
||||||
for (Long id : ids) {
|
for (Long id : ids) {
|
||||||
CrmProductDO product = productMap.get(id);
|
CrmProductDO product = productMap.get(id);
|
||||||
|
|
@ -177,7 +177,7 @@ public class CrmProductServiceImpl implements CrmProductService {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return productMapper.selectBatchIds(ids);
|
return productMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
|
||||||
receivablePlanMapper.updateById(updateObj);
|
receivablePlanMapper.updateById(updateObj);
|
||||||
|
|
||||||
// 3. 记录操作日志上下文
|
// 3. 记录操作日志上下文
|
||||||
|
updateReqVO.setOwnerUserId(oldReceivablePlan.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况
|
||||||
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldReceivablePlan, CrmReceivablePlanSaveReqVO.class));
|
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldReceivablePlan, CrmReceivablePlanSaveReqVO.class));
|
||||||
LogRecordContext.putVariable("receivablePlan", oldReceivablePlan);
|
LogRecordContext.putVariable("receivablePlan", oldReceivablePlan);
|
||||||
}
|
}
|
||||||
|
|
@ -165,7 +166,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return ListUtil.empty();
|
return ListUtil.empty();
|
||||||
}
|
}
|
||||||
return receivablePlanMapper.selectBatchIds(ids);
|
return receivablePlanMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -162,14 +162,14 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
|
||||||
Assert.notNull(updateReqVO.getId(), "回款编号不能为空");
|
Assert.notNull(updateReqVO.getId(), "回款编号不能为空");
|
||||||
updateReqVO.setOwnerUserId(null).setCustomerId(null).setContractId(null).setPlanId(null); // 不允许修改的字段
|
updateReqVO.setOwnerUserId(null).setCustomerId(null).setContractId(null).setPlanId(null); // 不允许修改的字段
|
||||||
// 1.1 校验存在
|
// 1.1 校验存在
|
||||||
CrmReceivableDO receivable = validateReceivableExists(updateReqVO.getId());
|
CrmReceivableDO oldReceivable = validateReceivableExists(updateReqVO.getId());
|
||||||
updateReqVO.setOwnerUserId(receivable.getOwnerUserId()).setCustomerId(receivable.getCustomerId())
|
updateReqVO.setOwnerUserId(oldReceivable.getOwnerUserId()).setCustomerId(oldReceivable.getCustomerId())
|
||||||
.setContractId(receivable.getContractId()).setPlanId(receivable.getPlanId()); // 设置已存在的值
|
.setContractId(oldReceivable.getContractId()).setPlanId(oldReceivable.getPlanId()); // 设置已存在的值
|
||||||
// 1.2 校验可回款金额超过上限
|
// 1.2 校验可回款金额超过上限
|
||||||
validateReceivablePriceExceedsLimit(updateReqVO);
|
validateReceivablePriceExceedsLimit(updateReqVO);
|
||||||
|
|
||||||
// 1.3 只有草稿、审批中,可以编辑;
|
// 1.3 只有草稿、审批中,可以编辑;
|
||||||
if (!ObjectUtils.equalsAny(receivable.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(),
|
if (!ObjectUtils.equalsAny(oldReceivable.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(),
|
||||||
CrmAuditStatusEnum.PROCESS.getStatus())) {
|
CrmAuditStatusEnum.PROCESS.getStatus())) {
|
||||||
throw exception(RECEIVABLE_UPDATE_FAIL_EDITING_PROHIBITED);
|
throw exception(RECEIVABLE_UPDATE_FAIL_EDITING_PROHIBITED);
|
||||||
}
|
}
|
||||||
|
|
@ -179,9 +179,10 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
|
||||||
receivableMapper.updateById(updateObj);
|
receivableMapper.updateById(updateObj);
|
||||||
|
|
||||||
// 3. 记录操作日志上下文
|
// 3. 记录操作日志上下文
|
||||||
LogRecordContext.putVariable("receivable", receivable);
|
updateReqVO.setOwnerUserId(oldReceivable.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况
|
||||||
LogRecordContext.putVariable("period", getReceivablePeriod(receivable.getPlanId()));
|
LogRecordContext.putVariable("oldReceivable", oldReceivable);
|
||||||
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(receivable, CrmReceivableSaveReqVO.class));
|
LogRecordContext.putVariable("period", getReceivablePeriod(oldReceivable.getPlanId()));
|
||||||
|
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldReceivable, CrmReceivableSaveReqVO.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Integer getReceivablePeriod(Long planId) {
|
private Integer getReceivablePeriod(Long planId) {
|
||||||
|
|
@ -277,7 +278,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return ListUtil.empty();
|
return ListUtil.empty();
|
||||||
}
|
}
|
||||||
return receivableMapper.selectBatchIds(ids);
|
return receivableMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,7 @@ import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.ACCOUNT_NOT_ENABLE;
|
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
|
||||||
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.ACCOUNT_NOT_EXISTS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ERP 结算账户 Service 实现类
|
* ERP 结算账户 Service 实现类
|
||||||
|
|
@ -102,7 +101,7 @@ public class ErpAccountServiceImpl implements ErpAccountService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ErpAccountDO> getAccountList(Collection<Long> ids) {
|
public List<ErpAccountDO> getAccountList(Collection<Long> ids) {
|
||||||
return accountMapper.selectBatchIds(ids);
|
return accountMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -110,4 +109,4 @@ public class ErpAccountServiceImpl implements ErpAccountService {
|
||||||
return accountMapper.selectPage(pageReqVO);
|
return accountMapper.selectPage(pageReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService {
|
||||||
financePaymentItemMapper.updateBatch(diffList.get(1));
|
financePaymentItemMapper.updateBatch(diffList.get(1));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||||
financePaymentItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpFinancePaymentItemDO::getId));
|
financePaymentItemMapper.deleteByIds(convertList(diffList.get(2), ErpFinancePaymentItemDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 第三步,更新采购入库、退货的付款金额情况
|
// 第三步,更新采购入库、退货的付款金额情况
|
||||||
|
|
@ -214,7 +214,7 @@ public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deleteFinancePayment(List<Long> ids) {
|
public void deleteFinancePayment(List<Long> ids) {
|
||||||
// 1. 校验不处于已审批
|
// 1. 校验不处于已审批
|
||||||
List<ErpFinancePaymentDO> payments = financePaymentMapper.selectBatchIds(ids);
|
List<ErpFinancePaymentDO> payments = financePaymentMapper.selectByIds(ids);
|
||||||
if (CollUtil.isEmpty(payments)) {
|
if (CollUtil.isEmpty(payments)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -230,7 +230,7 @@ public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService {
|
||||||
financePaymentMapper.deleteById(payment.getId());
|
financePaymentMapper.deleteById(payment.getId());
|
||||||
// 2.2 删除付款单项
|
// 2.2 删除付款单项
|
||||||
List<ErpFinancePaymentItemDO> paymentItems = financePaymentItemMapper.selectListByPaymentId(payment.getId());
|
List<ErpFinancePaymentItemDO> paymentItems = financePaymentItemMapper.selectListByPaymentId(payment.getId());
|
||||||
financePaymentItemMapper.deleteBatchIds(convertSet(paymentItems, ErpFinancePaymentItemDO::getId));
|
financePaymentItemMapper.deleteByIds(convertSet(paymentItems, ErpFinancePaymentItemDO::getId));
|
||||||
|
|
||||||
// 2.3 更新采购入库、退货的付款金额情况
|
// 2.3 更新采购入库、退货的付款金额情况
|
||||||
updatePurchasePrice(paymentItems);
|
updatePurchasePrice(paymentItems);
|
||||||
|
|
@ -270,4 +270,4 @@ public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService {
|
||||||
return financePaymentItemMapper.selectListByPaymentIds(paymentIds);
|
return financePaymentItemMapper.selectListByPaymentIds(paymentIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ public class ErpFinanceReceiptServiceImpl implements ErpFinanceReceiptService {
|
||||||
financeReceiptItemMapper.updateBatch(diffList.get(1));
|
financeReceiptItemMapper.updateBatch(diffList.get(1));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||||
financeReceiptItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpFinanceReceiptItemDO::getId));
|
financeReceiptItemMapper.deleteByIds(convertList(diffList.get(2), ErpFinanceReceiptItemDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 第三步,更新销售出库、退货的收款金额情况
|
// 第三步,更新销售出库、退货的收款金额情况
|
||||||
|
|
@ -214,7 +214,7 @@ public class ErpFinanceReceiptServiceImpl implements ErpFinanceReceiptService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deleteFinanceReceipt(List<Long> ids) {
|
public void deleteFinanceReceipt(List<Long> ids) {
|
||||||
// 1. 校验不处于已审批
|
// 1. 校验不处于已审批
|
||||||
List<ErpFinanceReceiptDO> receipts = financeReceiptMapper.selectBatchIds(ids);
|
List<ErpFinanceReceiptDO> receipts = financeReceiptMapper.selectByIds(ids);
|
||||||
if (CollUtil.isEmpty(receipts)) {
|
if (CollUtil.isEmpty(receipts)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -230,7 +230,7 @@ public class ErpFinanceReceiptServiceImpl implements ErpFinanceReceiptService {
|
||||||
financeReceiptMapper.deleteById(receipt.getId());
|
financeReceiptMapper.deleteById(receipt.getId());
|
||||||
// 2.2 删除收款单项
|
// 2.2 删除收款单项
|
||||||
List<ErpFinanceReceiptItemDO> receiptItems = financeReceiptItemMapper.selectListByReceiptId(receipt.getId());
|
List<ErpFinanceReceiptItemDO> receiptItems = financeReceiptItemMapper.selectListByReceiptId(receipt.getId());
|
||||||
financeReceiptItemMapper.deleteBatchIds(convertSet(receiptItems, ErpFinanceReceiptItemDO::getId));
|
financeReceiptItemMapper.deleteByIds(convertSet(receiptItems, ErpFinanceReceiptItemDO::getId));
|
||||||
|
|
||||||
// 2.3 更新销售出库、退货的收款金额情况
|
// 2.3 更新销售出库、退货的收款金额情况
|
||||||
updateSalePrice(receiptItems);
|
updateSalePrice(receiptItems);
|
||||||
|
|
@ -270,4 +270,4 @@ public class ErpFinanceReceiptServiceImpl implements ErpFinanceReceiptService {
|
||||||
return financeReceiptItemMapper.selectListByReceiptIds(receiptIds);
|
return financeReceiptItemMapper.selectListByReceiptIds(receiptIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ErpProductCategoryDO> getProductCategoryList(Collection<Long> ids) {
|
public List<ErpProductCategoryDO> getProductCategoryList(Collection<Long> ids) {
|
||||||
return erpProductCategoryMapper.selectBatchIds(ids);
|
return erpProductCategoryMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,20 +12,15 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO;
|
||||||
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
|
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
|
||||||
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
|
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
|
||||||
import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper;
|
import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
|
||||||
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.PRODUCT_NOT_ENABLE;
|
|
||||||
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.PRODUCT_NOT_EXISTS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ERP 产品 Service 实现类
|
* ERP 产品 Service 实现类
|
||||||
|
|
@ -77,7 +72,7 @@ public class ErpProductServiceImpl implements ErpProductService {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
List<ErpProductDO> list = productMapper.selectBatchIds(ids);
|
List<ErpProductDO> list = productMapper.selectByIds(ids);
|
||||||
Map<Long, ErpProductDO> productMap = convertMap(list, ErpProductDO::getId);
|
Map<Long, ErpProductDO> productMap = convertMap(list, ErpProductDO::getId);
|
||||||
for (Long id : ids) {
|
for (Long id : ids) {
|
||||||
ErpProductDO product = productMap.get(id);
|
ErpProductDO product = productMap.get(id);
|
||||||
|
|
@ -113,7 +108,7 @@ public class ErpProductServiceImpl implements ErpProductService {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
List<ErpProductDO> list = productMapper.selectBatchIds(ids);
|
List<ErpProductDO> list = productMapper.selectByIds(ids);
|
||||||
return buildProductVOList(list);
|
return buildProductVOList(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,4 +144,4 @@ public class ErpProductServiceImpl implements ErpProductService {
|
||||||
return productMapper.selectCountByUnitId(unitId);
|
return productMapper.selectCountByUnitId(unitId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ public class ErpProductUnitServiceImpl implements ErpProductUnitService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ErpProductUnitDO> getProductUnitList(Collection<Long> ids) {
|
public List<ErpProductUnitDO> getProductUnitList(Collection<Long> ids) {
|
||||||
return productUnitMapper.selectBatchIds(ids);
|
return productUnitMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ public class ErpPurchaseInServiceImpl implements ErpPurchaseInService {
|
||||||
|
|
||||||
// 2.1 插入入库
|
// 2.1 插入入库
|
||||||
ErpPurchaseInDO purchaseIn = BeanUtils.toBean(createReqVO, ErpPurchaseInDO.class, in -> in
|
ErpPurchaseInDO purchaseIn = BeanUtils.toBean(createReqVO, ErpPurchaseInDO.class, in -> in
|
||||||
.setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()))
|
.setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()))
|
||||||
.setOrderNo(purchaseOrder.getNo()).setSupplierId(purchaseOrder.getSupplierId());
|
.setOrderNo(purchaseOrder.getNo()).setSupplierId(purchaseOrder.getSupplierId());
|
||||||
calculateTotalPrice(purchaseIn, purchaseInItems);
|
calculateTotalPrice(purchaseIn, purchaseInItems);
|
||||||
purchaseInMapper.insert(purchaseIn);
|
purchaseInMapper.insert(purchaseIn);
|
||||||
|
|
@ -232,7 +232,7 @@ public class ErpPurchaseInServiceImpl implements ErpPurchaseInService {
|
||||||
purchaseInItemMapper.updateBatch(diffList.get(1));
|
purchaseInItemMapper.updateBatch(diffList.get(1));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||||
purchaseInItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpPurchaseInItemDO::getId));
|
purchaseInItemMapper.deleteByIds(convertList(diffList.get(2), ErpPurchaseInItemDO::getId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,7 +240,7 @@ public class ErpPurchaseInServiceImpl implements ErpPurchaseInService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deletePurchaseIn(List<Long> ids) {
|
public void deletePurchaseIn(List<Long> ids) {
|
||||||
// 1. 校验不处于已审批
|
// 1. 校验不处于已审批
|
||||||
List<ErpPurchaseInDO> purchaseIns = purchaseInMapper.selectBatchIds(ids);
|
List<ErpPurchaseInDO> purchaseIns = purchaseInMapper.selectByIds(ids);
|
||||||
if (CollUtil.isEmpty(purchaseIns)) {
|
if (CollUtil.isEmpty(purchaseIns)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -305,4 +305,4 @@ public class ErpPurchaseInServiceImpl implements ErpPurchaseInService {
|
||||||
return purchaseInItemMapper.selectListByInIds(inIds);
|
return purchaseInItemMapper.selectListByInIds(inIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,7 @@ public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService {
|
||||||
purchaseOrderItemMapper.updateBatch(diffList.get(1));
|
purchaseOrderItemMapper.updateBatch(diffList.get(1));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||||
purchaseOrderItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpPurchaseOrderItemDO::getId));
|
purchaseOrderItemMapper.deleteByIds(convertList(diffList.get(2), ErpPurchaseOrderItemDO::getId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -231,7 +231,7 @@ public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deletePurchaseOrder(List<Long> ids) {
|
public void deletePurchaseOrder(List<Long> ids) {
|
||||||
// 1. 校验不处于已审批
|
// 1. 校验不处于已审批
|
||||||
List<ErpPurchaseOrderDO> purchaseOrders = purchaseOrderMapper.selectBatchIds(ids);
|
List<ErpPurchaseOrderDO> purchaseOrders = purchaseOrderMapper.selectByIds(ids);
|
||||||
if (CollUtil.isEmpty(purchaseOrders)) {
|
if (CollUtil.isEmpty(purchaseOrders)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -292,4 +292,4 @@ public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService {
|
||||||
return purchaseOrderItemMapper.selectListByOrderIds(orderIds);
|
return purchaseOrderItemMapper.selectListByOrderIds(orderIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService {
|
||||||
|
|
||||||
// 2.1 插入退货
|
// 2.1 插入退货
|
||||||
ErpPurchaseReturnDO purchaseReturn = BeanUtils.toBean(createReqVO, ErpPurchaseReturnDO.class, in -> in
|
ErpPurchaseReturnDO purchaseReturn = BeanUtils.toBean(createReqVO, ErpPurchaseReturnDO.class, in -> in
|
||||||
.setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()))
|
.setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()))
|
||||||
.setOrderNo(purchaseOrder.getNo()).setSupplierId(purchaseOrder.getSupplierId());
|
.setOrderNo(purchaseOrder.getNo()).setSupplierId(purchaseOrder.getSupplierId());
|
||||||
calculateTotalPrice(purchaseReturn, purchaseReturnItems);
|
calculateTotalPrice(purchaseReturn, purchaseReturnItems);
|
||||||
purchaseReturnMapper.insert(purchaseReturn);
|
purchaseReturnMapper.insert(purchaseReturn);
|
||||||
|
|
@ -228,7 +228,7 @@ public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService {
|
||||||
purchaseReturnItemMapper.updateBatch(diffList.get(1));
|
purchaseReturnItemMapper.updateBatch(diffList.get(1));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||||
purchaseReturnItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpPurchaseReturnItemDO::getId));
|
purchaseReturnItemMapper.deleteByIds(convertList(diffList.get(2), ErpPurchaseReturnItemDO::getId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,7 +236,7 @@ public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deletePurchaseReturn(List<Long> ids) {
|
public void deletePurchaseReturn(List<Long> ids) {
|
||||||
// 1. 校验不处于已审批
|
// 1. 校验不处于已审批
|
||||||
List<ErpPurchaseReturnDO> purchaseReturns = purchaseReturnMapper.selectBatchIds(ids);
|
List<ErpPurchaseReturnDO> purchaseReturns = purchaseReturnMapper.selectByIds(ids);
|
||||||
if (CollUtil.isEmpty(purchaseReturns)) {
|
if (CollUtil.isEmpty(purchaseReturns)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -301,4 +301,4 @@ public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService {
|
||||||
return purchaseReturnItemMapper.selectListByReturnIds(returnIds);
|
return purchaseReturnItemMapper.selectListByReturnIds(returnIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,7 @@ import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.SUPPLIER_NOT_ENABLE;
|
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
|
||||||
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.SUPPLIER_NOT_EXISTS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ERP 供应商 Service 实现类
|
* ERP 供应商 Service 实现类
|
||||||
|
|
@ -79,7 +78,7 @@ public class ErpSupplierServiceImpl implements ErpSupplierService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ErpSupplierDO> getSupplierList(Collection<Long> ids) {
|
public List<ErpSupplierDO> getSupplierList(Collection<Long> ids) {
|
||||||
return supplierMapper.selectBatchIds(ids);
|
return supplierMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -92,4 +91,4 @@ public class ErpSupplierServiceImpl implements ErpSupplierService {
|
||||||
return supplierMapper.selectListByStatus(status);
|
return supplierMapper.selectListByStatus(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ public class ErpCustomerServiceImpl implements ErpCustomerService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ErpCustomerDO> getCustomerList(Collection<Long> ids) {
|
public List<ErpCustomerDO> getCustomerList(Collection<Long> ids) {
|
||||||
return customerMapper.selectBatchIds(ids);
|
return customerMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -94,4 +94,4 @@ public class ErpCustomerServiceImpl implements ErpCustomerService {
|
||||||
return customerMapper.selectListByStatus(status);
|
return customerMapper.selectListByStatus(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -195,7 +195,7 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService {
|
||||||
saleOrderItemMapper.updateBatch(diffList.get(1));
|
saleOrderItemMapper.updateBatch(diffList.get(1));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||||
saleOrderItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpSaleOrderItemDO::getId));
|
saleOrderItemMapper.deleteByIds(convertList(diffList.get(2), ErpSaleOrderItemDO::getId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -243,7 +243,7 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deleteSaleOrder(List<Long> ids) {
|
public void deleteSaleOrder(List<Long> ids) {
|
||||||
// 1. 校验不处于已审批
|
// 1. 校验不处于已审批
|
||||||
List<ErpSaleOrderDO> saleOrders = saleOrderMapper.selectBatchIds(ids);
|
List<ErpSaleOrderDO> saleOrders = saleOrderMapper.selectByIds(ids);
|
||||||
if (CollUtil.isEmpty(saleOrders)) {
|
if (CollUtil.isEmpty(saleOrders)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -304,4 +304,4 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService {
|
||||||
return saleOrderItemMapper.selectListByOrderIds(orderIds);
|
return saleOrderItemMapper.selectListByOrderIds(orderIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,7 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService {
|
||||||
saleOutItemMapper.updateBatch(diffList.get(1));
|
saleOutItemMapper.updateBatch(diffList.get(1));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||||
saleOutItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpSaleOutItemDO::getId));
|
saleOutItemMapper.deleteByIds(convertList(diffList.get(2), ErpSaleOutItemDO::getId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -248,7 +248,7 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deleteSaleOut(List<Long> ids) {
|
public void deleteSaleOut(List<Long> ids) {
|
||||||
// 1. 校验不处于已审批
|
// 1. 校验不处于已审批
|
||||||
List<ErpSaleOutDO> saleOuts = saleOutMapper.selectBatchIds(ids);
|
List<ErpSaleOutDO> saleOuts = saleOutMapper.selectByIds(ids);
|
||||||
if (CollUtil.isEmpty(saleOuts)) {
|
if (CollUtil.isEmpty(saleOuts)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -313,4 +313,4 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService {
|
||||||
return saleOutItemMapper.selectListByOutIds(outIds);
|
return saleOutItemMapper.selectListByOutIds(outIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,7 @@ public class ErpSaleReturnServiceImpl implements ErpSaleReturnService {
|
||||||
saleReturnItemMapper.updateBatch(diffList.get(1));
|
saleReturnItemMapper.updateBatch(diffList.get(1));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||||
saleReturnItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpSaleReturnItemDO::getId));
|
saleReturnItemMapper.deleteByIds(convertList(diffList.get(2), ErpSaleReturnItemDO::getId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -248,7 +248,7 @@ public class ErpSaleReturnServiceImpl implements ErpSaleReturnService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deleteSaleReturn(List<Long> ids) {
|
public void deleteSaleReturn(List<Long> ids) {
|
||||||
// 1. 校验不处于已审批
|
// 1. 校验不处于已审批
|
||||||
List<ErpSaleReturnDO> saleReturns = saleReturnMapper.selectBatchIds(ids);
|
List<ErpSaleReturnDO> saleReturns = saleReturnMapper.selectByIds(ids);
|
||||||
if (CollUtil.isEmpty(saleReturns)) {
|
if (CollUtil.isEmpty(saleReturns)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -313,4 +313,4 @@ public class ErpSaleReturnServiceImpl implements ErpSaleReturnService {
|
||||||
return saleReturnItemMapper.selectListByReturnIds(returnIds);
|
return saleReturnItemMapper.selectListByReturnIds(returnIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
|
||||||
stockCheckItemMapper.updateBatch(diffList.get(1));
|
stockCheckItemMapper.updateBatch(diffList.get(1));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||||
stockCheckItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockCheckItemDO::getId));
|
stockCheckItemMapper.deleteByIds(convertList(diffList.get(2), ErpStockCheckItemDO::getId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,7 +177,7 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deleteStockCheck(List<Long> ids) {
|
public void deleteStockCheck(List<Long> ids) {
|
||||||
// 1. 校验不处于已审批
|
// 1. 校验不处于已审批
|
||||||
List<ErpStockCheckDO> stockChecks = stockCheckMapper.selectBatchIds(ids);
|
List<ErpStockCheckDO> stockChecks = stockCheckMapper.selectByIds(ids);
|
||||||
if (CollUtil.isEmpty(stockChecks)) {
|
if (CollUtil.isEmpty(stockChecks)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -229,4 +229,4 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
|
||||||
return stockCheckItemMapper.selectListByCheckIds(checkIds);
|
return stockCheckItemMapper.selectListByCheckIds(checkIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ public class ErpStockInServiceImpl implements ErpStockInService {
|
||||||
stockInItemMapper.updateBatch(diffList.get(1));
|
stockInItemMapper.updateBatch(diffList.get(1));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||||
stockInItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockInItemDO::getId));
|
stockInItemMapper.deleteByIds(convertList(diffList.get(2), ErpStockInItemDO::getId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -173,7 +173,7 @@ public class ErpStockInServiceImpl implements ErpStockInService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deleteStockIn(List<Long> ids) {
|
public void deleteStockIn(List<Long> ids) {
|
||||||
// 1. 校验不处于已审批
|
// 1. 校验不处于已审批
|
||||||
List<ErpStockInDO> stockIns = stockInMapper.selectBatchIds(ids);
|
List<ErpStockInDO> stockIns = stockInMapper.selectByIds(ids);
|
||||||
if (CollUtil.isEmpty(stockIns)) {
|
if (CollUtil.isEmpty(stockIns)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -225,4 +225,4 @@ public class ErpStockInServiceImpl implements ErpStockInService {
|
||||||
return stockInItemMapper.selectListByInIds(inIds);
|
return stockInItemMapper.selectListByInIds(inIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService {
|
||||||
stockMoveItemMapper.updateBatch(diffList.get(1));
|
stockMoveItemMapper.updateBatch(diffList.get(1));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||||
stockMoveItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockMoveItemDO::getId));
|
stockMoveItemMapper.deleteByIds(convertList(diffList.get(2), ErpStockMoveItemDO::getId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -174,7 +174,7 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deleteStockMove(List<Long> ids) {
|
public void deleteStockMove(List<Long> ids) {
|
||||||
// 1. 校验不处于已审批
|
// 1. 校验不处于已审批
|
||||||
List<ErpStockMoveDO> stockMoves = stockMoveMapper.selectBatchIds(ids);
|
List<ErpStockMoveDO> stockMoves = stockMoveMapper.selectByIds(ids);
|
||||||
if (CollUtil.isEmpty(stockMoves)) {
|
if (CollUtil.isEmpty(stockMoves)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -226,4 +226,4 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService {
|
||||||
return stockMoveItemMapper.selectListByMoveIds(moveIds);
|
return stockMoveItemMapper.selectListByMoveIds(moveIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
|
||||||
stockOutItemMapper.updateBatch(diffList.get(1));
|
stockOutItemMapper.updateBatch(diffList.get(1));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||||
stockOutItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockOutItemDO::getId));
|
stockOutItemMapper.deleteByIds(convertList(diffList.get(2), ErpStockOutItemDO::getId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -173,7 +173,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deleteStockOut(List<Long> ids) {
|
public void deleteStockOut(List<Long> ids) {
|
||||||
// 1. 校验不处于已审批
|
// 1. 校验不处于已审批
|
||||||
List<ErpStockOutDO> stockOuts = stockOutMapper.selectBatchIds(ids);
|
List<ErpStockOutDO> stockOuts = stockOutMapper.selectByIds(ids);
|
||||||
if (CollUtil.isEmpty(stockOuts)) {
|
if (CollUtil.isEmpty(stockOuts)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -225,4 +225,4 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
|
||||||
return stockOutItemMapper.selectListByOutIds(outIds);
|
return stockOutItemMapper.selectListByOutIds(outIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,7 @@ import java.util.Map;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||||
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_NOT_ENABLE;
|
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
|
||||||
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_NOT_EXISTS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ERP 仓库 Service 实现类
|
* ERP 仓库 Service 实现类
|
||||||
|
|
@ -94,7 +93,7 @@ public class ErpWarehouseServiceImpl implements ErpWarehouseService {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
List<ErpWarehouseDO> list = warehouseMapper.selectBatchIds(ids);
|
List<ErpWarehouseDO> list = warehouseMapper.selectByIds(ids);
|
||||||
Map<Long, ErpWarehouseDO> warehouseMap = convertMap(list, ErpWarehouseDO::getId);
|
Map<Long, ErpWarehouseDO> warehouseMap = convertMap(list, ErpWarehouseDO::getId);
|
||||||
for (Long id : ids) {
|
for (Long id : ids) {
|
||||||
ErpWarehouseDO warehouse = warehouseMap.get(id);
|
ErpWarehouseDO warehouse = warehouseMap.get(id);
|
||||||
|
|
@ -115,7 +114,7 @@ public class ErpWarehouseServiceImpl implements ErpWarehouseService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ErpWarehouseDO> getWarehouseList(Collection<Long> ids) {
|
public List<ErpWarehouseDO> getWarehouseList(Collection<Long> ids) {
|
||||||
return warehouseMapper.selectBatchIds(ids);
|
return warehouseMapper.selectByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -123,4 +122,4 @@ public class ErpWarehouseServiceImpl implements ErpWarehouseService {
|
||||||
return warehouseMapper.selectPage(pageReqVO);
|
return warehouseMapper.selectPage(pageReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,9 @@
|
||||||
<if test="endTime != null">
|
<if test="endTime != null">
|
||||||
AND in_time < #{endTime}
|
AND in_time < #{endTime}
|
||||||
</if>
|
</if>
|
||||||
AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getRequiredTenantId()}
|
<if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
|
||||||
|
AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
|
||||||
|
</if>
|
||||||
AND deleted = 0) -
|
AND deleted = 0) -
|
||||||
(SELECT IFNULL(SUM(total_price), 0)
|
(SELECT IFNULL(SUM(total_price), 0)
|
||||||
FROM erp_purchase_return
|
FROM erp_purchase_return
|
||||||
|
|
@ -18,7 +20,9 @@
|
||||||
<if test="endTime != null">
|
<if test="endTime != null">
|
||||||
AND return_time < #{endTime}
|
AND return_time < #{endTime}
|
||||||
</if>
|
</if>
|
||||||
AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getRequiredTenantId()}
|
<if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
|
||||||
|
AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
|
||||||
|
</if>
|
||||||
AND deleted = 0)
|
AND deleted = 0)
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,9 @@
|
||||||
<if test="endTime != null">
|
<if test="endTime != null">
|
||||||
AND out_time < #{endTime}
|
AND out_time < #{endTime}
|
||||||
</if>
|
</if>
|
||||||
AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getRequiredTenantId()}
|
<if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
|
||||||
|
AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
|
||||||
|
</if>
|
||||||
AND deleted = 0) -
|
AND deleted = 0) -
|
||||||
(SELECT IFNULL(SUM(total_price), 0)
|
(SELECT IFNULL(SUM(total_price), 0)
|
||||||
FROM erp_sale_return
|
FROM erp_sale_return
|
||||||
|
|
@ -18,7 +20,9 @@
|
||||||
<if test="endTime != null">
|
<if test="endTime != null">
|
||||||
AND return_time < #{endTime}
|
AND return_time < #{endTime}
|
||||||
</if>
|
</if>
|
||||||
AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getRequiredTenantId()}
|
<if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
|
||||||
|
AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
|
||||||
|
</if>
|
||||||
AND deleted = 0)
|
AND deleted = 0)
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,11 @@ public enum CodegenFrontTypeEnum {
|
||||||
VUE3_VBEN2_ANTD_SCHEMA(30), // Vue3 VBEN2 + ANTD + Schema 模版
|
VUE3_VBEN2_ANTD_SCHEMA(30), // Vue3 VBEN2 + ANTD + Schema 模版
|
||||||
|
|
||||||
VUE3_VBEN5_ANTD_SCHEMA(40), // Vue3 VBEN5 + ANTD + schema 模版
|
VUE3_VBEN5_ANTD_SCHEMA(40), // Vue3 VBEN5 + ANTD + schema 模版
|
||||||
|
|
||||||
VUE3_VBEN5_ANTD_GENERAL(41), // Vue3 VBEN5 + ANTD 标准模版
|
VUE3_VBEN5_ANTD_GENERAL(41), // Vue3 VBEN5 + ANTD 标准模版
|
||||||
|
|
||||||
|
// TODO @puhui999::50、51 会好点;
|
||||||
|
VUE3_VBEN5_EP_SCHEMA(42), // Vue3 VBEN5 + EP + schema 模版
|
||||||
|
VUE3_VBEN5_EP_GENERAL(43), // Vue3 VBEN5 + EP 标准模版
|
||||||
;
|
;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
|
||||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserNickname;
|
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserNickname;
|
||||||
import static cn.iocoder.yudao.module.infra.framework.file.core.utils.FileTypeUtils.writeAttachment;
|
import static cn.iocoder.yudao.module.infra.framework.file.core.utils.FileTypeUtils.writeAttachment;
|
||||||
|
|
||||||
|
|
@ -123,6 +122,15 @@ public class CodegenController {
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "批量删除数据库的表和字段定义")
|
||||||
|
@DeleteMapping("/delete-list")
|
||||||
|
@Parameter(name = "tableIds", description = "表编号列表", required = true)
|
||||||
|
@PreAuthorize("@ss.hasPermission('infra:codegen:delete')")
|
||||||
|
public CommonResult<Boolean> deleteCodegenList(@RequestParam("tableIds") List<Long> tableIds) {
|
||||||
|
codegenService.deleteCodegenList(tableIds);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
@Operation(summary = "预览生成代码")
|
@Operation(summary = "预览生成代码")
|
||||||
@GetMapping("/preview")
|
@GetMapping("/preview")
|
||||||
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
|
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,15 @@ public class ConfigController {
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/delete-list")
|
||||||
|
@Operation(summary = "批量删除参数配置")
|
||||||
|
@Parameter(name = "ids", description = "编号列表", required = true)
|
||||||
|
@PreAuthorize("@ss.hasPermission('infra:config:delete')")
|
||||||
|
public CommonResult<Boolean> deleteConfigList(@RequestParam("ids") List<Long> ids) {
|
||||||
|
configService.deleteConfigList(ids);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/get")
|
@GetMapping(value = "/get")
|
||||||
@Operation(summary = "获得参数配置")
|
@Operation(summary = "获得参数配置")
|
||||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
|
|
@ -92,7 +101,7 @@ public class ConfigController {
|
||||||
return success(ConfigConvert.INSTANCE.convertPage(page));
|
return success(ConfigConvert.INSTANCE.convertPage(page));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/export")
|
@GetMapping("/export-excel")
|
||||||
@Operation(summary = "导出参数配置")
|
@Operation(summary = "导出参数配置")
|
||||||
@PreAuthorize("@ss.hasPermission('infra:config:export')")
|
@PreAuthorize("@ss.hasPermission('infra:config:export')")
|
||||||
@ApiAccessLog(operateType = EXPORT)
|
@ApiAccessLog(operateType = EXPORT)
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,12 @@ import cn.iocoder.yudao.module.infra.service.db.DataSourceConfigService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.validation.Valid;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
|
@ -52,6 +52,15 @@ public class DataSourceConfigController {
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/delete-list")
|
||||||
|
@Operation(summary = "批量删除数据源配置")
|
||||||
|
@Parameter(name = "ids", description = "编号列表", required = true)
|
||||||
|
@PreAuthorize("@ss.hasPermission('infra:data-source-config:delete')")
|
||||||
|
public CommonResult<Boolean> deleteDataSourceConfigList(@RequestParam("ids") List<Long> ids) {
|
||||||
|
dataSourceConfigService.deleteDataSourceConfigList(ids);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/get")
|
@GetMapping("/get")
|
||||||
@Operation(summary = "获得数据源配置")
|
@Operation(summary = "获得数据源配置")
|
||||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import java.time.LocalDateTime;
|
||||||
public class DataSourceConfigRespVO {
|
public class DataSourceConfigRespVO {
|
||||||
|
|
||||||
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
private Integer id;
|
private Long id;
|
||||||
|
|
||||||
@Schema(description = "数据源名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "test")
|
@Schema(description = "数据源名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "test")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ public class Demo01ContactController {
|
||||||
@Operation(summary = "批量删除示例联系人")
|
@Operation(summary = "批量删除示例联系人")
|
||||||
@PreAuthorize("@ss.hasPermission('infra:demo01-contact:delete')")
|
@PreAuthorize("@ss.hasPermission('infra:demo01-contact:delete')")
|
||||||
public CommonResult<Boolean> deleteDemo0iContactList(@RequestParam("ids") List<Long> ids) {
|
public CommonResult<Boolean> deleteDemo0iContactList(@RequestParam("ids") List<Long> ids) {
|
||||||
demo01ContactService.deleteDemo0iContactListByIds(ids);
|
demo01ContactService.deleteDemo0iContactList(ids);
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,7 @@ public class Demo03StudentErpController {
|
||||||
@Operation(summary = "批量删除学生")
|
@Operation(summary = "批量删除学生")
|
||||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
|
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
|
||||||
public CommonResult<Boolean> deleteDemo03StudentList(@RequestParam("ids") List<Long> ids) {
|
public CommonResult<Boolean> deleteDemo03StudentList(@RequestParam("ids") List<Long> ids) {
|
||||||
// TODO @puhui999:deleteDemo03StudentList
|
demo03StudentErpService.deleteDemo03StudentList(ids);
|
||||||
demo03StudentErpService.deleteDemo03StudentListByIds(ids);
|
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -142,7 +141,7 @@ public class Demo03StudentErpController {
|
||||||
@Operation(summary = "批量删除学生课程")
|
@Operation(summary = "批量删除学生课程")
|
||||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
|
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
|
||||||
public CommonResult<Boolean> deleteDemo03CourseList(@RequestParam("ids") List<Long> ids) {
|
public CommonResult<Boolean> deleteDemo03CourseList(@RequestParam("ids") List<Long> ids) {
|
||||||
demo03StudentErpService.deleteDemo03CourseListByIds(ids);
|
demo03StudentErpService.deleteDemo03CourseList(ids);
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,7 +193,7 @@ public class Demo03StudentErpController {
|
||||||
@Operation(summary = "批量删除学生班级")
|
@Operation(summary = "批量删除学生班级")
|
||||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
|
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
|
||||||
public CommonResult<Boolean> deleteDemo03GradeList(@RequestParam("ids") List<Long> ids) {
|
public CommonResult<Boolean> deleteDemo03GradeList(@RequestParam("ids") List<Long> ids) {
|
||||||
demo03StudentErpService.deleteDemo03GradeListByIds(ids);
|
demo03StudentErpService.deleteDemo03GradeList(ids);
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ public class Demo03StudentInnerController {
|
||||||
@Operation(summary = "批量删除学生")
|
@Operation(summary = "批量删除学生")
|
||||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
|
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
|
||||||
public CommonResult<Boolean> deleteDemo03StudentList(@RequestParam("ids") List<Long> ids) {
|
public CommonResult<Boolean> deleteDemo03StudentList(@RequestParam("ids") List<Long> ids) {
|
||||||
demo03StudentInnerService.deleteDemo03StudentListByIds(ids);
|
demo03StudentInnerService.deleteDemo03StudentList(ids);
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ public class Demo03StudentNormalController {
|
||||||
@Operation(summary = "批量删除学生")
|
@Operation(summary = "批量删除学生")
|
||||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
|
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
|
||||||
public CommonResult<Boolean> deleteDemo03StudentList(@RequestParam("ids") List<Long> ids) {
|
public CommonResult<Boolean> deleteDemo03StudentList(@RequestParam("ids") List<Long> ids) {
|
||||||
demo03StudentNormalService.deleteDemo03StudentListByIds(ids);
|
demo03StudentNormalService.deleteDemo03StudentList(ids);
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,13 @@ import cn.iocoder.yudao.module.infra.service.file.FileConfigService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import java.util.List;
|
||||||
import javax.validation.Valid;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
|
@ -61,6 +62,15 @@ public class FileConfigController {
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/delete-list")
|
||||||
|
@Operation(summary = "批量删除文件配置")
|
||||||
|
@Parameter(name = "ids", description = "编号列表", required = true)
|
||||||
|
@PreAuthorize("@ss.hasPermission('infra:file-config:delete')")
|
||||||
|
public CommonResult<Boolean> deleteFileConfigList(@RequestParam("ids") List<Long> ids) {
|
||||||
|
fileConfigService.deleteFileConfigList(ids);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/get")
|
@GetMapping("/get")
|
||||||
@Operation(summary = "获得文件配置")
|
@Operation(summary = "获得文件配置")
|
||||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
import static cn.iocoder.yudao.module.infra.framework.file.core.utils.FileTypeUtils.writeAttachment;
|
import static cn.iocoder.yudao.module.infra.framework.file.core.utils.FileTypeUtils.writeAttachment;
|
||||||
|
|
||||||
|
|
@ -75,6 +77,15 @@ public class FileController {
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/delete-list")
|
||||||
|
@Operation(summary = "批量删除文件")
|
||||||
|
@Parameter(name = "ids", description = "编号列表", required = true)
|
||||||
|
@PreAuthorize("@ss.hasPermission('infra:file:delete')")
|
||||||
|
public CommonResult<Boolean> deleteFileList(@RequestParam("ids") List<Long> ids) throws Exception {
|
||||||
|
fileService.deleteFileList(ids);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/{configId}/get/**")
|
@GetMapping("/{configId}/get/**")
|
||||||
@PermitAll
|
@PermitAll
|
||||||
@TenantIgnore
|
@TenantIgnore
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file;
|
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.AssertTrue;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 上传文件 Request VO")
|
@Schema(description = "管理后台 - 上传文件 Request VO")
|
||||||
@Data
|
@Data
|
||||||
public class FileUploadReqVO {
|
public class FileUploadReqVO {
|
||||||
|
|
@ -17,4 +19,10 @@ public class FileUploadReqVO {
|
||||||
@Schema(description = "文件目录", example = "XXX/YYY")
|
@Schema(description = "文件目录", example = "XXX/YYY")
|
||||||
private String directory;
|
private String directory;
|
||||||
|
|
||||||
|
@AssertTrue(message = "文件目录不正确")
|
||||||
|
@JsonIgnore
|
||||||
|
public boolean isDirectoryValid() {
|
||||||
|
return !StrUtil.containsAny(directory, "..", "/", "\\");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
package cn.iocoder.yudao.module.infra.controller.admin.job;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
|
|
||||||
|
|
||||||
@Tag(name = "管理后台 - 定时任务")
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/infra/job")
|
|
||||||
@Validated
|
|
||||||
public class JobController {
|
|
||||||
|
|
||||||
@GetMapping("/page")
|
|
||||||
@Operation(summary = "获得定时任务分页")
|
|
||||||
@PreAuthorize("@ss.hasPermission('infra:job:query')")
|
|
||||||
public CommonResult<String> getJobPage() {
|
|
||||||
return error(-1, "Cloud 版本使用 XXL-Job 作为定时任务!请参考 https://cloud.iocoder.cn/job/ 文档操作");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
package cn.iocoder.yudao.module.infra.controller.app.file.vo;
|
package cn.iocoder.yudao.module.infra.controller.app.file.vo;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.AssertTrue;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
@Schema(description = "用户 App - 上传文件 Request VO")
|
@Schema(description = "用户 App - 上传文件 Request VO")
|
||||||
@Data
|
@Data
|
||||||
public class AppFileUploadReqVO {
|
public class AppFileUploadReqVO {
|
||||||
|
|
@ -17,4 +19,10 @@ public class AppFileUploadReqVO {
|
||||||
@Schema(description = "文件目录", example = "XXX/YYY")
|
@Schema(description = "文件目录", example = "XXX/YYY")
|
||||||
private String directory;
|
private String directory;
|
||||||
|
|
||||||
|
@AssertTrue(message = "文件目录不正确")
|
||||||
|
@JsonIgnore
|
||||||
|
public boolean isDirectoryValid() {
|
||||||
|
return !StrUtil.containsAny(directory, "..", "/", "\\");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
|
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
|
|
@ -17,8 +18,12 @@ public interface CodegenColumnMapper extends BaseMapperX<CodegenColumnDO> {
|
||||||
}
|
}
|
||||||
|
|
||||||
default void deleteListByTableId(Long tableId) {
|
default void deleteListByTableId(Long tableId) {
|
||||||
|
delete(CodegenColumnDO::getTableId, tableId);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void deleteListByTableId(Collection<Long> tableIds) {
|
||||||
delete(new LambdaQueryWrapperX<CodegenColumnDO>()
|
delete(new LambdaQueryWrapperX<CodegenColumnDO>()
|
||||||
.eq(CodegenColumnDO::getTableId, tableId));
|
.in(CodegenColumnDO::getTableId, tableIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue