完成初版
This commit is contained in:
@@ -4,6 +4,11 @@ public enum AssetsMapConstans {
|
||||
plugin("assetsmap",""),
|
||||
ASSETSFORMNO("assetsformno","资产表单"),
|
||||
ASSETSDETAILURLCONFIGFORMNO("","资产详情URL配置表单"),
|
||||
FILESYSTEMHOST("http://localhost:8080","SeeyonFileSystem网盘服务地址"),
|
||||
FILESYSAPPID("","SeeyonFileSystemAppId"),
|
||||
FILESYSAUSER("","文档系统用户"),
|
||||
BOUNDCONFIGUPDATELOGFORMNO("","边界数据变更日志表编码"),
|
||||
FORMLOGINNAME("","登录名"),
|
||||
;
|
||||
|
||||
private String defaultValue;
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.seeyon.apps.assetsmap.fieldCtrl;
|
||||
|
||||
import com.seeyon.cap4.form.bean.ParamDefinition;
|
||||
import com.seeyon.cap4.form.bean.fieldCtrl.FormFieldCustomCtrl;
|
||||
import com.seeyon.cap4.form.util.Enums;
|
||||
|
||||
/**
|
||||
* 关联附件控件
|
||||
* 弹框查询网盘文件列表,勾选后获取预览链接回填到表单
|
||||
*/
|
||||
public class FileRefFieldCtrl extends FormFieldCustomCtrl {
|
||||
|
||||
@Override
|
||||
public String getPCInjectionInfo() {
|
||||
return "{path:'apps_res/cap/customCtrlResources/fileUploadResources',jsUri:'/js/fileRef.js',initMethod:'init',nameSpace:'" + getNameSpace() + "'}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMBInjectionInfo() {
|
||||
return "{path:'apps_res/cap/customCtrlResources/fileUploadResources',jsUri:'/js/fileRef.js',initMethod:'init',nameSpace:'" + getNameSpace() + "'}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "88661234567890123457";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Enums.FormType formType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultVal(String s) {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
public String getNameSpace() {
|
||||
return "field_" + this.getKey();
|
||||
}
|
||||
|
||||
public String getFieldLength() {
|
||||
return "5000";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "关联附件";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enums.FieldType[] getFieldType() {
|
||||
return new Enums.FieldType[]{Enums.FieldType.LONGTEXT};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
setPluginId("assetsmap");
|
||||
setIcon("cap-icon-custom-button");
|
||||
|
||||
ParamDefinition param = new ParamDefinition();
|
||||
param.setParamType(Enums.ParamType.text);
|
||||
addDefinition(param);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.seeyon.apps.assetsmap.fieldCtrl;
|
||||
|
||||
import com.seeyon.cap4.form.bean.ParamDefinition;
|
||||
import com.seeyon.cap4.form.bean.fieldCtrl.FormFieldCustomCtrl;
|
||||
import com.seeyon.cap4.form.util.Enums;
|
||||
|
||||
/**
|
||||
* 从明细表获取数据重新生成边界数据控件
|
||||
*/
|
||||
public class GBCFromSubTableFieldCtrl extends FormFieldCustomCtrl {
|
||||
|
||||
@Override
|
||||
public String getPCInjectionInfo() {
|
||||
return "{path:'apps_res/cap/customCtrlResources/GBCFromSubTableResources',jsUri:'/js/fileRef.js',initMethod:'init',nameSpace:'" + getNameSpace() + "'}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMBInjectionInfo() {
|
||||
return "{path:'http://bgcSubTableBtn.v5.cmp/v1.0.0/',weixinpath:'bgcSubTableBtn',jsUri:'js/bgcSubTableBtn.js',initMethod:'init',nameSpace:'" + getNameSpace() + "'}";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "88661234567890123656";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Enums.FormType formType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultVal(String s) {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
public String getNameSpace() {
|
||||
return "field_" + this.getKey();
|
||||
}
|
||||
|
||||
public String getFieldLength() {
|
||||
return "5000";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "边界配置重新生成";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enums.FieldType[] getFieldType() {
|
||||
return new Enums.FieldType[]{Enums.FieldType.LONGTEXT};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
setPluginId("assetsmap");
|
||||
setIcon("cap-icon-custom-button");
|
||||
|
||||
ParamDefinition param = new ParamDefinition();
|
||||
param.setParamType(Enums.ParamType.text);
|
||||
addDefinition(param);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.seeyon.apps.assetsmap.node;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import com.seeyon.apps.assetsmap.constants.AssetsMapConstans;
|
||||
import com.seeyon.apps.assetsmap.service.FileUploadService;
|
||||
import com.seeyon.apps.common.workflow.constants.WorkFlowType;
|
||||
import com.seeyon.apps.common.workflow.node.ACommonSuperNode;
|
||||
import com.seeyon.apps.ext.workflow.vo.FieldDataVo;
|
||||
import com.seeyon.apps.ext.workflow.vo.FormDataVo;
|
||||
import com.seeyon.apps.ext.workflow.vo.SuperNodeContext;
|
||||
import com.seeyon.cap4.form.bean.FormDataMasterBean;
|
||||
import com.seeyon.ctp.common.AppContext;
|
||||
|
||||
public class AssetsCreateFolderNode extends ACommonSuperNode {
|
||||
|
||||
private FileUploadService fileUploadService = (FileUploadService) AppContext.getBean("fileUploadService");
|
||||
private static final Log log = Log.get(AssetsCreateFolderNode.class);
|
||||
|
||||
@Override
|
||||
public String getPluginId() {
|
||||
return AssetsMapConstans.getPluginId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFormParse() {
|
||||
return "json";
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuperNodeContext proceed(String s, FormDataVo formDataVo, FormDataMasterBean formDataMasterBean) throws Exception {
|
||||
SuperNodeContext context = new SuperNodeContext();
|
||||
context.setNeedSave(true);
|
||||
log.info("开始新增资产影像资料文件夹");
|
||||
try {
|
||||
FieldDataVo fieldData = formDataVo.getFieldData("资产编号");
|
||||
String assetsNo = fieldData.getStringValue();
|
||||
fileUploadService.createFolder(assetsNo,assetsNo);
|
||||
}catch (Exception e){
|
||||
log.warn(e.getMessage());
|
||||
}
|
||||
return context.success("新增资产影像资料文件夹超级节点业务执行结束");
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkFlowType[] getTypes() {
|
||||
return new WorkFlowType[] {WorkFlowType.superNode};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNodeId() {
|
||||
return "ndesgkzcyxzl20260715";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNodeName() {
|
||||
return "新增资产影像资料文件夹";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.seeyon.apps.assetsmap.service;
|
||||
|
||||
import com.seeyon.apps.assetsmap.config.AssetsMapConfigProvider;
|
||||
import com.seeyon.apps.assetsmap.constants.AssetsMapConstans;
|
||||
import com.seeyon.apps.assetsmap.vo.AssetsItem;
|
||||
import com.seeyon.ctp.common.AppContext;
|
||||
import com.seeyon.ctp.common.authenticate.domain.User;
|
||||
import com.seeyon.utils.form.FormSaveUtil;
|
||||
import com.seeyon.v3x.services.form.FormFactory;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AssetsBoundUpdateLogService {
|
||||
|
||||
private AssetsMapConfigProvider configProvider = (AssetsMapConfigProvider) AppContext.getBean("assetsMapConfigProvider");
|
||||
private FormFactory factory = (FormFactory) AppContext.getBean("formFactory");
|
||||
private AssetsQueryService assetsQueryService = (AssetsQueryService) AppContext.getBean("assetsQueryService");
|
||||
private DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
private String getFormNo(){
|
||||
return configProvider.getBizConfigByKey(AssetsMapConstans.BOUNDCONFIGUPDATELOGFORMNO);
|
||||
}
|
||||
|
||||
public void recordLog(String configValue,String formId,String isSubForm) {
|
||||
try {
|
||||
User user = AppContext.getCurrentUser();
|
||||
Long userId = user.getId();
|
||||
String loginName = configProvider.getBizConfigByKey(AssetsMapConstans.FORMLOGINNAME);
|
||||
AssetsItem assetsItem = assetsQueryService.getDetailById(formId);
|
||||
Map<String,Object> mainData = new HashMap<>();
|
||||
if(assetsItem != null) {
|
||||
mainData.put("资产编码",assetsItem.getAssetCode());
|
||||
mainData.put("资产名称",assetsItem.getAssetName());
|
||||
}
|
||||
mainData.put("数据来源",isSubForm.equals("1") ? "明细表生成" : "主表生成");
|
||||
mainData.put("更新时间",df.format(new Date()));
|
||||
mainData.put("更新结果",configValue);
|
||||
mainData.put("操作人员",userId);
|
||||
FormSaveUtil.formSave(loginName,getFormNo(),factory,mainData,null);
|
||||
}catch (Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
package com.seeyon.apps.assetsmap.service;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.seeyon.aicloud.common.JsonUtils;
|
||||
import com.seeyon.apps.assetsmap.config.AssetsMapConfigProvider;
|
||||
import com.seeyon.apps.assetsmap.constants.AssetsMapConstans;
|
||||
import com.seeyon.apps.assetsmap.vo.AssetsCatagory;
|
||||
import com.seeyon.apps.assetsmap.vo.AssetsItem;
|
||||
import com.seeyon.apps.assetsmap.vo.BoundsQueryVo;
|
||||
import com.seeyon.apps.assetsmap.vo.RegionVo;
|
||||
import com.seeyon.apps.assetsmap.vo.*;
|
||||
import com.seeyon.ctp.common.AppContext;
|
||||
import com.seeyon.ctp.common.exceptions.BusinessException;
|
||||
import com.seeyon.ctp.common.po.ctpenumnew.CtpEnumItem;
|
||||
@@ -24,6 +23,7 @@ public class AssetsQueryService {
|
||||
|
||||
private AssetsMapConfigProvider configProvider = (AssetsMapConfigProvider) AppContext.getBean("assetsMapConfigProvider");
|
||||
private OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager");
|
||||
private FileUploadService fileUploadService = (FileUploadService) AppContext.getBean("fileUploadService");
|
||||
private static final Log log = Log.get(AssetsQueryService.class);
|
||||
// 部门名称缓存,避免 N+1 查询
|
||||
private Map<Long, String> deptCache = new HashMap<>();
|
||||
@@ -133,6 +133,21 @@ public class AssetsQueryService {
|
||||
}
|
||||
}
|
||||
|
||||
public AssetsItem getDetailById(String id) throws BusinessException {
|
||||
TableContext tableContext = FormTableExecutor.master(getFormNo());
|
||||
List<FormWhereCondition> conditions = new ArrayList<>();
|
||||
conditions.add(FormWhereCondition.build().display("ID").value(id));
|
||||
FormColumn formColumn = FormTableExecutor.queryOne(tableContext, conditions, true);
|
||||
if(formColumn == null || formColumn.getId() == null) {
|
||||
return new AssetsItem();
|
||||
}
|
||||
AssetsItem assetsItem = new AssetsItem();
|
||||
Map<String, Object> fieldsMap = formColumn.getFieldsMap();
|
||||
assetsItem.setAssetName((String)fieldsMap.get("资产编号"));
|
||||
assetsItem.setAssetName((String)fieldsMap.get("名称编号"));
|
||||
return assetsItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录者单位及其所有下级单位的ID列表
|
||||
*/
|
||||
@@ -209,7 +224,7 @@ public class AssetsQueryService {
|
||||
TableContext master = FormTableExecutor.master(configProvider.getBizConfigByKey(AssetsMapConstans.ASSETSDETAILURLCONFIGFORMNO));
|
||||
List<FormWhereCondition> conditions = new ArrayList<>();
|
||||
if(StringUtils.isBlank(assetsType)) {
|
||||
conditions.add(FormWhereCondition.build().display("资产类型").value("不动产"));
|
||||
conditions.add(FormWhereCondition.build().display("资产类型").value("默认"));
|
||||
}else {
|
||||
conditions.add(FormWhereCondition.build().display("资产类型").value(assetsType));
|
||||
}
|
||||
@@ -221,6 +236,42 @@ public class AssetsQueryService {
|
||||
return urlObj == null ? null : urlObj.toString();
|
||||
}
|
||||
|
||||
public Map<String,Object> reComputedBoundConfig(){
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("fieldName","");
|
||||
map.put("value","");
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据资产编号查询资产详情(名称、经纬度、边界数据)
|
||||
*/
|
||||
public Map<String, Object> getAssetDetail(String assetCode) throws Exception {
|
||||
if (StringUtils.isBlank(assetCode)) {
|
||||
return null;
|
||||
}
|
||||
TableContext tableContext = FormTableExecutor.master(getFormNo());
|
||||
List<FormWhereCondition> conditions = new ArrayList<>();
|
||||
conditions.add(FormWhereCondition.build().display("资产编号").value(assetCode));
|
||||
FormColumn formColumn = FormTableExecutor.queryOne(tableContext, conditions, true);
|
||||
if (formColumn == null) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> fieldsMap = formColumn.getFieldsMap();
|
||||
if (fieldsMap == null) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("id", getStringValue(fieldsMap, "id"));
|
||||
result.put("assetCode", getStringValue(fieldsMap, "资产编号"));
|
||||
result.put("assetName", getStringValue(fieldsMap, "资产名称"));
|
||||
result.put("lat", Optional.ofNullable(fieldsMap.get("纬度-")).map(Object::toString).orElse(null));
|
||||
result.put("lng", Optional.ofNullable(fieldsMap.get("经度-")).map(Object::toString).orElse(null));
|
||||
Object boundObj = fieldsMap.get("资产边界数据");
|
||||
result.put("boundData", boundObj == null ? null : boundObj.toString());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询单个资产的边界数据
|
||||
*/
|
||||
@@ -315,7 +366,7 @@ public class AssetsQueryService {
|
||||
|
||||
public Map<String,AssetsCatagory> getAssetsCatagorySelectOptions() throws Exception {
|
||||
TableContext tableContext = FormTableExecutor.master(getFormNo());
|
||||
Map<String, CtpEnumItem> enumItemMap = EnumMapUtils.getEnumItemMap(tableContext.getTableBean(), "资产分类");
|
||||
Map<String, CtpEnumItem> enumItemMap = EnumMapUtils.getEnumItemMap(tableContext.getTableBean(), "资产分类-");
|
||||
if(enumItemMap == null) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
@@ -413,7 +464,8 @@ public class AssetsQueryService {
|
||||
AssetsItem assetsItem = new AssetsItem();
|
||||
assetsItem.setId(getStringValue(fieldsMap, "id"));
|
||||
assetsItem.setArea(fieldsMap.get("数量面积") == null ? null : Double.parseDouble(fieldsMap.get("数量面积") + ""));
|
||||
assetsItem.setAssetCode(getStringValue(fieldsMap, "资产编号"));
|
||||
String assetsCode = getStringValue(fieldsMap, "资产编号");
|
||||
assetsItem.setAssetCode(assetsCode);
|
||||
assetsItem.setRemark(getStringValue(fieldsMap, "备注"));
|
||||
assetsItem.setAssetName(getStringValue(fieldsMap, "资产名称"));
|
||||
assetsItem.setAddress(getStringValue(fieldsMap, "所在位置"));
|
||||
@@ -421,6 +473,33 @@ public class AssetsQueryService {
|
||||
assetsItem.setLng(Optional.ofNullable(fieldsMap.get("经度-")).map(Object::toString).orElse(null));
|
||||
assetsItem.setManager(getStringValue(fieldsMap,"管理单位"));
|
||||
assetsItem.setAssetType(getStringValue(fieldsMap, "资产类型一级"));
|
||||
assetsItem.setTroubledAssets(getStringValue(fieldsMap,"是否问题资产-主表"));
|
||||
// 媒体字段:JSON数组字符串,解析为FileItemVO列表
|
||||
try {
|
||||
String folderId = fileUploadService.getFolderIdByBizId(assetsCode);
|
||||
if(folderId != null) {
|
||||
FileListVO fileListVO = fileUploadService.listFolderChildren(folderId);
|
||||
if(fileListVO != null) {
|
||||
List<FileItemVO> imgs = new ArrayList<>();
|
||||
List<FileItemVO> videos = new ArrayList<>();
|
||||
for (FileItemVO file : fileListVO.getFiles()) {
|
||||
String mimeType = file.getMimeType();
|
||||
if(mimeType.startsWith("image")){
|
||||
imgs.add(file);
|
||||
}else if(mimeType.startsWith("video")){
|
||||
videos.add(file);
|
||||
}
|
||||
}
|
||||
assetsItem.setImages(imgs);
|
||||
assetsItem.setVideos(videos);
|
||||
}
|
||||
}
|
||||
|
||||
// assetsItem.setPanoramas();
|
||||
// assetsItem.setAttachments();
|
||||
}catch (Exception e){
|
||||
|
||||
}
|
||||
return assetsItem;
|
||||
}
|
||||
|
||||
@@ -429,6 +508,23 @@ public class AssetsQueryService {
|
||||
return val == null ? null : val.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析JSON数组字符串为FileItemVO列表
|
||||
* 字段值格式: [{"id":null,"name":"xxx.png","previewUrl":"http://..."}]
|
||||
*/
|
||||
private List<FileItemVO> parseFileItemList(Map<String, Object> fieldsMap, String key) {
|
||||
String json = getStringValue(fieldsMap, key);
|
||||
if (json == null || json.trim().isEmpty() || "[]".equals(json.trim())) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
try {
|
||||
return JsonUtils.parseObject(json, new TypeReference<List<FileItemVO>>() {});
|
||||
} catch (Exception e) {
|
||||
log.warn("解析媒体字段失败, key=" + key + ", value=" + json, e);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 优化:一次查询全量数据,内存中分类计数,替代3次独立查询
|
||||
*/
|
||||
@@ -498,9 +594,10 @@ public class AssetsQueryService {
|
||||
conditions.add(FormWhereCondition.build().display("资产分类-").value(vo.getLevel3()));
|
||||
}
|
||||
if (StringUtils.isNotBlank(vo.getKeyword())) {
|
||||
// keyword 与 owner 用 AND 连接,缩小范围而非扩大
|
||||
conditions.add(FormWhereCondition.build().display("资产名称").value(vo.getKeyword()).clauseFactor(ClauseFactor.LIKE)
|
||||
.concatFactor(ClauseFactor.OR));
|
||||
conditions.add(FormWhereCondition.build().display("资产编号").value(vo.getKeyword()).clauseFactor(ClauseFactor.LIKE));
|
||||
.concatFactor(ClauseFactor.OR).startWithBracket(1));
|
||||
conditions.add(FormWhereCondition.build().display("资产编号").value(vo.getKeyword()).clauseFactor(ClauseFactor.LIKE).endWithBracket(1));
|
||||
}
|
||||
conditions.add(FormWhereCondition.build().display("经度-").clauseFactor(ClauseFactor.NOT_NULL));
|
||||
conditions.add(FormWhereCondition.build().display("纬度-").clauseFactor(ClauseFactor.NOT_NULL));
|
||||
@@ -515,7 +612,8 @@ public class AssetsQueryService {
|
||||
.filter(col -> {
|
||||
Map<String, Object> fields = col.getFieldsMap();
|
||||
if (fields == null) return false;
|
||||
String perm = (String) fields.get("查看权限-选单位");
|
||||
Object permObj = fields.get("查看权限-选单位");
|
||||
String perm = permObj == null ? null : permObj.toString();
|
||||
return hasPermission(perm, unitIds);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
@@ -0,0 +1,518 @@
|
||||
package com.seeyon.apps.assetsmap.service;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.seeyon.aicloud.common.JsonUtils;
|
||||
import com.seeyon.apps.assetsmap.config.AssetsMapConfigProvider;
|
||||
import com.seeyon.apps.assetsmap.constants.AssetsMapConstans;
|
||||
import com.seeyon.apps.assetsmap.vo.ApiResultVO;
|
||||
import com.seeyon.apps.assetsmap.vo.FileItemVO;
|
||||
import com.seeyon.apps.assetsmap.vo.FileListVO;
|
||||
import com.seeyon.apps.assetsmap.vo.FolderItemVO;
|
||||
import com.seeyon.ctp.common.AppContext;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 文件上传服务
|
||||
* 封装与 SeeyonFileSystem 网盘服务的所有交互
|
||||
*/
|
||||
public class FileUploadService {
|
||||
|
||||
private static final Log log = Log.get(FileUploadService.class);
|
||||
private AssetsMapConfigProvider configProvider = (AssetsMapConfigProvider) AppContext.getBean("assetsMapConfigProvider");
|
||||
|
||||
/**
|
||||
* 获取网盘服务地址
|
||||
*/
|
||||
public String getFsHost() {
|
||||
return configProvider.getBizConfigByKey(AssetsMapConstans.FILESYSTEMHOST);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查网盘服务是否已配置
|
||||
*/
|
||||
public boolean isConfigured() {
|
||||
return StringUtils.isNotBlank(getFsHost());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件夹子项列表
|
||||
*/
|
||||
public FileListVO listFolderChildren(String folderId) throws Exception {
|
||||
if (StringUtils.isBlank(folderId)) {
|
||||
folderId = "0";
|
||||
}
|
||||
String url = getFsHost() + "/api/folder/" + folderId + "/children";
|
||||
String resp = httpGet(url, getToken());
|
||||
|
||||
ApiResultVO apiResult = parseResponse(resp);
|
||||
if (apiResult == null || !apiResult.isSuccess()) {
|
||||
log.warn("listFolderChildren 接口调用失败");
|
||||
return null;
|
||||
}
|
||||
|
||||
JSONObject data = apiResult.getDataJsonObject();
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
FileListVO result = new FileListVO();
|
||||
result.setTotalFiles(data.getString("total_files"));
|
||||
result.setTotalFolders(data.getString("total_folders"));
|
||||
result.setPage(data.getString("page"));
|
||||
result.setPageSize(data.getString("page_size"));
|
||||
|
||||
// 文件夹列表
|
||||
List<FolderItemVO> folders = new ArrayList<>();
|
||||
JSONArray folderArray = data.getJSONArray("folders");
|
||||
if (folderArray != null && !folderArray.isEmpty()) {
|
||||
for (int i = 0; i < folderArray.size(); i++) {
|
||||
JSONObject fObj = folderArray.getJSONObject(i);
|
||||
FolderItemVO vo = new FolderItemVO();
|
||||
vo.setId(fObj.getString("id"));
|
||||
vo.setBizId(fObj.getString("biz_id"));
|
||||
vo.setName(fObj.getString("name"));
|
||||
vo.setParentId(fObj.getString("parent_id"));
|
||||
vo.setPath(fObj.getString("path"));
|
||||
vo.setVersion(fObj.getInteger("version"));
|
||||
folders.add(vo);
|
||||
}
|
||||
}
|
||||
result.setFolders(folders);
|
||||
|
||||
// 文件列表
|
||||
List<FileItemVO> files = new ArrayList<>();
|
||||
JSONArray fileArray = data.getJSONArray("files");
|
||||
if (fileArray != null && !fileArray.isEmpty()) {
|
||||
for (int i = 0; i < fileArray.size(); i++) {
|
||||
JSONObject fObj = fileArray.getJSONObject(i);
|
||||
files.add(parseFileItem(fObj));
|
||||
}
|
||||
}
|
||||
result.setFiles(files);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换文件项
|
||||
*/
|
||||
private FileItemVO parseFileItem(JSONObject fObj) {
|
||||
FileItemVO vo = new FileItemVO();
|
||||
vo.setId(fObj.getString("id"));
|
||||
vo.setName(fObj.getString("name"));
|
||||
vo.setExtension(fObj.getString("extension"));
|
||||
vo.setFolderId(fObj.getString("folder_id"));
|
||||
vo.setSize(fObj.getLong("size"));
|
||||
vo.setMimeType(fObj.getString("mime_type"));
|
||||
vo.setPreviewUrl(fObj.getString("preview_url"));
|
||||
return vo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过业务ID获取文件夹ID
|
||||
*/
|
||||
public void createFolder(String bizId,String folderName) throws Exception {
|
||||
if (StringUtils.isBlank(bizId)) {
|
||||
return;
|
||||
}
|
||||
String url = getFsHost() + "/api/folder";
|
||||
Map<String,String> params = new HashMap<>();
|
||||
params.put("name",folderName);
|
||||
params.put("biz_id",bizId);
|
||||
String resp = httpPost(url, JsonUtils.toJSONString(params), getToken());
|
||||
ApiResultVO apiResult = parseResponse(resp);
|
||||
if (apiResult == null || !apiResult.isSuccess()) {
|
||||
log.error("创建文件夹失败 失败 bizId={}", bizId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过业务ID获取文件夹ID
|
||||
*/
|
||||
public String getFolderIdByBizId(String bizId) throws Exception {
|
||||
if (StringUtils.isBlank(bizId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String url = getFsHost() + "/api/folder/by-bizid/" + URLEncoder.encode(bizId, "UTF-8");
|
||||
String resp = httpGet(url, getToken());
|
||||
|
||||
ApiResultVO apiResult = parseResponse(resp);
|
||||
if (apiResult == null || !apiResult.isSuccess()) {
|
||||
log.warn("getFolderIdByBizId 失败 bizId={}", bizId);
|
||||
return null;
|
||||
}
|
||||
|
||||
JSONObject data = apiResult.getDataJsonObject();
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String folderId = data.getString("id");
|
||||
if (StringUtils.isBlank(folderId)) {
|
||||
folderId = data.getString("folder_id");
|
||||
}
|
||||
return folderId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件到网盘(默认100MB分片阈值)
|
||||
*/
|
||||
public String uploadFile(byte[] fileBytes, String fileName, String folderId) throws Exception {
|
||||
return uploadFile(fileBytes, fileName, folderId, 100 * 1024 * 1024);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件到网盘(自动判断直接上传或分片上传)
|
||||
* @param fileBytes 文件内容
|
||||
* @param fileName 文件名
|
||||
* @param folderId 目标文件夹ID
|
||||
* @param chunkSize 分片阈值(字节),超过此大小走分片上传
|
||||
* @return 上传结果JSON字符串
|
||||
*/
|
||||
public String uploadFile(byte[] fileBytes, String fileName, String folderId, long chunkSize) throws Exception {
|
||||
if (StringUtils.isBlank(folderId)) folderId = "0";
|
||||
if (chunkSize <= 0) chunkSize = 5 * 1024 * 1024; // 默认5MB
|
||||
|
||||
if (fileBytes.length <= chunkSize) {
|
||||
return uploadDirect(fileBytes, fileName, folderId);
|
||||
} else {
|
||||
return uploadChunked(fileBytes, fileName, folderId, chunkSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接上传(小文件)
|
||||
*/
|
||||
private String uploadDirect(byte[] fileBytes, String fileName, String folderId) throws Exception {
|
||||
String url = getFsHost() + "/api/file/upload?folder_id=" + folderId;
|
||||
String resp = httpMultipartPost(url, fileBytes, fileName, getToken());
|
||||
ApiResultVO apiResult = parseResponse(resp);
|
||||
if (apiResult == null || !apiResult.isSuccess()) {
|
||||
log.error("直接上传失败: " + resp);
|
||||
return null;
|
||||
}
|
||||
return apiResult.getDataJsonObject().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分片上传(大文件)
|
||||
* 流程:init → 逐片上传 → merge
|
||||
*/
|
||||
private String uploadChunked(byte[] fileBytes, String fileName, String folderId, long chunkSize) throws Exception {
|
||||
String token = getToken();
|
||||
long totalSize = fileBytes.length;
|
||||
int totalChunks = (int) Math.ceil((double) totalSize / chunkSize);
|
||||
|
||||
// 1. 初始化分片上传
|
||||
JSONObject initBody = new JSONObject();
|
||||
initBody.put("file_name", fileName);
|
||||
initBody.put("file_size", totalSize);
|
||||
initBody.put("folder_id", Long.parseLong(folderId));
|
||||
|
||||
String initResp = httpPost(getFsHost() + "/api/file/upload/init", initBody.toString(), token);
|
||||
ApiResultVO initResult = parseResponse(initResp);
|
||||
if (initResult == null || !initResult.isSuccess()) {
|
||||
log.error("分片上传初始化失败: " + initResp);
|
||||
return null;
|
||||
}
|
||||
|
||||
JSONObject initData = initResult.getDataJsonObject();
|
||||
String uploadId = initData.getString("upload_id");
|
||||
int chunkSizeResp = initData.getIntValue("chunk_size");
|
||||
if (chunkSizeResp > 0) chunkSize = chunkSizeResp;
|
||||
totalChunks = (int) Math.ceil((double) totalSize / chunkSize);
|
||||
|
||||
log.info("分片上传开始: uploadId=" + uploadId + ", fileName=" + fileName + ", chunks=" + totalChunks);
|
||||
|
||||
// 2. 逐片上传
|
||||
for (int i = 0; i < totalChunks; i++) {
|
||||
int offset = i * (int) chunkSize;
|
||||
int length = (int) Math.min(chunkSize, totalSize - offset);
|
||||
byte[] chunk = new byte[length];
|
||||
System.arraycopy(fileBytes, offset, chunk, 0, length);
|
||||
|
||||
String chunkUrl = getFsHost() + "/api/file/upload/chunk/" + uploadId + "/" + i;
|
||||
String chunkResp = httpMultipartPost(chunkUrl, chunk, "chunk", token);
|
||||
ApiResultVO chunkResult = parseResponse(chunkResp);
|
||||
if (chunkResult == null || !chunkResult.isSuccess()) {
|
||||
log.error("分片上传失败: chunk=" + i + ", resp=" + chunkResp);
|
||||
return null;
|
||||
}
|
||||
log.info("分片上传进度: " + (i + 1) + "/" + totalChunks);
|
||||
}
|
||||
|
||||
// 3. 合并分片
|
||||
String mergeUrl = getFsHost() + "/api/file/upload/merge/" + uploadId;
|
||||
String mergeResp = httpPost(mergeUrl, "{}", token);
|
||||
ApiResultVO mergeResult = parseResponse(mergeResp);
|
||||
if (mergeResult == null || !mergeResult.isSuccess()) {
|
||||
log.error("分片合并失败: " + mergeResp);
|
||||
return null;
|
||||
}
|
||||
|
||||
log.info("分片上传完成: uploadId=" + uploadId);
|
||||
return mergeResult.getDataJsonObject().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件下载链接
|
||||
*/
|
||||
public String getFileDownloadUrl(String fileId) throws Exception {
|
||||
String url = getFsHost() + "/api/file/" + fileId + "/download-url";
|
||||
String resp = httpGet(url, getToken());
|
||||
|
||||
ApiResultVO apiResult = parseResponse(resp);
|
||||
if (apiResult == null || !apiResult.isSuccess()) {
|
||||
return null;
|
||||
}
|
||||
Map<String,Object> data = (Map<String, Object>) apiResult.getData();
|
||||
return data == null ? null : (String)data.get("download_url");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件预览链接
|
||||
*/
|
||||
public String getFilePreviewUrl(String fileId) throws Exception {
|
||||
String url = getFsHost() + "/api/file/" + fileId + "/preview-url";
|
||||
String resp = httpGet(url, getToken());
|
||||
|
||||
ApiResultVO apiResult = parseResponse(resp);
|
||||
if (apiResult == null || !apiResult.isSuccess()) {
|
||||
return null;
|
||||
}
|
||||
Map<String,Object> data = (Map<String, Object>) apiResult.getData();
|
||||
return data == null ? null : (String)data.get("preview_url");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件详情
|
||||
*/
|
||||
public String getFileInfo(String fileId) throws Exception {
|
||||
String url = getFsHost() + "/api/file/" + fileId;
|
||||
String resp = httpGet(url, getToken());
|
||||
|
||||
ApiResultVO apiResult = parseResponse(resp);
|
||||
if (apiResult == null || !apiResult.isSuccess()) {
|
||||
return null;
|
||||
}
|
||||
Object data = apiResult.getData();
|
||||
return data == null ? null : data.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索文件
|
||||
*/
|
||||
public List<FileItemVO> searchFiles(String keyword) throws Exception {
|
||||
String url = getFsHost() + "/api/file/search?keyword=" + URLEncoder.encode(keyword, "UTF-8");
|
||||
String resp = httpGet(url, getToken());
|
||||
|
||||
ApiResultVO apiResult = parseResponse(resp);
|
||||
List<FileItemVO> result = new ArrayList<>();
|
||||
if (apiResult == null || !apiResult.isSuccess()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
JSONArray dataArray = apiResult.getDataJsonObject().getJSONArray("data");
|
||||
if (dataArray == null || dataArray.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (int i = 0; i < dataArray.size(); i++) {
|
||||
JSONObject fObj = dataArray.getJSONObject(i);
|
||||
result.add(parseFileItem(fObj));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// ==================== 统一响应解析 ====================
|
||||
private ApiResultVO parseResponse(String resp) {
|
||||
if (StringUtils.isBlank(resp)) {
|
||||
log.warn("响应为空");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return JSONObject.parseObject(resp, ApiResultVO.class);
|
||||
} catch (Exception e) {
|
||||
log.error("解析响应JSON失败: {}", resp, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== HTTP 工具 ====================
|
||||
private String httpGet(String urlStr, String token) throws Exception {
|
||||
URL url = new URL(urlStr);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
|
||||
if (StringUtils.isNotBlank(token)) {
|
||||
conn.setRequestProperty("token", token);
|
||||
}
|
||||
conn.setConnectTimeout(10000);
|
||||
conn.setReadTimeout(30000);
|
||||
|
||||
int code = conn.getResponseCode();
|
||||
InputStream is = code >= 400 ? conn.getErrorStream() : conn.getInputStream();
|
||||
String result = readStream(is);
|
||||
conn.disconnect();
|
||||
|
||||
if (code >= 400) {
|
||||
log.warn("GET 请求异常 url={} code={}", urlStr, code);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String httpPost(String urlStr, String jsonBody, String token) throws Exception {
|
||||
URL url = new URL(urlStr);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
|
||||
if (StringUtils.isNotBlank(token)) {
|
||||
conn.setRequestProperty("token", token);
|
||||
}
|
||||
conn.setConnectTimeout(10000);
|
||||
conn.setReadTimeout(30000);
|
||||
conn.setDoOutput(true);
|
||||
|
||||
try (OutputStream os = conn.getOutputStream()) {
|
||||
os.write(jsonBody.getBytes(StandardCharsets.UTF_8));
|
||||
os.flush();
|
||||
}
|
||||
|
||||
int code = conn.getResponseCode();
|
||||
InputStream is = code >= 400 ? conn.getErrorStream() : conn.getInputStream();
|
||||
String result = readStream(is);
|
||||
conn.disconnect();
|
||||
|
||||
if (code >= 400) {
|
||||
log.warn("POST 请求异常 url={} code={}", urlStr, code);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String httpMultipartPost(String urlStr, byte[] fileBytes, String fileName, String token) throws Exception {
|
||||
if (fileBytes == null || fileBytes.length == 0) {
|
||||
throw new IllegalArgumentException("文件内容不能为空");
|
||||
}
|
||||
if (StringUtils.isBlank(fileName)) {
|
||||
fileName = "upload_file";
|
||||
}
|
||||
|
||||
String boundary = "----SeeyonBoundary" + System.currentTimeMillis();
|
||||
URL url = new URL(urlStr);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
|
||||
if (StringUtils.isNotBlank(token)) {
|
||||
conn.setRequestProperty("Authorization", "Bearer " + token);
|
||||
}
|
||||
conn.setConnectTimeout(10000);
|
||||
conn.setReadTimeout(60000);
|
||||
conn.setDoOutput(true);
|
||||
|
||||
try (OutputStream os = conn.getOutputStream();
|
||||
PrintWriter writer = new PrintWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8), true)) {
|
||||
|
||||
writer.append("--").append(boundary).append("\r\n");
|
||||
writer.append("Content-Disposition: form-data; name=\"file\"; filename=\"").append(fileName).append("\"\r\n");
|
||||
writer.append("Content-Type: application/octet-stream\r\n\r\n");
|
||||
writer.flush();
|
||||
os.write(fileBytes);
|
||||
os.flush();
|
||||
writer.append("\r\n");
|
||||
writer.append("--").append(boundary).append("--\r\n");
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
int code = conn.getResponseCode();
|
||||
InputStream is = code >= 400 ? conn.getErrorStream() : conn.getInputStream();
|
||||
String result = readStream(is);
|
||||
conn.disconnect();
|
||||
|
||||
if (code >= 400) {
|
||||
log.warn("上传文件异常 url={} code={}", urlStr, code);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String readStream(InputStream is) throws Exception {
|
||||
if (is == null) {
|
||||
return "{}";
|
||||
}
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Token 缓存 ====================
|
||||
private String cachedToken = null;
|
||||
private long tokenExpireTime = 0;
|
||||
|
||||
public String getToken() {
|
||||
if (cachedToken != null && System.currentTimeMillis() < tokenExpireTime - 300000) {
|
||||
return cachedToken;
|
||||
}
|
||||
|
||||
String host = getFsHost();
|
||||
if (StringUtils.isBlank(host)) {
|
||||
log.warn("网盘服务地址未配置");
|
||||
return null;
|
||||
}
|
||||
|
||||
String username = configProvider.getBizConfigByKey(AssetsMapConstans.FILESYSAUSER);
|
||||
String appId = configProvider.getBizConfigByKey(AssetsMapConstans.FILESYSAPPID);
|
||||
|
||||
if (StringUtils.isBlank(username)) {
|
||||
log.warn("网盘登录用户未配置");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
String loginUrl = host + "/api/auth/app-login";
|
||||
JSONObject body = new JSONObject();
|
||||
body.put("username", username);
|
||||
body.put("app_id", appId);
|
||||
|
||||
String resp = httpPost(loginUrl, body.toString(), null);
|
||||
ApiResultVO apiResult = parseResponse(resp);
|
||||
|
||||
if (apiResult == null || !apiResult.isSuccess()) {
|
||||
log.error("网盘登录失败");
|
||||
return null;
|
||||
}
|
||||
|
||||
JSONObject data = apiResult.getDataJsonObject();
|
||||
if (data == null || !data.containsKey("token")) {
|
||||
log.error("登录返回无token");
|
||||
return null;
|
||||
}
|
||||
|
||||
cachedToken = data.getString("token");
|
||||
tokenExpireTime = System.currentTimeMillis() + 23 * 3600 * 1000L;
|
||||
log.info("网盘Token获取成功");
|
||||
return cachedToken;
|
||||
} catch (Exception e) {
|
||||
log.error("获取Token异常", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,563 @@
|
||||
package com.seeyon.apps.assetsmap.service;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import com.seeyon.apps.assetsmap.config.AssetsMapConfigProvider;
|
||||
import com.seeyon.apps.assetsmap.constants.AssetsMapConstans;
|
||||
import com.seeyon.apps.assetsmap.vo.AssetsCatagory;
|
||||
import com.seeyon.apps.assetsmap.vo.AssetsItem;
|
||||
import com.seeyon.apps.assetsmap.vo.BoundsQueryVo;
|
||||
import com.seeyon.apps.assetsmap.vo.RegionVo;
|
||||
import com.seeyon.ctp.common.AppContext;
|
||||
import com.seeyon.ctp.common.exceptions.BusinessException;
|
||||
import com.seeyon.ctp.common.po.ctpenumnew.CtpEnumItem;
|
||||
import com.seeyon.ctp.organization.bo.V3xOrgAccount;
|
||||
import com.seeyon.ctp.organization.manager.OrgManager;
|
||||
import com.seeyon.ctp.util.JDBCAgent;
|
||||
import com.seeyon.utils.form.*;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ManageAssetsQueryService {
|
||||
|
||||
private AssetsMapConfigProvider configProvider = (AssetsMapConfigProvider) AppContext.getBean("assetsMapConfigProvider");
|
||||
private OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager");
|
||||
private static final Log log = Log.get(ManageAssetsQueryService.class);
|
||||
// 部门名称缓存,避免 N+1 查询
|
||||
private Map<Long, String> deptCache = new HashMap<>();
|
||||
|
||||
private String getFormNo(){
|
||||
return configProvider.getBizConfigByKey(AssetsMapConstans.ASSETSFORMNO);
|
||||
}
|
||||
|
||||
private TableContext getMasterTableContext() throws Exception {
|
||||
return FormTableExecutor.master(getFormNo());
|
||||
}
|
||||
|
||||
public List<RegionVo> queryAllZoneAssets() throws Exception {
|
||||
TableContext tableContext = FormTableExecutor.master(getFormNo());
|
||||
List<FormWhereCondition> conditions = buildQueryCondition();
|
||||
List<FormColumn> formColumns = FormTableExecutor.query(tableContext, null, conditions, true);
|
||||
System.out.println("查询出的数据条数:" + formColumns.size());
|
||||
|
||||
// 用 Map 做 O(1) 查找,替代 List 遍历
|
||||
Map<String, RegionVo> regionMap = new HashMap<>();
|
||||
|
||||
for (FormColumn formColumn : formColumns) {
|
||||
Map<String, Object> fieldsMap = formColumn.getFieldsMap();
|
||||
if (fieldsMap == null) {
|
||||
continue;
|
||||
}
|
||||
upsertRegionVos(regionMap, fieldsMap);
|
||||
}
|
||||
return new ArrayList<>(regionMap.values());
|
||||
}
|
||||
|
||||
private List<FormWhereCondition> buildQueryCondition() {
|
||||
long currentAccountId = AppContext.currentAccountId();
|
||||
List<FormWhereCondition> conditions = new ArrayList<>();
|
||||
conditions.add(FormWhereCondition.build().display("所属单位-").value(currentAccountId).concatFactor(ClauseFactor.OR));
|
||||
conditions.add(FormWhereCondition.build().display("管理单位-").value(currentAccountId).concatFactor(ClauseFactor.OR));
|
||||
return conditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 视口懒加载:通过数据库层经纬度范围过滤,只查询视口内的资产
|
||||
* 生成 SQL: WHERE 纬度 >= south AND 纬度 <= north AND 经度 >= west AND 经度 <= east
|
||||
*/
|
||||
public List<RegionVo> queryAssetsByBounds(BoundsQueryVo vo) throws Exception {
|
||||
TableContext tableContext = FormTableExecutor.master(getFormNo());
|
||||
List<FormWhereCondition> conditions = new ArrayList<>();
|
||||
// 如果传了 assetId,按 资产编号 精确查询,忽略经纬度范围
|
||||
if (StringUtils.isNotBlank(vo.getAssetId())) {
|
||||
conditions.add(FormWhereCondition.build().display("资产编号").value(vo.getAssetId()));
|
||||
} else {
|
||||
conditions.add(FormWhereCondition.build().display("经度-").between(vo.getWest(), vo.getEast()));
|
||||
conditions.add(FormWhereCondition.build().display("纬度-").between(vo.getSouth(), vo.getNorth()));
|
||||
}
|
||||
conditions.add(FormWhereCondition.build().display("经度-").clauseFactor(ClauseFactor.NOT_NULL));
|
||||
conditions.add(FormWhereCondition.build().display("纬度-").clauseFactor(ClauseFactor.NOT_NULL));
|
||||
// 代码层过滤权限,避免 LIKE 导致索引失效
|
||||
boolean showAll = showAll();
|
||||
log.info("是否允许查看所有数据: " + showAll);
|
||||
if (StringUtils.isNotBlank(vo.getOwner())) {
|
||||
conditions.add(FormWhereCondition.build().display("所属单位").value(vo.getOwner()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(vo.getLevel2())) {
|
||||
conditions.add(FormWhereCondition.build().display("资产类型二级").value(vo.getLevel2()));
|
||||
}
|
||||
if (StringUtils.isNotBlank(vo.getLevel1())) {
|
||||
conditions.add(FormWhereCondition.build().display("资产类型一级").value(vo.getLevel1()));
|
||||
}
|
||||
if (StringUtils.isNotBlank(vo.getLevel3())) {
|
||||
conditions.add(FormWhereCondition.build().display("资产分类-").value(vo.getLevel3()));
|
||||
}
|
||||
System.out.println("开始查询资产数据");
|
||||
List<FormColumn> formColumns = FormTableExecutor.query(tableContext, null, conditions, true);
|
||||
|
||||
// 代码层过滤权限(当前单位及下级单位)
|
||||
if (!showAll && formColumns != null) {
|
||||
List<String> unitIds = getCurrentAndChildUnitIds();
|
||||
formColumns = formColumns.stream()
|
||||
.filter(col -> {
|
||||
Map<String, Object> fields = col.getFieldsMap();
|
||||
if (fields == null) return false;
|
||||
Object permObj = fields.get("查看权限-选单位");
|
||||
String perm = permObj == null ? null : permObj.toString();
|
||||
return hasPermission(perm, unitIds);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
log.info("权限过滤后的数据条数: " + formColumns.size());
|
||||
Map<String, RegionVo> regionMap = new HashMap<>();
|
||||
for (FormColumn formColumn : formColumns) {
|
||||
Map<String, Object> fieldsMap = formColumn.getFieldsMap();
|
||||
if (fieldsMap == null) continue;
|
||||
upsertRegionVos(regionMap, fieldsMap);
|
||||
}
|
||||
log.info("返回资产数据结果");
|
||||
return new ArrayList<>(regionMap.values());
|
||||
}
|
||||
|
||||
private boolean showAll() throws Exception {
|
||||
V3xOrgAccount currentAccount = orgManager.getAccountById(AppContext.currentAccountId());
|
||||
if(currentAccount == null) {
|
||||
return false;
|
||||
}else {
|
||||
return currentAccount.getName().contains("国清办")
|
||||
|| currentAccount.getName().contains("国资局")
|
||||
|| currentAccount.getName().contains("软件开发");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录者单位及其所有下级单位的ID列表
|
||||
*/
|
||||
private List<String> getCurrentAndChildUnitIds() {
|
||||
List<String> ids = new ArrayList<>();
|
||||
long currentAccountId = AppContext.currentAccountId();
|
||||
JDBCAgent jdbcAgent = new JDBCAgent();
|
||||
try {
|
||||
// 查当前单位的 path
|
||||
jdbcAgent.execute("select path from org_unit where id = ?", currentAccountId);
|
||||
List list = jdbcAgent.resultSetToList();
|
||||
if (list == null || list.isEmpty()) {
|
||||
ids.add(String.valueOf(currentAccountId));
|
||||
return ids;
|
||||
}
|
||||
Map unitMap = (Map) list.get(0);
|
||||
String rootPath = unitMap.get("path") + "";
|
||||
|
||||
// 查所有子单位
|
||||
jdbcAgent.execute("select id from org_unit where path like ?", rootPath + "%");
|
||||
list = jdbcAgent.resultSetToList();
|
||||
if (list != null) {
|
||||
for (Object o : list) {
|
||||
Map map = (Map) o;
|
||||
ids.add(map.get("id") + "");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ids.add(String.valueOf(currentAccountId));
|
||||
} finally {
|
||||
jdbcAgent.close();
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查权限字段是否包含当前单位或下级单位
|
||||
* permField: 逗号分隔的单位ID字符串,如 "100,200,300"
|
||||
* unitIds: 当前单位及下级单位ID列表
|
||||
*/
|
||||
private boolean hasPermission(String permField, List<String> unitIds) {
|
||||
if (StringUtils.isBlank(permField) || unitIds == null || unitIds.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
// 用逗号分隔后逐一匹配
|
||||
String[] permParts = permField.split(",");
|
||||
for (String part : permParts) {
|
||||
String trimmed = part.trim();
|
||||
if (unitIds.contains(trimmed)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存资产边界数据到表单字段"资产边界数据"
|
||||
* polygonData: JSON格式,包含polygon坐标和color颜色
|
||||
*/
|
||||
public void saveAssetPolygon(String assetId, String polygonData) throws Exception {
|
||||
if (StringUtils.isBlank(assetId)) {
|
||||
throw new IllegalArgumentException("assetId不能为空");
|
||||
}
|
||||
List<FormUpdateField> updateFields = new ArrayList<>();
|
||||
updateFields.add(FormUpdateField.build().display("资产边界数据").value(polygonData));
|
||||
List<FormWhereCondition> conditions = new ArrayList<>();
|
||||
conditions.add(FormWhereCondition.build().display("id").value(assetId));
|
||||
FormTableExecutor.update(getMasterTableContext(),updateFields,conditions);
|
||||
}
|
||||
|
||||
|
||||
public String getDetailBaseUrlByAssetsType(String assetsType) throws Exception {
|
||||
TableContext master = FormTableExecutor.master(configProvider.getBizConfigByKey(AssetsMapConstans.ASSETSDETAILURLCONFIGFORMNO));
|
||||
List<FormWhereCondition> conditions = new ArrayList<>();
|
||||
if(StringUtils.isBlank(assetsType)) {
|
||||
conditions.add(FormWhereCondition.build().display("资产类型").value("默认"));
|
||||
}else {
|
||||
conditions.add(FormWhereCondition.build().display("资产类型").value(assetsType));
|
||||
}
|
||||
FormColumn formColumn = FormTableExecutor.queryOne(master, conditions, true);
|
||||
if(formColumn == null) {
|
||||
return null;
|
||||
}
|
||||
Object urlObj = formColumn.getFieldsMap().get("前置地址");
|
||||
return urlObj == null ? null : urlObj.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询单个资产的边界数据
|
||||
*/
|
||||
public Map<String, String> getAssetBound(String assetId) throws Exception {
|
||||
if (StringUtils.isBlank(assetId)) {
|
||||
return null;
|
||||
}
|
||||
TableContext tableContext = FormTableExecutor.master(getFormNo());
|
||||
List<FormWhereCondition> conditions = new ArrayList<>();
|
||||
conditions.add(FormWhereCondition.build().display("id").value(assetId));
|
||||
FormColumn formColumn = FormTableExecutor.queryOne(tableContext, conditions, true);
|
||||
if (formColumn == null) {
|
||||
log.info("getAssetBound: 未查到记录, assetId=" + assetId);
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> fieldsMap = formColumn.getFieldsMap();
|
||||
if (fieldsMap == null) {
|
||||
return null;
|
||||
}
|
||||
log.info("getAssetBound: 查到记录, assetId=" + assetId + ", 资产编号=" + fieldsMap.get("资产编号") + ", 资产名称=" + fieldsMap.get("资产名称"));
|
||||
log.info("getAssetBound: 资产边界数据字段值=" + fieldsMap.get("资产边界数据") + ", 类型=" + (fieldsMap.get("资产边界数据") == null ? "null" : fieldsMap.get("资产边界数据").getClass().getName()));
|
||||
Object boundObj = fieldsMap.get("资产边界数据");
|
||||
String boundData = boundObj == null ? null : boundObj.toString();
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put("boundData", boundData);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前登录者单位的树形结构
|
||||
* path 每4字符代表一个层级,如 0000 → 00000001 → 000000010001
|
||||
*/
|
||||
public List<Map<String, Object>> getDeptSelectOptions() throws BusinessException {
|
||||
long currentAccountId = AppContext.currentAccountId();
|
||||
JDBCAgent jdbcAgent = new JDBCAgent();
|
||||
try {
|
||||
// 查当前单位的 path
|
||||
jdbcAgent.execute("select path from org_unit where id = ?", currentAccountId);
|
||||
List list = jdbcAgent.resultSetToList();
|
||||
if (list == null || list.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
Map unitMap = (Map) list.get(0);
|
||||
String rootPath = unitMap.get("path") + "";
|
||||
|
||||
// 查所有子单位
|
||||
jdbcAgent.execute("select id, name, path from org_unit where path like ?", rootPath + "%");
|
||||
list = jdbcAgent.resultSetToList();
|
||||
|
||||
// 用 LinkedHashMap 保持插入顺序,path → node
|
||||
Map<String, Map<String, Object>> nodeMap = new LinkedHashMap<>();
|
||||
for (Object o : list) {
|
||||
Map map = (Map) o;
|
||||
String path = map.get("path") + "";
|
||||
Map<String, Object> node = new LinkedHashMap<>();
|
||||
node.put("id", map.get("id") + "");
|
||||
node.put("name", map.get("name") + "");
|
||||
node.put("path", path);
|
||||
node.put("children", new ArrayList<Map<String, Object>>());
|
||||
nodeMap.put(path, node);
|
||||
}
|
||||
|
||||
// 按 path 长度排序(浅层先处理),逐个挂到父节点
|
||||
List<Map<String, Object>> roots = new ArrayList<>();
|
||||
List<String> sortedPaths = new ArrayList<>(nodeMap.keySet());
|
||||
Collections.sort(sortedPaths, Comparator.comparingInt(String::length));
|
||||
|
||||
for (String path : sortedPaths) {
|
||||
Map<String, Object> node = nodeMap.get(path);
|
||||
if (path.equals(rootPath) || path.length() <= 4) {
|
||||
roots.add(node);
|
||||
} else {
|
||||
// 父节点 path = 去掉最后4字符
|
||||
String parentPath = path.substring(0, path.length() - 4);
|
||||
Map<String, Object> parent = nodeMap.get(parentPath);
|
||||
if (parent != null) {
|
||||
((List<Map<String, Object>>) parent.get("children")).add(node);
|
||||
} else {
|
||||
// 找不到父节点,作为根节点
|
||||
roots.add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
return roots;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return new ArrayList<>();
|
||||
} finally {
|
||||
jdbcAgent.close();
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String,AssetsCatagory> getAssetsCatagorySelectOptions() throws Exception {
|
||||
TableContext tableContext = FormTableExecutor.master(getFormNo());
|
||||
Map<String, CtpEnumItem> enumItemMap = EnumMapUtils.getEnumItemMap(tableContext.getTableBean(), "资产分类");
|
||||
if(enumItemMap == null) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
Map<String,AssetsCatagory> resultMap = new HashMap<>();
|
||||
for (String key : enumItemMap.keySet()) {
|
||||
CtpEnumItem tempItem = enumItemMap.get(key);
|
||||
AssetsCatagory assetsCatagory = new AssetsCatagory();
|
||||
assetsCatagory.setId(tempItem.getId() + "");
|
||||
assetsCatagory.setShowValue(key);
|
||||
resultMap.put(key,assetsCatagory);
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 region 的唯一 key,用于 Map 查找
|
||||
*/
|
||||
private String regionKey(double lat, double lng, String address) {
|
||||
return lat + "_" + lng + "_" + address;
|
||||
}
|
||||
|
||||
/**
|
||||
* 优化:接收 Map 而非 List,O(1) 查找替代 O(n) 遍历
|
||||
*/
|
||||
public void upsertRegionVos(Map<String, RegionVo> regionMap, Map<String, Object> fieldsMap) {
|
||||
|
||||
BigDecimal latObj = (BigDecimal) fieldsMap.get("纬度-");
|
||||
BigDecimal lngObj = (BigDecimal) fieldsMap.get("经度-");
|
||||
|
||||
if (latObj == null || lngObj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
double lat = Double.parseDouble(latObj.toString());
|
||||
double lng = Double.parseDouble(lngObj.toString());
|
||||
|
||||
Object addrObj = fieldsMap.get("所在位置");
|
||||
String address = addrObj == null ? null : addrObj.toString();
|
||||
|
||||
if (StringUtils.isBlank(address)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String assetId = getStringValue(fieldsMap, "id");
|
||||
AssetsItem newAsset = buildAssetsItem(fieldsMap);
|
||||
|
||||
String key = regionKey(lat, lng, address);
|
||||
RegionVo regionVo = regionMap.get(key);
|
||||
|
||||
if (regionVo != null) {
|
||||
// 判断资产是否已存在
|
||||
boolean exists = regionVo.getAssets().stream()
|
||||
.anyMatch(a -> a.getId().equals(assetId));
|
||||
if (!exists) {
|
||||
regionVo.getAssets().add(newAsset);
|
||||
}
|
||||
} else {
|
||||
// 新建区域
|
||||
RegionVo newRegion = new RegionVo();
|
||||
newRegion.setLat(lat);
|
||||
newRegion.setLng(lng);
|
||||
newRegion.setAddress(address);
|
||||
newRegion.setManager(getStringValue(fieldsMap,"管理单位"));
|
||||
|
||||
List<AssetsItem> assets = new ArrayList<>();
|
||||
assets.add(newAsset);
|
||||
newRegion.setAssets(assets);
|
||||
|
||||
regionMap.put(key, newRegion);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 优化:带缓存的单位名称查询
|
||||
*/
|
||||
private String getUnitName(Long unitId) {
|
||||
if (unitId == null) {
|
||||
return null;
|
||||
}
|
||||
if (deptCache.containsKey(unitId)) {
|
||||
return deptCache.get(unitId);
|
||||
}
|
||||
try {
|
||||
V3xOrgAccount account = orgManager.getAccountById(unitId);
|
||||
String name = account != null ? account.getName() : null;
|
||||
deptCache.put(unitId, name);
|
||||
return name;
|
||||
} catch (Exception e) {
|
||||
deptCache.put(unitId, null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private AssetsItem buildAssetsItem(Map<String, Object> fieldsMap) {
|
||||
AssetsItem assetsItem = new AssetsItem();
|
||||
assetsItem.setId(getStringValue(fieldsMap, "id"));
|
||||
assetsItem.setArea(fieldsMap.get("数量面积") == null ? null : Double.parseDouble(fieldsMap.get("数量面积") + ""));
|
||||
assetsItem.setAssetCode(getStringValue(fieldsMap, "资产编号"));
|
||||
assetsItem.setRemark(getStringValue(fieldsMap, "备注"));
|
||||
assetsItem.setAssetName(getStringValue(fieldsMap, "资产名称"));
|
||||
assetsItem.setAddress(getStringValue(fieldsMap, "所在位置"));
|
||||
assetsItem.setLat(Optional.ofNullable(fieldsMap.get("纬度-")).map(Object::toString).orElse(null));
|
||||
assetsItem.setLng(Optional.ofNullable(fieldsMap.get("经度-")).map(Object::toString).orElse(null));
|
||||
assetsItem.setManager(getStringValue(fieldsMap,"管理单位"));
|
||||
assetsItem.setAssetType(getStringValue(fieldsMap, "资产类型一级"));
|
||||
return assetsItem;
|
||||
}
|
||||
|
||||
private String getStringValue(Map<String, Object> fieldsMap, String key) {
|
||||
Object val = fieldsMap.get(key);
|
||||
return val == null ? null : val.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 优化:一次查询全量数据,内存中分类计数,替代3次独立查询
|
||||
*/
|
||||
public Map<String, Integer> countAllStats() throws Exception {
|
||||
TableContext tableContext = FormTableExecutor.master(getFormNo());
|
||||
List<FormColumn> formColumns = FormTableExecutor.query(tableContext, null, null, true);
|
||||
|
||||
int total = 0;
|
||||
int rented = 0;
|
||||
int vacant = 0;
|
||||
|
||||
String rentedValue = EnumMapUtils.getEnumItemValueByDisplayValue(tableContext.getTableBean(), "资产状态", "已租");
|
||||
String vacantValue = EnumMapUtils.getEnumItemValueByDisplayValue(tableContext.getTableBean(), "资产状态", "待租");
|
||||
|
||||
for (FormColumn col : formColumns) {
|
||||
Map<String, Object> fields = col.getFieldsMap();
|
||||
if (fields == null) continue;
|
||||
total++;
|
||||
String status = fields.get("资产状态") == null ? null : fields.get("资产状态") + "";
|
||||
if (rentedValue != null && rentedValue.equals(status)) {
|
||||
rented++;
|
||||
} else if (vacantValue != null && vacantValue.equals(status)) {
|
||||
vacant++;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Integer> result = new HashMap<>();
|
||||
result.put("total", total);
|
||||
result.put("rented", rented);
|
||||
result.put("vacant", vacant);
|
||||
return result;
|
||||
}
|
||||
|
||||
public Integer countAssets(String type) throws Exception {
|
||||
TableContext tableContext = FormTableExecutor.master(getFormNo());
|
||||
List<FormWhereCondition> conditions = new ArrayList<FormWhereCondition>();
|
||||
if(type == null || "0".equals(type)) {
|
||||
conditions = null;
|
||||
}
|
||||
if("1".equals(type)) {
|
||||
conditions.add(FormWhereCondition.build().display("资产状态").value(EnumMapUtils.getEnumItemValueByDisplayValue(tableContext.getTableBean(),"资产状态","已租")));
|
||||
}
|
||||
if("2".equals(type)) {
|
||||
conditions.add(FormWhereCondition.build().display("资产状态").value(EnumMapUtils.getEnumItemValueByDisplayValue(tableContext.getTableBean(),"资产状态","待租")));
|
||||
}
|
||||
List<FormColumn> formColumns = FormTableExecutor.query(tableContext,null, conditions, true);
|
||||
return formColumns.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 按筛选条件分页查询资产列表(不走视口),用于地图右侧列表展示
|
||||
* 返回格式: {records: [...], total: n}
|
||||
*/
|
||||
public Map<String, Object> queryAssetList(BoundsQueryVo vo) throws Exception {
|
||||
TableContext tableContext = FormTableExecutor.master(getFormNo());
|
||||
List<FormWhereCondition> conditions = new ArrayList<>();
|
||||
if (StringUtils.isNotBlank(vo.getOwner())) {
|
||||
conditions.add(FormWhereCondition.build().display("所属单位").value(vo.getOwner()));
|
||||
}
|
||||
if (StringUtils.isNotBlank(vo.getLevel1())) {
|
||||
conditions.add(FormWhereCondition.build().display("资产类型一级").value(vo.getLevel1()));
|
||||
}
|
||||
if (StringUtils.isNotBlank(vo.getLevel2())) {
|
||||
conditions.add(FormWhereCondition.build().display("资产类型二级").value(vo.getLevel2()));
|
||||
}
|
||||
if (StringUtils.isNotBlank(vo.getLevel3())) {
|
||||
conditions.add(FormWhereCondition.build().display("资产分类-").value(vo.getLevel3()));
|
||||
}
|
||||
if (StringUtils.isNotBlank(vo.getKeyword())) {
|
||||
conditions.add(FormWhereCondition.build().display("资产名称").value(vo.getKeyword()).clauseFactor(ClauseFactor.LIKE)
|
||||
.concatFactor(ClauseFactor.OR));
|
||||
conditions.add(FormWhereCondition.build().display("资产编号").value(vo.getKeyword()).clauseFactor(ClauseFactor.LIKE));
|
||||
}
|
||||
conditions.add(FormWhereCondition.build().display("经度-").clauseFactor(ClauseFactor.NOT_NULL));
|
||||
conditions.add(FormWhereCondition.build().display("纬度-").clauseFactor(ClauseFactor.NOT_NULL));
|
||||
// 先查全量用于权限过滤
|
||||
List<FormColumn> formColumns = FormTableExecutor.query(tableContext, null, conditions, true);
|
||||
|
||||
// 权限过滤(当前单位及下级单位)
|
||||
boolean showAll = showAll();
|
||||
if (!showAll) {
|
||||
List<String> unitIds = getCurrentAndChildUnitIds();
|
||||
formColumns = formColumns.stream()
|
||||
.filter(col -> {
|
||||
Map<String, Object> fields = col.getFieldsMap();
|
||||
if (fields == null) return false;
|
||||
String perm = (String) fields.get("查看权限-选单位");
|
||||
return hasPermission(perm, unitIds);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
int total = formColumns.size();
|
||||
|
||||
// 分页
|
||||
int pageNum = vo.getPageNum() != null && vo.getPageNum() > 0 ? vo.getPageNum() : 1;
|
||||
int pageSize = vo.getPageSize() != null && vo.getPageSize() > 0 ? vo.getPageSize() : 10;
|
||||
int fromIndex = (pageNum - 1) * pageSize;
|
||||
int toIndex = Math.min(fromIndex + pageSize, total);
|
||||
|
||||
List<AssetsItem> records = new ArrayList<>();
|
||||
if (fromIndex < total) {
|
||||
List<FormColumn> pageColumns = formColumns.subList(fromIndex, toIndex);
|
||||
for (FormColumn col : pageColumns) {
|
||||
Map<String, Object> fieldsMap = col.getFieldsMap();
|
||||
if (fieldsMap == null) continue;
|
||||
records.add(buildAssetsItem(fieldsMap));
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("records", records);
|
||||
result.put("total", total);
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<AssetsItem> queryAssetsByKeyword(String keyword) throws Exception {
|
||||
List<FormWhereCondition> conditions = new ArrayList<FormWhereCondition>();
|
||||
if(StringUtils.isNotBlank(keyword)){
|
||||
conditions.add(FormWhereCondition.build().display("所在位置").value(keyword).concatFactor(ClauseFactor.OR).clauseFactor(ClauseFactor.LIKE));
|
||||
}
|
||||
TableContext tableContext = FormTableExecutor.master(getFormNo());
|
||||
List<FormColumn> formColumns = FormTableExecutor.pageQuery(tableContext,null, conditions, 1,10,true);
|
||||
List<AssetsItem> assetsItems = new ArrayList<AssetsItem>();
|
||||
for (FormColumn formColumn : formColumns) {
|
||||
AssetsItem assetsItem = buildAssetsItem(formColumn.getFieldsMap());
|
||||
assetsItems.add(assetsItem);
|
||||
}
|
||||
return assetsItems;
|
||||
}
|
||||
|
||||
}
|
||||
28
src/main/java/com/seeyon/apps/assetsmap/vo/ApiResultVO.java
Normal file
28
src/main/java/com/seeyon/apps/assetsmap/vo/ApiResultVO.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package com.seeyon.apps.assetsmap.vo;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
public class ApiResultVO {
|
||||
|
||||
private Integer code;
|
||||
private String message;
|
||||
private Object data;
|
||||
|
||||
public boolean isSuccess() {
|
||||
return code != null && code == 0;
|
||||
}
|
||||
|
||||
// 快速获取 data 转为 JSONObject
|
||||
public JSONObject getDataJsonObject() {
|
||||
if (data == null) return null;
|
||||
return (JSONObject) JSONObject.toJSON(data);
|
||||
}
|
||||
|
||||
// getter / setter
|
||||
public Integer getCode() { return code; }
|
||||
public void setCode(Integer code) { this.code = code; }
|
||||
public String getMessage() { return message; }
|
||||
public void setMessage(String message) { this.message = message; }
|
||||
public Object getData() { return data; }
|
||||
public void setData(Object data) { this.data = data; }
|
||||
}
|
||||
22
src/main/java/com/seeyon/apps/assetsmap/vo/AssetsFileVo.java
Normal file
22
src/main/java/com/seeyon/apps/assetsmap/vo/AssetsFileVo.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.seeyon.apps.assetsmap.vo;
|
||||
|
||||
public class AssetsFileVo {
|
||||
private String name;
|
||||
private String url;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.seeyon.apps.assetsmap.vo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AssetsItem {
|
||||
private String id;
|
||||
private String assetCode;
|
||||
@@ -19,6 +21,11 @@ public class AssetsItem {
|
||||
private String assetType;
|
||||
private String assetCategory;
|
||||
private String boundData;
|
||||
private String troubledAssets;
|
||||
private List<FileItemVO> images;
|
||||
private List<FileItemVO> videos;
|
||||
private List<FileItemVO> panoramas;
|
||||
private List<FileItemVO> attachments;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
@@ -163,4 +170,44 @@ public class AssetsItem {
|
||||
public void setBoundData(String boundData) {
|
||||
this.boundData = boundData;
|
||||
}
|
||||
|
||||
public String getTroubledAssets() {
|
||||
return troubledAssets;
|
||||
}
|
||||
|
||||
public void setTroubledAssets(String troubledAssets) {
|
||||
this.troubledAssets = troubledAssets;
|
||||
}
|
||||
|
||||
public List<FileItemVO> getImages() {
|
||||
return images;
|
||||
}
|
||||
|
||||
public void setImages(List<FileItemVO> images) {
|
||||
this.images = images;
|
||||
}
|
||||
|
||||
public List<FileItemVO> getVideos() {
|
||||
return videos;
|
||||
}
|
||||
|
||||
public void setVideos(List<FileItemVO> videos) {
|
||||
this.videos = videos;
|
||||
}
|
||||
|
||||
public List<FileItemVO> getPanoramas() {
|
||||
return panoramas;
|
||||
}
|
||||
|
||||
public void setPanoramas(List<FileItemVO> panoramas) {
|
||||
this.panoramas = panoramas;
|
||||
}
|
||||
|
||||
public List<FileItemVO> getAttachments() {
|
||||
return attachments;
|
||||
}
|
||||
|
||||
public void setAttachments(List<FileItemVO> attachments) {
|
||||
this.attachments = attachments;
|
||||
}
|
||||
}
|
||||
59
src/main/java/com/seeyon/apps/assetsmap/vo/FileItemVO.java
Normal file
59
src/main/java/com/seeyon/apps/assetsmap/vo/FileItemVO.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package com.seeyon.apps.assetsmap.vo;
|
||||
|
||||
|
||||
/**
|
||||
* 网盘文件视图对象
|
||||
*/
|
||||
public class FileItemVO {
|
||||
private String id;
|
||||
private String name;
|
||||
private String extension;
|
||||
private String folderId;
|
||||
private Long size;
|
||||
private String mimeType;
|
||||
private String previewUrl;
|
||||
private String downloadUrl;
|
||||
private Integer version;
|
||||
|
||||
public String getName() { return name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
|
||||
public String getExtension() { return extension; }
|
||||
public void setExtension(String extension) { this.extension = extension; }
|
||||
|
||||
public String getMimeType() { return mimeType; }
|
||||
public void setMimeType(String mimeType) { this.mimeType = mimeType; }
|
||||
|
||||
public String getPreviewUrl() { return previewUrl; }
|
||||
public void setPreviewUrl(String previewUrl) { this.previewUrl = previewUrl; }
|
||||
|
||||
public String getDownloadUrl() { return downloadUrl; }
|
||||
public void setDownloadUrl(String downloadUrl) { this.downloadUrl = downloadUrl; }
|
||||
|
||||
public Integer getVersion() { return version; }
|
||||
public void setVersion(Integer version) { this.version = version; }
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getFolderId() {
|
||||
return folderId;
|
||||
}
|
||||
|
||||
public void setFolderId(String folderId) {
|
||||
this.folderId = folderId;
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(Long size) {
|
||||
this.size = size;
|
||||
}
|
||||
}
|
||||
54
src/main/java/com/seeyon/apps/assetsmap/vo/FileListVO.java
Normal file
54
src/main/java/com/seeyon/apps/assetsmap/vo/FileListVO.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package com.seeyon.apps.assetsmap.vo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 网盘文件夹子项列表视图对象
|
||||
* 对应 GET /api/folder/:id/children 的响应 data 部分
|
||||
*/
|
||||
public class FileListVO {
|
||||
private List<FolderItemVO> folders;
|
||||
private List<FileItemVO> files;
|
||||
private String totalFiles;
|
||||
private String totalFolders;
|
||||
private String page;
|
||||
private String pageSize;
|
||||
|
||||
public List<FolderItemVO> getFolders() { return folders; }
|
||||
public void setFolders(List<FolderItemVO> folders) { this.folders = folders; }
|
||||
|
||||
public List<FileItemVO> getFiles() { return files; }
|
||||
public void setFiles(List<FileItemVO> files) { this.files = files; }
|
||||
|
||||
public String getTotalFiles() {
|
||||
return totalFiles;
|
||||
}
|
||||
|
||||
public void setTotalFiles(String totalFiles) {
|
||||
this.totalFiles = totalFiles;
|
||||
}
|
||||
|
||||
public String getTotalFolders() {
|
||||
return totalFolders;
|
||||
}
|
||||
|
||||
public void setTotalFolders(String totalFolders) {
|
||||
this.totalFolders = totalFolders;
|
||||
}
|
||||
|
||||
public String getPage() {
|
||||
return page;
|
||||
}
|
||||
|
||||
public void setPage(String page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public String getPageSize() {
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
public void setPageSize(String pageSize) {
|
||||
this.pageSize = pageSize;
|
||||
}
|
||||
}
|
||||
42
src/main/java/com/seeyon/apps/assetsmap/vo/FolderItemVO.java
Normal file
42
src/main/java/com/seeyon/apps/assetsmap/vo/FolderItemVO.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package com.seeyon.apps.assetsmap.vo;
|
||||
|
||||
|
||||
/**
|
||||
* 网盘文件夹视图对象
|
||||
*/
|
||||
public class FolderItemVO {
|
||||
private String id;
|
||||
private String bizId;
|
||||
private String name;
|
||||
private String parentId;
|
||||
private String path;
|
||||
private Integer version;
|
||||
|
||||
public String getBizId() { return bizId; }
|
||||
public void setBizId(String bizId) { this.bizId = bizId; }
|
||||
|
||||
public String getName() { return name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
|
||||
public String getPath() { return path; }
|
||||
public void setPath(String path) { this.path = path; }
|
||||
|
||||
public Integer getVersion() { return version; }
|
||||
public void setVersion(Integer version) { this.version = version; }
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getParentId() {
|
||||
return parentId;
|
||||
}
|
||||
|
||||
public void setParentId(String parentId) {
|
||||
this.parentId = parentId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.seeyon.apps.assetsmap.vo;
|
||||
|
||||
public class SubBoundConfig {
|
||||
private Integer blockNum;
|
||||
private Integer pathOrder;
|
||||
private String lat;
|
||||
private String lng;
|
||||
|
||||
public String getLat() {
|
||||
return lat;
|
||||
}
|
||||
|
||||
public void setLat(String lat) {
|
||||
this.lat = lat;
|
||||
}
|
||||
|
||||
public Integer getBlockNum() {
|
||||
return blockNum;
|
||||
}
|
||||
|
||||
public void setBlockNum(Integer blockNum) {
|
||||
this.blockNum = blockNum;
|
||||
}
|
||||
|
||||
public Integer getPathOrder() {
|
||||
return pathOrder;
|
||||
}
|
||||
|
||||
public void setPathOrder(Integer pathOrder) {
|
||||
this.pathOrder = pathOrder;
|
||||
}
|
||||
|
||||
public String getLng() {
|
||||
return lng;
|
||||
}
|
||||
|
||||
public void setLng(String lng) {
|
||||
this.lng = lng;
|
||||
}
|
||||
}
|
||||
@@ -4,21 +4,30 @@ import cn.hutool.log.Log;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.seeyon.aicloud.common.JsonUtils;
|
||||
import com.seeyon.apps.assetsmap.kit.CAP4FormKit;
|
||||
import com.seeyon.apps.assetsmap.service.AssetsBoundUpdateLogService;
|
||||
import com.seeyon.apps.assetsmap.service.AssetsQueryService;
|
||||
import com.seeyon.apps.assetsmap.service.FileUploadService;
|
||||
import com.seeyon.apps.assetsmap.vo.AssetsCatagory;
|
||||
import com.seeyon.apps.assetsmap.vo.BoundsQueryVo;
|
||||
import com.seeyon.apps.assetsmap.vo.FileItemVO;
|
||||
import com.seeyon.apps.assetsmap.vo.SubBoundConfig;
|
||||
import com.seeyon.cap4.form.bean.FormDataMasterBean;
|
||||
import com.seeyon.cap4.form.bean.FormFieldBean;
|
||||
import com.seeyon.cap4.form.bean.FormTableBean;
|
||||
import com.seeyon.cap4.form.service.CAP4FormManager;
|
||||
import com.seeyon.cap4.template.util.CAPFormUtil;
|
||||
import com.seeyon.ctp.common.AppContext;
|
||||
import com.seeyon.ctp.rest.resources.BaseResource;
|
||||
import com.seeyon.utils.form.FormTableExecutor;
|
||||
import com.seeyon.utils.form.TableContext;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Path("/assetsRegion")
|
||||
@@ -28,7 +37,8 @@ public class AssetsRegionResources extends BaseResource {
|
||||
private static final Log log = Log.get(AssetsRegionResources.class);
|
||||
private CAP4FormManager cap4FormManager = (CAP4FormManager) AppContext.getBean("cap4FormManager");
|
||||
private AssetsQueryService assetsQueryService = (AssetsQueryService) AppContext.getBean("assetsQueryService");
|
||||
|
||||
private FileUploadService fileUploadService = (FileUploadService) AppContext.getBean("fileUploadService");
|
||||
private AssetsBoundUpdateLogService assetsBoundUpdateLogService = (AssetsBoundUpdateLogService) AppContext.getBean("assetsBoundUpdateLogService");
|
||||
|
||||
@POST
|
||||
@Path("/getall")
|
||||
@@ -115,6 +125,93 @@ public class AssetsRegionResources extends BaseResource {
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/getAssetDetail")
|
||||
@Produces({"application/json"})
|
||||
public Response getAssetDetail(@QueryParam("assetCode") String assetCode){
|
||||
try {
|
||||
return success(assetsQueryService.getAssetDetail(assetCode));
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
e.printStackTrace();
|
||||
return fail("查询失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/reComputedBoundConfig")
|
||||
@Produces({"application/json"})
|
||||
@Consumes({"application/json"})
|
||||
public Response reComputedBoundConfig(Map<String, Object> params){
|
||||
try {
|
||||
String formId = (String) params.get("formId");
|
||||
String fieldDisplay = (String) params.get("fieldDisplay");
|
||||
String color = "#27ae60";
|
||||
// 解析 subBoundConfigs
|
||||
List<?> rawList = (List<?>) params.get("subBoundConfigs");
|
||||
List<SubBoundConfig> configs = new ArrayList<>();
|
||||
if (rawList != null) {
|
||||
for (Object item : rawList) {
|
||||
if (item instanceof Map) {
|
||||
Map<String, Object> map = (Map<String, Object>) item;
|
||||
SubBoundConfig cfg = new SubBoundConfig();
|
||||
cfg.setBlockNum(map.get("blockNum") != null ? Integer.parseInt((String)map.get("blockNum")) : 0);
|
||||
cfg.setPathOrder(map.get("pathOrder") != null ? Integer.parseInt((String)map.get("pathOrder")) : 0);
|
||||
cfg.setLat(map.get("lat") != null ? map.get("lat").toString() : null);
|
||||
cfg.setLng(map.get("lng") != null ? map.get("lng").toString() : null);
|
||||
configs.add(cfg);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 按 blockNum 分组,按 pathOrder 排序
|
||||
Map<Integer, List<SubBoundConfig>> blockMap = new java.util.LinkedHashMap<>();
|
||||
for (SubBoundConfig cfg : configs) {
|
||||
int block = cfg.getBlockNum() != null ? cfg.getBlockNum() : 0;
|
||||
blockMap.computeIfAbsent(block, k -> new ArrayList<>()).add(cfg);
|
||||
}
|
||||
// 生成 regions
|
||||
List<Map<String, Object>> regions = new ArrayList<>();
|
||||
for (Map.Entry<Integer, List<SubBoundConfig>> entry : blockMap.entrySet()) {
|
||||
List<SubBoundConfig> points = entry.getValue();
|
||||
points.sort(java.util.Comparator.comparingInt(p -> p.getPathOrder() != null ? p.getPathOrder() : 0));
|
||||
List<List<Double>> outer = new ArrayList<>();
|
||||
for (SubBoundConfig p : points) {
|
||||
if (p.getLat() != null && p.getLng() != null) {
|
||||
List<Double> coord = new ArrayList<>();
|
||||
coord.add(Double.parseDouble(p.getLat()));
|
||||
coord.add(Double.parseDouble(p.getLng()));
|
||||
outer.add(coord);
|
||||
}
|
||||
}
|
||||
if (outer.size() < 3) continue;
|
||||
Map<String, Object> region = new HashMap<>();
|
||||
region.put("id", System.currentTimeMillis() + entry.getKey());
|
||||
region.put("outer", outer);
|
||||
region.put("holes", new ArrayList<>());
|
||||
regions.add(region);
|
||||
}
|
||||
// 构建边界JSON字符串
|
||||
Map<String, Object> boundData = new HashMap<>();
|
||||
boundData.put("regions", regions);
|
||||
boundData.put("color", color);
|
||||
String value = JsonUtils.toJSONString(boundData);
|
||||
// 回填到表单
|
||||
TableContext master = FormTableExecutor.master("esassetsdoc");
|
||||
FormTableBean tableBean = master.getTableBean();
|
||||
FormFieldBean fieldBean = tableBean.getFieldBeanByDisplay("资产边界数据");
|
||||
Map<String,Object> resMap = new HashMap<>();
|
||||
resMap.put("updateData",value);
|
||||
resMap.put("targetField",fieldBean.getColumnName());
|
||||
//日志记录
|
||||
assetsBoundUpdateLogService.recordLog(value,formId,"1");
|
||||
return success(resMap);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
e.printStackTrace();
|
||||
return fail("转换失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/search")
|
||||
@Produces({"application/json"})
|
||||
@@ -132,21 +229,45 @@ public class AssetsRegionResources extends BaseResource {
|
||||
@Path("/formBackFill")
|
||||
@Produces({"application/json"})
|
||||
@Consumes({"application/json"})
|
||||
public Response boundRefCallBack(Map<String, Object> params) {
|
||||
public Response formRefCallBack(Map<String, Object> params) {
|
||||
try {
|
||||
String masterId = (String) params.get("masterId");
|
||||
String fieldDisplay = (String) params.get("fieldDisplay");
|
||||
String isFile = (String)params.get("isFile");
|
||||
Object value = params.get("value");
|
||||
|
||||
FormDataMasterBean cacheFormData = cap4FormManager.getSessioMasterDataBean(Long.parseLong(masterId));
|
||||
FormFieldBean fieldBean = CAP4FormKit.getFieldBean(cacheFormData, fieldDisplay);
|
||||
Map<String, Object> displayValueMap = CAPFormUtil.getDisplayValueMap(value, fieldBean, null);
|
||||
cacheFormData.addFieldValue(fieldBean.getName(), value);
|
||||
|
||||
Map<String, Object> mainData = new HashMap<>();
|
||||
mainData.put(fieldBean.getName(), displayValueMap);
|
||||
|
||||
return success(mainData);
|
||||
if("true".equals(isFile)) {
|
||||
// 需要回填的主表字段
|
||||
List<FileItemVO> fileRefs = new ArrayList<>();
|
||||
//把旧值的json字符串转换成List<FileItemVO>,然后追加到fileRefs中
|
||||
List<Object> files = (ArrayList) value;
|
||||
for (Object file : files) {
|
||||
Map<String,String> fileMap = (Map<String,String>) file;
|
||||
FileItemVO fileItemVO = new FileItemVO();
|
||||
fileItemVO.setId(fileMap.get("fileKey"));
|
||||
fileItemVO.setName(fileMap.get("fileName"));
|
||||
String url = fileUploadService.getFilePreviewUrl(fileMap.get("fileKey"));
|
||||
fileItemVO.setPreviewUrl(url);
|
||||
fileRefs.add(fileItemVO);
|
||||
}
|
||||
// CAPFormUtil可以用于生成前端需要的数据结构
|
||||
Map<String, Object> fileUrlRes = CAPFormUtil.getDisplayValueMap(JsonUtils.toJSONString(fileRefs), fieldBean, null);
|
||||
// 数据加入缓存
|
||||
cacheFormData.addFieldValue(fieldBean.getName(), fileUrlRes);
|
||||
// 前端需要的数据
|
||||
mainData.put(fieldBean.getName(), fileUrlRes);
|
||||
return success(mainData);
|
||||
}else {
|
||||
Map<String, Object> displayValueMap = CAPFormUtil.getDisplayValueMap(value, fieldBean, null);
|
||||
cacheFormData.addFieldValue(fieldBean.getName(), value);
|
||||
mainData.put(fieldBean.getName(), displayValueMap);
|
||||
if(fieldDisplay.equals("资产边界数据")) {
|
||||
assetsBoundUpdateLogService.recordLog((String)value,masterId,"0");
|
||||
}
|
||||
return success(mainData);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return fail("保存失败:" + e.getMessage());
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
package com.seeyon.ctp.rest.resources.assetsmap;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.seeyon.apps.assetsmap.service.FileUploadService;
|
||||
import com.seeyon.apps.assetsmap.vo.FileListVO;
|
||||
import com.seeyon.ctp.common.AppContext;
|
||||
import com.seeyon.ctp.rest.resources.BaseResource;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 文件上传控件 REST 接口
|
||||
* 薄层:参数解析 + 调用 FileUploadService + 返回响应
|
||||
*/
|
||||
@Path("/fileUpload")
|
||||
@Produces({"application/json"})
|
||||
public class FileUploadResources extends BaseResource {
|
||||
|
||||
private static final Log log = Log.get(FileUploadResources.class);
|
||||
private FileUploadService fileUploadService = (FileUploadService) AppContext.getBean("fileUploadService");
|
||||
|
||||
/**
|
||||
* 获取文件夹子项列表
|
||||
* GET /seeyon/rest/fileUpload/folder/children?folderId=0
|
||||
*/
|
||||
@GET
|
||||
@Path("/folder/children")
|
||||
public Response listFolderChildren(@QueryParam("folderId") String folderId) {
|
||||
try {
|
||||
if (!fileUploadService.isConfigured()) {
|
||||
return fail("网盘服务地址未配置");
|
||||
}
|
||||
FileListVO result = fileUploadService.listFolderChildren(folderId);
|
||||
if (result == null) {
|
||||
return fail("获取文件夹列表失败");
|
||||
}
|
||||
return success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("获取文件夹列表失败", e);
|
||||
return fail("获取文件夹列表失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过业务ID获取文件夹ID
|
||||
* GET /seeyon/rest/fileUpload/folder/by-bizid?bizId=xxx
|
||||
*/
|
||||
@GET
|
||||
@Path("/folder/by-bizid")
|
||||
public Response getFolderIdByBizId(@QueryParam("bizId") String bizId) {
|
||||
try {
|
||||
if (!fileUploadService.isConfigured()) {
|
||||
return fail("网盘服务地址未配置");
|
||||
}
|
||||
String folderId = fileUploadService.getFolderIdByBizId(bizId);
|
||||
if (folderId != null) {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("folderId", folderId);
|
||||
return success(data);
|
||||
}
|
||||
return fail("未找到对应文件夹");
|
||||
} catch (Exception e) {
|
||||
log.error("获取文件夹ID失败", e);
|
||||
return fail("获取文件夹ID失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
* POST /seeyon/rest/fileUpload/upload?folderId=0
|
||||
* Body: multipart/form-data
|
||||
*/
|
||||
@POST
|
||||
@Path("/upload")
|
||||
@Consumes({"multipart/form-data"})
|
||||
@Produces({"text/html", "application/json"})
|
||||
public Response uploadFile(@Context HttpServletRequest request) {
|
||||
try {
|
||||
if (!fileUploadService.isConfigured()) {
|
||||
return fail("网盘服务地址未配置");
|
||||
}
|
||||
|
||||
CommonsMultipartResolver resolver = (CommonsMultipartResolver)AppContext.getBean("multipartResolver");
|
||||
MultipartHttpServletRequest multipartReq = resolver.resolveMultipart(request);
|
||||
Map<String, MultipartFile> fileMap = multipartReq.getFileMap();
|
||||
|
||||
// 从 multipart 中提取文件
|
||||
MultipartFile file = fileMap.get("file");
|
||||
if (file == null || file.isEmpty()) {
|
||||
return fail("未接收到文件数据");
|
||||
}
|
||||
|
||||
byte[] fileBytes = file.getBytes();
|
||||
String fileName = multipartReq.getParameter("fileName");
|
||||
if (fileName == null || fileName.isEmpty()) {
|
||||
fileName = file.getOriginalFilename();
|
||||
}
|
||||
String folderId = multipartReq.getParameter("folderId");
|
||||
|
||||
log.info("上传文件: fileName=" + fileName + ", folderId=" + folderId + ", size=" + fileBytes.length);
|
||||
// 超过100MB走分片上传
|
||||
long chunkSize = 100 * 1024 * 1024;
|
||||
String result = fileUploadService.uploadFile(fileBytes, fileName, folderId, chunkSize);
|
||||
if (result == null || result.isEmpty()) {
|
||||
return fail("上传失败:网盘服务无响应");
|
||||
}
|
||||
return success(JSONObject.parseObject(result));
|
||||
} catch (Exception e) {
|
||||
log.error("上传文件失败", e);
|
||||
return fail("上传文件失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 multipart header 中提取 part name
|
||||
*/
|
||||
private String extractPartName(String header) {
|
||||
int nameIdx = header.indexOf("name=\"");
|
||||
if (nameIdx < 0) return null;
|
||||
int start = nameIdx + 6;
|
||||
int end = header.indexOf("\"", start);
|
||||
return end > start ? header.substring(start, end) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 multipart header 中提取文件名
|
||||
*/
|
||||
private String extractFileName(String header) {
|
||||
int fnIdx = header.indexOf("filename=\"");
|
||||
if (fnIdx < 0) return null;
|
||||
int start = fnIdx + 10;
|
||||
int end = header.indexOf("\"", start);
|
||||
return end > start ? header.substring(start, end) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件下载链接
|
||||
* GET /seeyon/rest/fileUpload/file/download?fileId=xxx
|
||||
*/
|
||||
@GET
|
||||
@Path("/file/download")
|
||||
public Response getFileDownloadUrl(@QueryParam("fileId") String fileId) {
|
||||
try {
|
||||
if (!fileUploadService.isConfigured()) {
|
||||
return fail("网盘服务地址未配置");
|
||||
}
|
||||
String result = fileUploadService.getFileDownloadUrl(fileId);
|
||||
if (result == null || result.isEmpty()) {
|
||||
return fail("未找到文件");
|
||||
}
|
||||
return success(JSONObject.parseObject(result));
|
||||
} catch (Exception e) {
|
||||
log.error("获取下载链接失败", e);
|
||||
return fail("获取下载链接失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/file/info")
|
||||
public Response getFileInfo(@QueryParam("fileId") String fileId) {
|
||||
try {
|
||||
if (!fileUploadService.isConfigured()) {
|
||||
return fail("网盘服务地址未配置");
|
||||
}
|
||||
String result = fileUploadService.getFileInfo(fileId);
|
||||
if (result == null || result.isEmpty()) {
|
||||
return fail("未找到文件");
|
||||
}
|
||||
return success(JSONObject.parseObject(result));
|
||||
} catch (Exception e) {
|
||||
log.error("获取文件信息失败", e);
|
||||
return fail("获取文件信息失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索文件
|
||||
* GET /seeyon/rest/fileUpload/file/search?keyword=xxx
|
||||
*/
|
||||
@GET
|
||||
@Path("/file/search")
|
||||
public Response searchFiles(@QueryParam("keyword") String keyword) {
|
||||
try {
|
||||
if (!fileUploadService.isConfigured()) {
|
||||
return fail("网盘服务地址未配置");
|
||||
}
|
||||
java.util.List<com.seeyon.apps.assetsmap.vo.FileItemVO> result = fileUploadService.searchFiles(keyword);
|
||||
return success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("搜索文件失败", e);
|
||||
return fail("搜索文件失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user