Browse Source

Merge remote-tracking branch 'origin/dev' into dev

dev^2
hz 6 days ago
parent
commit
626777dba8
  1. 33
      common/common-association/src/main/java/apelet/association/controller/ContractController.java
  2. 28
      common/common-association/src/main/java/apelet/association/controller/QuotationController.java
  3. 18
      common/common-association/src/main/java/apelet/association/dao/ContractMapper.java
  4. 18
      common/common-association/src/main/java/apelet/association/dao/QuotationMapper.java
  5. 183
      common/common-association/src/main/java/apelet/association/model/Contract.java
  6. 195
      common/common-association/src/main/java/apelet/association/model/Quotation.java
  7. 168
      common/common-association/src/main/java/apelet/association/plugin/active/ActivityLiveArchivePlugin.java
  8. 53
      common/common-association/src/main/java/apelet/association/plugin/clueManage/ClueAuditNewOpPlugin.java
  9. 3
      common/common-association/src/main/java/apelet/association/plugin/clueManage/ClueManageFormPlugin.java
  10. 54
      common/common-association/src/main/java/apelet/association/plugin/clueManage/ClueSubmitNewOpPlugin.java
  11. 53
      common/common-association/src/main/java/apelet/association/plugin/clueManage/ClueUnAuditNewOpPlugin.java
  12. 53
      common/common-association/src/main/java/apelet/association/plugin/clueManage/ClueUnSubmitNewOpPlugin.java
  13. 169
      common/common-association/src/main/java/apelet/association/plugin/electronicJournal/ElectronicJournalFormPlugin.java
  14. 80
      common/common-association/src/main/java/apelet/association/plugin/fileLibraryMange/FileLibrayListPlugin.java
  15. 131
      common/common-association/src/main/java/apelet/association/plugin/quotation/QuotationPlugin.java
  16. 17
      common/common-association/src/main/java/apelet/association/service/ContractService.java
  17. 17
      common/common-association/src/main/java/apelet/association/service/QuotationService.java
  18. 19
      common/common-association/src/main/java/apelet/association/service/impl/ContractServiceImpl.java
  19. 19
      common/common-association/src/main/java/apelet/association/service/impl/QuotationServiceImpl.java
  20. 48
      common/common-association/src/main/java/apelet/association/vo/ContractListVo.java
  21. 48
      common/common-association/src/main/java/apelet/association/vo/QuotationListVo.java
  22. 23
      common/common-association/src/main/resources/mapper/ContractMapper.xml
  23. 29
      common/common-association/src/main/resources/mapper/QuotationMapper.xml

33
common/common-association/src/main/java/apelet/association/controller/ContractController.java

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
package apelet.association.controller;
import apelet.association.service.ContractService;
import apelet.association.vo.ContractListVo;
import apelet.common.core.object.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 合同管理
*/
@RestController
@RequestMapping("/tenantadmin/contract")
public class ContractController {
@Autowired
private ContractService contractService;
/**
* 查询所有合同合同签订日期报价负责人名称总报价产品服务交付日期
*
* @return 合同列表
*/
@GetMapping("/contractList")
public ResponseResult<List<ContractListVo>> contractList() {
List<ContractListVo> result = contractService.contractList();
return ResponseResult.success(result);
}
}

28
common/common-association/src/main/java/apelet/association/controller/QuotationController.java

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
package apelet.association.controller;
import apelet.association.service.QuotationService;
import apelet.association.vo.QuotationListVo;
import apelet.common.core.object.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 报价单管理
*/
@RestController
@RequestMapping("/tenantadmin")
public class QuotationController {
@Autowired
private QuotationService quotationService;
@GetMapping("/quotationSheetList")
public ResponseResult<List<QuotationListVo>> quotationSheetList() {
List<QuotationListVo> result = quotationService.quotationSheetList();
return ResponseResult.success(result);
}
}

18
common/common-association/src/main/java/apelet/association/dao/ContractMapper.java

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
package apelet.association.dao;
import apelet.association.model.Contract;
import apelet.association.vo.ContractListVo;
import apelet.common.core.base.dao.BaseDaoMapper;
import java.util.List;
public interface ContractMapper extends BaseDaoMapper<Contract> {
/**
* 查询所有合同关联 sys_user_info 解析报价负责人姓名
* 仅返回合同签订日期报价负责人(ID+姓名)名称总报价产品服务交付日期
*
* @return 合同列表
*/
List<ContractListVo> contractList();
}

18
common/common-association/src/main/java/apelet/association/dao/QuotationMapper.java

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
package apelet.association.dao;
import apelet.association.model.Quotation;
import apelet.association.vo.QuotationListVo;
import apelet.common.core.base.dao.BaseDaoMapper;
import java.util.List;
public interface QuotationMapper extends BaseDaoMapper<Quotation> {
/**
* 查询所有报价单关联 sys_user_info 解析报价负责人姓名并映射状态字典
* 仅返回创建时间报价负责人(ID+姓名)项目名称总报价状态(key+名称)
*
* @return 报价单列表
*/
List<QuotationListVo> listAllWithManagerName();
}

183
common/common-association/src/main/java/apelet/association/model/Contract.java

@ -0,0 +1,183 @@ @@ -0,0 +1,183 @@
package apelet.association.model;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 合同
*/
@Data
@TableName("contract")
public class Contract implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 创建人登录名称
*/
@TableField("create_user_id")
private String createUserId;
/**
* 创建日期
*/
@TableField("create_time")
private Date createTime;
/**
* 更新人登录名称
*/
@TableField("update_user_id")
private String updateUserId;
/**
* 更新日期
*/
@TableField("update_time")
private Date updateTime;
/**
* 逻辑删除标记(1: 正常 -1: 已删除)
*/
@TableField("deleted_flag")
private Integer deletedFlag;
/**
* 编码
*/
@TableField("number")
private String number;
/**
* 名称
*/
@TableField("name")
private String name;
/**
* 流程状态
*/
@TableField("flow_status")
private Integer flowStatus;
/**
* 流程最新状态
*/
@TableField("flow_approval_status")
private Integer flowApprovalStatus;
/**
* 流程实例id
*/
@TableField("pro_ins_id")
private String proInsId;
/**
* 状态
*/
@TableField("billstatus")
private String billstatus;
/**
* 公司
*/
@TableField("org")
private Integer org;
/**
* 来源单据ID
*/
@TableField("srcbillid")
private Integer srcbillid;
/**
* 来源单据编码
*/
@TableField("srcbillnumber")
private Integer srcbillnumber;
/**
* 来源分录Id
*/
@TableField("srcentryid")
private Integer srcentryid;
/**
* 总报价
*/
@TableField("qty")
private BigDecimal qty;
/**
* 报价负责人ID
*/
@TableField("managerperson")
private Long managerperson;
/**
* 项目类型
*/
@TableField("type")
private String type;
/**
* 合同签订日期
*/
@TableField("signing_date")
private Date signingDate;
/**
* 产品服务交付日期
*/
@TableField("delivery_date")
private Date deliveryDate;
/**
* 分包价格
*/
@TableField("price")
private BigDecimal price;
/**
* 收款计划
*/
@TableField("get_date")
private Date getDate;
/**
* 产品服务交付负责人
*/
@TableField("delivery_person")
private Long deliveryPerson;
/**
* 附件
*/
@TableField("file_text")
private String fileText;
/**
* 分包商
*/
@TableField("subcontractor")
private String subcontractor;
/**
* 客户
*/
@TableField("bd_customer")
private Long bdCustomer;
}

195
common/common-association/src/main/java/apelet/association/model/Quotation.java

@ -0,0 +1,195 @@ @@ -0,0 +1,195 @@
package apelet.association.model;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 报价单
*/
@Data
@TableName("quotation")
public class Quotation implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 创建人登录名称
*/
@TableField("create_user_id")
private String createUserId;
/**
* 创建日期
*/
@TableField("create_time")
private Date createTime;
/**
* 更新人登录名称
*/
@TableField("update_user_id")
private String updateUserId;
/**
* 更新日期
*/
@TableField("update_time")
private Date updateTime;
/**
* 逻辑删除标记(1: 正常 -1: 已删除)
*/
@TableField("deleted_flag")
private Integer deletedFlag;
/**
* 编码
*/
@TableField("number")
private String number;
/**
* 名称
*/
@TableField("name")
private String name;
/**
* 流程状态
*/
@TableField("flow_status")
private Integer flowStatus;
/**
* 流程最新状态
*/
@TableField("flow_approval_status")
private Integer flowApprovalStatus;
/**
* 流程实例id
*/
@TableField("pro_ins_id")
private String proInsId;
/**
* 状态
*/
@TableField("billstatus")
private String billstatus;
/**
* 公司
*/
@TableField("org")
private Integer org;
/**
* 来源单据ID
*/
@TableField("srcbillid")
private Long srcbillid;
/**
* 来源单据编码
*/
@TableField("srcbillnumber")
private Integer srcbillnumber;
/**
* 来源分录Id
*/
@TableField("srcentryid")
private Long srcentryid;
/**
* 项目类型ID
*/
@TableField("type")
private String type;
/**
* 总报价
*/
@TableField("qty")
private BigDecimal qty;
/**
* 报价负责人ID
*/
@TableField("managerperson")
private Long managerperson;
/**
* 报价单状态
*/
@TableField("status")
private String status;
/**
* 取消原因
*/
@TableField("canaelreason")
private String canaelreason;
/**
* 合同签订日期
*/
@TableField("signing_date")
private Date signingDate;
/**
* 产品服务交付日期
*/
@TableField("delivery_date")
private Date deliveryDate;
/**
* 分包价格
*/
@TableField("price")
private BigDecimal price;
/**
* 收款计划
*/
@TableField("get_date")
private Date getDate;
/**
* 产品服务交付负责人
*/
@TableField("delivery_person")
private Long deliveryPerson;
/**
* 附件
*/
@TableField("file_text")
private String fileText;
/**
* 分包商
*/
@TableField("subcontractor")
private String subcontractor;
/**
* 客户
*/
@TableField("bd_customer")
private Long bdCustomer;
}

168
common/common-association/src/main/java/apelet/association/plugin/active/ActivityLiveArchivePlugin.java

@ -0,0 +1,168 @@ @@ -0,0 +1,168 @@
package apelet.association.plugin.active;
import apelet.association.plugin.fileLibraryMange.FileLibrayFormPlugin;
import apelet.common.core.exception.MyRuntimeException;
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.abstractplugin.ExecutePluginParent;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
/**
* 活动直播文件归档插件
* 监听 association_activity 表单的"保存"按钮
* 将活动直播视频文件video 字段归档到文件库表 file_library
* - video 附件 JSON 数组整体存入 file_library.file_name
* - 自动解析第一个文件的大小与类型写入 file_size / file_type
* - 归档默认值分类classification4阅读权限read_auth1
* 阅读次数read_count0发布状态publish_status1
* - 补齐创建人/创建时间等公共字段其余字段保持 null
* 注意每次点击"保存"都会新增一条文件库记录
*/
public class ActivityLiveArchivePlugin extends ExecutePluginParent {
/** 文件库目标表 */
private static final String FILE_LIBRARY_TABLE = "file_library";
private final OrmGenDataSourceUtil ormGenDataSourceUtil;
public ActivityLiveArchivePlugin() {
ormGenDataSourceUtil = ApplicationContextHolder.getBean(OrmGenDataSourceUtil.class);
}
/**
* 按钮触发事件检测到"保存"按钮时将活动直播视频归档到文件库
*
* @param widgetVariableName 按钮标识
* @param objectValue 当前表单数据对象
*/
@Override
public void buttonTriggered(String widgetVariableName, ObjectValue objectValue) {
super.buttonTriggered(widgetVariableName, objectValue);
// 仅响应"保存"按钮
if (!"保存".equals(widgetVariableName)) {
return;
}
saveLiveVideoToFileLibrary(objectValue);
}
/**
* 保存活动直播视频到文件库表 file_library
* 视频字段为空时直接跳过不写入任何记录
*
* @param objectValue 活动表单数据对象
*/
private void saveLiveVideoToFileLibrary(ObjectValue objectValue) {
// 读取活动直播视频字段(association_activity.video),为空则跳过
Object videoObj = objectValue.get("video");
if (videoObj == null) {
return;
}
String videoText = videoObj.toString();
if (videoText.isEmpty()) {
return;
}
// 解析附件 JSON 数组
JSONArray fileArray;
try {
fileArray = JSON.parseArray(videoText);
} catch (Exception e) {
fileArray = null;
}
if (fileArray == null || fileArray.isEmpty()) {
return;
}
// file_size / file_type 为单值字段,取第一个文件的大小与类型
String fileType = null;
String fileSize = null;
JSONObject firstFile = fileArray.getJSONObject(0);
if (firstFile != null) {
fileType = resolveFileType(firstFile.getString("filename"));
fileSize = resolveFileSize(firstFile);
}
// 当前登录用户与当前时间(公共字段)
TokenData tokenData = TokenData.takeFromRequest();
Long userId = tokenData == null ? null : tokenData.getUserId();
Date now = new Date();
// 组装 file_library 记录
ObjectValue record = new ObjectValue(FILE_LIBRARY_TABLE);
record.put("file_name", videoText);
record.put("file_type", fileType);
record.put("file_size", fileSize);
// 活动直播归档默认值:分类 4、阅读权限 1、阅读次数 0、发布状态 1
record.put("classification", "4");
record.put("read_auth", "1");
record.put("read_count", 0);
record.put("publish_status", "1");
// 公共字段
record.put("create_user_id", userId);
record.put("create_time", now);
record.put("update_user_id", userId);
record.put("update_time", now);
record.put("deleted_flag", 1);
// 插入文件库表,主键 id 由框架自动生成
try {
ormGenDataSourceUtil.addNew(FILE_LIBRARY_TABLE, record);
} catch (Exception e) {
throw new MyRuntimeException("保存活动直播文件到文件库失败:" + e.getMessage());
}
}
/**
* 通过 HEAD 请求获取 OSS 文件大小并格式化为 KB/MB 展示字符串
* 获取失败返回 null不阻塞保存流程
*
* @param file 附件 JSON 中的单个文件对象
* @return 格式化后的文件大小 "1.6 MB"失败返回 null
*/
private String resolveFileSize(JSONObject file) {
String baseUrl = file.getString("baseUrl");
String uploadPath = file.getString("uploadPath");
String filename = file.getString("filename");
if (baseUrl == null || uploadPath == null || filename == null) {
return null;
}
String fullUrl = baseUrl + "/" + uploadPath + "/" + filename;
HttpURLConnection connection = null;
try {
URL url = new URL(fullUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("HEAD");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.connect();
long fileSize = connection.getContentLengthLong();
if (fileSize > 0) {
return FileLibrayFormPlugin.formatFileSize(fileSize);
}
} catch (Exception e) {
// 获取大小失败时返回 null,不影响保存
System.out.println("获取附件文件大小失败:" + fullUrl + "," + e.getMessage());
} finally {
if (connection != null) {
connection.disconnect();
}
}
return null;
}
/**
* 从文件名提取扩展名作为文件类型 "直播回放.mp4" -> "mp4"
*
* @param fileName 文件名
* @return 文件扩展名无法识别返回 null
*/
private String resolveFileType(String fileName) {
if (fileName == null || fileName.isEmpty() || !fileName.contains(".")) {
return null;
}
return fileName.substring(fileName.lastIndexOf(".") + 1);
}
}

53
common/common-association/src/main/java/apelet/association/plugin/clueManage/ClueAuditNewOpPlugin.java

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
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.util.ApplicationContextHolder;
import apelet.common.generator.utils.OrmGenDataSourceUtil;
import apelet.common.online.plugin.BeginOperationTransactionArgs;
import apelet.common.online.plugin.OperationServicePlugIn;
import apelet.common.online.plugin.OperationServicePlugInArgs;
import apelet.common.orm.impl.Selector;
import apelet.common.orm.impl.SelectorItem;
public class ClueAuditNewOpPlugin extends OperationServicePlugIn {
private final OrmGenDataSourceUtil ormGenDataSourceUtil;
public ClueAuditNewOpPlugin() {
ormGenDataSourceUtil = ApplicationContextHolder.getBean(OrmGenDataSourceUtil.class);
}
@Override
public void onPreparePropertys(OperationServicePlugInArgs e) {
e.addFiledKey("id");
e.addFiledKey("status");
}
@Override
public void beginOperationTransaction(BeginOperationTransactionArgs e) {
super.beginOperationTransaction(e);
ObjectCollection modelCollcetion = e.getModelCollcetion();
if (modelCollcetion != null && !modelCollcetion.isEmpty()) {
for (int i = 0; i < modelCollcetion.size(); i++) {
try {
// 获取单据对象
ObjectValue bill = modelCollcetion.getObject(i);
if (bill.get("status").equals("B")) {
bill.put("status", "C");
Selector selector = new Selector();
selector.getList().add(new SelectorItem("status"));
ormGenDataSourceUtil.update(bill.getTableName(), bill, selector);
} else {
throw new MyRuntimeException("单据不为提交状态");
}
} catch (Exception ex) {
throw new MyRuntimeException(ex.getMessage());
}
}
}
}
}

3
common/common-association/src/main/java/apelet/association/plugin/clueManage/ClueManageFormPlugin.java

@ -62,6 +62,9 @@ public class ClueManageFormPlugin extends ExecutePluginParent { @@ -62,6 +62,9 @@ public class ClueManageFormPlugin extends ExecutePluginParent {
if (objectValue.get("clue_type") == null) {
this.setWidgetAttribute("billstatus", AttributeEnum.VALUE_CHANGE, "A");
}
if (objectValue.get("clue_type") == null) {
this.setWidgetAttribute("status", AttributeEnum.VALUE_CHANGE, "A");
}
}

54
common/common-association/src/main/java/apelet/association/plugin/clueManage/ClueSubmitNewOpPlugin.java

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
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.util.ApplicationContextHolder;
import apelet.common.generator.utils.OrmGenDataSourceUtil;
import apelet.common.online.plugin.BeginOperationTransactionArgs;
import apelet.common.online.plugin.OperationResult;
import apelet.common.online.plugin.OperationServicePlugIn;
import apelet.common.online.plugin.OperationServicePlugInArgs;
import apelet.common.orm.impl.Selector;
import apelet.common.orm.impl.SelectorItem;
public class ClueSubmitNewOpPlugin extends OperationServicePlugIn {
private final OrmGenDataSourceUtil ormGenDataSourceUtil;
public ClueSubmitNewOpPlugin() {
ormGenDataSourceUtil = ApplicationContextHolder.getBean(OrmGenDataSourceUtil.class);
}
@Override
public void onPreparePropertys(OperationServicePlugInArgs e) {
e.addFiledKey("id");
e.addFiledKey("status");
}
@Override
public void beginOperationTransaction(BeginOperationTransactionArgs e) {
super.beginOperationTransaction(e);
ObjectCollection modelCollcetion = e.getModelCollcetion();
if (modelCollcetion != null && !modelCollcetion.isEmpty()) {
for (int i = 0; i < modelCollcetion.size(); i++) {
try {
// 获取单据对象
ObjectValue bill = modelCollcetion.getObject(i);
if (bill.get("status").equals("A")) {
bill.put("status", "B");
Selector selector = new Selector();
selector.getList().add(new SelectorItem("status"));
ormGenDataSourceUtil.update(bill.getTableName(), bill, selector);
} else {
throw new MyRuntimeException("单据不为编辑状态");
}
} catch (Exception ex) {
throw new MyRuntimeException(ex.getMessage());
}
}
}
}
}

53
common/common-association/src/main/java/apelet/association/plugin/clueManage/ClueUnAuditNewOpPlugin.java

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
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.util.ApplicationContextHolder;
import apelet.common.generator.utils.OrmGenDataSourceUtil;
import apelet.common.online.plugin.BeginOperationTransactionArgs;
import apelet.common.online.plugin.OperationServicePlugIn;
import apelet.common.online.plugin.OperationServicePlugInArgs;
import apelet.common.orm.impl.Selector;
import apelet.common.orm.impl.SelectorItem;
public class ClueUnAuditNewOpPlugin extends OperationServicePlugIn {
private final OrmGenDataSourceUtil ormGenDataSourceUtil;
public ClueUnAuditNewOpPlugin() {
ormGenDataSourceUtil = ApplicationContextHolder.getBean(OrmGenDataSourceUtil.class);
}
@Override
public void onPreparePropertys(OperationServicePlugInArgs e) {
e.addFiledKey("id");
e.addFiledKey("status");
}
@Override
public void beginOperationTransaction(BeginOperationTransactionArgs e) {
super.beginOperationTransaction(e);
ObjectCollection modelCollcetion = e.getModelCollcetion();
if (modelCollcetion != null && !modelCollcetion.isEmpty()) {
for (int i = 0; i < modelCollcetion.size(); i++) {
try {
// 获取单据对象
ObjectValue bill = modelCollcetion.getObject(i);
if (bill.get("status").equals("C")) {
bill.put("status", "A");
Selector selector = new Selector();
selector.getList().add(new SelectorItem("status"));
ormGenDataSourceUtil.update(bill.getTableName(), bill, selector);
} else {
throw new MyRuntimeException("单据不为审核状态");
}
} catch (Exception ex) {
throw new MyRuntimeException(ex.getMessage());
}
}
}
}
}

53
common/common-association/src/main/java/apelet/association/plugin/clueManage/ClueUnSubmitNewOpPlugin.java

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
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.util.ApplicationContextHolder;
import apelet.common.generator.utils.OrmGenDataSourceUtil;
import apelet.common.online.plugin.BeginOperationTransactionArgs;
import apelet.common.online.plugin.OperationServicePlugIn;
import apelet.common.online.plugin.OperationServicePlugInArgs;
import apelet.common.orm.impl.Selector;
import apelet.common.orm.impl.SelectorItem;
public class ClueUnSubmitNewOpPlugin extends OperationServicePlugIn {
private final OrmGenDataSourceUtil ormGenDataSourceUtil;
public ClueUnSubmitNewOpPlugin() {
ormGenDataSourceUtil = ApplicationContextHolder.getBean(OrmGenDataSourceUtil.class);
}
@Override
public void onPreparePropertys(OperationServicePlugInArgs e) {
e.addFiledKey("id");
e.addFiledKey("status");
}
@Override
public void beginOperationTransaction(BeginOperationTransactionArgs e) {
super.beginOperationTransaction(e);
ObjectCollection modelCollcetion = e.getModelCollcetion();
if (modelCollcetion != null && !modelCollcetion.isEmpty()) {
for (int i = 0; i < modelCollcetion.size(); i++) {
try {
// 获取单据对象
ObjectValue bill = modelCollcetion.getObject(i);
if (bill.get("status").equals("B")) {
bill.put("status", "A");
Selector selector = new Selector();
selector.getList().add(new SelectorItem("status"));
ormGenDataSourceUtil.update(bill.getTableName(), bill, selector);
} else {
throw new MyRuntimeException("单据不为提交状态不能撤销");
}
} catch (Exception ex) {
throw new MyRuntimeException(ex.getMessage());
}
}
}
}
}

169
common/common-association/src/main/java/apelet/association/plugin/electronicJournal/ElectronicJournalFormPlugin.java

@ -1,13 +1,22 @@ @@ -1,13 +1,22 @@
package apelet.association.plugin.electronicJournal;
import apelet.association.plugin.fileLibraryMange.FileLibrayFormPlugin;
import apelet.common.core.exception.MyRuntimeException;
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.abstractplugin.ExecutePluginParent;
import apelet.common.online.model.constant.AttributeEnum;
import apelet.common.orm.impl.Selector;
import apelet.common.orm.impl.SelectorItem;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
public class ElectronicJournalFormPlugin extends ExecutePluginParent {
@ -17,21 +26,155 @@ public class ElectronicJournalFormPlugin extends ExecutePluginParent { @@ -17,21 +26,155 @@ public class ElectronicJournalFormPlugin extends ExecutePluginParent {
ormGenDataSourceUtil = ApplicationContextHolder.getBean(OrmGenDataSourceUtil.class);
}
// @Override
// public void formCreated(String widgetVariableName, ObjectValue objectValue) {
// super.formCreated(widgetVariableName, objectValue);
// Object viewCount = objectValue.get("view_count");
// if (viewCount == null) {
// this.setWidgetAttribute("viewCount", AttributeEnum.VALUE_CHANGE, "0");
// } else {
// objectValue.put("view_count", (Integer) viewCount + 1);
// Selector selector = new Selector();
// selector.getList().add(new SelectorItem("view_count"));
// try {
// ormGenDataSourceUtil.update(objectValue.getTableName(), objectValue, selector);
// } catch (Exception e) {
// throw new MyRuntimeException(e.getMessage());
// }
// }
// }
/**
* 按钮触发事件检测到"保存"按钮时将电子期刊附件file同步写入文件库表 file_library
* - file 附件 JSON 数组整体存入 file_library.file_name
* - 自动解析第一个文件的大小与类型写入 file_size / file_type
* - 阅读权限read_auth阅读次数read_count状态publish_status分类classification默认 0
* - 补齐创建人/创建时间等公共字段其余字段保持 null
* 注意每次点击"保存"都会新增一条文件库记录
*
* @param widgetVariableName 按钮标识
* @param objectValue 当前表单数据对象
*/
@Override
public void formCreated(String widgetVariableName, ObjectValue objectValue) {
super.formCreated(widgetVariableName, objectValue);
Object viewCount = objectValue.get("view_count");
if (viewCount == null) {
this.setWidgetAttribute("viewCount", AttributeEnum.VALUE_CHANGE, "0");
} else {
objectValue.put("view_count", (Integer) viewCount + 1);
Selector selector = new Selector();
selector.getList().add(new SelectorItem("view_count"));
try {
ormGenDataSourceUtil.update(objectValue.getTableName(), objectValue, selector);
} catch (Exception e) {
throw new MyRuntimeException(e.getMessage());
public void buttonTriggered(String widgetVariableName, ObjectValue objectValue) {
super.buttonTriggered(widgetVariableName, objectValue);
// 仅响应"保存"按钮
if (!"保存".equals(widgetVariableName)) {
return;
}
saveAttachmentToFileLibrary(objectValue);
}
/**
* 保存电子期刊附件到文件库表 file_library
* 附件为空时直接跳过不写入任何记录
*
* @param objectValue 电子期刊表单数据对象
*/
private void saveAttachmentToFileLibrary(ObjectValue objectValue) {
// 读取附件字段(电子期刊表单的附件控件为 file),附件为空则跳过
Object fileObj = objectValue.get("file");
if (fileObj == null) {
return;
}
String fileText = fileObj.toString();
if (fileText.isEmpty()) {
return;
}
// 解析附件 JSON 数组
JSONArray fileArray;
try {
fileArray = JSON.parseArray(fileText);
} catch (Exception e) {
fileArray = null;
}
if (fileArray == null || fileArray.isEmpty()) {
return;
}
// file_size / file_type 为单值字段,取第一个文件的大小与类型
String fileType = null;
String fileSize = null;
JSONObject firstFile = fileArray.getJSONObject(0);
if (firstFile != null) {
fileType = resolveFileType(firstFile.getString("filename"));
fileSize = resolveFileSize(firstFile);
}
// 当前登录用户与当前时间(公共字段)
TokenData tokenData = TokenData.takeFromRequest();
Long userId = tokenData == null ? null : tokenData.getUserId();
Date now = new Date();
// 组装 file_library 记录
ObjectValue record = new ObjectValue("file_library");
record.put("file_name", fileText);
record.put("file_type", fileType);
record.put("file_size", fileSize);
// 阅读权限、阅读次数、状态、分类默认 0
record.put("read_auth", "1");
record.put("read_count", 0);
record.put("publish_status", "1");
record.put("classification", "2");
// 公共字段
record.put("create_user_id", userId);
record.put("create_time", now);
record.put("update_user_id", userId);
record.put("update_time", now);
record.put("deleted_flag", 1);
// 插入文件库表,主键 id 由框架自动生成
try {
ormGenDataSourceUtil.addNew("file_library", record);
} catch (Exception e) {
throw new MyRuntimeException("保存附件到文件库失败:" + e.getMessage());
}
}
/**
* 通过 HEAD 请求获取 OSS 文件大小并格式化为 KB/MB 展示字符串
* 获取失败返回 null不阻塞保存流程
*
* @param file 附件 JSON 中的单个文件对象
* @return 格式化后的文件大小 "1.6 MB"失败返回 null
*/
private String resolveFileSize(JSONObject file) {
String baseUrl = file.getString("baseUrl");
String uploadPath = file.getString("uploadPath");
String filename = file.getString("filename");
if (baseUrl == null || uploadPath == null || filename == null) {
return null;
}
String fullUrl = baseUrl + "/" + uploadPath + "/" + filename;
HttpURLConnection connection = null;
try {
URL url = new URL(fullUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("HEAD");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.connect();
long fileSize = connection.getContentLengthLong();
if (fileSize > 0) {
return FileLibrayFormPlugin.formatFileSize(fileSize);
}
} catch (Exception e) {
// 获取大小失败时返回 null,不影响保存
System.out.println("获取附件文件大小失败:" + fullUrl + "," + e.getMessage());
} finally {
if (connection != null) {
connection.disconnect();
}
}
return null;
}
/**
* 从文件名提取扩展名作为文件类型 "期刊.pdf" -> "pdf"
*
* @param fileName 文件名
* @return 文件扩展名无法识别返回 null
*/
private String resolveFileType(String fileName) {
if (fileName == null || fileName.isEmpty() || !fileName.contains(".")) {
return null;
}
return fileName.substring(fileName.lastIndexOf(".") + 1);
}
}

80
common/common-association/src/main/java/apelet/association/plugin/fileLibraryMange/FileLibrayListPlugin.java

@ -1,5 +1,10 @@ @@ -1,5 +1,10 @@
package apelet.association.plugin.fileLibraryMange;
import apelet.common.core.object.ObjectValue;
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.abstractplugin.ListPlugin;
import apelet.common.online.dto.OnlineEventPluginExecuteDto;
import apelet.common.online.dto.OnlineFilterDto;
@ -7,21 +12,84 @@ import apelet.common.orm.impl.Filter; @@ -7,21 +12,84 @@ import apelet.common.orm.impl.Filter;
import apelet.common.orm.impl.FilterItem;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class FileLibrayListPlugin extends ListPlugin {
@Override
protected Filter getFilter() {
public String getSql(ObjectValue objectValue) {
OnlineEventPluginExecuteDto filter1 = this.getDto();
ArrayList<OnlineFilterDto> filterDtoList = (ArrayList<OnlineFilterDto>) filter1.getListParams().get("filterDtoList");
Filter filter = new Filter();
// return super.getSql(objectValue);
String sql = "select * from file_library ";
//阅读权限
sql += "where (read_auth = 1";
if (!filterDtoList.isEmpty()) {
OnlineFilterDto onlineFilterDto = filterDtoList.get(0);
Object filterFile = onlineFilterDto.getColumnValue();
filter.add(new FilterItem("classification", "=", filterFile));
//上线
sql += " and classification = "+filterFile.toString();
}
System.out.println(sql);
Long userId = TokenData.takeFromRequest().getUserId();
//获取当前用户
ObjectValue user = ormGenDataSourceUtil().queryOne("xy_sys_user", userId);
String userName = user.getString("show_name");
String userType = user.getString("user_type");
} else {
filter = new Filter();
System.out.println("userName:" + userName+user.getString("user_type"));
if (userType.equals("0")) {
sql += " or read_auth = 2";
}
sql += " and publish_status = 1";
sql += " or (create_user_id = "+userId.toString()+" and read_auth = 3))";
//下线
sql += " or (publish_status = 2";
if (!filterDtoList.isEmpty()) {
OnlineFilterDto onlineFilterDto = filterDtoList.get(0);
Object filterFile = onlineFilterDto.getColumnValue();
sql += " and classification = "+filterFile.toString();
}
return filter;
if (userType.equals("0")) {
sql += " or read_auth = 2";
}
sql += " or (create_user_id = "+userId.toString()+" and read_auth = 3))";
return sql;
}
/**
* 编辑按钮检测仅允许选中文件的 classification=5上传文件时才可编辑
* 否则提示并取消编辑操作
*
* @param widgetVariableName 按钮标识
* @param objectValue 当前事件数据对象
*/
@Override
public void buttonTriggered(String widgetVariableName, ObjectValue objectValue) {
super.buttonTriggered(widgetVariableName, objectValue);
// 仅对"编辑"按钮做检测
if (!"编辑".equals(widgetVariableName)) {
return;
}
// 获取列表当前选中的行数据
List<Map> rowDatas = getDto().getModel().getRowDatas();
if (rowDatas == null || rowDatas.isEmpty()) {
showWarningMessage("请先在列表中选中要编辑的文件");
this.cancelOperate();
return;
}
// 遍历选中行,任一文件 classification != 5 则禁止编辑
for (Map rowData : rowDatas) {
Object classificationObj = rowData.get("classification");
String classification = classificationObj == null ? "" : String.valueOf(classificationObj);
if (!"5".equals(classification)) {
showWarningMessage("仅\"上传文件\"分类的文件允许编辑");
this.cancelOperate();
return;
}
}
}
}

131
common/common-association/src/main/java/apelet/association/plugin/quotation/QuotationPlugin.java

@ -1,5 +1,7 @@ @@ -1,5 +1,7 @@
package apelet.association.plugin.quotation;
import apelet.association.plugin.fileLibraryMange.FileLibrayFormPlugin;
import apelet.common.core.exception.MyRuntimeException;
import apelet.common.core.object.ObjectCollection;
import apelet.common.core.object.ObjectValue;
import apelet.common.core.object.TokenData;
@ -7,9 +9,15 @@ import apelet.common.core.util.ApplicationContextHolder; @@ -7,9 +9,15 @@ import apelet.common.core.util.ApplicationContextHolder;
import apelet.common.generator.utils.OrmGenDataSourceUtil;
import apelet.common.online.abstractplugin.ExecutePluginParent;
import apelet.common.online.model.constant.AttributeEnum;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import liquibase.repackaged.org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@ -92,4 +100,127 @@ public class QuotationPlugin extends ExecutePluginParent { @@ -92,4 +100,127 @@ public class QuotationPlugin extends ExecutePluginParent {
type = StringUtils.removeEnd(type, ",");
this.setWidgetAttribute("type", AttributeEnum.VALUE_CHANGE, type);
}
@Override
public void buttonTriggered(String widgetVariableName, ObjectValue objectValue) {
super.buttonTriggered(widgetVariableName, objectValue);
// 仅响应"保存"按钮
if (!"保存".equals(widgetVariableName)) {
return;
}
saveAttachmentToFileLibrary(objectValue);
}
/**
* 保存报价单附件到文件库表 file_library
* 附件为空时直接跳过不写入任何记录
*
* @param objectValue 报价单表单数据对象
*/
private void saveAttachmentToFileLibrary(ObjectValue objectValue) {
// 读取附件字段,附件为空则跳过
Object fileTextObj = objectValue.get("file_text");
if (fileTextObj == null) {
return;
}
String fileText = fileTextObj.toString();
if (fileText.isEmpty()) {
return;
}
// 解析附件 JSON 数组
JSONArray fileArray;
try {
fileArray = JSON.parseArray(fileText);
} catch (Exception e) {
fileArray = null;
}
if (fileArray == null || fileArray.isEmpty()) {
return;
}
// file_size / file_type 为单值字段,取第一个文件的大小与类型
String fileType = null;
String fileSize = null;
JSONObject firstFile = fileArray.getJSONObject(0);
if (firstFile != null) {
fileType = resolveFileType(firstFile.getString("filename"));
fileSize = resolveFileSize(firstFile);
}
// 当前登录用户与当前时间(公共字段)
TokenData tokenData = TokenData.takeFromRequest();
Long userId = tokenData == null ? null : tokenData.getUserId();
Date now = new Date();
// 组装 file_library 记录
ObjectValue record = new ObjectValue("file_library");
record.put("file_name", fileText);
record.put("file_type", fileType);
record.put("file_size", fileSize);
// 阅读权限、阅读次数、状态、分类默认 0
record.put("read_auth", "1");
record.put("read_count", 0);
record.put("publish_status", "1");
record.put("classification", "3");
// 公共字段
record.put("create_user_id", userId);
record.put("create_time", now);
record.put("update_user_id", userId);
record.put("update_time", now);
record.put("deleted_flag", 1);
// 插入文件库表,主键 id 由框架自动生成
try {
ormGenDataSourceUtil.addNew("file_library", record);
} catch (Exception e) {
throw new MyRuntimeException("保存附件到文件库失败:" + e.getMessage());
}
}
/**
* 通过 HEAD 请求获取 OSS 文件大小并格式化为 KB/MB 展示字符串
* 获取失败返回 null不阻塞保存流程
*
* @param file 附件 JSON 中的单个文件对象
* @return 格式化后的文件大小 "1.6 MB"失败返回 null
*/
private String resolveFileSize(JSONObject file) {
String baseUrl = file.getString("baseUrl");
String uploadPath = file.getString("uploadPath");
String filename = file.getString("filename");
if (baseUrl == null || uploadPath == null || filename == null) {
return null;
}
String fullUrl = baseUrl + "/" + uploadPath + "/" + filename;
HttpURLConnection connection = null;
try {
URL url = new URL(fullUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("HEAD");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.connect();
long fileSize = connection.getContentLengthLong();
if (fileSize > 0) {
return FileLibrayFormPlugin.formatFileSize(fileSize);
}
} catch (Exception e) {
// 获取大小失败时返回 null,不影响保存
System.out.println("获取附件文件大小失败:" + fullUrl + "," + e.getMessage());
} finally {
if (connection != null) {
connection.disconnect();
}
}
return null;
}
/**
* 从文件名提取扩展名作为文件类型 "合同.pdf" -> "pdf"
*
* @param fileName 文件名
* @return 文件扩展名无法识别返回 null
*/
private String resolveFileType(String fileName) {
if (StringUtils.isEmpty(fileName) || !fileName.contains(".")) {
return null;
}
return fileName.substring(fileName.lastIndexOf(".") + 1);
}
}

17
common/common-association/src/main/java/apelet/association/service/ContractService.java

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
package apelet.association.service;
import apelet.association.model.Contract;
import apelet.association.vo.ContractListVo;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
public interface ContractService extends IService<Contract> {
/**
* 查询所有合同合同签订日期报价负责人名称总报价产品服务交付日期
*
* @return 合同列表
*/
List<ContractListVo> contractList();
}

17
common/common-association/src/main/java/apelet/association/service/QuotationService.java

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
package apelet.association.service;
import apelet.association.model.Quotation;
import apelet.association.vo.QuotationListVo;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
public interface QuotationService extends IService<Quotation> {
/**
* 查询所有报价单仅返回创建时间报价负责人项目名称总报价状态
*
* @return 报价单列表
*/
List<QuotationListVo> quotationSheetList();
}

19
common/common-association/src/main/java/apelet/association/service/impl/ContractServiceImpl.java

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
package apelet.association.service.impl;
import apelet.association.dao.ContractMapper;
import apelet.association.model.Contract;
import apelet.association.service.ContractService;
import apelet.association.vo.ContractListVo;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> implements ContractService {
@Override
public List<ContractListVo> contractList() {
return baseMapper.contractList();
}
}

19
common/common-association/src/main/java/apelet/association/service/impl/QuotationServiceImpl.java

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
package apelet.association.service.impl;
import apelet.association.dao.QuotationMapper;
import apelet.association.model.Quotation;
import apelet.association.service.QuotationService;
import apelet.association.vo.QuotationListVo;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class QuotationServiceImpl extends ServiceImpl<QuotationMapper, Quotation> implements QuotationService {
@Override
public List<QuotationListVo> quotationSheetList() {
return baseMapper.listAllWithManagerName();
}
}

48
common/common-association/src/main/java/apelet/association/vo/ContractListVo.java

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
package apelet.association.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 合同列表展示对象
*/
@Data
public class ContractListVo {
/**
* 主键ID
*/
private Long id;
/**
* 合同签订日期
*/
private Date signingDate;
/**
* 报价负责人ID
*/
private Long managerperson;
/**
* 报价负责人姓名关联 sys_user_info.USER_NAME
*/
private String managerName;
/**
* 名称
*/
private String name;
/**
* 总报价
*/
private BigDecimal qty;
/**
* 产品服务交付日期
*/
private Date deliveryDate;
}

48
common/common-association/src/main/java/apelet/association/vo/QuotationListVo.java

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
package apelet.association.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 报价单列表展示对象
*/
@Data
public class QuotationListVo {
/**
* 主键ID
*/
private Long id;
/**
* 创建日期
*/
private Date createTime;
/**
* 报价负责人ID
*/
private Long managerperson;
/**
* 报价负责人姓名关联 xy_sys_user.show_name
*/
private String managerName;
/**
* 项目名称
*/
private String name;
/**
* 总报价
*/
private BigDecimal qty;
/**
* 报价单状态(字典翻译后的中文值: 报价草案/报价审批/报价生效/作废)
*/
private String status;
}

23
common/common-association/src/main/resources/mapper/ContractMapper.xml

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.association.dao.ContractMapper">
<!-- 查询所有合同:关联 sys_user_info 解析负责人姓名 -->
<select id="contractList"
resultType="apelet.association.vo.ContractListVo">
SELECT
c.id AS id,
c.signing_date AS signingDate,
c.managerperson AS managerperson,
u.USER_NAME AS managerName,
c.name AS name,
c.qty AS qty,
c.delivery_date AS deliveryDate
FROM contract c
LEFT JOIN sys_user_info u ON c.managerperson = u.user_id
WHERE c.deleted_flag = 1
ORDER BY c.signing_date DESC
</select>
</mapper>

29
common/common-association/src/main/resources/mapper/QuotationMapper.xml

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.association.dao.QuotationMapper">
<!-- 查询所有报价单:关联 sys_user_info 解析负责人姓名,CASE WHEN 映射状态字典 -->
<select id="listAllWithManagerName"
resultType="apelet.association.vo.QuotationListVo">
SELECT
q.id AS id,
q.create_time AS createTime,
q.managerperson AS managerperson,
u.USER_NAME AS managerName,
q.name AS name,
q.qty AS qty,
CASE q.status
WHEN '1' THEN '报价草案'
WHEN '2' THEN '报价审批'
WHEN '3' THEN '报价生效'
WHEN '4' THEN '作废'
ELSE q.status
END AS status
FROM quotation q
LEFT JOIN sys_user_info u ON q.managerperson = u.user_id
WHERE q.deleted_flag = 1
ORDER BY q.create_time DESC
</select>
</mapper>
Loading…
Cancel
Save