From 1305b2f13e256681c62203fa2b8b8870d4e4be28 Mon Sep 17 00:00:00 2001 From: huangdehua <2329023417@qq.com> Date: Tue, 11 Aug 2026 18:07:00 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E4=BC=9A=E5=91=98=E5=8F=98=E6=9B=B4?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E6=97=B6=E9=87=8D=E6=96=B0=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=8D=95=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../association/plugin/member/UnitNameChangeFormInitPlugin.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/common/common-association/src/main/java/apelet/association/plugin/member/UnitNameChangeFormInitPlugin.java b/common/common-association/src/main/java/apelet/association/plugin/member/UnitNameChangeFormInitPlugin.java index 2d9dd7c..e9781c8 100644 --- a/common/common-association/src/main/java/apelet/association/plugin/member/UnitNameChangeFormInitPlugin.java +++ b/common/common-association/src/main/java/apelet/association/plugin/member/UnitNameChangeFormInitPlugin.java @@ -6,6 +6,7 @@ import apelet.common.generator.utils.OrmGenDataSourceUtil; import apelet.common.online.abstractplugin.ExecutePluginParent; import apelet.common.online.model.constant.AttributeEnum; import com.alibaba.fastjson.JSONObject; +import org.apache.commons.lang3.StringUtils; import java.util.HashMap; import java.util.List; @@ -98,6 +99,7 @@ public class UnitNameChangeFormInitPlugin extends ExecutePluginParent { // 获取源单据ID String sourceBillId = getSourceBillId(objectValue); String sourceBillNumber = getSourceBillNumber(objectValue); + this.setWidgetAttribute("history",AttributeEnum.VALUE_CHANGE, "0"); // 如果没有源单据ID,说明不是变更操作,正常返回 if (sourceBillId == null || sourceBillId.isEmpty()) { @@ -147,6 +149,10 @@ public class UnitNameChangeFormInitPlugin extends ExecutePluginParent { if (sourceBillId == null || sourceBillId.trim().isEmpty()) { sourceBillId = objectValue.getString(PARAM_BILL_ID_ALT); } + Object idObj = objectValue.get("id"); + if (idObj != null && !Integer.valueOf(0).equals(idObj)) { + return false; + } return sourceBillId != null && !sourceBillId.trim().isEmpty(); } @@ -166,6 +172,7 @@ public class UnitNameChangeFormInitPlugin extends ExecutePluginParent { } newBill.put(getDbFieldKey(key), entry.getValue()); } + newBill.put("history", "0"); ObjectCollection detailEntry = copyEntryForManualSave(objectValue.getObjectCollection(CHILD_WIDGET_KEY)); if (detailEntry != null && !detailEntry.isEmpty()) { From 37a31d6f4c68e06feb2fc875fe4dc3be761c6d3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BD=8A?= <23> Date: Thu, 13 Aug 2026 11:14:32 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application-tenant/tenant-admin/pom.xml | 4 +- .../java/apelet/tenantadmin/config/CorsConfig.java | 16 +++ .../upms/controller/LoginController.java | 30 ++---- .../src/main/resources/application-config.yml | 2 +- .../src/main/resources/tenant-admin-dev.yml | 8 +- common/common-association/pom.xml | 6 +- .../apelet/association/config/FrontendConfig.java | 16 +++ .../controller/DoPracticeProblemsController.java | 21 +++- .../association/controller/HomeController.java | 71 +++++++++++++ .../apelet/association/dto/UserExerciseDto.java | 12 +-- .../plugin/active/ActivityInfoDetailsPlugin.java | 110 +++++++++++++++++++++ .../active/ActivityRegistrationSavePlugin.java | 15 +++ .../active/ActivityRegistrationUpdatePlugin.java | 98 ++++++++++++++++++ .../plugin/active/ActivitySignConfigPlugin.java | 16 +-- .../plugin/active/CompetitionDetailsPlugin.java | 7 +- .../plugin/member/MembershipFeePayPlugin.java | 72 ++++++++++++++ .../plugin/member/MembershipPayPopupPlugin.java | 29 +++--- .../plugin/member/UnitNameChangePopupPlugin.java | 25 +++++ .../plugin/question/QuestionBankListPlugin.java | 6 +- .../task/ContractPaymentReminderTask.java | 30 ++++++ .../association/task/UserRenewalReminderTask.java | 68 ++++++------- common/common-qy/pom.xml | 4 +- pom.xml | 2 +- 23 files changed, 559 insertions(+), 109 deletions(-) create mode 100644 application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/config/CorsConfig.java create mode 100644 common/common-association/src/main/java/apelet/association/config/FrontendConfig.java create mode 100644 common/common-association/src/main/java/apelet/association/controller/HomeController.java create mode 100644 common/common-association/src/main/java/apelet/association/plugin/active/ActivityInfoDetailsPlugin.java create mode 100644 common/common-association/src/main/java/apelet/association/plugin/active/ActivityRegistrationSavePlugin.java create mode 100644 common/common-association/src/main/java/apelet/association/plugin/active/ActivityRegistrationUpdatePlugin.java create mode 100644 common/common-association/src/main/java/apelet/association/plugin/member/MembershipFeePayPlugin.java create mode 100644 common/common-association/src/main/java/apelet/association/task/ContractPaymentReminderTask.java diff --git a/application-tenant/tenant-admin/pom.xml b/application-tenant/tenant-admin/pom.xml index eb54156..b2ab632 100644 --- a/application-tenant/tenant-admin/pom.xml +++ b/application-tenant/tenant-admin/pom.xml @@ -84,7 +84,7 @@ apelet common-online - 1.0.0 + 1.0.3 apelet @@ -140,7 +140,7 @@ apelet common-orm - 1.0.0 + 1.0.2 apelet diff --git a/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/config/CorsConfig.java b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/config/CorsConfig.java new file mode 100644 index 0000000..0fc7bd5 --- /dev/null +++ b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/config/CorsConfig.java @@ -0,0 +1,16 @@ +package apelet.tenantadmin.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class CorsConfig implements WebMvcConfigurer { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") // 允许所有源 + .allowedMethods("*") // 允许所有请求方法 + .allowedHeaders("*"); // 允许所有请求头 + } +} diff --git a/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/controller/LoginController.java b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/controller/LoginController.java index 9516e0e..970b03b 100644 --- a/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/controller/LoginController.java +++ b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/controller/LoginController.java @@ -1144,33 +1144,15 @@ public class LoginController { String sessionId = user.getLoginName() + "_" + deviceType + "_" + MyCommonUtil.generateUuid(); JSONObject jsonData = this.createResponseData(user, sessionId); TokenData tokenData = this.buildTokenData(user, sessionId, deviceType); - String zwcjName = null; - try { - String result = (String)EasUtil.executeOsfServiceWs("com.kingdee.shr.custom.plat.osf.service.GetPersonalDataService" - ,user.getLoginName(),new HashMap()); - JSONObject personData = JSONObject.parseObject(result); - tokenData.setPersonId((String) personData.get("personId")); - jsonData.put("personData", JSONObject.parseObject(result)); - zwcjName = (String)personData.get("zwcjName"); - }catch(Exception e) { - e.printStackTrace(); - throw new RuntimeException(e); - } this.putTokenDataToSessionCache(tokenData); // 这里手动将TokenData存入request,便于OperationLogAspect统一处理操作日志。 TokenData.addToRequest(tokenData); List mobileEntryList; - String roleId = getShrRole(zwcjName); - if(!StringUtils.isEmpty(roleId)){ - mobileEntryList = mobileEntryService.getMobileEntryListByRoleIds(roleId); - }else{ - if (isAdmin) { - mobileEntryList = mobileEntryService.getAllListByOrder(SHOW_ORDER_FIELD); - } else { - mobileEntryList = mobileEntryService.getMobileEntryListByRoleIds(tokenData.getRoleIds()); - } + if (isAdmin) { + mobileEntryList = mobileEntryService.getAllListByOrder(SHOW_ORDER_FIELD); + } else { + mobileEntryList = mobileEntryService.getMobileEntryListByRoleIds(tokenData.getRoleIds()); } - jsonData.put("mobileEntryList", mobileEntryList); Set permSet = new HashSet<>(); if (!isAdmin) { @@ -1205,8 +1187,6 @@ public class LoginController { sysPermService.putUserSysPermCache(sessionId, user.getUserId(), permSet); sysDataPermService.putDataPermCache(sessionId, user.getUserId(), user.getDeptId()); } - - return jsonData; } @@ -1552,4 +1532,6 @@ public class LoginController { private List permCodeList; private List permList; } + + } diff --git a/application-tenant/tenant-admin/src/main/resources/application-config.yml b/application-tenant/tenant-admin/src/main/resources/application-config.yml index f753b89..f0748e1 100644 --- a/application-tenant/tenant-admin/src/main/resources/application-config.yml +++ b/application-tenant/tenant-admin/src/main/resources/application-config.yml @@ -92,7 +92,7 @@ aliyun: accessKey: LTAI5t5fEgzRRtdmBvczVS6r secretKey: uESFiyyi6EwCkM5w4a4pbx6TmVhqgx bucketName: yy-test12 - + nginxOssUrl: minio: enabled: false diff --git a/application-tenant/tenant-admin/src/main/resources/tenant-admin-dev.yml b/application-tenant/tenant-admin/src/main/resources/tenant-admin-dev.yml index d622b1e..0ff9796 100644 --- a/application-tenant/tenant-admin/src/main/resources/tenant-admin-dev.yml +++ b/application-tenant/tenant-admin/src/main/resources/tenant-admin-dev.yml @@ -218,9 +218,9 @@ spring: password: X7&9p8L2@6z4K7!8 driverClassName: com.mysql.cj.jdbc.Driver name: tenant-admin - initialSize: 10 - minIdle: 10 - maxActive: 50 + initialSize: 5 + minIdle: 5 + maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 @@ -229,7 +229,7 @@ spring: maxOpenPreparedStatements: 20 validationQuery: SELECT 'x' testWhileIdle: true - testOnBorrow: false + testOnBorrow: true testOnReturn: false connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 filters: stat,wall diff --git a/common/common-association/pom.xml b/common/common-association/pom.xml index 8740d9b..e97366e 100644 --- a/common/common-association/pom.xml +++ b/common/common-association/pom.xml @@ -42,17 +42,17 @@ apelet common-generator - 1.0.0 + 1.0.2 apelet common-online - 1.0.0 + 1.0.3 common-orm apelet - 1.0.0 + 1.0.2 common-msg-notice diff --git a/common/common-association/src/main/java/apelet/association/config/FrontendConfig.java b/common/common-association/src/main/java/apelet/association/config/FrontendConfig.java new file mode 100644 index 0000000..74b3a6e --- /dev/null +++ b/common/common-association/src/main/java/apelet/association/config/FrontendConfig.java @@ -0,0 +1,16 @@ +package apelet.association.config; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +@Configuration +@Data +public class FrontendConfig { + +// @Value("${frontend.address}") + public String address; + + +} + diff --git a/common/common-association/src/main/java/apelet/association/controller/DoPracticeProblemsController.java b/common/common-association/src/main/java/apelet/association/controller/DoPracticeProblemsController.java index 4b73ddd..03412dc 100644 --- a/common/common-association/src/main/java/apelet/association/controller/DoPracticeProblemsController.java +++ b/common/common-association/src/main/java/apelet/association/controller/DoPracticeProblemsController.java @@ -74,8 +74,10 @@ public class DoPracticeProblemsController { long batchNumber = IdUtil.getSnowflakeNextId(); result.put("batchNumber", batchNumber); - collection.forEach(f -> { - ObjectValue examQuestions = f.getObjectValue("exam_questions_id"); + for (int i = 0; i < collection.size(); i++) { + ObjectValue object = collection.getObject(i); + + ObjectValue examQuestions = object.getObjectValue("exam_questions_id"); list.add(examQuestions.getString("id")); ObjectValue userExercise = new ObjectValue("user_exercise"); @@ -92,7 +94,9 @@ public class DoPracticeProblemsController { } catch (Exception e) { throw new RuntimeException(e); } - }); + + } + List> examQuestionsList = new ArrayList<>(); result.put("examQuestionsList", examQuestionsList); @@ -101,7 +105,9 @@ public class DoPracticeProblemsController { filter.add(new FilterItem("type", FilterItem.not_equals, 4)); ObjectCollection examQuestions = ormGenDataSourceUtil.query("exam_questions", filter, new Selector()); int no = 1; - for (ObjectValue examQuestion : examQuestions) { + for (int i = 0; i < examQuestions.size(); i++) { + ObjectValue examQuestion = examQuestions.getObject(i); + Map hashMap = new HashMap<>(); hashMap.put("id", examQuestion.getString("id")); hashMap.put("no", no); @@ -118,11 +124,16 @@ public class DoPracticeProblemsController { hashMap.put("difficulty", examQuestion.getString("difficulty")); ObjectCollection examQuestionsEntry = examQuestion.getObjectCollection("exam_questions_entry"); List> option = new ArrayList<>(); - examQuestionsEntry.forEach(f -> option.add(f.getValues())); + for (int i1 = 0; i1 < examQuestionsEntry.size(); i1++) { + ObjectValue object = examQuestionsEntry.getObject(i1); + option.add(object.getValues()); + } hashMap.put("options", option); examQuestionsList.add(hashMap); no++; + } + return ResponseResult.success(result); } diff --git a/common/common-association/src/main/java/apelet/association/controller/HomeController.java b/common/common-association/src/main/java/apelet/association/controller/HomeController.java new file mode 100644 index 0000000..794bb3b --- /dev/null +++ b/common/common-association/src/main/java/apelet/association/controller/HomeController.java @@ -0,0 +1,71 @@ +package apelet.association.controller; + +import apelet.common.core.object.ObjectCollection; +import apelet.common.core.object.ResponseResult; +import apelet.common.generator.utils.OrmGenDataSourceUtil; +import apelet.common.orm.impl.Filter; +import apelet.common.orm.impl.FilterItem; +import apelet.common.orm.impl.Selector; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + + +/** + * 课程管理 + */ +@RestController +@RequestMapping("/tenantadmin/home") +public class HomeController { + + @Autowired + private OrmGenDataSourceUtil ormGenDataSourceUtil; + + @PostMapping("/homeData") + public ResponseResult homeData() { + HashMap map = new HashMap<>(); + //报名审核 + map.put("ApplicationReview", 0); + + //会费逾期 + ObjectCollection feePay = ormGenDataSourceUtil.query("membership_fee_pay", new Filter(), new Selector()); + ArrayList objects = new ArrayList<>(); + for (int i = 0; i < feePay.size(); i++) { + objects.add(feePay.getObject(i).getValues()); + } + Map> parentMap = objects.stream().collect(Collectors.groupingBy(m -> m.get("parent_id"))); + AtomicInteger OverdueMembershipFees = new AtomicInteger(); + parentMap.forEach((k, v) -> { + // 是否存在任意一条 end_time > 当前时间 + boolean anyAfterNow = v.stream() + .anyMatch(m2 -> { + Object endTimeObj = m2.get("end_time"); + if(endTimeObj == null){ + return false; + } + Date endTime = (Date) endTimeObj; + // end_time > 当前时间 + return endTime.after(new Date()); + }); + if(anyAfterNow){ + OverdueMembershipFees.getAndIncrement(); + } + + }); + map.put("OverdueMembershipFees", OverdueMembershipFees.get()); + + + // 入会申请 + Filter filter = new Filter(); + filter.add(new FilterItem("billstatus", FilterItem.not_equals, "C")); + ObjectCollection membershipApply = ormGenDataSourceUtil.query("membership_apply", filter, new Selector()); + map.put("MembershipApplication", membershipApply.size()); + + return ResponseResult.success(map); + } + + +} diff --git a/common/common-association/src/main/java/apelet/association/dto/UserExerciseDto.java b/common/common-association/src/main/java/apelet/association/dto/UserExerciseDto.java index 816a5ae..812ed28 100644 --- a/common/common-association/src/main/java/apelet/association/dto/UserExerciseDto.java +++ b/common/common-association/src/main/java/apelet/association/dto/UserExerciseDto.java @@ -1,19 +1,19 @@ package apelet.association.dto; -import apelet.association.model.UserExercise; +import apelet.association.model.*; import lombok.Data; import org.flowable.spring.security.UserDto; import java.util.List; @Data -public class UserExerciseDto { +public class UserExerciseDto extends ExamQuestions { - // 考试id - Long examId; + // 考试 + Exam exam; - // 题库id - Long questionBankId; + // 题库 + QuestionBank questionBank; // 答题用户id Long userId; diff --git a/common/common-association/src/main/java/apelet/association/plugin/active/ActivityInfoDetailsPlugin.java b/common/common-association/src/main/java/apelet/association/plugin/active/ActivityInfoDetailsPlugin.java new file mode 100644 index 0000000..e3736ec --- /dev/null +++ b/common/common-association/src/main/java/apelet/association/plugin/active/ActivityInfoDetailsPlugin.java @@ -0,0 +1,110 @@ +package apelet.association.plugin.active; + +import apelet.association.utils.MyFileUtil; +import apelet.association.utils.QRCodeUtil; +import apelet.common.core.exception.MyRuntimeException; +import apelet.common.core.object.ObjectValue; +import apelet.common.core.upload.UploadResponseInfo; +import apelet.common.core.util.ApplicationContextHolder; +import apelet.common.core.util.RsaUtil; +import apelet.common.generator.utils.OrmGenDataSourceUtil; +import apelet.common.online.abstractplugin.ListPlugin; +import apelet.common.online.dto.OnlineEventPluginExecuteDto; +import apelet.common.online.model.OnlineDatasource; +import apelet.common.online.model.OnlineTable; +import apelet.common.online.model.constant.AttributeEnum; +import apelet.common.online.service.OnlineDatasourceService; +import apelet.common.online.service.OnlineTableService; +import apelet.common.orm.impl.FilterItem; +import apelet.common.orm.impl.Selector; +import apelet.common.orm.impl.SelectorItem; +import cn.hutool.core.bean.BeanUtil; +import com.alibaba.fastjson.JSONObject; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * 活动详情 + */ +public class ActivityInfoDetailsPlugin extends ListPlugin { + + + private final OrmGenDataSourceUtil ormGenDataSourceUtil; + private final MyFileUtil myFileUtil; + private final QRCodeUtil qrCodeUtil; + private final OnlineDatasourceService onlineDatasourceService; + private final OnlineTableService onlineTableService; + + + public ActivityInfoDetailsPlugin() { + myFileUtil = ApplicationContextHolder.getBean(MyFileUtil.class); + qrCodeUtil = ApplicationContextHolder.getBean(QRCodeUtil.class); + ormGenDataSourceUtil = ApplicationContextHolder.getBean(OrmGenDataSourceUtil.class); + onlineDatasourceService = ApplicationContextHolder.getBean(OnlineDatasourceService.class); + onlineTableService = ApplicationContextHolder.getBean(OnlineTableService.class); + } + + + @Override + public void formCreated(String widgetVariableName, ObjectValue objectValue) { + this.setWidgetAttribute("id", AttributeEnum.SHOW, false); + + } + + @Override + public void change(String widgetVariableName, ObjectValue objectValue) { + + } + + @Override + public void buttonTriggered(String widgetVariableName, ObjectValue objectValue) { + if (widgetVariableName.equals("button1786587153460")) { + String registrationQr = objectValue.getString("registration_qr"); + if(StringUtils.isNotEmpty(registrationQr)){ + this.showErrorMessage("当前已存在报名二维码, 请勿重复生成!!!"); + return; + } + OnlineEventPluginExecuteDto dto = getDto(); + String savePath = System.getProperty("user.dir") + "\\zz-resource\\qrcode"; + File QRFile = null; + try { + OnlineDatasource onlineDatasource = onlineDatasourceService.getById(dto.getModel().getDatasourceId()); + OnlineTable table = onlineTableService.getOnlineTableFromCache(onlineDatasource.getMasterTableId()); + // 生成 报名二维码 + long id = objectValue.getLong("id"); + + String url = "http://58.48.135.5:8069" + "/#/?" + + "loginName=" + "admin" + + "&password=" + "123456" + + "&entryId=" + "2087413611113746432" + + "&bindType=" + "1" + + "&onlineFormId=" + "2087385700075835392" + + "&activeId=" + id; + + byte[] checkInQr = qrCodeUtil.generateQrCode(url, 350, 350); + QRFile = MyFileUtil.writeToFile(checkInQr, savePath, "qrcode-" + System.currentTimeMillis() + ".png"); + MultipartFile checkInMultipart = MyFileUtil.readFileAsMultipartFile(QRFile, "image/png"); + UploadResponseInfo registrationQR = myFileUtil.uploadMyFile(table, "registration_qr", true, checkInMultipart); + this.setWidgetAttribute("registrationQr", AttributeEnum.VALUE_CHANGE, registrationQR); + + objectValue.put("registration_qr", "["+new JSONObject(BeanUtil.beanToMap(registrationQR)).toJSONString()+"]"); + Selector selector = new Selector(); + selector.getList().add(new SelectorItem("registration_qr")); + ormGenDataSourceUtil.update(objectValue.getTableName(), objectValue, selector); + + } catch (Exception e) { + throw new MyRuntimeException(e.getMessage()); + } finally { + QRFile.delete(); + } + + + } + } +} diff --git a/common/common-association/src/main/java/apelet/association/plugin/active/ActivityRegistrationSavePlugin.java b/common/common-association/src/main/java/apelet/association/plugin/active/ActivityRegistrationSavePlugin.java new file mode 100644 index 0000000..3999fc7 --- /dev/null +++ b/common/common-association/src/main/java/apelet/association/plugin/active/ActivityRegistrationSavePlugin.java @@ -0,0 +1,15 @@ +package apelet.association.plugin.active; + +import apelet.common.core.object.ObjectValue; +import apelet.common.online.plugin.EndOperationTransactionArgs; +import apelet.common.online.plugin.OperationServicePlugIn; + +public class ActivityRegistrationSavePlugin extends OperationServicePlugIn { + + + @Override + public void endOperationTransaction(EndOperationTransactionArgs e) { + ObjectValue objectValue = e.getModel(); + + } +} diff --git a/common/common-association/src/main/java/apelet/association/plugin/active/ActivityRegistrationUpdatePlugin.java b/common/common-association/src/main/java/apelet/association/plugin/active/ActivityRegistrationUpdatePlugin.java new file mode 100644 index 0000000..389ce54 --- /dev/null +++ b/common/common-association/src/main/java/apelet/association/plugin/active/ActivityRegistrationUpdatePlugin.java @@ -0,0 +1,98 @@ +package apelet.association.plugin.active; + +import apelet.common.core.exception.MyRuntimeException; +import apelet.common.core.object.ObjectCollection; +import apelet.common.core.object.ObjectValue; +import apelet.common.core.util.ApplicationContextHolder; +import apelet.common.generator.utils.OrmGenDataSourceUtil; +import apelet.common.online.abstractplugin.ListPlugin; +import apelet.common.online.dto.OnlineEventPluginExecuteDto; +import apelet.common.online.model.constant.AttributeEnum; +import apelet.common.online.plugin.EndOperationTransactionArgs; +import apelet.common.online.plugin.OperationServicePlugIn; +import apelet.common.orm.impl.Filter; +import apelet.common.orm.impl.FilterItem; +import apelet.common.orm.impl.Selector; +import com.alibaba.fastjson.JSONObject; + +public class ActivityRegistrationUpdatePlugin extends ListPlugin { + + private OrmGenDataSourceUtil ormGenDataSourceUtil; + + public ActivityRegistrationUpdatePlugin() { + + ormGenDataSourceUtil = ApplicationContextHolder.getBean(OrmGenDataSourceUtil.class); + } + + @Override + public void formCreated(String widgetVariableName, ObjectValue objectValue) { + + setWidgetAttribute("id", AttributeEnum.SHOW, false); + + JSONObject eventparams = JSONObject.parseObject(objectValue.getString("eventparams")); + JSONObject jsonObject = eventparams.getJSONObject("urlParams"); + String activeId = jsonObject.getString("activeId"); + if(activeId == null){ + throw new MyRuntimeException("活动id不能为空"); + } + ObjectValue active = ormGenDataSourceUtil.queryOne("association_activity", activeId); + + this.setWidgetAttribute("name", AttributeEnum.VALUE_CHANGE, active.get("name")); + this.setWidgetAttribute("startDate", AttributeEnum.VALUE_CHANGE, active.get("start_time")); + this.setWidgetAttribute("endDate", AttributeEnum.VALUE_CHANGE, active.get("end_time")); + + this.setWidgetAttribute("parentId", AttributeEnum.VALUE_CHANGE, active.get("id")); + this.setWidgetAttribute("parentId", AttributeEnum.SHOW, false); + + } + + + @Override + public void buttonTriggered(String widgetVariableName, ObjectValue objectValue) { + + String unitName = objectValue.getString("unit_name"); + String person = objectValue.getString("person"); + String phone = objectValue.getString("phone"); + String parentId = objectValue.getString("parent_id"); + + Filter filter1 = new Filter(); + filter1.add(new FilterItem("unit_name", FilterItem.equals, unitName)); + filter1.add(new FilterItem("person", FilterItem.equals, person)); + filter1.add(new FilterItem("phone", FilterItem.equals, phone)); + filter1.add(new FilterItem("parent_id", FilterItem.equals, parentId)); + ObjectCollection collection = ormGenDataSourceUtil.query("activity_register", filter1, new Selector()); + if(!collection.isEmpty()){ + this.showWarningMessage("当前单位联系人已报名成功, 请勿重复提交!!!"); + this.cancelOperate(); + return; + } + ObjectValue activityRegister = new ObjectValue("activity_register"); + activityRegister.put("unit_name", unitName); + activityRegister.put("person", person); + activityRegister.put("phone", phone); + activityRegister.put("parent_id", parentId); + + Filter filter = new Filter(); + filter.add(new FilterItem("unit_name", FilterItem.equals, unitName)); + ObjectCollection membershipApplyList = ormGenDataSourceUtil.query("membership_apply", filter, new Selector()); + + filter = new Filter(); + filter.add(new FilterItem("name", FilterItem.equals, person)); + ObjectCollection expertManageList = ormGenDataSourceUtil.query("expert_manage", filter, new Selector()); + + if(membershipApplyList != null && !membershipApplyList.isEmpty()){ + ObjectValue object = membershipApplyList.getObject(0); + activityRegister.put("membership_apply_id", object); + }else if(expertManageList != null && !expertManageList.isEmpty()){ + ObjectValue object = expertManageList.getObject(0); + activityRegister.put("expert_manage_id", object); + } + try { + ormGenDataSourceUtil.addNew(activityRegister.getTableName(), activityRegister); + } catch (Exception e) { + throw new MyRuntimeException(e.getMessage()); + } + this.showMessage("保存成功"); + this.cancelOperate(); + } +} diff --git a/common/common-association/src/main/java/apelet/association/plugin/active/ActivitySignConfigPlugin.java b/common/common-association/src/main/java/apelet/association/plugin/active/ActivitySignConfigPlugin.java index 65817b9..73d6f9a 100644 --- a/common/common-association/src/main/java/apelet/association/plugin/active/ActivitySignConfigPlugin.java +++ b/common/common-association/src/main/java/apelet/association/plugin/active/ActivitySignConfigPlugin.java @@ -36,6 +36,8 @@ import java.util.Map; @Slf4j public class ActivitySignConfigPlugin extends ListPlugin { + private final String url = "http://58.48.135.5:8069"; + private final MyFileUtil myFileUtil; private final QRCodeUtil qrCodeUtil; @@ -100,11 +102,11 @@ public class ActivitySignConfigPlugin extends ListPlugin { Model model = dto.getModel(); if ("button1778742711763".equals(widgetVariableName)) { -// if (StringUtils.isNotBlank(objectValue.getString("sign_in_code")) && -// StringUtils.isNotBlank(objectValue.getString("sign_out_code"))) { -// showWarningMessage("当前已存在二维码, 请勿重复生产!!!"); -// return; -// } + if (StringUtils.isNotBlank(objectValue.getString("sign_in_code")) && + StringUtils.isNotBlank(objectValue.getString("sign_out_code"))) { + showWarningMessage("当前已存在二维码, 请勿重复生产!!!"); + return; + } // 生成二维码 String savePath = System.getProperty("user.dir") + "\\zz-resource\\qrcode"; @@ -117,14 +119,14 @@ public class ActivitySignConfigPlugin extends ListPlugin { OnlineDatasource onlineDatasource = onlineDatasourceService.getById(model.getDatasourceId()); OnlineTable table = onlineTableService.getOnlineTableFromCache(onlineDatasource.getMasterTableId()); - String checkIn = "http://192.168.100.22:8080/#/pages/login/routerHdView?activityId=" + activityId + "&activityName=" + activityName + "&type=" + 1; + String checkIn = url + "/#/pages/login/routerHdView?activityId=" + activityId + "&activityName=" + activityName + "&type=" + 1; byte[] checkInQr = qrCodeUtil.generateQrCode(checkIn, 350, 350); checkInFile = MyFileUtil.writeToFile(checkInQr, savePath, "qrcode-" + System.currentTimeMillis() + ".png"); MultipartFile checkInMultipart = MyFileUtil.readFileAsMultipartFile(checkInFile, "image/png"); UploadResponseInfo checkInUpload = myFileUtil.uploadMyFile(table, "sign_in_code", true, checkInMultipart); this.setWidgetAttribute("signInCode", AttributeEnum.VALUE_CHANGE, checkInUpload); - String checkOut = "http://192.168.100.22:8080/#/pages/login/routerHdView?activityId=" + activityId + "&activityName=" + activityName + "&type=" + 2; + String checkOut = url + "#/pages/login/routerHdView?activityId=" + activityId + "&activityName=" + activityName + "&type=" + 2; byte[] checkOutQr = qrCodeUtil.generateQrCode(checkOut, 300, 300); checkOutFile = MyFileUtil.writeToFile(checkOutQr, savePath, "qrcode-" + System.currentTimeMillis() + ".png"); MultipartFile checkOutMultipart = MyFileUtil.readFileAsMultipartFile(checkOutFile, "image/png"); diff --git a/common/common-association/src/main/java/apelet/association/plugin/active/CompetitionDetailsPlugin.java b/common/common-association/src/main/java/apelet/association/plugin/active/CompetitionDetailsPlugin.java index 3718f70..2b9f304 100644 --- a/common/common-association/src/main/java/apelet/association/plugin/active/CompetitionDetailsPlugin.java +++ b/common/common-association/src/main/java/apelet/association/plugin/active/CompetitionDetailsPlugin.java @@ -30,9 +30,10 @@ public class CompetitionDetailsPlugin extends ListPlugin { filter.add(new FilterItem("association_activity_id",FilterItem.equals, objectValue.get("id"))); ObjectCollection collection = ormGenDataSourceUtil.query("competition_entries", filter, new Selector()); JSONArray jsonArray = new JSONArray(); - collection.forEach(f -> { - jsonArray.add(f.getValues()); - }); + for (int i = 0; i < collection.size(); i++) { + jsonArray.add(collection.getObject(i).getValues()); + } + setWidgetAttribute("table1783059589608", AttributeEnum.ADD_ROWS, jsonArray); } diff --git a/common/common-association/src/main/java/apelet/association/plugin/member/MembershipFeePayPlugin.java b/common/common-association/src/main/java/apelet/association/plugin/member/MembershipFeePayPlugin.java new file mode 100644 index 0000000..1982e84 --- /dev/null +++ b/common/common-association/src/main/java/apelet/association/plugin/member/MembershipFeePayPlugin.java @@ -0,0 +1,72 @@ +package apelet.association.plugin.member; + +import apelet.common.core.exception.MyRuntimeException; +import apelet.common.core.object.ObjectCollection; +import apelet.common.core.object.ObjectValue; +import apelet.common.core.util.ApplicationContextHolder; +import apelet.common.generator.utils.OrmGenDataSourceUtil; +import apelet.common.online.abstractplugin.ExecutePluginParent; +import apelet.common.online.dto.OnlineEventPluginExecuteDto; +import apelet.common.online.model.ShowParameter; +import apelet.common.online.model.constant.AttributeEnum; +import apelet.common.online.model.constant.ShowTypeEnum; +import apelet.common.online.model.constant.ViewStatus; +import apelet.common.orm.impl.Filter; +import apelet.common.orm.impl.FilterItem; +import apelet.common.orm.impl.Selector; + +import java.sql.Date; +import java.util.HashMap; +import java.util.Map; + + +public class MembershipFeePayPlugin extends ExecutePluginParent { + + private OrmGenDataSourceUtil ormGenDataSourceUtil; + + public MembershipFeePayPlugin(){ + ormGenDataSourceUtil = ApplicationContextHolder.getBean(OrmGenDataSourceUtil.class); + } + + @Override + public void formCreated(String widgetVariableName, ObjectValue objectValue) { + super.formCreated(widgetVariableName, objectValue); + OnlineEventPluginExecuteDto dto = getDto(); + Map eventParams = dto.getEventParams(); + if (eventParams != null) { + this.setWidgetAttribute("parentId", AttributeEnum.VALUE_CHANGE, eventParams.get("id")); + this.setWidgetAttribute("parentId", AttributeEnum.SHOW, false); + + this.setWidgetAttribute("membershipDate", AttributeEnum.VALUE_CHANGE, eventParams.get("create_time")); + this.setWidgetAttribute("membershipType", AttributeEnum.VALUE_CHANGE, eventParams.get("membership_type")); + } + + } + + @Override + public void buttonTriggered(String widgetVariableName, ObjectValue objectValue) { + if(widgetVariableName.equals("保存")){ + String parentId = objectValue.getString("parent_id"); + + Date startTime1= objectValue.getDate("membership_date"); + Date endTime1 = objectValue.getDate("end_time"); + + Filter filter = new Filter(); + filter.add(new FilterItem("parent_id", FilterItem.equals, parentId)); + ObjectCollection collection = ormGenDataSourceUtil.query(objectValue.getTableName(), filter, new Selector()); + for (int i = 0; i < collection.size(); i++) { + ObjectValue object = collection.getObject(i); + + Date startTime2= object.getDate("membership_date"); + Date endTime2 = object.getDate("end_time"); + // 判断 startTime - endTime 和 startTime2 - endTime2 是否存在交集 + + if (startTime1.before(endTime2) && startTime2.before(endTime1)) { + // 存在交集,抛出异常 + throw new MyRuntimeException("会费已缴纳, 请勿重复缴纳!!!"); + } + } + } + } +} + diff --git a/common/common-association/src/main/java/apelet/association/plugin/member/MembershipPayPopupPlugin.java b/common/common-association/src/main/java/apelet/association/plugin/member/MembershipPayPopupPlugin.java index e62157c..60091c8 100644 --- a/common/common-association/src/main/java/apelet/association/plugin/member/MembershipPayPopupPlugin.java +++ b/common/common-association/src/main/java/apelet/association/plugin/member/MembershipPayPopupPlugin.java @@ -22,11 +22,6 @@ public class MembershipPayPopupPlugin extends ExecutePluginParent { */ private static final Object FORM_ID = "2049040032123064320"; - /** - * 触发按钮的标识 - 对应表单上按钮的 key/标识 - * 点击此按钮时触发弹窗 - */ - private static final String BUTTON_KEY = "会费缴纳"; /** * 按钮点击事件 @@ -38,19 +33,21 @@ public class MembershipPayPopupPlugin extends ExecutePluginParent { @Override public void buttonTriggered(String buttonKey, ObjectValue objectValue) { // 仅响应指定按钮的点击事件 - if (!BUTTON_KEY.equals(buttonKey)) { - return; + if ("会费缴纳".equals(buttonKey)) { + // 调用 showForm 打开 membershipFeePay 表单 + ShowParameter showParameter = new ShowParameter(); + showParameter.setFormId(FORM_ID.toString()); + showParameter.setHowType(ShowTypeEnum.OPEN_ONLINE_MODAL); + showParameter.setStatus(ViewStatus.EDIT); + Map customParam = new HashMap<>(); + customParam.putAll(objectValue.getValues()); + showParameter.setCustomParam(customParam); + super.showForm(showParameter); + + } - // 调用 showForm 打开 membershipFeePay 表单 - ShowParameter showParameter = new ShowParameter(); - showParameter.setFormId(FORM_ID.toString()); - showParameter.setHowType(ShowTypeEnum.OPEN_ONLINE_MODAL); - showParameter.setStatus(ViewStatus.EDIT); - Map customParam = new HashMap<>(); - customParam.put("id", " "); - showParameter.setCustomParam(customParam); - super.showForm(showParameter); + } } diff --git a/common/common-association/src/main/java/apelet/association/plugin/member/UnitNameChangePopupPlugin.java b/common/common-association/src/main/java/apelet/association/plugin/member/UnitNameChangePopupPlugin.java index 64e45d0..61d1290 100644 --- a/common/common-association/src/main/java/apelet/association/plugin/member/UnitNameChangePopupPlugin.java +++ b/common/common-association/src/main/java/apelet/association/plugin/member/UnitNameChangePopupPlugin.java @@ -50,6 +50,31 @@ public class UnitNameChangePopupPlugin extends ListPlugin { return filter; } + + @Override + protected void afterLoadData(List> dataList) { + super.afterLoadData(dataList); + } + + @Override + public void afterLoadFormData(String widgetVariableName, ObjectValue objectValue) { + super.afterLoadFormData(widgetVariableName, objectValue); + + } + + @Override + public void beforeLoadTableData(String widgetVariableName, ObjectValue objectValue) { + OnlineEventPluginExecuteDto dto = getDto(); + super.beforeLoadTableData(widgetVariableName, objectValue); + + } + + @Override + public void formCreated(String widgetVariableName, ObjectValue objectValue) { + super.formCreated(widgetVariableName, objectValue); + + } + /** * 按钮点击事件(列表按钮) * 点击"变更"按钮时,通过 getSelectData 获取列表中选中行的单据数据, diff --git a/common/common-association/src/main/java/apelet/association/plugin/question/QuestionBankListPlugin.java b/common/common-association/src/main/java/apelet/association/plugin/question/QuestionBankListPlugin.java index 23aa429..6fe2428 100644 --- a/common/common-association/src/main/java/apelet/association/plugin/question/QuestionBankListPlugin.java +++ b/common/common-association/src/main/java/apelet/association/plugin/question/QuestionBankListPlugin.java @@ -39,7 +39,8 @@ public class QuestionBankListPlugin extends ListPlugin { return; } long batchNumber = IdUtil.getSnowflakeNextId(); - collection.forEach(f -> { + for (int i = 0; i < collection.size(); i++) { + ObjectValue f = collection.getObject(i); ObjectValue userExercise = new ObjectValue("user_exercise"); userExercise.put("question_bank_id", questionBank); userExercise.put("exam_questions_id", f.getObjectValue("exam_questions_id")); @@ -51,7 +52,8 @@ public class QuestionBankListPlugin extends ListPlugin { } catch (Exception e) { throw new RuntimeException(e); } - }); + } + ObjectValue object = collection.getObject(0); ObjectValue examQuestions = object.getObjectValue("exam_questions_id"); ShowParameter showParameter = new ShowParameter(); diff --git a/common/common-association/src/main/java/apelet/association/task/ContractPaymentReminderTask.java b/common/common-association/src/main/java/apelet/association/task/ContractPaymentReminderTask.java new file mode 100644 index 0000000..3f2d37e --- /dev/null +++ b/common/common-association/src/main/java/apelet/association/task/ContractPaymentReminderTask.java @@ -0,0 +1,30 @@ +package apelet.association.task; + + +import apelet.common.generator.utils.OrmGenDataSourceUtil; +import apelet.common.orm.impl.Filter; +import apelet.msgnotice.service.SystemMessageService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +@Component +public class ContractPaymentReminderTask { + + // 提前 30 天提醒 + private static final int REMIND_BEFORE_DAYS = 7; + + @Autowired + private OrmGenDataSourceUtil ormGenDataSourceUtil; + + @Autowired + private SystemMessageService systemMessageService; + + @Scheduled(cron = "0 0 1 * * ?") + public void sendRemind() { + Filter filter = new Filter(); + +// ormGenDataSourceUtil.query("", ) + } + +} diff --git a/common/common-association/src/main/java/apelet/association/task/UserRenewalReminderTask.java b/common/common-association/src/main/java/apelet/association/task/UserRenewalReminderTask.java index 3098e7c..858fed9 100644 --- a/common/common-association/src/main/java/apelet/association/task/UserRenewalReminderTask.java +++ b/common/common-association/src/main/java/apelet/association/task/UserRenewalReminderTask.java @@ -6,6 +6,8 @@ import apelet.common.core.object.ObjectValue; import apelet.common.generator.utils.OrmGenDataSourceUtil; import apelet.common.orm.impl.Filter; import apelet.common.orm.impl.Selector; +import apelet.msgnotice.dto.SendSystemMessageDto; +import apelet.msgnotice.service.SystemMessageService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -13,6 +15,7 @@ import org.springframework.stereotype.Component; import java.time.LocalDate; import java.time.ZoneId; import java.time.temporal.ChronoUnit; +import java.util.Arrays; import java.util.Date; @Component @@ -20,11 +23,13 @@ public class UserRenewalReminderTask { // 提前 30 天提醒 private static final int REMIND_BEFORE_DAYS = 30; - // 会员年度天数(固定 365) - private static final int YEAR_DAYS = 365; + @Autowired private OrmGenDataSourceUtil ormGenDataSourceUtil; + @Autowired + private SystemMessageService systemMessageService; + @Scheduled(cron = "0 0 1 * * ?") public void sendRemind() { ObjectCollection collection = ormGenDataSourceUtil.query("membership_apply", new Filter(), new Selector()); @@ -33,40 +38,37 @@ public class UserRenewalReminderTask { } for (int i = 0; i < collection.size(); i++) { ObjectValue objectValue = collection.getObject(i); - Date registTime = objectValue.getDate("regist_time"); - if (needRemind(registTime)) { - // TODO 发送消息提示续费 - + ObjectCollection feePay = objectValue.getObjectCollection("membership_fee_pay"); + Date endTime = null; + for (int j = 0; j < feePay.size(); j++) { + if (j == 0) { + endTime = feePay.getObject(j).getDate("end_time"); + } else { + Date endTime1 = feePay.getObject(j).getDate("end_time"); + if (endTime1.after(endTime)) { + endTime = endTime1; + } + } + } + // 判断 Date endTime 30天后是否是今天 + LocalDate endLocalDate = endTime.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + + // endTime +30天 + LocalDate plus30Day = endLocalDate.plusDays(30); + // 获取今天日期 + LocalDate today = LocalDate.now(); + if (plus30Day.isEqual(today)) { + // 发送消息提醒 + SendSystemMessageDto sendSystemMessageDto = new SendSystemMessageDto(); + sendSystemMessageDto.setTitle("会员续费提醒"); + sendSystemMessageDto.setContent("您的会员期限还有30天到期,请及时续费。"); + sendSystemMessageDto.setRecipientUserIds(Arrays.asList(objectValue.getLong("membership_manger_id"))); + systemMessageService.sendSystemMessage(sendSystemMessageDto); } - - } - - - } - - - public boolean needRemind(Date date) { - LocalDate today = LocalDate.now(); - LocalDate join = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); - - if (today.isBefore(join)) { - return false; } - // 入会到今天总天数 - long totalDays = ChronoUnit.DAYS.between(join, today); - // 第几个年度(从 1 开始) - int yearIndex = (int) (totalDays / YEAR_DAYS) + 1; - - // 该年度到期日 - LocalDate expireDate = join.plusDays((long) YEAR_DAYS * yearIndex); - - // 提醒开始日:到期前 30 天 - LocalDate remindStart = expireDate.minusDays(REMIND_BEFORE_DAYS); - - // 今天在 [remindStart, expireDate] 区间内,则提醒 - return !today.isBefore(remindStart) && !today.isAfter(expireDate); } - } diff --git a/common/common-qy/pom.xml b/common/common-qy/pom.xml index 88684a1..6871b25 100644 --- a/common/common-qy/pom.xml +++ b/common/common-qy/pom.xml @@ -26,12 +26,12 @@ apelet common-generator - 1.0.0 + 1.0.2 apelet common-orm - 1.0.0 + 1.0.2 diff --git a/pom.xml b/pom.xml index 386b01c..f504ec9 100644 --- a/pom.xml +++ b/pom.xml @@ -289,7 +289,7 @@ apelet common-orm - 1.0.0 + 1.0.2 From ee584216ec86db9af6b7069a660fddcf1c022be6 Mon Sep 17 00:00:00 2001 From: huangdehua <2329023417@qq.com> Date: Thu, 13 Aug 2026 13:52:26 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E4=BC=9A=E5=91=98=E5=8F=98=E6=9B=B4?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E6=97=B6=E9=87=8D=E6=96=B0=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=8D=95=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/MembershipApplyListFilterPlugin.java | 2 +- .../member/UnitNameChangeFormInitPlugin.java | 76 ++++++++++++++++++---- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/common/common-association/src/main/java/apelet/association/plugin/member/MembershipApplyListFilterPlugin.java b/common/common-association/src/main/java/apelet/association/plugin/member/MembershipApplyListFilterPlugin.java index a1530a6..b34db84 100644 --- a/common/common-association/src/main/java/apelet/association/plugin/member/MembershipApplyListFilterPlugin.java +++ b/common/common-association/src/main/java/apelet/association/plugin/member/MembershipApplyListFilterPlugin.java @@ -26,7 +26,7 @@ public class MembershipApplyListFilterPlugin extends ListPlugin { /** * 非历史记录 */ - private static final String IS_HISTORY_NO = "0"; + private static final String IS_HISTORY_NO = "1"; @Override protected Filter getFilter() { diff --git a/common/common-association/src/main/java/apelet/association/plugin/member/UnitNameChangeFormInitPlugin.java b/common/common-association/src/main/java/apelet/association/plugin/member/UnitNameChangeFormInitPlugin.java index e9781c8..e0b1fbd 100644 --- a/common/common-association/src/main/java/apelet/association/plugin/member/UnitNameChangeFormInitPlugin.java +++ b/common/common-association/src/main/java/apelet/association/plugin/member/UnitNameChangeFormInitPlugin.java @@ -6,7 +6,6 @@ import apelet.common.generator.utils.OrmGenDataSourceUtil; import apelet.common.online.abstractplugin.ExecutePluginParent; import apelet.common.online.model.constant.AttributeEnum; import com.alibaba.fastjson.JSONObject; -import org.apache.commons.lang3.StringUtils; import java.util.HashMap; import java.util.List; @@ -162,6 +161,8 @@ public class UnitNameChangeFormInitPlugin extends ExecutePluginParent { throw new RuntimeException("获取数据库连接失败"); } + int version = markOldBillsHistory(ormUtil, objectValue); + ObjectValue newBill = new ObjectValue("membership_apply"); Map values = objectValue.getValues(); for (Object item : values.entrySet()) { @@ -173,6 +174,7 @@ public class UnitNameChangeFormInitPlugin extends ExecutePluginParent { newBill.put(getDbFieldKey(key), entry.getValue()); } newBill.put("history", "0"); + newBill.put("version_number", version); ObjectCollection detailEntry = copyEntryForManualSave(objectValue.getObjectCollection(CHILD_WIDGET_KEY)); if (detailEntry != null && !detailEntry.isEmpty()) { @@ -182,6 +184,64 @@ public class UnitNameChangeFormInitPlugin extends ExecutePluginParent { ormUtil.addNew("membership_apply", newBill); } + private int markOldBillsHistory(OrmGenDataSourceUtil ormUtil, ObjectValue objectValue) throws Exception { + String sourceBillId = getSourceBillId(objectValue); + if (sourceBillId == null || sourceBillId.trim().isEmpty()) { + sourceBillId = objectValue.getString(PARAM_BILL_ID); + } + if (sourceBillId == null || sourceBillId.trim().isEmpty()) { + sourceBillId = objectValue.getString(PARAM_BILL_ID_ALT); + } + if (sourceBillId == null || sourceBillId.trim().isEmpty()) { + return 1; + } + + apelet.common.orm.impl.Filter sourceFilter = new apelet.common.orm.impl.Filter(); + sourceFilter.add(new apelet.common.orm.impl.FilterItem("id", "=", sourceBillId)); + ObjectCollection sourceCollection = ormUtil.query("membership_apply", sourceFilter, null); + if (sourceCollection == null || sourceCollection.isEmpty()) { + return 1; + } + + ObjectValue sourceBill = sourceCollection.getObject(0); + if (sourceBill == null) { + return 1; + } + + String number = sourceBill.getString("number"); + if (number == null || number.trim().isEmpty()) { + return 1; + } + + apelet.common.orm.impl.Filter sameNumberFilter = new apelet.common.orm.impl.Filter(); + sameNumberFilter.add(new apelet.common.orm.impl.FilterItem("number", "=", number)); + ObjectCollection sameBills = ormUtil.query("membership_apply", sameNumberFilter, null); + if (sameBills == null || sameBills.isEmpty()) { + sourceBill.put("history", "1"); + sourceBill.put("version_number", 1); + ormUtil.update("membership_apply", sourceBill, null); + return 2; + } + + List bills = new java.util.ArrayList<>(); + for (int i = 0; i < sameBills.size(); i++) { + ObjectValue bill = sameBills.getObject(i); + if (bill != null) { + bills.add(bill); + } + } + + bills.sort(java.util.Comparator.comparingInt(this::getVersionNumberSafe)); + int version = 1; + for (ObjectValue bill : bills) { + bill.put("history", "1"); + bill.put("version_number", version); + ormUtil.update("membership_apply", bill, null); + version++; + } + return version; + } + private boolean shouldSkipManualSaveField(String key) { return "id".equals(key) || "eventparams".equals(key) @@ -398,21 +458,13 @@ public class UnitNameChangeFormInitPlugin extends ExecutePluginParent { int version = 1; if (sameBills != null && !sameBills.isEmpty()) { - List bills = new java.util.ArrayList<>(); for (int i = 0; i < sameBills.size(); i++) { ObjectValue bill = sameBills.getObject(i); - if (bill != null) { - bills.add(bill); + int billVersion = getVersionNumberSafe(bill); + if (billVersion >= version) { + version = billVersion + 1; } } - - bills.sort(java.util.Comparator.comparingInt(this::getVersionNumberSafe)); - for (ObjectValue bill : bills) { - bill.put("is_history", 1); - bill.put("version_number", version); - ormUtil.update("membership_apply", bill, null); - version++; - } } objectValue.put("is_history", 0); From f079aab8dc56aec71c6a4d9f92b2ba3e17612a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BD=8A?= <23> Date: Fri, 14 Aug 2026 10:38:08 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application-tenant/tenant-admin/pom.xml | 22 ++++- .../upms/controller/LoginController.java | 94 +++++++++++----------- .../upms/controller/SysUserController.java | 14 +++- .../apelet/tenantadmin/upms/dto/SysUserDto.java | 5 ++ .../apelet/tenantadmin/upms/model/SysUser.java | 4 + .../java/apelet/tenantadmin/upms/vo/SysUserVo.java | 2 + .../src/main/resources/application-config.yml | 2 +- .../association/controller/HomeController.java | 12 ++- .../plugin/active/ActivityInfoDetailsPlugin.java | 60 ++++++++++++-- .../plugin/active/ActivitySignConfigPlugin.java | 21 ++--- .../plugin/clueManage/ClueSaveOpPlugin.java | 76 +++++++++++++++++ .../plugin/quotation/ContractPlugin.java | 19 +++++ .../java/apelet/association/utils/WordDocUtil.java | 82 +++++++++++++++++++ 13 files changed, 336 insertions(+), 77 deletions(-) create mode 100644 common/common-association/src/main/java/apelet/association/plugin/clueManage/ClueSaveOpPlugin.java create mode 100644 common/common-association/src/main/java/apelet/association/utils/WordDocUtil.java diff --git a/application-tenant/tenant-admin/pom.xml b/application-tenant/tenant-admin/pom.xml index b2ab632..9c94759 100644 --- a/application-tenant/tenant-admin/pom.xml +++ b/application-tenant/tenant-admin/pom.xml @@ -25,6 +25,8 @@ mybatis-plus-generator ${mybatisplus.version} + + cn.afterturn easypoi-base @@ -40,6 +42,20 @@ easypoi-annotation 4.4.0 + + + + org.apache.xmlbeans + xmlbeans + 3.1.0 + + + + cn.hutool + hutool-all + 5.8.26 + + org.jetbrains annotations @@ -57,7 +73,7 @@ org.quartz-scheduler quartz - 2.3.2 + 2.3.2 org.mybatis @@ -158,8 +174,6 @@ 1.0.0 - - @@ -171,4 +185,4 @@ - \ No newline at end of file + diff --git a/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/controller/LoginController.java b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/controller/LoginController.java index 970b03b..7387b36 100644 --- a/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/controller/LoginController.java +++ b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/controller/LoginController.java @@ -70,6 +70,7 @@ import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; + /** * 登录接口控制器类。 * @@ -138,6 +139,7 @@ public class LoginController { private static final String SHOW_NAME_FIELD = "showName"; private static final String SHOW_ORDER_FIELD = "showOrder"; private static final String HEAD_IMAGE_URL_FIELD = "headImageUrl"; + private static final String SIGNATURE_IMAGE = "signatureImage"; private static final String THIRD_PARTY_CONFIG = "third_party_config"; @@ -145,20 +147,18 @@ public class LoginController { private OrmGenDataSourceUtil ormGenDataSourceUtil; - - @PostMapping("/getEhrLtpa") @NoAuthInterface public ResponseResult getEhrLtap( @MyRequestBody String username - ){ + ) { EasConfig easConfig = ApplicationContextHolder.getBean("easConfig"); String path = easConfig.getLtpaToken(); // String path = "/ehrapp/yd/LtpaToken.properties"; // 测试环境地址 System.out.println("getEasSsoUrl path = " + path); String password = LtpaTokenManager.generate(username, path).toString(); JSONObject jsonData = new JSONObject(); - jsonData.put("ltap",password); + jsonData.put("ltap", password); return ResponseResult.success(jsonData); } @@ -220,7 +220,7 @@ public class LoginController { if (entryValue.get(entryFiledKey) instanceof ObjectValue) { ObjectValue entityValue = (ObjectValue) entryValue.get(entryFiledKey); Long pk = entityValue.getPkValue(); - if (pk == null || pk == 0L) { + if (pk == 0L) { continue; } entityValue = ormGenDataSourceUtil.queryOne(entityValue.getTableName(), pk); @@ -610,7 +610,7 @@ public class LoginController { return; } responseInfo.setDownloadUri("/tenantadmin/upms/login/downloadHeadImage"); - String newHeadImage = JSONArray.toJSONString(CollUtil.newArrayList(responseInfo)); + String newHeadImage = JSON.toJSONString(CollUtil.newArrayList(responseInfo)); if (!sysUserService.changeHeadImage(TokenData.takeFromRequest().getUserId(), newHeadImage)) { ResponseResult.output(HttpServletResponse.SC_FORBIDDEN, ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST)); return; @@ -657,7 +657,7 @@ public class LoginController { log.info("Rest api login."); try { // Object tokenObj = redissonClient.getBucket(appid).get(); - String accessToken=""; + String accessToken = ""; // if (tokenObj != null) { // accessToken=tokenObj.toString(); // }else { @@ -669,7 +669,7 @@ public class LoginController { paramMap.put("scope", "app"); // 发送 POST 请求 String tokenData = HttpUtil.post(tokenUrl, paramMap); - if (StringUtils.isBlank(tokenData)){ + if (StringUtils.isBlank(tokenData)) { return ResponseResult.error("500", "通过appId获取AccessToken失败,appId:" + appid); } JSONObject tokenJson = JSONObject.parseObject(tokenData); @@ -679,10 +679,10 @@ public class LoginController { accessToken = ((JSONObject) (tokenJson.get("data"))).get("accessToken").toString(); //accessToken的有效时间为6400秒,在该有效期内多次获取均返回同一token, //连许多次请求会被拦截,因此需要本地缓存。为防止极端情况,设置过期时间为6200s - redissonClient.getBucket(appid).set(accessToken,6200,TimeUnit.SECONDS); + redissonClient.getBucket(appid).set(accessToken, 6200, TimeUnit.SECONDS); // } String jsonInputString = String.format("{\"appid\":\"%s\", \"ticket\":\"%s\"}", appid, ticket); - String infoUrl="https://www.yunzhijia.com/gateway/ticket/user/acquirecontext?accessToken="+accessToken; + String infoUrl = "https://www.yunzhijia.com/gateway/ticket/user/acquirecontext?accessToken=" + accessToken; String userStr = HttpUtil.post(infoUrl, jsonInputString); log.info("validateHubCloudLogin appid:{}, ticket:{} ", appid, ticket); JSONObject userObj = JSONObject.parseObject(userStr); @@ -729,11 +729,11 @@ public class LoginController { log.info("Rest api mlogin."); try { // Object tokenObj = redissonClient.getBucket(appid).get(); - String accessToken=""; + String accessToken = ""; // if (tokenObj != null) { // accessToken=tokenObj.toString(); // }else { - if(StringUtils.isEmpty(appid)){ + if (StringUtils.isEmpty(appid)) { appid = hubCloudAppId; } String tokenUrl = "https://www.yunzhijia.com/gateway/oauth2/token/getAccessToken"; @@ -744,7 +744,7 @@ public class LoginController { paramMap.put("scope", "app"); // 发送 POST 请求 String tokenData = HttpUtil.post(tokenUrl, paramMap); - if (StringUtils.isBlank(tokenData)){ + if (StringUtils.isBlank(tokenData)) { return ResponseResult.error("500", "通过appId获取AccessToken失败,appId:" + appid); } JSONObject tokenJson = JSONObject.parseObject(tokenData); @@ -754,10 +754,10 @@ public class LoginController { accessToken = ((JSONObject) (tokenJson.get("data"))).get("accessToken").toString(); //accessToken的有效时间为6400秒,在该有效期内多次获取均返回同一token, //连许多次请求会被拦截,因此需要本地缓存。为防止极端情况,设置过期时间为6200s - redissonClient.getBucket(appid).set(accessToken,6200,TimeUnit.SECONDS); + redissonClient.getBucket(appid).set(accessToken, 6200, TimeUnit.SECONDS); // } String jsonInputString = String.format("{\"appid\":\"%s\", \"ticket\":\"%s\"}", appid, ticket); - String infoUrl="https://www.yunzhijia.com/gateway/ticket/user/acquirecontext?accessToken="+accessToken; + String infoUrl = "https://www.yunzhijia.com/gateway/ticket/user/acquirecontext?accessToken=" + accessToken; String userStr = HttpUtil.post(infoUrl, jsonInputString); log.info("validateHubCloudLogin appid:{}, ticket:{} ", appid, ticket); JSONObject userObj = JSONObject.parseObject(userStr); @@ -804,27 +804,27 @@ public class LoginController { log.info("Rest api login."); try { Object tokenObj = redissonClient.getBucket(appKey).get(); - String accessToken=""; + String accessToken = ""; if (tokenObj != null) { - accessToken=tokenObj.toString(); - }else { + accessToken = tokenObj.toString(); + } else { String tokenUrl = "https://api.dingtalk.com/v1.0/oauth2/accessToken"; String jsonInputString = String.format( "{\"appKey\":\"%s\", \"appSecret\":\"%s\"}", appKey, dingTalkSecret); // 发送 POST 请求 String tokenData = HttpUtil.post(tokenUrl, jsonInputString); - if (StringUtils.isBlank(tokenData)){ + if (StringUtils.isBlank(tokenData)) { return ResponseResult.error("500", "通过appKey获取AccessToken失败,appKey:" + appKey); } JSONObject tokenJson = JSONObject.parseObject(tokenData); accessToken = tokenJson.get("accessToken").toString(); //accessToken的有效时间为7200秒,在该有效期内多次获取均返回同一token, //连许多次请求会被拦截,因此需要本地缓存。为防止极端情况,设置过期时间为6200s - redissonClient.getBucket(appKey).set(accessToken,7000,TimeUnit.SECONDS); + redissonClient.getBucket(appKey).set(accessToken, 7000, TimeUnit.SECONDS); } - String jsonInputString = String.format("{\"code\":\"%s\"}",code); - String infoUrl="https://oapi.dingtalk.com/topapi/v2/user/getuserinfo?access_token="+accessToken; + String jsonInputString = String.format("{\"code\":\"%s\"}", code); + String infoUrl = "https://oapi.dingtalk.com/topapi/v2/user/getuserinfo?access_token=" + accessToken; String userStr = HttpUtil.post(infoUrl, jsonInputString); log.info("validateHubCloudLogin appKey:{}, code:{} ", appKey, code); JSONObject userObj = JSONObject.parseObject(userStr); @@ -841,7 +841,7 @@ public class LoginController { if (user.getUserStatus() == SysUserStatus.STATUS_LOCKED) { return ResponseResult.error(ErrorCodeEnum.INVALID_USER_STATUS, "登录失败,用户账号被锁定!"); } - JSONObject jsonData = this.buildLoginData(user,null,null); + JSONObject jsonData = this.buildLoginData(user, null, null); return ResponseResult.success(jsonData); } catch (Exception e) { e.printStackTrace(); @@ -869,14 +869,14 @@ public class LoginController { log.info("Rest api login."); try { - if(StringUtils.isBlank(ticket)){ - return ResponseResult.error("500","ticket不能为空"); + if (StringUtils.isBlank(ticket)) { + return ResponseResult.error("500", "ticket不能为空"); } - String jsonInputString = String.format("{\"ticket\":\"%s\",\"appId\":\"%s\",\"checkType\":1}",ticket,appId); + String jsonInputString = String.format("{\"ticket\":\"%s\",\"appId\":\"%s\",\"checkType\":1}", ticket, appId); log.info("doLoginValidateDingTalkmJzt ", jsonInputString); String userStr = HttpUtil.post(ticketUrl, jsonInputString); - if(StringUtils.isBlank(userStr)){ - return ResponseResult.error("500","ticket异常:"+ticket); + if (StringUtils.isBlank(userStr)) { + return ResponseResult.error("500", "ticket异常:" + ticket); } log.info(" get user result:", userStr); JSONObject userObj = JSONObject.parseObject(userStr); @@ -896,7 +896,7 @@ public class LoginController { return ResponseResult.success(jsonData); } catch (Exception e) { e.printStackTrace(); - return ResponseResult.error("500", "自动登录失败:"+e.getMessage()); + return ResponseResult.error("500", "自动登录失败:" + e.getMessage()); } } @@ -1114,24 +1114,24 @@ public class LoginController { } - private String getShrRole(String zwcjName){ + private String getShrRole(String zwcjName) { String roleId = ""; - if(!StringUtils.isEmpty(zwcjName)){ + if (!StringUtils.isEmpty(zwcjName)) { SysRole role = new SysRole(); - if(!zwcjName.equals("员工")){//非员工 + if (!zwcjName.equals("员工")) {//非员工 role.setRoleName("非员工"); - List roleList = sysRoleService.getSysRoleList(role,""); - if(roleList.size() > 0){ + List roleList = sysRoleService.getSysRoleList(role, ""); + if (roleList.size() > 0) { roleId = roleId + roleList.get(0).getRoleId(); } } role.setRoleName(zwcjName); - List roleList = sysRoleService.getSysRoleList(role,""); - if(roleList.size() > 0){ - if(StringUtils.isEmpty(roleId)){ - roleId = roleList.get(0).getRoleId()+""; - }else{ - roleId = roleId +","+roleList.get(0).getRoleId(); + List roleList = sysRoleService.getSysRoleList(role, ""); + if (roleList.size() > 0) { + if (StringUtils.isEmpty(roleId)) { + roleId = roleList.get(0).getRoleId() + ""; + } else { + roleId = roleId + "," + roleList.get(0).getRoleId(); } } } @@ -1167,11 +1167,11 @@ public class LoginController { if (mobileEntry.getPcurl() != null) { mobileEntry.setPcurl(EasUtil.getEasSsoUrl(user.getLoginName(), mobileEntry.getPcurl())); } - if(mobileEntry.getExtraUrl() != null){ - if(mobileEntry.getExtraUrl().contains("?")){ - mobileEntry.setExtraUrl(mobileEntry.getExtraUrl()+"&userNumber="+user.getLoginName()); - }else{ - mobileEntry.setExtraUrl(mobileEntry.getExtraUrl()+"?userNumber="+user.getLoginName()); + if (mobileEntry.getExtraUrl() != null) { + if (mobileEntry.getExtraUrl().contains("?")) { + mobileEntry.setExtraUrl(mobileEntry.getExtraUrl() + "&userNumber=" + user.getLoginName()); + } else { + mobileEntry.setExtraUrl(mobileEntry.getExtraUrl() + "?userNumber=" + user.getLoginName()); } } } @@ -1201,7 +1201,7 @@ public class LoginController { jsonData.put(IS_ADMIN, user.getUserType() == SysUserType.TYPE_ADMIN); if (user.getDeptId() != null) { SysDept dept = sysDeptService.getById(user.getDeptId()); - if(dept != null){ + if (dept != null) { jsonData.put("deptName", dept.getDeptName()); } @@ -1532,6 +1532,6 @@ public class LoginController { private List permCodeList; private List permList; } - + } diff --git a/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/controller/SysUserController.java b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/controller/SysUserController.java index a19d724..2d00389 100644 --- a/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/controller/SysUserController.java +++ b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/controller/SysUserController.java @@ -20,6 +20,7 @@ import apelet.tenantadmin.upms.model.SysUser; import apelet.tenantadmin.upms.service.SysUserService; import apelet.tenantadmin.upms.vo.SysUserVo; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.ReflectUtil; import com.alibaba.fastjson.*; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -225,7 +226,7 @@ public class SysUserController { * @return 应答结果对象,包含查询结果集。 */ @PostMapping("/list") - public ResponseResult> list( + public ResponseResult list( @MyRequestBody SysUserDto sysUserDtoFilter, @MyRequestBody MyOrderParam orderParam, @MyRequestBody MyPageParam pageParam) { @@ -235,7 +236,16 @@ public class SysUserController { SysUser sysUserFilter = MyModelUtil.copyTo(sysUserDtoFilter, SysUser.class); String orderBy = MyOrderParam.buildOrderBy(orderParam, SysUser.class); List sysUserList = sysUserService.getSysUserListWithRelation(sysUserFilter, orderBy); - return ResponseResult.success(MyPageUtil.makeResponseData(sysUserList, SysUser.INSTANCE)); + + MyPageData sysUserVoMyPageData = MyPageUtil.makeResponseData(sysUserList, SysUser.INSTANCE); + sysUserVoMyPageData.getDataList().forEach(f ->{ + List collect = sysUserList.stream().filter(u -> f.getUserId().equals(u.getUserId())).collect(Collectors.toList()); + SysUser sysUser = collect.get(0); + f.setSignatureImage(sysUser.getSignatureImage()); + }); + return ResponseResult.success(sysUserVoMyPageData); + + } diff --git a/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/dto/SysUserDto.java b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/dto/SysUserDto.java index e096b69..86f1feb 100644 --- a/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/dto/SysUserDto.java +++ b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/dto/SysUserDto.java @@ -1,5 +1,7 @@ package apelet.tenantadmin.upms.dto; +import apelet.common.core.annotation.UploadFlagColumn; +import apelet.common.core.upload.UploadStoreTypeEnum; import apelet.common.core.validator.AddGroup; import apelet.common.core.validator.ConstDictRef; import apelet.common.core.validator.UpdateGroup; @@ -70,6 +72,9 @@ public class SysUserDto { @Schema(description = "用户头像的Url") private String headImageUrl; + @Schema(description = "签名") + private String signatureImage; + /** * 用户状态(0: 正常 1: 锁定)。 */ diff --git a/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/model/SysUser.java b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/model/SysUser.java index e1ed6fb..85dba06 100644 --- a/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/model/SysUser.java +++ b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/model/SysUser.java @@ -63,6 +63,10 @@ public class SysUser { @UploadFlagColumn(storeType = UploadStoreTypeEnum.LOCAL_SYSTEM) private String headImageUrl; + + @UploadFlagColumn(storeType = UploadStoreTypeEnum.LOCAL_SYSTEM) + private String signatureImage; + /** * 用户状态(0: 正常 1: 锁定)。 */ diff --git a/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/vo/SysUserVo.java b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/vo/SysUserVo.java index 25c11ea..0125b29 100644 --- a/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/vo/SysUserVo.java +++ b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/upms/vo/SysUserVo.java @@ -53,6 +53,8 @@ public class SysUserVo { @Schema(description = "用户头像的Url") private String headImageUrl; + @Schema(description = "签名") + private String signatureImage; /** * 用户状态(0: 正常 1: 锁定)。 */ diff --git a/application-tenant/tenant-admin/src/main/resources/application-config.yml b/application-tenant/tenant-admin/src/main/resources/application-config.yml index f0748e1..b51ea11 100644 --- a/application-tenant/tenant-admin/src/main/resources/application-config.yml +++ b/application-tenant/tenant-admin/src/main/resources/application-config.yml @@ -88,7 +88,7 @@ aliyun: oss: enabled: true expireSeconds: 1000 - endpoint: https://oss-cn-beijing.aliyuncs.com + endpoint: oss-cn-beijing.aliyuncs.com accessKey: LTAI5t5fEgzRRtdmBvczVS6r secretKey: uESFiyyi6EwCkM5w4a4pbx6TmVhqgx bucketName: yy-test12 diff --git a/common/common-association/src/main/java/apelet/association/controller/HomeController.java b/common/common-association/src/main/java/apelet/association/controller/HomeController.java index 794bb3b..370cee8 100644 --- a/common/common-association/src/main/java/apelet/association/controller/HomeController.java +++ b/common/common-association/src/main/java/apelet/association/controller/HomeController.java @@ -1,14 +1,21 @@ package apelet.association.controller; -import apelet.common.core.object.ObjectCollection; -import apelet.common.core.object.ResponseResult; +import apelet.association.utils.WordDocUtil; +import apelet.common.core.annotation.NoAuthInterface; +import apelet.common.core.object.*; import apelet.common.generator.utils.OrmGenDataSourceUtil; import apelet.common.orm.impl.Filter; import apelet.common.orm.impl.FilterItem; import apelet.common.orm.impl.Selector; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.net.URLEncoder; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -68,4 +75,5 @@ public class HomeController { } + } diff --git a/common/common-association/src/main/java/apelet/association/plugin/active/ActivityInfoDetailsPlugin.java b/common/common-association/src/main/java/apelet/association/plugin/active/ActivityInfoDetailsPlugin.java index e3736ec..018c538 100644 --- a/common/common-association/src/main/java/apelet/association/plugin/active/ActivityInfoDetailsPlugin.java +++ b/common/common-association/src/main/java/apelet/association/plugin/active/ActivityInfoDetailsPlugin.java @@ -3,6 +3,7 @@ package apelet.association.plugin.active; import apelet.association.utils.MyFileUtil; import apelet.association.utils.QRCodeUtil; import apelet.common.core.exception.MyRuntimeException; +import apelet.common.core.object.ObjectCollection; import apelet.common.core.object.ObjectValue; import apelet.common.core.upload.UploadResponseInfo; import apelet.common.core.util.ApplicationContextHolder; @@ -27,7 +28,9 @@ import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * 活动详情 @@ -59,14 +62,52 @@ public class ActivityInfoDetailsPlugin extends ListPlugin { @Override public void change(String widgetVariableName, ObjectValue objectValue) { + //添加 会员 + if (widgetVariableName.equals("table1786587576012")) { + ObjectCollection memberInvitations = objectValue.getObjectCollection("member_invitation"); + List collect = memberInvitations.stream().filter(f -> f.getString("rowkey").equals(objectValue.getString("rowkeysubset"))).collect(Collectors.toList()); + if (!collect.isEmpty()) { + ObjectValue memberInvitation = collect.get(0); + ObjectValue membershipApplyId = memberInvitation.getObjectValue("membership_apply_id"); + if (membershipApplyId == null) { + return; + } + ObjectValue membershipApply = ormGenDataSourceUtil.queryOne(membershipApplyId.getTableName(), membershipApplyId.getString("id")); + ObjectCollection applyEntry = membershipApply.getObjectCollection("membership_apply_entry"); + if (applyEntry == null) { + return; + } + ObjectValue entryObject = applyEntry.getObject(0); + this.setWidgetAttributeByEntry("table1786587576012", "unit_name", AttributeEnum.VALUE_CHANGE, membershipApply.getString("unit_name"), objectValue.getString("rowkeysubset")); + this.setWidgetAttributeByEntry("table1786587576012", "person", AttributeEnum.VALUE_CHANGE, entryObject.getString("contact_name"), objectValue.getString("rowkeysubset")); + this.setWidgetAttributeByEntry("table1786587576012", "phone", AttributeEnum.VALUE_CHANGE, entryObject.getString("contact_phone"), objectValue.getString("rowkeysubset")); + } + } + //专家邀请 + if(widgetVariableName.equals("table1786587648327")){ + ObjectCollection expertInvitations = objectValue.getObjectCollection("expert_invitation"); + List collect = expertInvitations.stream().filter(f -> f.getString("rowkey").equals(objectValue.getString("rowkeysubset"))).collect(Collectors.toList()); + if (!collect.isEmpty()) { + ObjectValue expertInvitation = collect.get(0); + ObjectValue expert = expertInvitation.getObjectValue("expert_id"); + expert = ormGenDataSourceUtil.queryOne(expert.getTableName(), expert.getString("id")); + this.setWidgetAttributeByEntry("table1786587648327", "person", AttributeEnum.VALUE_CHANGE, expert.getString("name"), objectValue.getString("rowkeysubset")); + this.setWidgetAttributeByEntry("table1786587648327", "phone", AttributeEnum.VALUE_CHANGE, expert.getString("phone"), objectValue.getString("rowkeysubset")); + } + } + //访客邀请 + if(widgetVariableName.equals("table1786587726532")){ + + } } @Override public void buttonTriggered(String widgetVariableName, ObjectValue objectValue) { + // 生成报名二维码 if (widgetVariableName.equals("button1786587153460")) { String registrationQr = objectValue.getString("registration_qr"); - if(StringUtils.isNotEmpty(registrationQr)){ + if (StringUtils.isNotEmpty(registrationQr)) { this.showErrorMessage("当前已存在报名二维码, 请勿重复生成!!!"); return; } @@ -79,26 +120,31 @@ public class ActivityInfoDetailsPlugin extends ListPlugin { // 生成 报名二维码 long id = objectValue.getLong("id"); - String url = "http://58.48.135.5:8069" + "/#/?" + + String url = "http://192.168.100.42:8099" + "/#/?" + "loginName=" + "admin" + "&password=" + "123456" + - "&entryId=" + "2087413611113746432" + + "&entryId=" + "2087710350152568832" + "&bindType=" + "1" + - "&onlineFormId=" + "2087385700075835392" + + "&onlineFormId=" + "2048951917157027840" + "&activeId=" + id; byte[] checkInQr = qrCodeUtil.generateQrCode(url, 350, 350); QRFile = MyFileUtil.writeToFile(checkInQr, savePath, "qrcode-" + System.currentTimeMillis() + ".png"); MultipartFile checkInMultipart = MyFileUtil.readFileAsMultipartFile(QRFile, "image/png"); - UploadResponseInfo registrationQR = myFileUtil.uploadMyFile(table, "registration_qr", true, checkInMultipart); - this.setWidgetAttribute("registrationQr", AttributeEnum.VALUE_CHANGE, registrationQR); + UploadResponseInfo registrationQR = myFileUtil.uploadMyFile(table, "qr", true, checkInMultipart); + + String s = "[" + new JSONObject(BeanUtil.beanToMap(registrationQR)).toJSONString() + "]"; + this.setWidgetAttribute("registrationQr", AttributeEnum.VALUE_CHANGE, s); + this.setWidgetAttribute("qr", AttributeEnum.VALUE_CHANGE, s); - objectValue.put("registration_qr", "["+new JSONObject(BeanUtil.beanToMap(registrationQR)).toJSONString()+"]"); + objectValue.put("registration_qr", s); + objectValue.put("qr", s); Selector selector = new Selector(); selector.getList().add(new SelectorItem("registration_qr")); ormGenDataSourceUtil.update(objectValue.getTableName(), objectValue, selector); } catch (Exception e) { + e.printStackTrace(); throw new MyRuntimeException(e.getMessage()); } finally { QRFile.delete(); diff --git a/common/common-association/src/main/java/apelet/association/plugin/active/ActivitySignConfigPlugin.java b/common/common-association/src/main/java/apelet/association/plugin/active/ActivitySignConfigPlugin.java index 73d6f9a..4c40e69 100644 --- a/common/common-association/src/main/java/apelet/association/plugin/active/ActivitySignConfigPlugin.java +++ b/common/common-association/src/main/java/apelet/association/plugin/active/ActivitySignConfigPlugin.java @@ -102,16 +102,16 @@ public class ActivitySignConfigPlugin extends ListPlugin { Model model = dto.getModel(); if ("button1778742711763".equals(widgetVariableName)) { - if (StringUtils.isNotBlank(objectValue.getString("sign_in_code")) && - StringUtils.isNotBlank(objectValue.getString("sign_out_code"))) { - showWarningMessage("当前已存在二维码, 请勿重复生产!!!"); - return; - } +// if (StringUtils.isNotBlank(objectValue.getString("sign_in_code")) && +// StringUtils.isNotBlank(objectValue.getString("sign_out_code"))) { +// showWarningMessage("当前已存在二维码, 请勿重复生产!!!"); +// return; +// } // 生成二维码 String savePath = System.getProperty("user.dir") + "\\zz-resource\\qrcode"; - File checkOutFile; - File checkInFile; + File checkOutFile = null; + File checkInFile = null; try { Object activityId = objectValue.get("id"); Object activityName = objectValue.get("name"); @@ -135,13 +135,6 @@ public class ActivitySignConfigPlugin extends ListPlugin { } catch (Exception e) { e.printStackTrace(); throw new MyRuntimeException("二维码生成失败, 请联系管理员!!!"); - } finally { - try { - FileUtils.cleanDirectory(new File(savePath)); - } catch (IOException e) { - e.printStackTrace(); - System.err.println("文件刪除失敗!!!"); - } } } } diff --git a/common/common-association/src/main/java/apelet/association/plugin/clueManage/ClueSaveOpPlugin.java b/common/common-association/src/main/java/apelet/association/plugin/clueManage/ClueSaveOpPlugin.java new file mode 100644 index 0000000..d5d6a7d --- /dev/null +++ b/common/common-association/src/main/java/apelet/association/plugin/clueManage/ClueSaveOpPlugin.java @@ -0,0 +1,76 @@ +package apelet.association.plugin.clueManage; + +import apelet.common.core.exception.MyRuntimeException; +import apelet.common.core.object.ObjectCollection; +import apelet.common.core.object.ObjectValue; +import apelet.common.core.object.TokenData; +import apelet.common.core.util.ApplicationContextHolder; +import apelet.common.generator.utils.OrmGenDataSourceUtil; +import apelet.common.online.plugin.*; +import apelet.common.orm.impl.Selector; +import apelet.common.orm.impl.SelectorItem; +import cn.hutool.core.date.DateUtil; +import org.redisson.api.RBucket; +import org.redisson.api.RedissonClient; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @ClassName: ClueActivateOpPlugin + * @Author: lihuangbin + * @Date: 2026/5/11 + * @Description: 激活放弃的线索 + */ + +public class ClueSaveOpPlugin extends OperationServicePlugIn { + + private final OrmGenDataSourceUtil ormGenDataSourceUtil; + private final RedissonClient redissonClient; + + public ClueSaveOpPlugin() { + ormGenDataSourceUtil = ApplicationContextHolder.getBean(OrmGenDataSourceUtil.class); + redissonClient = ApplicationContextHolder.getBean(RedissonClient.class); + } + + + @Override + public void endOperationTransaction(EndOperationTransactionArgs e) { + ObjectValue objectValue = e.getModel(); + String redisKey = "clue -- " + DateUtil.today(); + RBucket>> bucket = redissonClient.getBucket(redisKey); + Map> map; + // 修复:key存在则读取,不存在新建空map + if (bucket.isExists()) { + map = bucket.get(); + } else { + map = new HashMap<>(); + } + Long userId = TokenData.takeFromRequest().getUserId(); + Map userClueMap = map.get(userId); + if (userClueMap == null || userClueMap.isEmpty()) { + userClueMap = new HashMap<>(); + } + String context = "完成线索, 名称: " +objectValue.getString("name") + + ", 咨询内容: " + objectValue.getString("seek_info"); + userClueMap.put(objectValue.getLong("id"), context); + map.put(userId, userClueMap); + + bucket.set(map); + + // 判断:key不存在,写入同时设置过期;key已经存在,只更新value,**不修改TTL** + if (!bucket.isExists()) { + // 计算到次日0点毫秒 + LocalDateTime tomorrowZero = LocalDate.now().plusDays(1).atStartOfDay(); + long expireMs = ChronoUnit.MILLIS.between(LocalDateTime.now(), tomorrowZero); + // 原子:只有key不存在才写入并设置过期 + bucket.expire(expireMs, TimeUnit.MILLISECONDS); + } + } + + +} diff --git a/common/common-association/src/main/java/apelet/association/plugin/quotation/ContractPlugin.java b/common/common-association/src/main/java/apelet/association/plugin/quotation/ContractPlugin.java index d423550..6380ec7 100644 --- a/common/common-association/src/main/java/apelet/association/plugin/quotation/ContractPlugin.java +++ b/common/common-association/src/main/java/apelet/association/plugin/quotation/ContractPlugin.java @@ -1,9 +1,14 @@ package apelet.association.plugin.quotation; +import apelet.association.utils.WordDocUtil; +import apelet.common.core.object.ObjectValue; import apelet.common.online.abstractplugin.ListPlugin; import apelet.common.orm.impl.Filter; import apelet.common.orm.impl.FilterItem; +import java.time.LocalDate; +import java.util.Map; + /* 合同列表界面设置过滤条件 @@ -15,4 +20,18 @@ public class ContractPlugin extends ListPlugin { filter.add(new FilterItem("status", FilterItem.equals, "3")); return filter; } + + @Override + public void buttonTriggered(String widgetVariableName, ObjectValue objectValue) { + if(widgetVariableName.equals("合同导出")){ + try { + Map values = objectValue.getValues(); + String template = System.getProperty("user.dir") + "\\zz-resource\\quotation_template.docx"; + String outPath = System.getProperty("user.dir") + "\\zz-resource\\quotation_"+ System.currentTimeMillis()+".docx"; + WordDocUtil.renderLocalDoc(template, outPath, values); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } } diff --git a/common/common-association/src/main/java/apelet/association/utils/WordDocUtil.java b/common/common-association/src/main/java/apelet/association/utils/WordDocUtil.java new file mode 100644 index 0000000..1ac88b2 --- /dev/null +++ b/common/common-association/src/main/java/apelet/association/utils/WordDocUtil.java @@ -0,0 +1,82 @@ +package apelet.association.utils; + +import com.deepoove.poi.XWPFTemplate; +import com.deepoove.poi.config.Configure; +import com.deepoove.poi.data.PictureRenderData; +import com.deepoove.poi.data.PictureType; +import com.deepoove.poi.data.Pictures; + +import java.io.*; +import java.util.Map; + +public class WordDocUtil { + + /** + * 本地模板生成docx文件,输出到本地磁盘 + * + * @param templateLocalPath 本地模板绝对路径 + * @param outLocalPath 输出文件路径 + * @param dataMap 填充数据 + * @throws Exception IO异常 + */ + public static void renderLocalDoc(String templateLocalPath, String outLocalPath, Map dataMap) throws Exception { + // 自动创建输出文件夹 + File outFile = new File(outLocalPath); + if (!outFile.getParentFile().exists()) { + outFile.getParentFile().mkdirs(); + } + Configure config = Configure.builder() + .buildGramer("#{", "}") + .build(); + try (InputStream templateIn = new FileInputStream(templateLocalPath); + OutputStream fileOut = new FileOutputStream(outLocalPath); + XWPFTemplate template = XWPFTemplate.compile(templateIn, config).render(dataMap)) { + template.write(fileOut); + } + } + + /** + * ✅【新增】模板渲染直接输出到输出流(用于浏览器下载,不生成本地临时文件) + * @param templateLocalPath 模板文件路径 + * @param outputStream response.getOutputStream() + * @param dataMap 填充数据 + * @throws Exception ex + */ + public static void renderToOutputStream(String templateLocalPath, OutputStream outputStream, Map dataMap) throws Exception { + Configure config = Configure.builder() + .buildGramer("#{", "}") + .build(); + try (InputStream templateIn = new FileInputStream(templateLocalPath); + XWPFTemplate template = XWPFTemplate.compile(templateIn, config).render(dataMap)) { + template.write(outputStream); + } + } + + /** + * OSS/网络URL图片构建(签字图片专用) + * + * @param ossUrl OSS完整图片地址 https://xxx.oss-cn-beijing.aliyuncs.com/sign/sign001.png + * @param widthCm 图片宽度 单位cm + * @param heightCm 图片高度 单位cm + * @return PictureRenderData + */ + public static PictureRenderData getOssPic(String ossUrl, double widthCm, double heightCm) { + // poi‑tl size 参数单位是 像素,注意:不是厘米!!! + return Pictures.ofUrl(ossUrl) + .size((int) widthCm, (int) heightCm) + .create(); + } + + // 本地图片(备用) + public static PictureRenderData getLocalPic(String imgLocalPath, double width, double height) { + return Pictures.ofLocal(imgLocalPath).size((int) width, (int) height).create(); + } + + // base64图片(备用) + public static PictureRenderData getBase64Pic(String base64Str, double width, double height) { + return Pictures.ofBase64(base64Str, PictureType.PNG) + .size((int) width, (int) height) + .create(); + } + +} From b3b6c9df44221126255524bc89dc9cf7056e9f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BD=8A?= <23> Date: Fri, 14 Aug 2026 10:38:37 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tenant/controller/DocxTemplateController.java | 141 +++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/DocxTemplateController.java diff --git a/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/DocxTemplateController.java b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/DocxTemplateController.java new file mode 100644 index 0000000..1c3af35 --- /dev/null +++ b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/DocxTemplateController.java @@ -0,0 +1,141 @@ + +package apelet.tenantadmin.tenant.controller; + +import apelet.common.core.annotation.MyRequestBody; +import apelet.common.core.exception.MyRuntimeException; +import apelet.common.core.object.ObjectValue; +import apelet.common.generator.utils.OrmGenDataSourceUtil; +import cn.hutool.core.io.IoUtil; +import org.apache.poi.xwpf.usermodel.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ClassPathResource; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@RestController +@RequestMapping("/api/template") +public class DocxTemplateController { + + + @Autowired + private OrmGenDataSourceUtil ormGenDataSourceUtil; + + private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\$\\{(.+?)\\}"); + + /** + * 替换字符串中 ${key},JDK8兼容 + */ + private String replaceContent(String text, Map dataMap) { + if (text == null) return ""; + Matcher matcher = PLACEHOLDER_PATTERN.matcher(text); + StringBuffer sb = new StringBuffer(); + while (matcher.find()) { + String key = matcher.group(1).trim(); + Object val = dataMap.get(key); + String realVal = val == null ? "" : val.toString(); + matcher.appendReplacement(sb, Matcher.quoteReplacement(realVal)); + } + matcher.appendTail(sb); + return sb.toString(); + } + + @GetMapping("/downloadDocx") + public void downloadDocx(@RequestParam("id") String quotationId, HttpServletResponse response) { + XWPFDocument document = null; + InputStream templateIs = null; + OutputStream out = null; + try { + // 1. 查数据 + ObjectValue objectValue = ormGenDataSourceUtil.queryOne("quotation", quotationId); + Map hashMap = new HashMap<>(); + hashMap.put("name", objectValue.getString("name")); + hashMap.put("number", objectValue.getString("number")); + hashMap.put("create_time", objectValue.getString("create_time")); + hashMap.put("qty", objectValue.getObjectValue("qty")); + ObjectValue managerperson = objectValue.getObjectValue("managerperson"); + if(managerperson != null){ + managerperson = ormGenDataSourceUtil.queryOne(managerperson.getTableName(), managerperson.getString("id")); + hashMap.put("managerperson",1); + } + // 2. 读模板 + File file = new File("D:\\work\\xykj-project\\xhgl\\zz-resource\\quotation_template.docx"); + templateIs = new FileInputStream(file); + document = new XWPFDocument(templateIs); + // 3. 替换占位符 + replaceParagraph(document, hashMap); + replaceTable(document, hashMap); + // 4. 设置响应头 —— 关键! + response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); + response.setCharacterEncoding("UTF-8"); + String fileName = URLEncoder.encode("报价单.docx", StandardCharsets.UTF_8.name()) + .replaceAll("\\+", "%20"); + // 兼容各浏览器的文件名写法 + response.setHeader("Content-Disposition", + "attachment; filename=\"" + fileName + "\"; filename*=UTF-8''" + fileName); + response.setHeader("Pragma", "no-cache"); + response.setHeader("Cache-Control", "no-cache"); + response.setDateHeader("Expires", 0); + // 5. 写出 + out = response.getOutputStream(); + document.write(out); + out.flush(); + } catch (Exception e) { + e.printStackTrace(); + throw new MyRuntimeException("导出失败: " + e.getMessage()); + } finally { + IoUtil.close(document); + IoUtil.close(templateIs); + IoUtil.close(out); + } + } + + + + + private void replaceParagraph(XWPFDocument document, Map dataMap) { + for (XWPFParagraph paragraph : document.getParagraphs()) { + String text = paragraph.getText(); + Matcher matcher = PLACEHOLDER_PATTERN.matcher(text); + if (!matcher.find()) { + continue; + } + //清空原有run + for (XWPFRun run : paragraph.getRuns()) { + run.setText("", 0); + } + String newText = replaceContent(text, dataMap); + paragraph.createRun().setText(newText); + } + } + + private void replaceTable(XWPFDocument document, Map dataMap) { + for (XWPFTable table : document.getTables()) { + for (XWPFTableRow row : table.getRows()) { + for (XWPFTableCell cell : row.getTableCells()) { + for (XWPFParagraph paragraph : cell.getParagraphs()) { + String text = paragraph.getText(); + Matcher matcher = PLACEHOLDER_PATTERN.matcher(text); + if (!matcher.find()) { + continue; + } + for (XWPFRun run : paragraph.getRuns()) { + run.setText("", 0); + } + String newText = replaceContent(text, dataMap); + paragraph.createRun().setText(newText); + } + } + } + } + } + + +} From 4b8f8eefbff464b383dd9c3dab682008e8583529 Mon Sep 17 00:00:00 2001 From: myf Date: Sat, 15 Aug 2026 15:43:12 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E4=BF=9D=E5=AD=98=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/member/MembershipSavePlugin.java | 360 +++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 common/common-association/src/main/java/apelet/association/plugin/member/MembershipSavePlugin.java diff --git a/common/common-association/src/main/java/apelet/association/plugin/member/MembershipSavePlugin.java b/common/common-association/src/main/java/apelet/association/plugin/member/MembershipSavePlugin.java new file mode 100644 index 0000000..b36b002 --- /dev/null +++ b/common/common-association/src/main/java/apelet/association/plugin/member/MembershipSavePlugin.java @@ -0,0 +1,360 @@ +package apelet.association.plugin.member; + +import apelet.common.core.exception.MyRuntimeException; +import apelet.common.core.object.ObjectCollection; +import apelet.common.core.object.ObjectValue; +import apelet.common.online.abstractplugin.ExecutePluginParent; +import apelet.common.orm.impl.Filter; +import apelet.common.orm.impl.FilterItem; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.Map; + +/** + * @ClassName: test + * @Date: 2026/8/14 + * @Description: PC 与移动端共用的"保存"插件 + * 场景:移动端小程序无法直连后端调试,将 PC 表单与移动端绑定同一个插件, + * 在 PC 上点击"保存"即可复现移动端小程序的保存逻辑,控制台/日志可看到保存报错。 + * + * 保存逻辑: + * 1. 根据表单 id 区分"新增"与"修改": + * - 新增(id 为空/0):先按 unit_name 验重,已存在则拒绝新增;否则生成单据号(S + yyyyMMdd + 4 位流水)后 addNew + * - 修改(id 非空):按 id 直接 update,不验重 + * 2. 无论新增还是修改,均写入默认值:flow_status / flow_approval_status / org / srcbillid / srcbillnumber / srcentryid = 0,history = 1 + */ +public class MembershipSavePlugin extends ExecutePluginParent { + + /** 保存的目标主表 */ + private static final String TABLE_NAME = "membership_apply"; + + /** 单据号前缀 */ + private static final String NUMBER_PREFIX = "S"; + + /** 单据号日期格式 */ + private static final String DATE_PATTERN = "yyyyMMdd"; + + /** 流水号位数(不足补零,如 0001) */ + private static final int SEQ_LENGTH = 4; + + /** 唯一键:单位名称数据库字段 */ + private static final String FIELD_UNIT_NAME = "unit_name"; + + /** 数据库字段 -> 表单控件 key 映射(与 UnitNameChangeFormInitPlugin 保持一致) */ + private static final Map DB_FIELD_WIDGET_MAPPING = new HashMap<>(); + + static { + DB_FIELD_WIDGET_MAPPING.put("create_user_id", "createUserId"); + DB_FIELD_WIDGET_MAPPING.put("create_time", "createTime"); + DB_FIELD_WIDGET_MAPPING.put("update_user_id", "updateUserId"); + DB_FIELD_WIDGET_MAPPING.put("update_time", "updateTime"); + DB_FIELD_WIDGET_MAPPING.put("deleted_flag", "deletedFlag"); + DB_FIELD_WIDGET_MAPPING.put("is_history", "history"); + DB_FIELD_WIDGET_MAPPING.put("nature_unit", "natureUnit"); + DB_FIELD_WIDGET_MAPPING.put("unit_name", "unitName"); + DB_FIELD_WIDGET_MAPPING.put("membership_manger_id", "membershipMangerId"); + DB_FIELD_WIDGET_MAPPING.put("membership_type", "membershipType"); + DB_FIELD_WIDGET_MAPPING.put("menbership_attributes", "menbershipAttributes"); + DB_FIELD_WIDGET_MAPPING.put("scope_business", "scopeBusiness"); + DB_FIELD_WIDGET_MAPPING.put("business_regist_number", "businessRegistNumber"); + DB_FIELD_WIDGET_MAPPING.put("regist_capital", "registCapital"); + DB_FIELD_WIDGET_MAPPING.put("regist_time", "registTime"); + DB_FIELD_WIDGET_MAPPING.put("company_address", "companyAddress"); + DB_FIELD_WIDGET_MAPPING.put("version_number", "versionNumber"); + DB_FIELD_WIDGET_MAPPING.put("change_reason", "changeReason"); + } + + /** 保存时需要跳过的非主表字段(objectValue 中的控件 key) */ + private static final String[] SKIP_WIDGET_KEYS = { + "id", // 主键,由框架自动生成或单独处理 + "eventparams", // 弹窗参数,非表字段 + "sourcebillid", // 来源单据参数 + "srcbillid", + "sourcebillnumber", + "srcbillnumber", + "membership_apply_entry", // 子表(本次保存不处理子表) + "table1777360622546", + "rowkeysubset" // 框架内部字段 + }; + + /** + * 按钮点击事件:处理"保存"按钮 + * + * @param widgetVariableName 按钮标识 + * @param objectValue 当前表单数据对象 + */ + @Override + public void buttonTriggered(String widgetVariableName, ObjectValue objectValue) { + // 仅响应"保存"按钮 + if (!"保存".equals(widgetVariableName)) { + return; + } + + try { + // 根据表单 id 区分新增/修改 + boolean isNew = isNewBill(objectValue); + if (isNew) { + // 新增:先按 unit_name 验重,再生成单据号入库 + saveAsNew(objectValue); + this.showMessage("保存成功(新增)"); + } else { + // 修改:按 id 直接更新,不验重 + saveAsUpdate(objectValue); + this.showMessage("保存成功(修改)"); + } + this.cancelOperate(); + } catch (Exception e) { + // 保存失败:打印完整堆栈到控制台/日志,便于定位移动端小程序保存报错 + e.printStackTrace(); + // 抛出异常,让 PC 端弹窗显示具体错误 + throw new MyRuntimeException("保存失败:" + e.getMessage()); + } + } + + /** + * 判断当前表单是新增还是修改 + * 表单 id 为空或 0 视为新增,否则视为修改 + * + * @param objectValue 表单数据对象 + * @return true 表示新增 + */ + private boolean isNewBill(ObjectValue objectValue) { + Object idObj = objectValue.get("id"); + if (idObj == null) { + return true; + } + String idStr = idObj.toString().trim(); + return idStr.isEmpty() || "0".equals(idStr); + } + + /** + * 新增逻辑:按 unit_name 验重 -> 生成单据号 -> addNew + * + * @param objectValue 表单数据对象 + */ + private void saveAsNew(ObjectValue objectValue) throws Exception { + // 取唯一键单位名称(兼容 unit_name / unitName 两种控件 key) + String unitName = getUnitName(objectValue); + + // 新增验重:unit_name 已存在则拒绝新增 + ObjectValue existBill = findExistBillByUnitName(unitName); + if (existBill != null) { + throw new MyRuntimeException("单位【" + unitName + "】已存在,请勿重复新增"); + } + + // 自动生成单据号(S + yyyyMMdd + 4 位流水号) + String number = generateNumber(); + // 组装数据库记录并新增 + ObjectValue newBill = buildNewBill(objectValue, number); + ormGenDataSourceUtil().addNew(TABLE_NAME, newBill); + } + + /** + * 修改逻辑:按 id 组装记录并 update(不验重) + * 先查出原记录的单据号 number 并填回,避免整体覆盖更新时把 number 置为 null + * + * @param objectValue 表单数据对象 + */ + private void saveAsUpdate(ObjectValue objectValue) throws Exception { + ObjectValue updateBill = buildUpdateBill(objectValue); + + // 按主键查询原记录,把单据号 number 填回(update 为整体覆盖,缺失字段会被置空) + Object idObj = objectValue.get("id"); + if (idObj != null) { + Filter filter = new Filter(); + filter.add(new FilterItem("id", FilterItem.equals, idObj)); + ObjectCollection collection = ormGenDataSourceUtil().query(TABLE_NAME, filter, null); + if (collection != null && !collection.isEmpty()) { + String existNumber = collection.getObject(0).getString("number"); + if (existNumber != null && !existNumber.isEmpty()) { + updateBill.put("number", existNumber); + } + } + } + + ormGenDataSourceUtil().update(TABLE_NAME, updateBill, null); + } + + /** + * 根据单位名称查询已存在的单据(用于新增验重) + * + * @param unitName 单位名称 + * @return 已存在的单据;不存在返回 null + */ + private ObjectValue findExistBillByUnitName(String unitName) throws Exception { + if (unitName == null || unitName.trim().isEmpty()) { + return null; + } + Filter filter = new Filter(); + filter.add(new FilterItem(FIELD_UNIT_NAME, FilterItem.equals, unitName)); + ObjectCollection collection = ormGenDataSourceUtil().query(TABLE_NAME, filter, null); + if (collection != null && !collection.isEmpty()) { + return collection.getObject(0); + } + return null; + } + + /** + * 组装新增记录:填充表单字段 + 单据号 + 默认值 + * + * @param objectValue 表单数据对象 + * @param number 自动生成的单据号 + * @return 组装好的数据库记录 + */ + private ObjectValue buildNewBill(ObjectValue objectValue, String number) { + ObjectValue newBill = new ObjectValue(TABLE_NAME); + fillFields(newBill, objectValue); + // 设置自动生成的单据号 + newBill.put("number", number); + // 设置默认值 + setDefaultValues(newBill); + return newBill; + } + + /** + * 组装修改记录:带主键 id,覆盖表单字段,单据号保留数据库原值 + * + * @param objectValue 表单数据对象 + * @return 组装好的数据库记录 + */ + private ObjectValue buildUpdateBill(ObjectValue objectValue) { + ObjectValue bill = new ObjectValue(TABLE_NAME); + // 主键 id 作为 update 条件 + Object idObj = objectValue.get("id"); + if (idObj != null) { + bill.put("id", idObj); + } + fillFields(bill, objectValue); + // 设置默认值 + setDefaultValues(bill); + return bill; + } + + /** + * 把表单字段复制到目标记录(跳过 id、number、非主表字段,控件 key 转数据库字段) + * + * @param target 目标数据库记录 + * @param source 表单数据对象 + */ + private void fillFields(ObjectValue target, ObjectValue source) { + Map values = source.getValues(); + if (values == null) { + return; + } + for (Object item : values.entrySet()) { + Map.Entry entry = (Map.Entry) item; + String widgetKey = entry.getKey().toString(); + + // 跳过主键、参数、子表等非主表字段 + if (shouldSkipField(widgetKey)) { + continue; + } + + // 控件 key 转成数据库字段名 + String dbKey = getDbFieldKey(widgetKey); + // id 由单独逻辑处理,number 保留数据库原值(新增时才生成) + if ("id".equals(dbKey) || "number".equals(dbKey)) { + continue; + } + target.put(dbKey, entry.getValue()); + } + } + + /** + * 设置默认值:流程状态/来源单据等字段 = 0 + * + * @param bill 数据库记录 + */ + private void setDefaultValues(ObjectValue bill) { + bill.put("flow_status", 0); + bill.put("flow_approval_status", 0); + bill.put("org", 0); + bill.put("srcbillid", 0); + bill.put("srcbillnumber", 0); + bill.put("srcentryid", 0); + bill.put("history", 0); + } + + /** + * 自动生成单据号:S + yyyyMMdd + 当天最大流水号 + 1(补 4 位零) + * 例如当天已有 S202608140001,则生成 S202608140002 + * + * @return 新单据号 + */ + private String generateNumber() throws Exception { + String prefix = NUMBER_PREFIX + LocalDate.now().format(DateTimeFormatter.ofPattern(DATE_PATTERN)); + + // 查询当天所有单据号,取最大流水号 + Filter filter = new Filter(); + filter.add(new FilterItem("number", FilterItem.like, prefix + "%")); + ObjectCollection collection = ormGenDataSourceUtil().query(TABLE_NAME, filter, null); + + int maxSeq = 0; + if (collection != null) { + for (int i = 0; i < collection.size(); i++) { + String number = collection.getObject(i).getString("number"); + if (number != null && number.length() > prefix.length()) { + try { + // 截取前缀后的流水号部分并比较 + int seq = Integer.parseInt(number.substring(prefix.length())); + if (seq > maxSeq) { + maxSeq = seq; + } + } catch (NumberFormatException ignored) { + // 忽略非数字流水号 + } + } + } + } + + // 流水号 +1 并补零到指定位数 + return prefix + String.format("%0" + SEQ_LENGTH + "d", maxSeq + 1); + } + + /** + * 获取单位名称(唯一键),兼容 unit_name / unitName 两种控件 key + * + * @param objectValue 表单数据对象 + * @return 单位名称 + */ + private String getUnitName(ObjectValue objectValue) { + String unitName = objectValue.getString(FIELD_UNIT_NAME); + if (unitName == null || unitName.isEmpty()) { + unitName = objectValue.getString("unitName"); + } + return unitName; + } + + /** + * 判断字段是否需要跳过(主键/弹窗参数/来源参数/子表等) + * + * @param widgetKey 控件 key + * @return true 表示跳过 + */ + private boolean shouldSkipField(String widgetKey) { + for (String skipKey : SKIP_WIDGET_KEYS) { + if (skipKey.equalsIgnoreCase(widgetKey)) { + return true; + } + } + return false; + } + + /** + * 控件 key 转数据库字段名(通过 DB_FIELD_WIDGET_MAPPING 反向查找) + * 若未匹配则原样返回(可能是数据库字段名或无需转换的字段) + * + * @param widgetKey 控件 key + * @return 数据库字段名 + */ + private String getDbFieldKey(String widgetKey) { + for (Map.Entry entry : DB_FIELD_WIDGET_MAPPING.entrySet()) { + if (entry.getValue().equalsIgnoreCase(widgetKey)) { + return entry.getKey(); + } + } + return widgetKey; + } +}