活动介绍

Map<String, String> requestParam = new HashMap<>(); requestParam.put("app_key", "100001"); requestParam.put("timestamp", "2018-01-22 10:10:10"); requestParam.put("format", "json"); requestParam.put("v", "1"); requestParam.put("sign_method", "MD5"); requestParam.put("session", "ee45021744e2d32eab172a5b7b04ae793bc6e97d"); requestParam.put("qr_code", "4yZB6nPiS4SXXkLKIpFLVg%3D%3D@993830"); //验证签名,详情见签名生成说明文档 requestParam.put("sign", SignUtil.signTopRequest(requestParam, "1590f337484080dfa05e949f6b2c3c0357948876", "MD5")) //构造form Form form = Form.form(); for (Map.Entry<String, String> entry : requestParam.entrySet()) { form.add(entry.getKey(), entry.getValue()); } //发起post请求 return Request.Post("https://openapi.dianping.com/router/tuangou/receipt/scanprepare") .bodyForm(form.build()) .setHeader("Content-Type", ContentType.create("application/x-www-form-urlencoded", "UTF-8").toString()) .execute().returnContent().asString(); 帮我用js重新写一下上面的代码

时间: 2023-07-24 14:13:15 浏览: 192
以下是使用 JavaScript 重新编写的代码,实现与您提供的 Java 代码类似的功能: ```javascript const requestParam = new Map(); requestParam.set("app_key", "100001"); requestParam.set("timestamp", "2018-01-22 10:10:10"); requestParam.set("format", "json"); requestParam.set("v", "1"); requestParam.set("sign_method", "MD5"); requestParam.set("session", "ee45021744e2d32eab172a5b7b04ae793bc6e97d"); requestParam.set("qr_code", "4yZB6nPiS4SXXkLKIpFLVg%3D%3D@993830"); // 构造签名 const appSecret = "1590f337484080dfa05e949f6b2c3c0357948876"; const sign = generateSignature(requestParam, appSecret, "MD5"); requestParam.set("sign", sign); // 构造请求参数 let formData = ""; for (const [key, value] of requestParam.entries()) { formData += encodeURIComponent(key) + "=" + encodeURIComponent(value) + "&"; } formData = formData.slice(0, -1); // 发起 POST 请求 fetch("https://openapi.dianping.com/router/tuangou/receipt/scanprepare", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8", }, body: formData, }) .then((response) => response.text()) .then((data) => console.log(data)) .catch((error) => console.log(error)); function generateSignature(params, appSecret, signMethod) { // 对参数名进行排序 const sortedKeys = Array.from(params.keys()).sort(); // 拼接参数名和参数值 let paramString = ""; sortedKeys.forEach((key) => { if (key !== "sign" && params.get(key) !== "") { paramString += key + params.get(key); } }); // 添加 appSecret paramString += appSecret; // 使用指定的签名方法对参数进行摘要 if (signMethod === "MD5") { return md5(paramString); } else { throw new Error("Unsupported sign method"); } } function md5(str) { const md5 = require("crypto-js/md5"); return md5(str).toString(); } ``` 请注意,上述代码中使用了 `fetch` 函数来发起 POST 请求。如果您在非浏览器环境下使用,可以使用其他适合的方式来发起请求,例如 `axios`、`node-fetch` 等。此外,`crypto-js` 库用于计算 MD5 摘要,请确保已经安装了该库。
阅读全文

相关推荐

package com.app.controller; import com.alibaba.fastjson.JSON; import com.annotation.IgnoreAuth; import com.baidu.aip.face.AipFace; import com.baidu.aip.face.MatchRequest; import com.baidu.aip.util.Base64Util; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.entity.ConfigEntity; import com.service.CommonService; import com.service.ConfigService; import com.utils.BaiduUtil; import com.utils.FileUtil; import com.utils.R; import com.utils.StringUtil; import org.apache.commons.lang3.StringUtils; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.*; /** * 通用接口 */ @RestController public class CommonController{ private static final Logger logger = LoggerFactory.getLogger(CommonController.class); @Autowired private CommonService commonService; @Autowired private ConfigService configService; private static AipFace client = null; private static String BAIDU_DITU_AK = null; @RequestMapping("/location") public R location(String lng,String lat) { if(BAIDU_DITU_AK==null) { BAIDU_DITU_AK = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "baidu_ditu_ak")).getValue(); if(BAIDU_DITU_AK==null) { return R.error("请在配置管理中正确配置baidu_ditu_ak"); } } Map<String, String> map = BaiduUtil.getCityByLonLat(BAIDU_DITU_AK, lng, lat); return R.ok().put("data", map); } /** * 人脸比对 * * @param face1 人脸1 * @param face2 人脸2 * @return */ @RequestMapping("/matchFace") public R matchFace(String face1, String face2, HttpServletRequest request) { if(client==null) { /*String AppID = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "AppID")).getValue();*/ String APIKey = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "APIKey")).getValue(); String SecretKey = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "SecretKey")).getValue(); String token = BaiduUtil.getAuth(APIKey, SecretKey); if(token==null) { return R.error("请在配置管理中正确配置APIKey和SecretKey"); } client = new AipFace(null, APIKey, SecretKey); client.setConnectionTimeoutInMillis(2000); client.setSocketTimeoutInMillis(60000); } JSONObject res = null; try { File file1 = new File(request.getSession().getServletContext().getRealPath("/upload")+"/"+face1); File file2 = new File(request.getSession().getServletContext().getRealPath("/upload")+"/"+face2); String img1 = Base64Util.encode(FileUtil.FileToByte(file1)); String img2 = Base64Util.encode(FileUtil.FileToByte(file2)); MatchRequest req1 = new MatchRequest(img1, "BASE64"); MatchRequest req2 = new MatchRequest(img2, "BASE64"); ArrayList<MatchRequest> requests = new ArrayList<MatchRequest>(); requests.add(req1); requests.add(req2); res = client.match(requests); System.out.println(res.get("result")); } catch (FileNotFoundException e) { e.printStackTrace(); return R.error("文件不存在"); } catch (IOException e) { e.printStackTrace(); } return R.ok().put("data", com.alibaba.fastjson.JSONObject.parse(res.get("result").toString())); } /** * 获取table表中的column列表(联动接口) * @return */ @RequestMapping("/option/{tableName}/{columnName}") @IgnoreAuth public R getOption(@PathVariable("tableName") String tableName, @PathVariable("columnName") String columnName,String level,String parent) { Map<String, Object> params = new HashMap<String, Object>(); params.put("table", tableName); params.put("column", columnName); if(StringUtils.isNotBlank(level)) { params.put("level", level); } if(StringUtils.isNotBlank(parent)) { params.put("parent", parent); } List<String> data = commonService.getOption(params); return R.ok().put("data", data); } /** * 根据table中的column获取单条记录 * @return */ @RequestMapping("/follow/{tableName}/{columnName}") @IgnoreAuth public R getFollowByOption(@PathVariable("tableName") String tableName, @PathVariable("columnName") String columnName, @RequestParam String columnValue) { Map<String, Object> params = new HashMap<String, Object>(); params.put("table", tableName); params.put("column", columnName); params.put("columnValue", columnValue); Map<String, Object> result = commonService.getFollowByOption(params); return R.ok().put("data", result); } /** * 修改table表的sfsh状态 * @param map * @return */ @RequestMapping("/sh/{tableName}") public R sh(@PathVariable("tableName") String tableName, @RequestBody Map<String, Object> map) { map.put("table", tableName); commonService.sh(map); return R.ok(); } /** * 获取需要提醒的记录数 * @param tableName * @param columnName * @param type 1:数字 2:日期 * @param map * @return */ @RequestMapping("/remind/{tableName}/{columnName}/{type}") @IgnoreAuth public R remindCount(@PathVariable("tableName") String tableName, @PathVariable("columnName") String columnName, @PathVariable("type") String type,@RequestParam Map<String, Object> map) { map.put("table", tableName); map.put("column", columnName); map.put("type", type); if(type.equals("2")) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Calendar c = Calendar.getInstance(); Date remindStartDate = null; Date remindEndDate = null; if(map.get("remindstart")!=null) { Integer remindStart = Integer.parseInt(map.get("remindstart").toString()); c.setTime(new Date()); c.add(Calendar.DAY_OF_MONTH,remindStart); remindStartDate = c.getTime(); map.put("remindstart", sdf.format(remindStartDate)); } if(map.get("remindend")!=null) { Integer remindEnd = Integer.parseInt(map.get("remindend").toString()); c.setTime(new Date()); c.add(Calendar.DAY_OF_MONTH,remindEnd); remindEndDate = c.getTime(); map.put("remindend", sdf.format(remindEndDate)); } } int count = commonService.remindCount(map); return R.ok().put("count", count); } /** * 圖表统计 */ @IgnoreAuth @RequestMapping("/group/{tableName}") public R group1(@PathVariable("tableName") String tableName, @RequestParam Map<String,Object> params) { params.put("table1", tableName); List<Map<String, Object>> result = commonService.chartBoth(params); return R.ok().put("data", result); } /** * 单列求和 */ @RequestMapping("/cal/{tableName}/{columnName}") @IgnoreAuth public R cal(@PathVariable("tableName") String tableName, @PathVariable("columnName") String columnName) { Map<String, Object> params = new HashMap<String, Object>(); params.put("table", tableName); params.put("column", columnName); Map<String, Object> result = commonService.selectCal(params); return R.ok().put("data", result); } /** * 分组统计 */ @RequestMapping("/group/{tableName}/{columnName}") @IgnoreAuth public R group(@PathVariable("tableName") String tableName, @PathVariable("columnName") String columnName) { Map<String, Object> params = new HashMap<String, Object>(); params.put("table", tableName); params.put("column", columnName); List<Map<String, Object>> result = commonService.selectGroup(params); return R.ok().put("data", result); } /** * (按值统计) */ @RequestMapping("/value/{tableName}/{xColumnName}/{yColumnName}") @IgnoreAuth public R value(@PathVariable("tableName") String tableName, @PathVariable("yColumnName") String yColumnName, @PathVariable("xColumnName") String xColumnName) { Map<String, Object> params = new HashMap<String, Object>(); params.put("table", tableName); params.put("xColumn", xColumnName); params.put("yColumn", yColumnName); List<Map<String, Object>> result = commonService.selectValue(params); return R.ok().put("data", result); } /** * 下面为新加的 * * * */ /** * 查询字典表的分组求和 * tableName 表名 * groupColumn 分组字段 * sumCloum 统计字段 * @return */ @RequestMapping("/newSelectGroupSum") public R newSelectGroupSum(@RequestParam Map<String,Object> params) { logger.debug("newSelectGroupSum:,,Controller:{},,params:{}",this.getClass().getName(),params); List<Map<String, Object>> result = commonService.newSelectGroupSum(params); return R.ok().put("data", result); } /** tableName 查询表 condition1 条件1 condition1Value 条件1值 average 计算平均评分 取值 有值 Number(res.data.value.toFixed(1)) 无值 if(res.data){} * */ @IgnoreAuth @RequestMapping("/queryScore") public R queryScore(@RequestParam Map<String, Object> params) { logger.debug("queryScore:,,Controller:{},,params:{}",this.getClass().getName(),params); Map<String, Object> queryScore = commonService.queryScore(params); return R.ok().put("data", queryScore); } /** * 查询字典表的分组统计总条数 * tableName 表名 * groupColumn 分组字段 * @return */ @RequestMapping("/newSelectGroupCount") public R newSelectGroupCount(@RequestParam Map<String,Object> params) { logger.debug("newSelectGroupCount:,,Controller:{},,params:{}",this.getClass().getName(),params); List<Map<String, Object>> result = commonService.newSelectGroupCount(params); return R.ok().put("data", result); } /** * 当前表的日期分组求和 * tableName 表名 * groupColumn 分组字段 * sumCloum 统计字段 * dateFormatType 日期格式化类型 1:年 2:月 3:日 * @return */ @RequestMapping("/newSelectDateGroupSum") public R newSelectDateGroupSum(@RequestParam Map<String,Object> params) { logger.debug("newSelectDateGroupSum:,,Controller:{},,params:{}",this.getClass().getName(),params); String dateFormatType = String.valueOf(params.get("dateFormatType")); if("1".equals(dateFormatType)){ params.put("dateFormat", "%Y"); }else if("2".equals(dateFormatType)){ params.put("dateFormat", "%Y-%m"); }else if("3".equals(dateFormatType)){ params.put("dateFormat", "%Y-%m-%d"); }else{ R.error("日期格式化不正确"); } List<Map<String, Object>> result = commonService.newSelectDateGroupSum(params); return R.ok().put("data", result); } /** * * 查询字典表的分组统计总条数 * tableName 表名 * groupColumn 分组字段 * dateFormatType 日期格式化类型 1:年 2:月 3:日 * @return */ @RequestMapping("/newSelectDateGroupCount") public R newSelectDateGroupCount(@RequestParam Map<String,Object> params) { logger.debug("newSelectDateGroupCount:,,Controller:{},,params:{}",this.getClass().getName(),params); String dateFormatType = String.valueOf(params.get("dateFormatType")); if("1".equals(dateFormatType)){ params.put("dateFormat", "%Y"); }else if("2".equals(dateFormatType)){ params.put("dateFormat", "%Y-%m"); }else if("3".equals(dateFormatType)){ params.put("dateFormat", "%Y-%m-%d"); }else{ R.error("日期格式化类型不正确"); } List<Map<String, Object>> result = commonService.newSelectDateGroupCount(params); return R.ok().put("data", result); } /** * 饼状图 * -- 饼状图 查询当前表 -- 查询字典表【月】 -- 统计 -- 查询某个月的每个类型的订单销售数量 -- 求和 -- 查询某个月的每个类型的订单销售额 -- 查询某个字符串【月】 -- 统计 -- 查询某个月的每个员工的订单销售数量 -- 求和 -- 查询某个月的每个员工的订单销售额 -- 查询时间【年】 -- 统计 -- 查询每个月的订单销售数量 -- 求和 -- 查询每个月的订单销售额 -- 饼状图 查询级联表 -- 查询字典表 -- 统计 -- 查询某个月的每个类型的订单销售数量 -- 求和 -- 查询某个月的每个类型的订单销售额 -- 查询某个字符串 -- 统计 -- 查询某个月的每个员工的订单销售数量 -- 求和 -- 查询某个月的每个员工的订单销售额 -- 查询时间 -- 统计 -- 统计每个月的订单销售数量 -- 求和 -- 查询每个月的订单销售额 */ /** * 柱状图 -- 柱状图 查询当前表 -- 某个【年,月】 -- 当前表 2 级联表 1 -- 统计 -- 【日期,字符串,下拉框】 -- 求和 -- 【日期,字符串,下拉框】 -- 柱状图 查询级联表 -- 某个【年,月】 -- 统计 -- 【日期,字符串,下拉框】 -- 求和 -- 【日期,字符串,下拉框】 */ /** * 柱状图求和 */ @RequestMapping("/barSum") public R barSum(@RequestParam Map<String,Object> params) { logger.debug("barSum方法:,,Controller:{},,params:{}",this.getClass().getName(), com.alibaba.fastjson.JSONObject.toJSONString(params)); Boolean isJoinTableFlag = false;//是否有级联表相关 String one = "";//第一优先 String two = "";//第二优先 //处理thisTable和joinTable 处理内容是把json字符串转为Map并把带有,的切割为数组 //当前表 Map<String,Object> thisTable = JSON.parseObject(String.valueOf(params.get("thisTable")),Map.class); params.put("thisTable",thisTable); //级联表 String joinTableString = String.valueOf(params.get("joinTable")); if(StringUtil.isNotEmpty(joinTableString)) { Map<String, Object> joinTable = JSON.parseObject(joinTableString, Map.class); params.put("joinTable", joinTable); isJoinTableFlag = true; } if(StringUtil.isNotEmpty(String.valueOf(thisTable.get("date")))){//当前表日期 thisTable.put("date",String.valueOf(thisTable.get("date")).split(",")); one = "thisDate0"; } if(isJoinTableFlag){//级联表日期 Map<String, Object> joinTable = (Map<String, Object>) params.get("joinTable"); if(StringUtil.isNotEmpty(String.valueOf(joinTable.get("date")))){ joinTable.put("date",String.valueOf(joinTable.get("date")).split(",")); if(StringUtil.isEmpty(one)){ one ="joinDate0"; }else{ if(StringUtil.isEmpty(two)){ two ="joinDate0"; } } } } if(StringUtil.isNotEmpty(String.valueOf(thisTable.get("string")))){//当前表字符串 thisTable.put("string",String.valueOf(thisTable.get("string")).split(",")); if(StringUtil.isEmpty(one)){ one ="thisString0"; }else{ if(StringUtil.isEmpty(two)){ two ="thisString0"; } } } if(isJoinTableFlag){//级联表字符串 Map<String, Object> joinTable = (Map<String, Object>) params.get("joinTable"); if(StringUtil.isNotEmpty(String.valueOf(joinTable.get("string")))){ joinTable.put("string",String.valueOf(joinTable.get("string")).split(",")); if(StringUtil.isEmpty(one)){ one ="joinString0"; }else{ if(StringUtil.isEmpty(two)){ two ="joinString0"; } } } } if(StringUtil.isNotEmpty(String.valueOf(thisTable.get("types")))){//当前表类型 thisTable.put("types",String.valueOf(thisTable.get("types")).split(",")); if(StringUtil.isEmpty(one)){ one ="thisTypes0"; }else{ if(StringUtil.isEmpty(two)){ two ="thisTypes0"; } } } if(isJoinTableFlag){//级联表类型 Map<String, Object> joinTable = (Map<String, Object>) params.get("joinTable"); if(StringUtil.isNotEmpty(String.valueOf(joinTable.get("types")))){ joinTable.put("types",String.valueOf(joinTable.get("types")).split(",")); if(StringUtil.isEmpty(one)){ one ="joinTypes0"; }else{ if(StringUtil.isEmpty(two)){ two ="joinTypes0"; } } } } List<Map<String, Object>> result = commonService.barSum(params); List<String> xAxis = new ArrayList<>();//报表x轴 List> yAxis = new ArrayList<>();//y轴 List<String> legend = new ArrayList<>();//标题 if(StringUtil.isEmpty(two)){//不包含第二列 List<String> yAxis0 = new ArrayList<>(); yAxis.add(yAxis0); legend.add("数值"); for(Map<String, Object> map :result){ String oneValue = String.valueOf(map.get(one)); String value = String.valueOf(map.get("value")); xAxis.add(oneValue); yAxis0.add(value); } }else{//包含第二列 Map<String, HashMap<String, String>> dataMap = new LinkedHashMap<>(); if(StringUtil.isNotEmpty(two)){ for(Map<String, Object> map :result){ String oneValue = String.valueOf(map.get(one)); String twoValue = String.valueOf(map.get(two)); String value = String.valueOf(map.get("value")); if(!legend.contains(twoValue)){ legend.add(twoValue);//添加完成后 就是最全的第二列的类型 } if(dataMap.containsKey(oneValue)){ dataMap.get(oneValue).put(twoValue,value); }else{ HashMap<String, String> oneData = new HashMap<>(); oneData.put(twoValue,value); dataMap.put(oneValue,oneData); } } } for(int i =0; i<legend.size(); i++){ yAxis.add(new ArrayList<String>()); } Set<String> keys = dataMap.keySet(); for(String key:keys){ xAxis.add(key); HashMap<String, String> map = dataMap.get(key); for(int i =0; i<legend.size(); i++){ List<String> data = yAxis.get(i); if(StringUtil.isNotEmpty(map.get(legend.get(i)))){ data.add(map.get(legend.get(i))); }else{ data.add("0"); } } } System.out.println(); } Map<String, Object> resultMap = new HashMap<>(); resultMap.put("xAxis",xAxis); resultMap.put("yAxis",yAxis); resultMap.put("legend",legend); return R.ok().put("data", resultMap); } /** * 柱状图统计 */ @RequestMapping("/barCount") public R barCount(@RequestParam Map<String,Object> params) { logger.debug("barCount方法:,,Controller:{},,params:{}",this.getClass().getName(), com.alibaba.fastjson.JSONObject.toJSONString(params)); Boolean isJoinTableFlag = false;//是否有级联表相关 String one = "";//第一优先 String two = "";//第二优先 //处理thisTable和joinTable 处理内容是把json字符串转为Map并把带有,的切割为数组 //当前表 Map<String,Object> thisTable = JSON.parseObject(String.valueOf(params.get("thisTable")),Map.class); params.put("thisTable",thisTable); //级联表 String joinTableString = String.valueOf(params.get("joinTable")); if(StringUtil.isNotEmpty(joinTableString)) { Map<String, Object> joinTable = JSON.parseObject(joinTableString, Map.class); params.put("joinTable", joinTable); isJoinTableFlag = true; } if(StringUtil.isNotEmpty(String.valueOf(thisTable.get("date")))){//当前表日期 thisTable.put("date",String.valueOf(thisTable.get("date")).split(",")); one = "thisDate0"; } if(isJoinTableFlag){//级联表日期 Map<String, Object> joinTable = (Map<String, Object>) params.get("joinTable"); if(StringUtil.isNotEmpty(String.valueOf(joinTable.get("date")))){ joinTable.put("date",String.valueOf(joinTable.get("date")).split(",")); if(StringUtil.isEmpty(one)){ one ="joinDate0"; }else{ if(StringUtil.isEmpty(two)){ two ="joinDate0"; } } } } if(StringUtil.isNotEmpty(String.valueOf(thisTable.get("string")))){//当前表字符串 thisTable.put("string",String.valueOf(thisTable.get("string")).split(",")); if(StringUtil.isEmpty(one)){ one ="thisString0"; }else{ if(StringUtil.isEmpty(two)){ two ="thisString0"; } } } if(isJoinTableFlag){//级联表字符串 Map<String, Object> joinTable = (Map<String, Object>) params.get("joinTable"); if(StringUtil.isNotEmpty(String.valueOf(joinTable.get("string")))){ joinTable.put("string",String.valueOf(joinTable.get("string")).split(",")); if(StringUtil.isEmpty(one)){ one ="joinString0"; }else{ if(StringUtil.isEmpty(two)){ two ="joinString0"; } } } } if(StringUtil.isNotEmpty(String.valueOf(thisTable.get("types")))){//当前表类型 thisTable.put("types",String.valueOf(thisTable.get("types")).split(",")); if(StringUtil.isEmpty(one)){ one ="thisTypes0"; }else{ if(StringUtil.isEmpty(two)){ two ="thisTypes0"; } } } if(isJoinTableFlag){//级联表类型 Map<String, Object> joinTable = (Map<String, Object>) params.get("joinTable"); if(StringUtil.isNotEmpty(String.valueOf(joinTable.get("types")))){ joinTable.put("types",String.valueOf(joinTable.get("types")).split(",")); if(StringUtil.isEmpty(one)){ one ="joinTypes0"; }else{ if(StringUtil.isEmpty(two)){ two ="joinTypes0"; } } } } List<Map<String, Object>> result = commonService.barCount(params); List<String> xAxis = new ArrayList<>();//报表x轴 List> yAxis = new ArrayList<>();//y轴 List<String> legend = new ArrayList<>();//标题 if(StringUtil.isEmpty(two)){//不包含第二列 List<String> yAxis0 = new ArrayList<>(); yAxis.add(yAxis0); legend.add("数值"); for(Map<String, Object> map :result){ String oneValue = String.valueOf(map.get(one)); String value = String.valueOf(map.get("value")); xAxis.add(oneValue); yAxis0.add(value); } }else{//包含第二列 Map<String, HashMap<String, String>> dataMap = new LinkedHashMap<>(); if(StringUtil.isNotEmpty(two)){ for(Map<String, Object> map :result){ String oneValue = String.valueOf(map.get(one)); String twoValue = String.valueOf(map.get(two)); String value = String.valueOf(map.get("value")); if(!legend.contains(twoValue)){ legend.add(twoValue);//添加完成后 就是最全的第二列的类型 } if(dataMap.containsKey(oneValue)){ dataMap.get(oneValue).put(twoValue,value); }else{ HashMap<String, String> oneData = new HashMap<>(); oneData.put(twoValue,value); dataMap.put(oneValue,oneData); } } } for(int i =0; i<legend.size(); i++){ yAxis.add(new ArrayList<String>()); } Set<String> keys = dataMap.keySet(); for(String key:keys){ xAxis.add(key); HashMap<String, String> map = dataMap.get(key); for(int i =0; i<legend.size(); i++){ List<String> data = yAxis.get(i); if(StringUtil.isNotEmpty(map.get(legend.get(i)))){ data.add(map.get(legend.get(i))); }else{ data.add("0"); } } } System.out.println(); } Map<String, Object> resultMap = new HashMap<>(); resultMap.put("xAxis",xAxis); resultMap.put("yAxis",yAxis); resultMap.put("legend",legend); return R.ok().put("data", resultMap); } } 我现在使用springboot3.5.3和java17,这些文件需要修改吗,怎么修改,修改后的文件需要重新给出注释并给出完整的代码

<string name=“url”>https://192.168.31.177:3000</string> <string name=“url_all”>/app/all</string> <string name=“url_bancis”>/app/bancai/all</string> <string name=“url_caizhis”>/app/caizhi/all</string> <string name=“url_mupis”>/app/mupi/all</string> <string name=“url_dingdans”>/app/dingdan/all</string> <string name=“url_chanpins”>/app/chanpin/all</string> <string name=“url_zujians”>/app/zujian/all</string> <string name=“url_chanpin_zujians”>/app/chanpin_zujian/all</string> <string name=“url_dingdan_zujians”>/app/dingdan_zujian/all</string> <string name=“url_dingdan_chanpins”>/app/dingdan_chanpin/all</string> <string name=“url_jinhuos”>/app/jinhuo/all</string> <string name=“url_add_bancai”>/app/bancai/add</string> <string name=“url_add_dingdan”>/app/dingdan/add</string> <string name=“url_add_chanpin”>/app/chanpin/add</string> <string name=“url_add_zujian”>/app/zujian/add</string> <string name=“url_add_caizhi”>/app/caizhi/add</string> <string name=“url_add_mupi”>/app/mupi/add</string> <string name=“url_add_dingdan_chanpin”>/app/dingdan_chanpi/add</string> <string name=“url_add_dingdan_zujian”>/app/dingdan_zujian/add</string> <string name=“url_add_chanpin_zujian”>/app/chanpin_zujian/add</string> <string name=“url_add_jinhuo”>/app/jinhuo/add</string> <string name=“url_login”>/user/login</string>api url标准化,url规则url_{增删改查}_实体类名小写,获取全部url_实体类名小写+s

将以下JAVA代码转为PHP代码:import java.security.spec.*; import java.security.*; import java.util.*; import org.apache.commons.lang3.StringUtils; public class SignUtils { public static String signSHA256(byte[] message, byte[] privateKeyBytes) throws Exception { PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyBytes)); KeyFactory keyf = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyf.generatePrivate(priPKCS8); Signature sign = Signature.getInstance("SHA256withRSA"); sign.initSign(privateKey); sign.update(message); return Base64.getEncoder().encodeToString(sign.sign()); } public static String makeSignStr(Map<String, String> params) { List<String> keys = Lists.newArrayList(); for (Map.Entry<String, String> entry : params.entrySet()) { if ("sign".equals(entry.getKey())) { continue; } if (StringUtils.isNotBlank(entry.getValue())) { keys.add(entry.getKey()); } } Collections.sort(keys); List<String> temp = Lists.newArrayList(); for (String key : keys) { String value = params.get(key); temp.add(key + "=" + value); } return StringUtils.join(temp, "&"); } public static void main(String[] args) { try { //读取私钥 byte[] privateKeyBytes = null; Map<String, String> params = new HashMap<>(); params.put("mch_id", "商户编号"); params.put("app_id", "应用ID"); params.put("timestamp", "1541661668"); params.put("nonce_str", "aiz04enx0a2"); params.put("sign_type", "SHA"); params.put("version", "2.0"); params.put("content", "VBDExvz6/k56B1S5n7n3uOvI2sxZixcsV0Tdld92ym0CpnN8ooiCkXPgg0N1z8NC"); //签名 String sign = SignUtils.signSHA256(makeSignStr(params).getBytes("UTF-8"), privateKeyBytes); } catch (Exception e) { e.printStackTrace(); } } }

package com.kucun.Service; import java.io.Serializable; import java.lang.reflect.*; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.data.domain.Example; import org.springframework.data.domain.ExampleMatcher; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Service; import com.kucun.data.entity.Bancai; import com.kucun.data.entity.Dingdan_chanpin; import com.kucun.data.entity.Dingdan_chanpin_zujian; import com.kucun.data.entity.EntityBasis; import com.kucun.data.entity.Information; import com.kucun.data.entity.Kucun; import com.kucun.dataDo.BancaiRepository; import com.kucun.dataDo.CaizhiRepository; import com.kucun.dataDo.ChanpinRepository; import com.kucun.dataDo.ChanpinZujianRepository; import com.kucun.dataDo.DingdanChanpinRepository; import com.kucun.dataDo.DingdanChanpinZujianRepository; import com.kucun.dataDo.DingdanRepository; import com.kucun.dataDo.KucunRepository; import com.kucun.dataDo.MupiRepository; import com.kucun.dataDo.UserRepository; import com.kucun.dataDo.ZujianRepository; @Service public class AppService { // 注入所有需要的Repository @Autowired private CaizhiRepository caizhiRepository; @Autowired private BancaiRepository bancaiRepository; @Autowired private ChanpinRepository chanpinRepository; @Autowired private DingdanRepository dingdanRepository; @Autowired private MupiRepository mupiRepository; @Autowired private ZujianRepository zujianRepository; @Autowired private KucunRepository kucunRepository; @Autowired private UserRepository userRepository; @Autowired private ChanpinZujianRepository chanpinZujianRepository; @Autowired private DingdanChanpinZujianRepository dingdanChanpinZujianRepository; @Autowired private DingdanChanpinRepository dingdanChanpinRepository; @Autowired private DynamicRepositoryService repositoryService; @Autowired private EntityDependencyService dependencyService; public Information getAllDataWithChildIdse() { Map<String, Object> response = new HashMap<>(); for (String key : repositoryService.getRepositoryNameMap().keySet()) { response.put(key+"s", (repositoryService.getJpaRepository(key).findAll())); } return Information.NewSuccess(response); } public Information getAllDataWithChildIdse(String e) { JpaRepository<?, ?> jp = repositoryService.getJpaRepository(e); System.out.println(jp); return Information.NewSuccess(jp.findAll()); } public Information getAddEntity(Object e) { Class<?> entityClass = e.getClass(); try { // 处理关联字段 handleAssociations(e); @SuppressWarnings("unchecked") JpaRepository<Object, Serializable> jp = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entityClass); Object savedEntity = jp.save(e); if(savedEntity!=null) { if(savedEntity instanceof Bancai) { initializeKucunForBancai((Bancai)savedEntity); } } return Information.NewSuccess(savedEntity); } catch (Exception ex) { return Information.Newfail(500, "创建失败: " + ex.getMessage(), null); } } // 单独封装库存初始化方法 private void initializeKucunForBancai(Bancai bancai) throws Exception { Kucun kucun = new Kucun(null, bancai, 0); // 初始库存为0 try { bancai.setKucun(kucunRepository.save(kucun)); } catch (Exception e) { // TODO: handle exception throw new Exception("initializeKucunForBancai"+e); } } // 处理关联对象(转换为托管实体) private void handleAssociations(Object entity) throws Exception { Class<?> clazz = entity.getClass(); for (Field field : clazz.getDeclaredFields()) { field.setAccessible(true); Object value = field.get(entity); if (value == null) continue; // 处理单个关联实体 if (isEntityBasisField(field)) { EntityBasis associatedEntity = (EntityBasis) value; JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(associatedEntity.getClass()); // 获取托管状态的关联实体 Object managedEntity = repo.findById(associatedEntity.getId()) .orElseThrow(() -> new RuntimeException("关联实体不存在")); field.set(entity, managedEntity); } // 处理集合关联 else if (isCollectionField(field)) { Collection<?> collection = (Collection<?>) value; List<Object> managedEntities = new ArrayList<>(); for (Object item : collection) { if (item instanceof EntityBasis) { EntityBasis eb = (EntityBasis) item; JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(eb.getClass()); Object managedEntity = repo.findById(eb.getId()) .orElseThrow(() -> new RuntimeException("关联实体不存在")); managedEntities.add(managedEntity); } } // 更新集合为托管实体 if (!managedEntities.isEmpty()) { field.set(entity, managedEntities); } } } } /** * 更新 * @param e 实体待id * @return */ /** * 更新实体 * @param e 包含ID的实体 * @return 操作结果 */ public Information getupdateEntity(Object e) { if(e == null) { return Information.Newfail(403, "参数为空", null); } Class<?> entityClass = e.getClass(); try { Field idField = entityClass.getDeclaredField("id"); idField.setAccessible(true); Object idValue = idField.get(e); // 修正:应检查id是否为空,而不是不为空 if(idValue == null) { return Information.Newfail(403, "Id为空", null); } // 获取Repository @SuppressWarnings("unchecked") JpaRepository<Object, Serializable> jp = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entityClass); // 从数据库加载现有实体(托管状态) Object existingEntity = jp.findById((Serializable) idValue) .orElseThrow(() -> new RuntimeException("实体不存在")); // 复制属性(排除关联字段) copyNonNullProperties(e, existingEntity); // 保存托管状态的实体 Object updatedEntity = jp.save(existingEntity); return Information.NewSuccess(updatedEntity); } catch (Exception ex) { return Information.Newfail(500, "更新失败: " + ex.getMessage(), null); } } /** * 删除 * @param entity * @return */ public Information getdeleteEntity(EntityBasis entity) { Map<String, Object> response = new HashMap<>(); JpaRepository<Object, Integer> jp= (JpaRepository<Object, Integer>) repositoryService.getJpaRepository(entity.getClass().getSimpleName().toLowerCase()); if(!jp.existsById(entity.getId())) { return Information.NewFail("没有该数据"); } Object d=jp.findById(entity.getId()).orElse(null); for (Class<?> nt : repositoryService.getRepositoryMap().keySet()) { for (Field ent : nt.getDeclaredFields()) { if(ent.getClass().equals(entity.getClass())) { Object o=null; try { o = nt.newInstance(); ent.set(o, d); } catch (InstantiationException | IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(o); if(getSELECTEntity(o).getData()!=null) { return Information.NewFail("已在其他地方使用了,无法删除"); } } } } try { jp.deleteById(((EntityBasis)entity).getId()); } catch (Exception e) { // TODO: handle exception System.out.println(e.getLocalizedMessage()); } if(jp.existsById(entity.getId())) { System.out.println("删除失败"); return Information.NewFail("删除失败"); } return Information.NewSuccess(response); } // 复制非空属性(忽略关联字段) private void copyNonNullProperties(Object source, Object target) throws IllegalAccessException { Class<?> clazz = source.getClass(); for (Field field : clazz.getDeclaredFields()) { field.setAccessible(true); Object value = field.get(source); // 跳过关联字段和特殊字段 if (value != null && !isEntityBasisField(field) && !isCollectionField(field) && !field.getName().equals("id")) { Field targetField; try { targetField = target.getClass().getDeclaredField(field.getName()); targetField.setAccessible(true); targetField.set(target, value); } catch (NoSuchFieldException e) { // 忽略不存在的字段 } } } } // 检查是否为关联实体字段 private boolean isEntityBasisField(Field field) { return EntityBasis.class.isAssignableFrom(field.getType()); } // 检查是否为集合字段 private boolean isCollectionField(Field field) { return Collection.class.isAssignableFrom(field.getType()) || Map.class.isAssignableFrom(field.getType()); } /** * 根据非空属性值动态查询实体 * @param entity 包含查询条件的实体对象(非空属性作为查询条件) * @return 查询结果信息(成功时包含数据列表) */ public <T>Information getSELECTEntity(T entity) { if (entity == null) { return Information.NewFail("查询参数不能为空"); } Class<T> entityClass = (Class<T>) entity.getClass(); try { // 1. 获取非泛型的Repository JpaRepository repository = repositoryService.getJpaRepository(entityClass); // 2. 构建非泛型的Example查询 ExampleMatcher matcher = ExampleMatcher.matching() .withIgnoreNullValues() .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING); // 这里直接使用原始类型Example Example<T> example = Example.of(entity);//he type Example is not generic; it cannot be parameterized with arguments <T>the method of(T) is undefined for the type Example // 3. 执行查询 List<?> result = repository.findAll(example); return Information.NewSuccess(result); } catch (ClassCastException e) { return Information.NewFail("Repository类型不匹配: " + e.getMessage()); } catch (DataAccessException e) { return Information.NewFail("数据库访问错误: " + e.getMessage()); } catch (Exception e) { return Information.NewFail("系统错误: " + e.getMessage()); } } private List<Map<String, Object>> convertEntityBasis(List<EntityBasis> entities) { return entities.stream().map(entity -> { Map<String, Object> map = new HashMap<>(); Field[] fields = entity.getClass().getDeclaredFields(); try { // 添加实体自身的基本字段 map.put("id", entity.getId()); // 处理所有字段 for (Field field : fields) { field.setAccessible(true); // 允许访问私有字段 Object fieldValue = field.get(entity); if (fieldValue != null) { String fieldName = field.getName(); // 处理集合类型关联 if (isCollection(field)) { if (!((Collection<?>) fieldValue).isEmpty()) { List<Map<String, Object>> collectionItems = ((Collection<?>) fieldValue) .stream() .filter(item -> item instanceof EntityBasis) .map(item -> { Map<String, Object> itemMap = new HashMap<>(); itemMap.put("id", ((EntityBasis) item).getId()); return itemMap; }) .collect(Collectors.toList()); map.put(fieldName, collectionItems); } } // 处理单个实体关联 else if (implementsInterface(field, EntityBasis.class)) { Map<String, Object> associatedMap = new HashMap<>(); associatedMap.put("id", ((EntityBasis) fieldValue).getId()); map.put(fieldName, associatedMap); } // 处理其他基本类型字段 else if (!isSpecialField(fieldName)) { map.put(fieldName, fieldValue); } } } } catch (IllegalAccessException e) { e.printStackTrace(); } return map; }).collect(Collectors.toList()); } // 判断是否为特殊字段(需要排除的字段) private boolean isSpecialField(String fieldName) { return fieldName.equals("handler") || fieldName.equals("hibernateLazyInitializer"); } /** *-判断属性是否为集合类型 * @param field * @return */ boolean isCollection(Field field) { Class<?> type = field.getType(); // 检查是否为Java内置集合类型 if (Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type) || type.isArray()) { return true; } // 检查是否实现集合相关接口(如Iterable) for (Class<?> interfaceType : type.getInterfaces()) { if (Iterable.class.isAssignableFrom(interfaceType)) { return true; } } return false; } /** * -判断属性是否实现特定接口 * @param field * @param targetInterface * @return */ boolean implementsInterface(Field field, Class<?> targetInterface) { Class<?> type = field.getType(); // 检查类本身是否实现接口 if (targetInterface.isAssignableFrom(type)) { return true; } // 检查实现的接口是否继承目标接口 for (Class<?> interfaceType : type.getInterfaces()) { if (targetInterface.isAssignableFrom(interfaceType)) { return true; } } return false; } private Object convertDingdanChanpins(List<Dingdan_chanpin> findAll) { // TODO Auto-generated method stub return null; } private Object convertDingdanChanpinZujians(List<Dingdan_chanpin_zujian> findAll) { // TODO Auto-generated method stub return null; } } package com.kucun.Service; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Service; @Service public class DynamicRepositoryService { private final Map<Class<?>, JpaRepository<?, ?>> repositoryMap = new HashMap<>(); private final Map<String, JpaRepository<?, ?>> repositoryNameMap = new HashMap<>(); public Map<String, JpaRepository<?, ?>> getRepositoryNameMap() { return repositoryNameMap; } public Map<Class<?>, JpaRepository<?, ?>> getRepositoryMap() { return repositoryMap; } public JpaRepository<?,?> getJpaRepository(String e){ // System.out.println("String:"+e+mapToString(repositoryNameMap)); return repositoryNameMap.get(e); } public JpaRepository<?,?> getJpaRepository(Class<?> e){ // System.out.println("Class:"+e+mapToString(repositoryMap)); // System.out.println("Class:"+e); return repositoryMap.get(e); } // 自动注入所有JpaRepository实例 @Autowired public void initRepositories(Map<String, JpaRepository<?, ?>> repositories) { repositories.forEach((name, repo) -> { // 获取代理类实现的接口 Class<?>[] interfaces = repo.getClass().getInterfaces(); for (Class<?> iface : interfaces) { // 扫描接口上的泛型信息 Type[] genericInterfaces = iface.getGenericInterfaces(); for (Type type : genericInterfaces) { if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; // 检查原始类型是否是JpaRepository if (pt.getRawType().equals(JpaRepository.class)) { Type[] args = pt.getActualTypeArguments(); if (args.length >= 2 && args[0] instanceof Class) { Class<?> entityClass = (Class<?>) args[0]; repositoryMap.put(entityClass, repo); String key = entityClass.getSimpleName().toLowerCase(); repositoryNameMap.put(key, repo); // 调试日志 System.out.printf("Mapped %s -> %s [key: %s]%n", entityClass.getName(), repo.getClass().getName(), key); } } } } // 检查接口本身的泛型签名(如果继承的是参数化接口) Type genericSuper = iface.getGenericSuperclass(); if (genericSuper instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) genericSuper; if (pt.getRawType().equals(JpaRepository.class)) { Type[] args = pt.getActualTypeArguments(); if (args.length >= 2 && args[0] instanceof Class) { Class<?> entityClass = (Class<?>) args[0]; repositoryMap.put(entityClass, repo); String key = entityClass.getSimpleName().toLowerCase(); repositoryNameMap.put(key, repo); // 调试日志 System.out.printf("Mapped %s -> %s [key: %s]%n", entityClass.getName(), repo.getClass().getName(), key); } } } } }); } // 通用保存方法 public <T> T saveEntity(T entity) { JpaRepository<T, ?> repo = (JpaRepository<T, ?>) repositoryMap.get(entity.getClass()); if (repo != null) { return repo.save(entity); } throw new IllegalArgumentException("Repository not found for " + entity.getClass()); } public static String mapToString(Map<?, ?> map) { if (map == null || map.isEmpty()) { return ""; } StringBuilder sb = new StringBuilder(); for (Map.Entry<?, ?> entry : map.entrySet()) { sb.append(entry.getKey()).append("=").append(entry.getValue()).append(","); } // 删除最后一个多余的逗号 if (sb.length() > 0) { sb.setLength(sb.length() - 1); } return sb.toString(); } }package com.kucun.Service; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.metamodel.*; import org.springframework.stereotype.Service; import java.io.Serializable; import java.util.*; import java.util.stream.Collectors; @Service public class EntityDependencyService { @PersistenceContext private EntityManager entityManager; private final Map<Class<?>, Set<Attribute<?, ?>>> associationCache = new HashMap<>(); /** * 检查实体是否被其他实体引用 * @param entityClass 实体类 * @param entityId 实体ID * @return 存在引用返回true */ public boolean hasDependencies(Class<?> entityClass, Serializable entityId) { Metamodel metamodel = entityManager.getMetamodel(); Set<EntityType<?>> entities = metamodel.getEntities(); for (EntityType<?> entityType : entities) { // 跳过自身(避免自引用检查) if (entityType.getJavaType().equals(entityClass)) continue; Set<Attribute<?, ?>> associations = getAssociationAttributes(entityType); for (Attribute<?, ?> attr : associations) { if (attr.getJavaType().isAssignableFrom(entityClass)) { if (isReferenced(entityType, attr, entityId)) { return true; } } } } return false; } /** * 获取实体所有关联属性(带缓存) */ private Set<Attribute<?, ?>> getAssociationAttributes(EntityType<?> entityType) { return associationCache.computeIfAbsent(entityType.getJavaType(), k -> entityType.getAttributes().stream() .filter(Attribute::isAssociation) .collect(Collectors.toSet()) ); } /** * 检查特定关联是否引用目标实体 */ private boolean isReferenced(EntityType<?> entityType, Attribute<?, ?> attribute, Serializable targetId) { String jpql = buildReferenceQuery(entityType, attribute); Long count = (Long) entityManager.createQuery(jpql) .setParameter("targetId", targetId) .getSingleResult(); return count > 0; } /** * 构建引用检查查询 */ private String buildReferenceQuery(EntityType<?> entityType, Attribute<?, ?> attribute) { String entityName = entityType.getName(); String attrName = attribute.getName(); if (attribute instanceof PluralAttribute) { return String.format("SELECT COUNT(e) FROM %s e WHERE :targetId MEMBER OF e.%s", entityName, attrName); } else { return String.format("SELECT COUNT(e) FROM %s e WHERE e.%s.id = :targetId", entityName, attrName); } } }完善删除功能尽量简洁

C:\Users\86133\IdeaProjects\tools\src\main\java\com\org\example\tools\controller\AuthController.java:47:80 java: 不兼容的类型: com.org.example.tools.entity.SysUser.UserRole无法转换为java.lang.String // src/main/java/com/org/example/tools/controller/AuthController.java package com.org.example.tools.controller; import com.org.example.tools.dto.request.LoginRequest; import com.org.example.tools.dto.response.ApiResponse; import com.org.example.tools.entity.SysUser; import com.org.example.tools.mapper.SysUserMapper; import com.org.example.tools.security.JwtTokenProvider; import lombok.RequiredArgsConstructor; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; @RestController @RequestMapping("/auth") @RequiredArgsConstructor public class AuthController { private final AuthenticationManager authenticationManager; private final JwtTokenProvider tokenProvider; private final SysUserMapper sysUserMapper; @PostMapping("/login") public ApiResponse<Map<String, Object>> authenticateUser(@RequestBody LoginRequest loginRequest) { // 认证用户 Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken( loginRequest.getUsername(), loginRequest.getPassword() ) ); SecurityContextHolder.getContext().setAuthentication(authentication); // 获取用户信息 SysUser user = sysUserMapper.selectByUsername(loginRequest.getUsername()); // 使用新的 createToken 方法 String jwt = tokenProvider.createToken(user.getUsername(), user.getRole()); // 准备响应数据 Map<String, Object> response = new HashMap<>(); response.put("token", jwt); // 创建安全的用户信息响应 Map<String, Object> userInfo = new HashMap<>(); userInfo.put("id", user.getId()); userInfo.put("username", user.getUsername()); userInfo.put("email", user.getEmail()); userInfo.put("role", user.getRole()); response.put("user", userInfo); return ApiResponse.success(response); } }

package com.kucun.Service; import java.io.Serializable; import java.lang.reflect.*; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import javax.persistence.metamodel.Attribute; import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.Metamodel; import javax.persistence.metamodel.PluralAttribute; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.data.domain.Example; import org.springframework.data.domain.ExampleMatcher; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Service; import com.kucun.data.entity.Bancai; import com.kucun.data.entity.Caizhi; import com.kucun.data.entity.Chanpin; import com.kucun.data.entity.Chanpin_zujian; import com.kucun.data.entity.Dingdan; import com.kucun.data.entity.Dingdan_chanpin; import com.kucun.data.entity.Dingdan_chanpin_zujian; import com.kucun.data.entity.EntityBasis; import com.kucun.data.entity.Information; import com.kucun.data.entity.Kucun; import com.kucun.data.entity.Mupi; import com.kucun.data.entity.User; import com.kucun.data.entity.Zujian; import com.kucun.dataDo.BancaiRepository; import com.kucun.dataDo.CaizhiRepository; import com.kucun.dataDo.ChanpinRepository; import com.kucun.dataDo.ChanpinZujianRepository; import com.kucun.dataDo.DingdanChanpinRepository; import com.kucun.dataDo.DingdanChanpinZujianRepository; import com.kucun.dataDo.DingdanRepository; import com.kucun.dataDo.KucunRepository; import com.kucun.dataDo.MupiRepository; import com.kucun.dataDo.UserRepository; import com.kucun.dataDo.ZujianRepository; @Service public class AppService { // 注入所有需要的Repository @Autowired private CaizhiRepository caizhiRepository; @Autowired private BancaiRepository bancaiRepository; @Autowired private ChanpinRepository chanpinRepository; @Autowired private DingdanRepository dingdanRepository; @Autowired private MupiRepository mupiRepository; @Autowired private ZujianRepository zujianRepository; @Autowired private KucunRepository kucunRepository; @Autowired private UserRepository userRepository; @Autowired private ChanpinZujianRepository chanpinZujianRepository; @Autowired private DingdanChanpinZujianRepository dingdanChanpinZujianRepository; @Autowired private DingdanChanpinRepository dingdanChanpinRepository; @Autowired private DynamicRepositoryService repositoryService; // private Map<String, JpaRepository<?, ?>> shiti; // // // @Override // public void setApplicationContext(ApplicationContext context) { // this.shiti = getJpaRepositories(context); // } // // public Map<String, JpaRepository<?, ?>> getJpaRepositories(ApplicationContext context) { // return context.getBeansWithAnnotation(Repository.class) // .entrySet() // .stream() // .filter(entry -> entry.getValue() instanceof JpaRepository) // .collect(Collectors.toMap( // entry -> { // JpaRepository<?, ?> repo = (JpaRepository<?, ?>) entry.getValue(); // return getEntityClass(repo).getName(); // }, // entry -> (JpaRepository<?, ?>) entry.getValue() // )); // } // // public static Class<?> getEntityClass(JpaRepository<?, ?> repo) { // try { // // 处理Spring代理类 // Object target = repo; // while (target instanceof Advised) { // target = ((Advised) target).getTargetSource().getTarget(); // } // // // 通过Spring的ResolvableType解析泛型 // ResolvableType resolvableType = ResolvableType.forClass( // target.getClass()).as(JpaRepository.class); // // if (resolvableType.getGenerics().length > 0) { // Class<?> entityClass = resolvableType.getGeneric(0).resolve(); // if (entityClass != null) { // return entityClass; // } // } // // throw new IllegalStateException("无法解析实体类型"); // } catch (Exception e) { // throw new RuntimeException("获取实体类失败: " + e.getMessage(), e); // } // } // // public Information getAllDataWithChildIdse() { // Map<String, Object> response = new HashMap<>(); // // response.put("caizhis", (caizhiRepository.findAll())); // response.put("bancais", (bancaiRepository.findAll())); // response.put("chanpins", (chanpinRepository.findAll())); // response.put("dingdans", (dingdanRepository.findAll())); // response.put("mupis", (mupiRepository.findAll())); // response.put("zujians", (zujianRepository.findAll())); // response.put("kucuns", (kucunRepository.findAll())); // response.put("users", (userRepository.findAll())); // response.put("chanpin_zujians", (chanpinZujianRepository.findAll())); // response.put("chanpin_zujians", (dingdanChanpinZujianRepository.findAll())); // response.put("chanpin_zujians", (dingdanChanpinRepository.findAll())); // // return Information.NewSuccess(response); // } public Information getAllDataWithChildIdse() { Map<String, Object> response = new HashMap<>(); for (String key : repositoryService.getRepositoryNameMap().keySet()) { response.put(key+"s", (repositoryService.getJpaRepository(key).findAll())); } return Information.NewSuccess(response); } public Information getAllDataWithChildIdse(String e) { JpaRepository<?, ?> jp = repositoryService.getJpaRepository(e); System.out.println(jp); return Information.NewSuccess(jp.findAll()); } public Information getAddEntity(Object e) { Class<?> entityClass = e.getClass(); try { // 处理关联字段 handleAssociations(e); @SuppressWarnings("unchecked") JpaRepository<Object, Serializable> jp = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entityClass); Object savedEntity = jp.save(e); if(savedEntity!=null) { if(savedEntity instanceof Bancai) { initializeKucunForBancai((Bancai)savedEntity); } } return Information.NewSuccess(savedEntity); } catch (Exception ex) { return Information.Newfail(500, "创建失败: " + ex.getMessage(), null); } } // 单独封装库存初始化方法 private void initializeKucunForBancai(Bancai bancai) throws Exception { Kucun kucun = new Kucun(null, bancai, 0); // 初始库存为0 try { bancai.setKucun(kucunRepository.save(kucun)); } catch (Exception e) { // TODO: handle exception throw new Exception("initializeKucunForBancai"+e); } } // 处理关联对象(转换为托管实体) private void handleAssociations(Object entity) throws Exception { Class<?> clazz = entity.getClass(); for (Field field : clazz.getDeclaredFields()) { field.setAccessible(true); Object value = field.get(entity); if (value == null) continue; // 处理单个关联实体 if (isEntityBasisField(field)) { EntityBasis associatedEntity = (EntityBasis) value; JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(associatedEntity.getClass()); // 获取托管状态的关联实体 Object managedEntity = repo.findById(associatedEntity.getId()) .orElseThrow(() -> new RuntimeException("关联实体不存在")); field.set(entity, managedEntity); } // 处理集合关联 else if (isCollectionField(field)) { Collection<?> collection = (Collection<?>) value; List<Object> managedEntities = new ArrayList<>(); for (Object item : collection) { if (item instanceof EntityBasis) { EntityBasis eb = (EntityBasis) item; JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(eb.getClass()); Object managedEntity = repo.findById(eb.getId()) .orElseThrow(() -> new RuntimeException("关联实体不存在")); managedEntities.add(managedEntity); } } // 更新集合为托管实体 if (!managedEntities.isEmpty()) { field.set(entity, managedEntities); } } } } /** * 更新 * @param e 实体待id * @return */ /** * 更新实体 * @param e 包含ID的实体 * @return 操作结果 */ public Information getupdateEntity(Object e) { if(e == null) { return Information.Newfail(403, "参数为空", null); } Class<?> entityClass = e.getClass(); try { Field idField = entityClass.getDeclaredField("id"); idField.setAccessible(true); Object idValue = idField.get(e); // 修正:应检查id是否为空,而不是不为空 if(idValue == null) { return Information.Newfail(403, "Id为空", null); } // 获取Repository @SuppressWarnings("unchecked") JpaRepository<Object, Serializable> jp = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entityClass); // 从数据库加载现有实体(托管状态) Object existingEntity = jp.findById((Serializable) idValue) .orElseThrow(() -> new RuntimeException("实体不存在")); // 复制属性(排除关联字段) copyNonNullProperties(e, existingEntity); // 保存托管状态的实体 Object updatedEntity = jp.save(existingEntity); return Information.NewSuccess(updatedEntity); } catch (Exception ex) { return Information.Newfail(500, "更新失败: " + ex.getMessage(), null); } } /** * 删除 * @param entity * @return */ public Information getdeleteEntity(EntityBasis entity) { Map<String, Object> response = new HashMap<>(); JpaRepository<Object, Integer> jp= (JpaRepository<Object, Integer>) repositoryService.getJpaRepository(entity.getClass().getSimpleName().toLowerCase()); if(!jp.existsById(entity.getId())) { return Information.NewFail("没有该数据"); } Object d=jp.findById(entity.getId()).orElse(null); for (Class<?> nt : repositoryService.getRepositoryMap().keySet()) { for (Field ent : nt.getDeclaredFields()) { if(ent.getClass().equals(entity.getClass())) { Object o=null; try { o = nt.newInstance(); ent.set(o, d); } catch (InstantiationException | IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(o); if(getSELECTEntity(o).getData()!=null) { return Information.NewFail("已在其他地方使用了,无法删除"); } } } } try { jp.deleteById(((EntityBasis)entity).getId()); } catch (Exception e) { // TODO: handle exception System.out.println(e.getLocalizedMessage()); } if(jp.existsById(entity.getId())) { System.out.println("删除失败"); return Information.NewFail("删除失败"); } return Information.NewSuccess(response); } // 复制非空属性(忽略关联字段) private void copyNonNullProperties(Object source, Object target) throws IllegalAccessException { Class<?> clazz = source.getClass(); for (Field field : clazz.getDeclaredFields()) { field.setAccessible(true); Object value = field.get(source); // 跳过关联字段和特殊字段 if (value != null && !isEntityBasisField(field) && !isCollectionField(field) && !field.getName().equals("id")) { Field targetField; try { targetField = target.getClass().getDeclaredField(field.getName()); targetField.setAccessible(true); targetField.set(target, value); } catch (NoSuchFieldException e) { // 忽略不存在的字段 } } } } // 检查是否为关联实体字段 private boolean isEntityBasisField(Field field) { return EntityBasis.class.isAssignableFrom(field.getType()); } // 检查是否为集合字段 private boolean isCollectionField(Field field) { return Collection.class.isAssignableFrom(field.getType()) || Map.class.isAssignableFrom(field.getType()); } /** * 根据非空属性值动态查询实体 * @param entity 包含查询条件的实体对象(非空属性作为查询条件) * @return 查询结果信息(成功时包含数据列表) */ public <T>Information getSELECTEntity(T entity) { if (entity == null) { return Information.NewFail("查询参数不能为空"); } Class<T> entityClass = (Class<T>) entity.getClass(); try { // 1. 获取非泛型的Repository JpaRepository repository = repositoryService.getJpaRepository(entityClass); // 2. 构建非泛型的Example查询 ExampleMatcher matcher = ExampleMatcher.matching() .withIgnoreNullValues() .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING); // 这里直接使用原始类型Example Example<T> example = Example.of(entity);//he type Example is not generic; it cannot be parameterized with arguments <T>the method of(T) is undefined for the type Example // 3. 执行查询 List<?> result = repository.findAll(example); return Information.NewSuccess(result); } catch (ClassCastException e) { return Information.NewFail("Repository类型不匹配: " + e.getMessage()); } catch (DataAccessException e) { return Information.NewFail("数据库访问错误: " + e.getMessage()); } catch (Exception e) { return Information.NewFail("系统错误: " + e.getMessage()); } } private List<Map<String, Object>> convertEntityBasis(List<EntityBasis> entities) { return entities.stream().map(entity -> { Map<String, Object> map = new HashMap<>(); Field[] fields = entity.getClass().getDeclaredFields(); try { // 添加实体自身的基本字段 map.put("id", entity.getId()); // 处理所有字段 for (Field field : fields) { field.setAccessible(true); // 允许访问私有字段 Object fieldValue = field.get(entity); if (fieldValue != null) { String fieldName = field.getName(); // 处理集合类型关联 if (isCollection(field)) { if (!((Collection<?>) fieldValue).isEmpty()) { List<Map<String, Object>> collectionItems = ((Collection<?>) fieldValue) .stream() .filter(item -> item instanceof EntityBasis) .map(item -> { Map<String, Object> itemMap = new HashMap<>(); itemMap.put("id", ((EntityBasis) item).getId()); return itemMap; }) .collect(Collectors.toList()); map.put(fieldName, collectionItems); } } // 处理单个实体关联 else if (implementsInterface(field, EntityBasis.class)) { Map<String, Object> associatedMap = new HashMap<>(); associatedMap.put("id", ((EntityBasis) fieldValue).getId()); map.put(fieldName, associatedMap); } // 处理其他基本类型字段 else if (!isSpecialField(fieldName)) { map.put(fieldName, fieldValue); } } } } catch (IllegalAccessException e) { e.printStackTrace(); } return map; }).collect(Collectors.toList()); } // 判断是否为特殊字段(需要排除的字段) private boolean isSpecialField(String fieldName) { return fieldName.equals("handler") || fieldName.equals("hibernateLazyInitializer"); } /** *-判断属性是否为集合类型 * @param field * @return */ boolean isCollection(Field field) { Class<?> type = field.getType(); // 检查是否为Java内置集合类型 if (Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type) || type.isArray()) { return true; } // 检查是否实现集合相关接口(如Iterable) for (Class<?> interfaceType : type.getInterfaces()) { if (Iterable.class.isAssignableFrom(interfaceType)) { return true; } } return false; } /** * -判断属性是否实现特定接口 * @param field * @param targetInterface * @return */ boolean implementsInterface(Field field, Class<?> targetInterface) { Class<?> type = field.getType(); // 检查类本身是否实现接口 if (targetInterface.isAssignableFrom(type)) { return true; } // 检查实现的接口是否继承目标接口 for (Class<?> interfaceType : type.getInterfaces()) { if (targetInterface.isAssignableFrom(interfaceType)) { return true; } } return false; } private Object convertDingdanChanpins(List<Dingdan_chanpin> findAll) { // TODO Auto-generated method stub return null; } private Object convertDingdanChanpinZujians(List<Dingdan_chanpin_zujian> findAll) { // TODO Auto-generated method stub return null; } } 删除功能完善

package com.kucun.Service; import java.io.Serializable; import java.lang.reflect.Field; import java.util.*; import javax.persistence.EntityNotFoundException; import javax.transaction.Transactional; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Example; import org.springframework.data.domain.ExampleMatcher; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Service; import com.kucun.data.entity.*; import com.kucun.dataDo.*; /** * * * */ @Service public class AppService { // 自动注入所有依赖 @Autowired private KucunRepository kucunRepository; @Autowired private DynamicRepositoryService repositoryService; @Autowired private EntityDependencyService dependencyService; /** * 获取所有实体类型的数据 * @return 包含所有实体数据的Map * * */ public Information getAllData() { Map<String, Object> response = new HashMap<>(); repositoryService.getRepositoryNameMap().forEach((key, repo) -> response.put(key + "s", repo.findAll()) ); return Information.NewSuccess(response); } /** * 获取自指定时间以来的所有更新 * @param since 时间戳 * @return 按实体类型分组的更新数据 */ public Information getUpdatesSince(Date since) { Map<String, List<?>> updates = new HashMap<>(); Map<String, CustomRepository<?, ?>> repoMap = repositoryService.getRepositoryNameMap(); repoMap.forEach((entityName, repo) -> { // 使用反射查询大于指定时间的记录 List<?> results = repositoryService.findUpdatedSince(entityName, since); if (!results.isEmpty()) { updates.put(entityName+'s', results); } }); return Information.NewSuccess(updates); } /** * 获取指定实体类型的所有数据 * @param entityName 实体名称 * @return 实体数据列表 * * */ public Information getEntityData(String entityName) { JpaRepository<?, ?> repo = repositoryService.getJpaRepository(entityName); return Information.NewSuccess(repo.findAll()); } /** * 添加新实体 * @param entity 要添加的实体对象 * @return 添加结果 * * */ public Information addEntity(@Valid Object entity) { try { // 处理关联字段 handleAssociations(entity); // 获取对应的Repository并保存 JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entity.getClass()); //System.out.println(Information.NewSuccess(entity).DataJson()); if(entity instanceof User) { if(((User) entity).getPass()!=null) { String psass=((User) entity).getPass(); ((User) entity).setPass(PasswordService.hashPassword(psass)); } } Object savedEntity = repo.save(entity); // 如果是板材,初始化库存 if (savedEntity instanceof Bancai) { initializeKucunForBancai((Bancai) savedEntity); } return Information.NewSuccess(savedEntity); } catch (Exception ex) { return Information.Newfail(500, "创建失败: " + ex.getMessage(), null); } } /** * 更新实体 * @param entity 包含ID的实体对象 * @return 更新结果 * * */ public Information updateEntity(Object entity) { if (entity == null) { return Information.Newfail(403, "参数为空", null); } // 获取ID字段 Field idField=null; try { idField = getIdField(entity); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { idField.setAccessible(true); Object idValue = idField.get(entity); if (idValue == null) { return Information.Newfail(403, "ID为空", null); } // 获取Repository和现有实体 JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entity.getClass()); Object existingEntity = repo.findById((Serializable) idValue) .orElseThrow(() -> new RuntimeException("实体不存在")); if(entity instanceof User) { if(((User) entity).getPass()!=null) { String psass=((User) entity).getPass(); ((User) entity).setPass(PasswordService.hashPassword(psass)); } } // 复制非空属性并保存 copyNonNullProperties(entity, existingEntity); return Information.NewSuccess(repo.save(existingEntity)); } catch (Exception ex) { ex.fillInStackTrace(); return Information.Newfail(500, "更新失败: " + ex.getMessage(), null); } } /** * 删除实体 * @param entity 要删除的实体 * @return 删除结果 */ public Information deleteEntity(EntityBasis entity) { if (entity == null) { return Information.NewFail("删除对象不能为空"); } try { String entityName = entity.getClass().getSimpleName().toLowerCase(); JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entityName); // 先加载完整实体(关键步骤) Object managedEntity = repo.findById(entity.getId()) .orElseThrow(() -> new EntityNotFoundException("实体不存在")); if(entity instanceof Bancai) { Kucun k=kucunRepository.findByBancai((Bancai)entity); if(k!=null&&k.getShuliang()>0) { return Information.NewFail("库存不为零,无法删除"); } if(k!=null) { Field deletedField = k.getClass().getDeclaredField("deleted"); deletedField.setAccessible(true); deletedField.set(k, true); Field deletedAtField = k.getClass().getDeclaredField("deletedAt"); deletedAtField.setAccessible(true); deletedAtField.set(k, new Date()); kucunRepository.save(k); } } // 检查依赖关系 if (dependencyService.hasDependencies(entity.getClass(), entity.getId())) { return Information.NewFail("该记录已被引用,无法删除"); } // 使用实体对象删除(触发级联操作) Field deletedField = managedEntity.getClass().getDeclaredField("deleted"); deletedField.setAccessible(true); deletedField.set(managedEntity, true); Field deletedAtField = managedEntity.getClass().getDeclaredField("deletedAt"); deletedAtField.setAccessible(true); deletedAtField.set(managedEntity, new Date()); repo.save(managedEntity); return Information.NewSuccess("删除成功"); } catch (Exception e) { return Information.NewFail("删除错误: " + e.getMessage()); } }/** * 动态查询实体 * @param entity 包含查询条件的实体对象 * @return 查询结果 */ public <T extends EntityBasis> Information queryEntity(T entity) { if (entity == null) { return Information.NewFail("查询参数不能为空"); } try { JpaRepository<T, ?> repo = (JpaRepository<T, ?>) repositoryService.getJpaRepository(entity.getClass()); // 创建基础查询条件 ExampleMatcher matcher = ExampleMatcher.matching() .withIgnoreNullValues() .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING); if(entity.getDeleted()==null) { // 添加软删除过滤条件 if (entity instanceof EntityBasis) { // 动态设置deleted=false条件 Field deletedField = EntityBasis.class.getDeclaredField("deleted"); deletedField.setAccessible(true); deletedField.set(entity, false); } } Example<T> example = Example.of(entity, matcher); return Information.NewSuccess(repo.findAll(example)); } catch (Exception e) { return Information.NewFail("查询失败: " + e.getMessage()); } } // ====================== 私有辅助方法 ====================== /** * 为板材初始化库存 * @param bancai 板材对象 */ private void initializeKucunForBancai(Bancai bancai) throws Exception { Kucun kucun = new Kucun(null, bancai, 0); bancai.setKucun(kucunRepository.save(kucun)); } /** * 处理实体关联关系 * @param entity 要处理的实体 */ private void handleAssociations(Object entity) throws Exception { for (Field field : entity.getClass().getDeclaredFields()) { field.setAccessible(true); Object value = field.get(entity); if (value == null) continue; // 处理 JPA 实体关联 if (value instanceof EntityBasis) { EntityBasis associated = (EntityBasis) value; JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(associated.getClass().getSimpleName().toLowerCase()); // 只处理已存在实体(不创建新关联) if (associated.getId() != null) { Object managedEntity = repo.findById(associated.getId()) .orElseThrow(() -> new Exception("关联实体不存在")); field.set(entity, managedEntity); } } // 处理集合关联 else if (value instanceof Collection) { List<Object> managedEntities = new ArrayList<>(); for (Object item : (Collection<?>) value) { if (item instanceof EntityBasis) { EntityBasis eb = (EntityBasis) item; JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(eb.getClass().getSimpleName().toLowerCase()); if (eb.getId() != null) { managedEntities.add(repo.findById(eb.getId()) .orElseThrow(() -> new Exception("关联实体不存在"))); } } } if (!managedEntities.isEmpty()) { field.set(entity, managedEntities); } } } } /** * 处理实体关联关系 * @param entity 要处理的实体 */ private void handleAssociationss(Object entity) throws Exception { for (Field field : entity.getClass().getDeclaredFields()) { field.setAccessible(true); Object value = field.get(entity); if(value instanceof EntityBasis) { } } } /** * 复制非空属性 * @param source 源对象 * @param target 目标对象 */ private void copyNonNullProperties(Object source, Object target) throws IllegalAccessException { for (Field field : source.getClass().getDeclaredFields()) { field.setAccessible(true); Object value = field.get(source); // 跳过关联字段和ID字段 if (value != null && !(value instanceof EntityBasis) && !(value instanceof Collection) && !field.getName().equals("id")) { try { Field targetField = target.getClass().getDeclaredField(field.getName()); targetField.setAccessible(true); targetField.set(target, value); } catch (NoSuchFieldException ignored) {} } } } /* * 获取实体类的id字段(支持父类查找) * @param entity 实体对象 * @return Field对象或null */ public static Field getIdField(Object entity) { if (entity == null) { return null; } Class<?> clazz = entity.getClass(); // 递归查找类及其父类的id字段 while (clazz != null && clazz != Object.class) { try { Field idField = clazz.getDeclaredField("id"); idField.setAccessible(true); return idField; } catch (NoSuchFieldException e) { // 继续向上查找父类 clazz = clazz.getSuperclass(); } catch (SecurityException e) { e.printStackTrace(); return null; } } return null; } // ====================== 专用方法处理 Dingdan_bancai ====================== @Transactional public Information handleDingdanBancaiOperation( Dingdan_bancai entity, String operation ) { try { // 获取对应的Repository JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository("dingdan_bancai"); switch (operation) { case "add": Dingdan_bancai savedEntity = (Dingdan_bancai) repo.save(entity); updateKucunAndCreateJinhuo(savedEntity, savedEntity.getShuliang()); return Information.NewSuccess(savedEntity); case "update": // 先获取现有实体以计算差异 Dingdan_bancai existing = (Dingdan_bancai) repo.findById(entity.getId()) .orElseThrow(() -> new EntityNotFoundException("实体不存在")); int quantityDifference = entity.getShuliang() - existing.getShuliang(); Dingdan_bancai updatedEntity = (Dingdan_bancai) repo.save(entity); if (quantityDifference != 0) { updateKucunAndCreateJinhuo(updatedEntity, quantityDifference); } return Information.NewSuccess(updatedEntity); default: return Information.NewFail("不支持的操作类型: " + operation); } } catch (Exception ex) { return Information.NewFail(operation + "操作失败: " + ex.getMessage()); } } // 更新库存并创建进货记录 private void updateKucunAndCreateJinhuo(Dingdan_bancai db, int quantityChange) { // 1. 更新库存 Bancai bancai = db.getBancai(); Kucun kucun = kucunRepository.findByBancai(bancai); if (kucun == null) { kucun = new Kucun(null, bancai, 0); } kucun.setShuliang(kucun.getShuliang() + quantityChange); kucunRepository.save(kucun); // 2. 创建进货记录 Jinhuo jinhuo = new Jinhuo(); jinhuo.setDingdan_bancai(db); jinhuo.setShuliang(quantityChange); jinhuo.setDate(new Date()); // 使用临时字段设置用户 if (db.getCurrentUserId() != null) { User user = new User(); user.setId(db.getCurrentUserId()); jinhuo.setUser(user); } ((JinhuoRepository)repositoryService.getJpaRepository(jinhuo.getClass())).save( jinhuo); } // ... existing code ... /** * 保存所有实体类型的数据 * @param allData 包含所有实体数据的Map,key为实体类型名+"s",value为实体列表 * @return 保存结果 */ @Transactional public Information saveAllData(Map<String, List<?>> allData) { try { Map<String, Object> response = new HashMap<>(); Map<String, CustomRepository<?, ?>> repoMap = repositoryService.getRepositoryNameMap(); allData.forEach((key, entities) -> { // 去掉末尾的's'以获取实体类型名 String entityName = key.substring(0, key.length() - 1); CustomRepository<?, ?> repo = repoMap.get(entityName); if (repo != null && entities != null && !entities.isEmpty()) { try { // 保存实体列表 List<?> savedEntities = repo.saveAll(entities); response.put(key, savedEntities); } catch (Exception e) { response.put(key + "_error", "保存失败: " + e.getMessage()); } } }); return Information.NewSuccess(response); } catch (Exception ex) { return Information.Newfail(500, "保存全部数据失败: " + ex.getMessage(), null); } } // ... existing code ... } // 添加保存全部数据的API端点 @PostMapping("/save-all") public Information saveAllData(@RequestBody Map<String, List<?>> allData) { try { return appService.saveAllData(allData); } catch (Exception e) { return Information.NewFail("保存全部数据失败: " + e.getMessage()); } }-------------package com.kucun.dataDo; import java.util.Date; import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.NoRepositoryBean; import org.springframework.data.repository.query.Param; import com.kucun.data.entity.Bancai; import com.kucun.data.entity.Dingdan_bancai; //修改后 @NoRepositoryBean public interface CustomRepository<T, ID> extends JpaRepository<T, ID>{ // 符合命名规范 // 查询指定时间后的更新记录 List<T> findByLastUpdatedAfter(Date date); // 查询指定时间后的删除记录 List<T> findByDeletedAtAfter(Date date); // 查询指定时间后的所有变更(更新+删除) @Query("SELECT e FROM #{#entityName} e WHERE " + "e.lastUpdated > :since OR " + "(e.deleted = true AND e.deletedAt > :since)") List<T> findChangesSince(@Param("since") Date since); } package com.kucun.Service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.core.ResolvableType; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Service; import com.kucun.dataDo.CustomRepository; import javax.annotation.PostConstruct; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @Service public class DynamicRepositoryService { @Autowired private ApplicationContext applicationContext; // 修改为存储 CustomRepository 类型 private final Map<String, CustomRepository<?, ?>> repositoryMap = new HashMap<>(); private final Map<Class<?>, CustomRepository<?, ?>> classRepositoryMap = new HashMap<>(); private final Map<String, Class<?>> stringClassMap = new HashMap<>(); @PostConstruct public void init() { // 关键修改:获取 CustomRepository 类型而非 JpaRepository Map<String, CustomRepository> repositories = applicationContext.getBeansOfType(CustomRepository.class); repositories.forEach((beanName, repo) -> { Class<?> entityClass = resolveEntityClass(repo); if (entityClass != null) { String simpleName = entityClass.getSimpleName().toLowerCase(); repositoryMap.put(simpleName, repo); classRepositoryMap.put(entityClass, repo); stringClassMap.put(simpleName, entityClass); } }); } // 解析实体类的方法(保持不变) private Class<?> resolveEntityClass(CustomRepository<?, ?> repository) { ResolvableType repoType = ResolvableType.forClass(repository.getClass()); ResolvableType customRepoType = repoType.as(CustomRepository.class); ResolvableType entityType = customRepoType.getGeneric(0); return entityType.resolve(); } // 修改返回类型为 CustomRepository public CustomRepository<?, ?> getJpaRepository(String entityName) { CustomRepository<?, ?> repo = repositoryMap.get(entityName.toLowerCase()); if (repo == null) { throw new IllegalArgumentException("未找到实体 " + entityName + " 对应的Repository"); } return repo; } // 修改返回类型为 CustomRepository public CustomRepository<?, ?> getJpaRepository(Class<?> entityClass) { CustomRepository<?, ?> repo = classRepositoryMap.get(entityClass); if (repo == null) { throw new IllegalArgumentException("未找到实体类 " + entityClass.getName() + " 对应的Repository"); } return repo; } public Map<String, CustomRepository<?, ?>> getRepositoryNameMap() { return repositoryMap; } // 使用 CustomRepository 直接调用自定义方法 public List<?> findUpdatedSince(String entityName, Date since) { try { CustomRepository<?, ?> repo = repositoryMap.get(entityName.toLowerCase()); return repo.findByLastUpdatedAfter(since); } catch (Exception e) { return Collections.emptyList(); } } // Getter 方法保持兼容性 public Map<String, Class<?>> getStringClassMap() { return stringClassMap; } public Map<Class<?>, CustomRepository<?, ?>> getClassRepositoryMap() { return classRepositoryMap; } } The method saveAll(Iterable) in the type JpaRepository<capture#59-of ?,capture#60-of ?> is not applicable for the arguments (List<capture#61-of ?>)Java(67108979) List org.springframework.data.jpa.repository.JpaRepository.saveAll(Iterable entities) Saves all given entities. Specified by: saveAll(...) in CrudRepository Type Parameters: Parameters: entities must not be null nor must it contain null. Returns: the saved entities; will never be null. The returned Iterable will have the same size as the Iterable passed as an argument.

package org.example; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.reflect.TypeToken; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.io.BufferedReader; import java.io.IOException; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.*; import java.util.concurrent.*; import java.util.stream.Collectors; /** * 飞书公司圈帖子数据抓取并同步至多维表格 */ @RestController @RequestMapping("/feishu/events") public class MomentsBitableIntegration { private static final Logger logger = LoggerFactory.getLogger(MomentsBitableIntegration.class); private static final String APP_ID = "cli_a77e623b63fbd00d"; private static final String APP_SECRET = "p1y9z84vBOxSClmqn4y0CcVJPrdKeF3Y"; private static final String ENCRYPT_KEY = "eGXBxvckaDb7NdN8gC4ZW4YQishxILFi"; // 飞书事件加密密钥 private static final String TENANT_ACCESS_TOKEN_URL = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"; private static final String BITABLE_APP_TOKEN = "NQyxb7bxma1BNDszeFqcHLrbnje"; private static final String BITABLE_TABLE_ID = "tblycyMgokQQDoAd"; private static final String MOMENTS_POST_API = "https://open.feishu.cn/open-apis/moments/v1/posts/"; private static final String USER_INFO_API = "https://open.feishu.cn/open-apis/contact/v3/users/"; // 日期时间格式化器,用于解析多种格式的日期 private static final DateTimeFormatter[] DATE_TIME_FORMATTERS = { DateTimeFormatter.ISO_OFFSET_DATE_TIME, DateTimeFormatter.ISO_LOCAL_DATE_TIME, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") }; private final OkHttpClient httpClient = new OkHttpClient(); private final Gson gson = new Gson(); private final JsonParser jsonParser = new JsonParser(); private String tenantAccessToken; private long lastTokenRefreshTime; // 记录上次令牌刷新时间 private ScheduledExecutorService scheduler; private Map<String, PostData> postDataMap = new ConcurrentHashMap<>(); private final Map<String, String> userCache = new ConcurrentHashMap<>(); // 用户信息缓存 private final EventReceiver eventReceiver; // 帖子数据结构 static class PostData { String postId; String author; // 作者姓名 String authorId; // 作者ID(open_id等) List<String> mentionedUsers = new ArrayList<>(); int likeCount; int dislikeCount; double popularityScore; String content; long publishTimeUnix = 0; // 存储毫秒级Unix时间戳 public PostData(String postId) { this.postId = postId; } } public MomentsBitableIntegration() { this.eventReceiver = new EventReceiver(this); init(); scheduleWeeklyReport(); } // 初始化飞书认证 public void init() { try { refreshAccessToken(); scheduler = Executors.newScheduledThreadPool(2); // 添加定时刷新token任务(每90分钟刷新一次) scheduler.scheduleAtFixedRate(() -> { try { refreshAccessToken(); } catch (Exception e) { logger.error("刷新访问令牌失败", e); } }, 0, 90, TimeUnit.MINUTES); logger.info("飞书集成服务初始化完成"); } catch (Exception e) { logger.error("初始化失败", e); System.exit(1); } } // 刷新访问令牌 private void refreshAccessToken() throws IOException { MediaType JSON = MediaType.get("application/json; charset=utf-8"); String json = "{\"app_id\":\"" + APP_ID + "\",\"app_secret\":\"" + APP_SECRET + "\"}"; okhttp3.RequestBody body = okhttp3.RequestBody.create(json, JSON); Request request = new Request.Builder() .url(TENANT_ACCESS_TOKEN_URL) .post(body) .build(); try (Response response = httpClient.newCall(request).execute()) { if (!response.isSuccessful()) { logger.error("刷新令牌请求失败: HTTP {}", response.code()); throw new IOException("刷新令牌失败: HTTP " + response.code()); } String responseData = response.body().string(); Type type = new TypeToken<Map<String, Object>>(){}.getType(); Map<String, Object> result = gson.fromJson(responseData, type); if (result.containsKey("tenant_access_token")) { tenantAccessToken = (String) result.get("tenant_access_token"); lastTokenRefreshTime = System.currentTimeMillis(); logger.info("访问令牌刷新成功"); } else { logger.error("获取访问令牌失败: {}", responseData); throw new IOException("获取访问令牌失败: " + result.get("msg")); } } } // 检查令牌是否有效 private boolean isTokenValid() { // 令牌有效期为2小时,提前10分钟刷新 return System.currentTimeMillis() - lastTokenRefreshTime < 110 * 60 * 1000; } // 处理飞书事件推送 @PostMapping("/callback") public Map<String, Object> handleFeishuEvent(HttpServletRequest request) { String eventJson = null; try { // 读取请求体 StringBuilder requestBody = new StringBuilder(); try (BufferedReader reader = request.getReader()) { String line; while ((line = reader.readLine()) != null) { requestBody.append(line); } } eventJson = requestBody.toString(); logger.info("收到飞书事件: {}", eventJson); // 用于传递给EventReceiver的事件数据 String eventJsonForReceiver = null; Map<String, Object> eventData; // 判断是否为加密数据 if (eventJson.contains("\"encrypt\"")) { Map<String, Object> encryptedMap = gson.fromJson( eventJson, new TypeToken<Map<String, Object>>() {}.getType() ); String encryptedData = (String) encryptedMap.get("encrypt"); if (encryptedData == null || encryptedData.isEmpty()) { logger.warn("加密数据为空: {}", eventJson); return createErrorResponse(400, "Missing encrypt data"); } // 解密获取原始事件数据 String decryptedJson = FeishuEncryptUtils.decrypt(ENCRYPT_KEY, encryptedData); logger.info("解密后事件数据: {}", decryptedJson); eventJsonForReceiver = decryptedJson; eventData = gson.fromJson(decryptedJson, new TypeToken<Map<String, Object>>() {}.getType()); } else { eventJsonForReceiver = eventJson; eventData = gson.fromJson(eventJson, new TypeToken<Map<String, Object>>() {}.getType()); } if (eventData == null) { logger.warn("事件数据为空: {}", eventJson); return createErrorResponse(400, "Invalid event data"); } // 1. 优先处理URL验证事件 if (isUrlVerificationEvent(eventData)) { return handleUrlVerification(eventData); } // 2. 获取header Map<String, Object> header = getEventHeader(eventData); if (header == null) { logger.warn("事件header为空: {}", eventJson); return createErrorResponse(400, "Missing event header"); } // 3. 获取事件类型 String eventType = (String) header.get("event_type"); if (eventType == null) { logger.warn("事件类型为空: {}", eventJson); return createErrorResponse(400, "Missing event_type in event data"); } // 4. 验证签名 if (!verifySignature(request, eventJson)) { logger.warn("事件签名验证失败"); return createErrorResponse(401, "Unauthorized"); } // 传递事件数据 eventReceiver.handleEvent(eventJsonForReceiver); return createSuccessResponse(); } catch (Exception e) { logger.error("处理飞书事件失败: {}", eventJson, e); return createErrorResponse(500, "Internal Server Error"); } } // ===== 辅助方法 ===== private boolean isUrlVerificationEvent(Map<String, Object> eventData) { return "url_verification".equals(eventData.get("type")); } private Map<String, Object> getEventHeader(Map<String, Object> eventData) { Object headerObj = eventData.get("header"); if (headerObj instanceof Map) { @SuppressWarnings("unchecked") Map<String, Object> header = (Map<String, Object>) headerObj; return header; } return null; } private Map<String, Object> handleUrlVerification(Map<String, Object> eventData) { String challenge = (String) eventData.get("challenge"); if (challenge == null) { logger.warn("URL验证请求缺少challenge参数"); return createErrorResponse(400, "Missing challenge parameter"); } logger.info("完成URL验证,challenge: {}", challenge); return Collections.singletonMap("challenge", challenge); } // 验证事件签名 private boolean verifySignature(HttpServletRequest request, String eventJson) { if (ENCRYPT_KEY == null || ENCRYPT_KEY.isEmpty()) { return true; } String timestamp = request.getHeader("X-Lark-Request-Timestamp"); String nonce = request.getHeader("X-Lark-Request-Nonce"); String signature = request.getHeader("X-Lark-Signature"); if (timestamp == null || nonce == null || signature == null) { logger.warn("缺少签名参数:timestamp={}, nonce={}, signature={}", timestamp, nonce, signature); return false; } String signStr = timestamp + nonce + ENCRYPT_KEY + eventJson; try { MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] hashBytes = md.digest(signStr.getBytes(StandardCharsets.UTF_8)); String calculatedSignature = bytesToHex(hashBytes); return calculatedSignature.equals(signature); } catch (NoSuchAlgorithmException e) { logger.error("签名计算失败", e); return false; } } // 字节数组转十六进制字符串 private String bytesToHex(byte[] bytes) { StringBuilder hexString = new StringBuilder(); for (byte b : bytes) { String hex = String.format("%02x", b); hexString.append(hex); } return hexString.toString(); } // 处理表情互动创建事件 public void handleReactionCreatedEvent(Map<String, Object> eventData) { try { Map<String, Object> event = (Map<String, Object>) eventData.get("event"); if (event == null) { logger.warn("无效的表情互动事件: {}", eventData); return; } String postId = (String) event.get("entity_id"); String reactionType = (String) event.get("type"); if (postId == null || reactionType == null) { logger.warn("表情互动事件缺少必要字段: postId={}, reactionType={}", postId, reactionType); return; } PostData postData = postDataMap.computeIfAbsent(postId, PostData::new); // 核心增强:通过帖子ID获取作者信息 if (postData.author == null || postData.authorId == null) { try { // 第一步:获取帖子详情(包含作者ID) fetchPostDetails(postData); // 第二步:如果获取到了作者ID但还没有姓名,则调用用户接口 if (postData.authorId != null && (postData.author == null || postData.author.equals("未知作者"))) { logger.info("通过表情互动事件获取作者信息: 帖子ID={} → 作者ID={}", postId, postData.authorId); postData.author = getUserName(postData.authorId); logger.info("获取作者姓名成功: {} → {}", postData.authorId, postData.author); } } catch (Exception e) { logger.error("通过表情互动事件获取作者信息失败", e); } } if ("THUMBSUP".equals(reactionType)) { postData.likeCount++; logger.info("帖子 {} 收到新点赞,当前点赞数: {}", postId, postData.likeCount); } updatePopularityScore(postData); } catch (Exception e) { logger.error("处理表情互动事件失败", e); } } // 处理表情互动删除事件 public void handleReactionDeletedEvent(Map<String, Object> eventData) { try { Map<String, Object> event = (Map<String, Object>) eventData.get("event"); if (event == null) { logger.warn("无效的表情互动删除事件: {}", eventData); return; } String postId = (String) event.get("entity_id"); String reactionType = (String) event.get("type"); if (postId == null || reactionType == null) { logger.warn("表情互动删除事件缺少必要字段: postId={}, reactionType={}", postId, reactionType); return; } PostData postData = postDataMap.computeIfAbsent(postId, PostData::new); // 通过帖子ID获取作者信息 if (postData.author == null || postData.authorId == null) { try { fetchPostDetails(postData); if (postData.authorId != null && (postData.author == null || postData.author.equals("未知作者"))) { postData.author = getUserName(postData.authorId); } } catch (Exception e) { logger.error("获取帖子详情失败,但将继续处理事件", e); } } if ("THUMBSUP".equals(reactionType)) { if (postData.likeCount > 0) { postData.likeCount--; logger.info("帖子 {} 取消点赞,当前点赞数: {}", postId, postData.likeCount); } else { logger.warn("帖子 {} 点赞数为0,但收到取消点赞事件", postId); } } updatePopularityScore(postData); } catch (Exception e) { logger.error("处理表情互动删除事件失败", e); } } // 处理点踩创建事件 public void handleDislikeCreatedEvent(Map<String, Object> eventData) { try { Map<String, Object> event = (Map<String, Object>) eventData.get("event"); if (event == null) { logger.warn("无效的点踩事件: {}", eventData); return; } String postId = (String) event.get("entity_id"); if (postId == null) { logger.warn("点踩事件缺少必要字段: {}", eventData); return; } PostData postData = postDataMap.computeIfAbsent(postId, PostData::new); // 通过帖子ID获取作者信息 if (postData.author == null || postData.authorId == null) { try { fetchPostDetails(postData); if (postData.authorId != null && (postData.author == null || postData.author.equals("未知作者"))) { postData.author = getUserName(postData.authorId); } } catch (Exception e) { logger.error("获取帖子详情失败,但将继续处理事件", e); } } postData.dislikeCount++; logger.info("帖子 {} 收到新点踩,当前点踩数: {}", postId, postData.dislikeCount); updatePopularityScore(postData); } catch (Exception e) { logger.error("处理点踩事件失败", e); } } // 处理点踩删除事件 public void handleDislikeDeletedEvent(Map<String, Object> eventData) { try { Map<String, Object> event = (Map<String, Object>) eventData.get("event"); if (event == null) { logger.warn("无效的点踩删除事件: {}", eventData); return; } String postId = (String) event.get("entity_id"); if (postId == null) { logger.warn("点踩删除事件缺少必要字段: {}", eventData); return; } PostData postData = postDataMap.computeIfAbsent(postId, PostData::new); // 通过帖子ID获取作者信息 if (postData.author == null || postData.authorId == null) { try { fetchPostDetails(postData); if (postData.authorId != null && (postData.author == null || postData.author.equals("未知作者"))) { postData.author = getUserName(postData.authorId); } } catch (Exception e) { logger.error("获取帖子详情失败,但将继续处理事件", e); } } if (postData.dislikeCount > 0) { postData.dislikeCount--; logger.info("帖子 {} 取消点踩,当前点踩数: {}", postId, postData.dislikeCount); } else { logger.warn("帖子 {} 点踩数为0,但收到取消点踩事件", postId); } updatePopularityScore(postData); } catch (Exception e) { logger.error("处理点踩删除事件失败", e); } } public void handlePostCreatedEvent(Map<String, Object> eventData) { try { Map<String, Object> event = (Map<String, Object>) eventData.get("event"); if (event == null) { logger.warn("无效的帖子创建事件: {}", eventData); return; } String postId = (String) event.get("id"); if (postId == null) { logger.warn("帖子创建事件缺少必要字段: {}", eventData); return; } PostData postData = postDataMap.computeIfAbsent(postId, PostData::new); try { fetchPostDetails(postData); } catch (Exception e) { logger.error("获取帖子详情失败", e); } Map<String, Object> userIdentity = (Map<String, Object>) event.get("user_id"); String eventUserId = null; if (userIdentity != null) { eventUserId = (String) userIdentity.get("open_id"); if (eventUserId == null) { eventUserId = (String) userIdentity.get("union_id"); } } if (postData.author == null && eventUserId != null) { try { postData.author = getUserName(eventUserId); } catch (Exception e) { logger.error("获取用户姓名失败", e); postData.author = eventUserId; } } logger.info("新帖子创建: {}, 作者ID: {}, 发布时间: {}", postId, eventUserId, postData.publishTimeUnix); logger.info("作者姓名: {}", postData.author); } catch (Exception e) { logger.error("处理帖子创建事件失败", e); } } // 判断用户ID类型 private String determineUserIdType(String userId) { if (userId.startsWith("ou_")) return "open_id"; if (userId.startsWith("u_")) return "user_id"; if (userId.startsWith("on_")) return "union_id"; return null; } // 获取用户姓名(带缓存和重试机制) private String getUserName(String userId) throws IOException { // 检查缓存 if (userCache.containsKey(userId)) { String cachedName = userCache.get(userId); logger.info("用户信息命中缓存: {} → {}", userId, cachedName); // 调试日志:检查缓存中的名称是否是中文 if (!isValidChineseName(cachedName)) { logger.warn("缓存中的名称不是中文: {} → {}", userId, cachedName); } return cachedName; } if (userId == null || userId.isEmpty()) { logger.warn("用户ID为空"); return "无效ID"; } String userType = determineUserIdType(userId); if (userType == null) { logger.warn("不支持的用户ID类型: {}", userId); return "未知用户"; } int retries = 3; while (retries-- > 0) { try { String url = USER_INFO_API + userId + "?department_id_type=open_department_id&user_id_type=" + userType; logger.debug("调用用户信息API: {}", url); Request request = new Request.Builder() .url(url) .header("Authorization", "Bearer " + tenantAccessToken) .get() .build(); try (Response response = httpClient.newCall(request).execute()) { logger.debug("用户信息接口响应: HTTP {}", response.code()); if (!response.isSuccessful()) { logger.error("用户信息接口错误: HTTP {} - {}", response.code(), response.message()); if (response.code() == 429) { Thread.sleep(1000); continue; } else if (response.code() == 404) { logger.warn("用户不存在: {}", userId); return "已离职用户"; } throw new IOException("获取用户信息失败: HTTP " + response.code()); } String responseData = response.body().string(); logger.debug("用户信息API原始响应: {}", responseData); // 添加原始响应日志 JsonObject result = jsonParser.parse(responseData).getAsJsonObject(); if (result.has("code") && result.get("code").getAsInt() != 0) { logger.error("飞书API返回错误: {}", responseData); continue; } JsonObject data = result.getAsJsonObject("data"); if (data != null && data.has("user")) { JsonObject user = data.getAsJsonObject("user"); // === 详细调试日志开始 === logger.info("完整用户对象: {}", user.toString()); // 记录完整用户对象 String userName = null; String source = "未知来源"; // 1. 优先使用name字段 if (user.has("name")) { JsonElement nameElement = user.get("name"); if (nameElement.isJsonPrimitive()) { userName = nameElement.getAsString().trim(); source = "name字段"; logger.info("从{}获取用户名: {}", source, userName); // 检查是否是有效中文名 if (isValidChineseName(userName)) { logger.debug("name字段是有效中文名"); } else { logger.warn("name字段不是中文名: {}", userName); } } } // 2. 尝试custom_attrs获取中文名 if ((userName == null || !isValidChineseName(userName)) && user.has("custom_attrs")) { JsonObject customAttrs = user.getAsJsonObject("custom_attrs"); logger.debug("检查custom_attrs: {}", customAttrs); for (String key : customAttrs.keySet()) { // 查找包含"中文"或"姓名"的自定义字段 if (key.contains("中文") || key.contains("姓名")) { JsonElement attrElement = customAttrs.get(key); if (attrElement.isJsonPrimitive()) { String candidate = attrElement.getAsString().trim(); logger.debug("找到可能的中文名字段: {} = {}", key, candidate); if (isValidChineseName(candidate)) { userName = candidate; source = "custom_attrs." + key; logger.info("从{}获取中文名: {}", source, userName); break; } } } } } // 3. 尝试en_name字段 if ((userName == null || userName.isEmpty()) && user.has("en_name")) { JsonElement enNameElement = user.get("en_name"); if (enNameElement.isJsonPrimitive()) { userName = enNameElement.getAsString().trim(); source = "en_name字段"; logger.info("从{}获取用户名: {}", source, userName); } } // 4. 回退到user_id if ((userName == null || userName.isEmpty()) && user.has("user_id")) { JsonElement userIdElement = user.get("user_id"); if (userIdElement.isJsonPrimitive()) { userName = userIdElement.getAsString().trim(); source = "user_id字段"; logger.info("从{}获取用户名: {}", source, userName); } } // 5. 最终回退 if (userName == null || userName.isEmpty()) { userName = "未知用户"; source = "默认值"; logger.warn("无法获取有效用户名,使用默认值"); } // 检查最终用户名是否是中文 if (!isValidChineseName(userName)) { logger.warn("最终用户名不是中文: {} → {} (来源: {})", userId, userName, source); logger.warn("完整用户对象: {}", user.toString()); } else { logger.info("获取到中文名: {} → {}", userId, userName); } // === 详细调试日志结束 === // 缓存结果 logger.info("缓存用户信息: {} → {}", userId, userName); userCache.put(userId, userName); logger.info("最终确定的用户名: {} → {}", userId, userName); return userName; } } } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new IOException("用户信息请求被中断", e); } catch (Exception e) { logger.error("获取用户信息异常", e); if (retries == 0) { logger.error("最终获取用户信息失败: {}", userId, e); return "未知用户"; } try { Thread.sleep(2000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } } } return "未知用户"; } // 检查是否是有效中文名 private boolean isValidChineseName(String name) { if (name == null || name.isEmpty()) return false; // 简单检查:包含中文字符即为有效 return name.matches(".*[\\u4e00-\\u9fa5]+.*"); } // 获取帖子详情(严格使用user_id字段) private void fetchPostDetails(PostData postData) throws IOException { Request request = new Request.Builder() .url(MOMENTS_POST_API + postData.postId) .header("Authorization", "Bearer " + tenantAccessToken) .get() .build(); try (Response response = httpClient.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("获取帖子详情失败: HTTP " + response.code()); } String responseData = response.body().string(); logger.debug("帖子详情API响应: {}", responseData); JsonObject result = jsonParser.parse(responseData).getAsJsonObject(); JsonObject data = result.getAsJsonObject("data"); if (data != null) { JsonObject post = data.getAsJsonObject("post"); if (post != null) { // ===== 严格使用user_id字段 ===== String authorId = null; String authorSource = "unknown"; // 只使用user_id字段获取作者ID if (post.has("user_id")) { JsonElement userIdElem = post.get("user_id"); // 处理字符串格式的user_id if (userIdElem.isJsonPrimitive()) { authorId = userIdElem.getAsString(); authorSource = "user_id"; logger.info("从user_id字段获取作者ID: {}", authorId); // 标准化ID格式(确保以ou_开头) if (!authorId.startsWith("ou_") && authorId.length() == 32) { authorId = "ou_" + authorId; logger.info("标准化作者ID格式: {} → {}", authorId, authorId); } } // 处理对象格式的user_id else if (userIdElem.isJsonObject()) { JsonObject userIdObj = userIdElem.getAsJsonObject(); if (userIdObj.has("open_id")) { authorId = userIdObj.get("open_id").getAsString(); authorSource = "user_id.open_id"; logger.info("从user_id.open_id获取作者ID: {}", authorId); } } } // 存储作者ID if (authorId != null) { postData.authorId = authorId; logger.info("获取到帖子作者ID: {} (来源: {})", authorId, authorSource); // 获取作者姓名 if (postData.author == null) { try { postData.author = getUserName(authorId); logger.info("通过作者ID获取姓名: {} → {}", authorId, postData.author); } catch (Exception e) { logger.error("获取作者姓名失败", e); postData.author = "未知作者"; } } } else { logger.warn("无法确定帖子作者ID: {}", postData.postId); } // ===== 其他字段处理 ===== // 提及用户处理 if (post.has("mentions")) { for (JsonElement mention : post.getAsJsonArray("mentions")) { JsonObject mentionObj = mention.getAsJsonObject(); String mentionedUserId = null; if (mentionObj.has("open_id")) { mentionedUserId = mentionObj.get("open_id").getAsString(); } else if (mentionObj.has("user_id")) { mentionedUserId = mentionObj.get("user_id").getAsString(); } else if (mentionObj.has("id")) { mentionedUserId = mentionObj.get("id").getAsString(); } if (mentionedUserId != null) { postData.mentionedUsers.add(getUserName(mentionedUserId)); } else if (mentionObj.has("name")) { postData.mentionedUsers.add(mentionObj.get("name").getAsString()); } } } // 内容处理 if (post.has("content")) { // 解析富文本内容为纯文本 String contentJson = post.get("content").getAsString(); postData.content = parseRichTextToPlainText(contentJson); } // 时间处理逻辑 if (post.has("create_time")) { try { JsonElement elem = post.get("create_time"); if (elem.isJsonPrimitive()) { if (elem.getAsJsonPrimitive().isString()) { String timeStr = elem.getAsString(); // 尝试多种格式解析 postData.publishTimeUnix = parseTimeToUnixMillis(timeStr); logger.info("解析发布时间: {} → {}", timeStr, postData.publishTimeUnix); } else if (elem.getAsJsonPrimitive().isNumber()) { postData.publishTimeUnix = elem.getAsLong() * 1000; logger.info("解析发布时间戳: {}", postData.publishTimeUnix); } } } catch (Exception e) { logger.error("解析create_time失败", e); } } } } } catch (Exception e) { logger.error("解析帖子详情失败", e); throw new IOException("解析帖子详情失败: " + e.getMessage()); } } // 发布时间解析方法 private long parseTimeToUnixMillis(String timeStr) { if (timeStr == null || timeStr.isEmpty()) { return 0; } // 1. 尝试解析为数字(秒级时间戳) try { long seconds = Long.parseLong(timeStr); return seconds * 1000; } catch (NumberFormatException e) { // 不是数字,继续尝试其他格式 } // 2. 尝试多种日期格式 for (DateTimeFormatter formatter : DATE_TIME_FORMATTERS) { try { // 尝试带时区解析 if (formatter == DateTimeFormatter.ISO_OFFSET_DATE_TIME) { ZonedDateTime zdt = ZonedDateTime.parse(timeStr, formatter); return zdt.toInstant().toEpochMilli(); } // 尝试本地时间解析(默认时区) LocalDateTime ldt = LocalDateTime.parse(timeStr, formatter); return ldt.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); } catch (DateTimeParseException e) { } } // 3. 尝试其他可能的格式 try { // 尝试解析为毫秒级时间戳 return Long.parseLong(timeStr); } catch (NumberFormatException e) { // 解析失败 } logger.warn("无法解析时间字符串: {}", timeStr); return 0; } // 解析飞书富文本格式为纯文本 private String parseRichTextToPlainText(String richTextJson) { try { if (richTextJson == null || richTextJson.isEmpty()) { return ""; } JsonArray blocks = jsonParser.parse(richTextJson).getAsJsonArray(); StringBuilder plainText = new StringBuilder(); for (JsonElement block : blocks) { if (block.isJsonArray()) { JsonArray elements = block.getAsJsonArray(); for (JsonElement element : elements) { if (element.isJsonObject()) { JsonObject obj = element.getAsJsonObject(); if (obj.has("tag") && obj.has("text")) { String tag = obj.get("tag").getAsString(); String text = obj.get("text").getAsString(); // 处理不同类型的标签 if ("text".equals(tag)) { plainText.append(text); } else if ("hashtag".equals(tag)) { // 保留话题标签的文本内容 plainText.append("#").append(text).append(" "); } // 可以根据需要添加更多标签类型的处理 } } } // 块之间添加换行 plainText.append("\n"); } } return plainText.toString().trim(); } catch (Exception e) { logger.error("解析富文本失败: {}", richTextJson, e); // 如果解析失败,返回原始内容 return richTextJson; } } // 更新帖子热度值 private void updatePopularityScore(PostData postData) { double newScore = postData.likeCount * 1.0 - postData.dislikeCount * 0.5; double oldScore = postData.popularityScore; postData.popularityScore = newScore; logger.info("帖子 {} 热度更新: {} → {}", postData.postId, oldScore, newScore); } // 安排报告任务(每10分钟生成一次报告并清理缓存) public void scheduleWeeklyReport() { // 立即执行第一次报告生成和缓存清理 long initialDelay = 0; long period = 10; // 10分钟间隔 // 每10分钟生成报告 scheduler.scheduleAtFixedRate(() -> { try { logger.info("开始执行定期报告生成"); generateWeeklyReport(); } catch (Exception e) { logger.error("生成报告失败", e); } }, initialDelay, period, TimeUnit.MINUTES); // 每10分钟清理用户缓存 scheduler.scheduleAtFixedRate(() -> { logger.info("开始清理用户缓存"); int cacheSize = userCache.size(); userCache.clear(); logger.info("用户缓存已清除,共清理 {} 条记录", cacheSize); }, initialDelay, period, TimeUnit.MINUTES); LocalDateTime firstExecution = LocalDateTime.now().plusMinutes(initialDelay); logger.info("任务已安排:报告生成和缓存清理将于 {} 开始执行,每 {} 分钟运行一次", firstExecution.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")), period); } // 生成周报并同步至多维表格 private void generateWeeklyReport() throws IOException { logger.info("开始生成周报..."); long insertionTime = System.currentTimeMillis(); // 获取统一的插入时间 List topPosts = postDataMap.values().stream() .sorted(Comparator.comparingDouble(p -> -p.popularityScore)) .limit(3) .collect(Collectors.toList()); if (topPosts.isEmpty()) { logger.info("本周没有帖子数据"); return; } List<Map<String, Object>> records = new ArrayList<>(); for (int i = 0; i < topPosts.size(); i++) { PostData post = topPosts.get(i); Map<String, Object> record = new HashMap<>(); Map<String, Object> fields = new HashMap<>(); fields.put("板块信息", "夸一夸"); fields.put("帖子正文", post.content); fields.put("被@的人", String.join(", ", post.mentionedUsers)); fields.put("排名", i + 1); fields.put("综合热度值", post.popularityScore); fields.put("点赞数量", post.likeCount); fields.put("作者", post.author); // 使用帖子自身的发布时间 fields.put("发布时间", post.publishTimeUnix); record.put("fields", fields); records.add(record); logger.info("添加记录: 帖子ID={}, 作者={}, 发布时间={}", post.postId, post.author, post.publishTimeUnix); } insertRecordsToBitable(records); postDataMap.clear(); logger.info("周报生成完成,已同步至多维表格"); } // 插入记录到多维表格(增强错误处理) private void insertRecordsToBitable(List<Map<String, Object>> records) throws IOException { // 检查令牌有效性 if (!isTokenValid()) { logger.warn("访问令牌即将过期,正在刷新..."); refreshAccessToken(); } String url = "https://open.feishu.cn/open-apis/bitable/v1/apps/" + BITABLE_APP_TOKEN + "/tables/" + BITABLE_TABLE_ID + "/records/batch_create"; Map<String, Object> requestBody = new HashMap<>(); requestBody.put("records", records); MediaType JSON = MediaType.get("application/json; charset=utf-8"); okhttp3.RequestBody body = okhttp3.RequestBody.create(gson.toJson(requestBody), JSON); Request request = new Request.Builder() .url(url) .header("Authorization", "Bearer " + tenantAccessToken) .post(body) .build(); try (Response response = httpClient.newCall(request).execute()) { if (!response.isSuccessful()) { String errorBody = response.body().string(); logger.error("多维表格插入失败: HTTP {} - {}", response.code(), errorBody); // 处理403错误:尝试刷新令牌并重试 if (response.code() == 403) { logger.warn("访问令牌可能失效,尝试刷新并重试..."); refreshAccessToken(); Request newRequest = request.newBuilder() .header("Authorization", "Bearer " + tenantAccessToken) .build(); try (Response retryResponse = httpClient.newCall(newRequest).execute()) { if (!retryResponse.isSuccessful()) { String retryErrorBody = retryResponse.body().string(); logger.error("重试插入失败: HTTP {} - {}", retryResponse.code(), retryErrorBody); throw new IOException("重试插入失败: HTTP " + retryResponse.code()); } logger.info("重试插入成功"); return; } } throw new IOException("插入多维表格失败: HTTP " + response.code()); } String responseData = response.body().string(); logger.info("插入多维表格成功: {}", responseData); } } // 错误响应 private Map<String, Object> createErrorResponse(int code, String msg) { Map<String, Object> result = new HashMap<>(); result.put("code", code); result.put("msg", msg); return result; } // 成功响应 private Map<String, Object> createSuccessResponse() { Map<String, Object> result = new HashMap<>(); result.put("code", 0); result.put("msg", "success"); return result; } } 目前接口返回200

package com.kucun.Service; import java.io.Serializable; import java.lang.reflect.Field; import java.util.*; import java.util.stream.Collectors; import javax.persistence.EntityNotFoundException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.data.domain.Example; import org.springframework.data.domain.ExampleMatcher; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Service; import com.kucun.data.entity.*; import com.kucun.dataDo.*; @Service public class AppService { // 自动注入所有依赖 @Autowired private KucunRepository kucunRepository; @Autowired private DynamicRepositoryService repositoryService; @Autowired private EntityDependencyService dependencyService; /** * 获取所有实体类型的数据 * @return 包含所有实体数据的Map */ public Information getAllData() { Map<String, Object> response = new HashMap<>(); repositoryService.getRepositoryNameMap().forEach((key, repo) -> response.put(key + "s", repo.findAll()) ); return Information.NewSuccess(response); } /** * 获取指定实体类型的所有数据 * @param entityName 实体名称 * @return 实体数据列表 */ public Information getEntityData(String entityName) { JpaRepository<?, ?> repo = repositoryService.getJpaRepository(entityName); return Information.NewSuccess(repo.findAll()); } /** * 添加新实体 * @param entity 要添加的实体对象 * @return 添加结果 */ public Information addEntity(Object entity) { try { // 处理关联字段 handleAssociations(entity); // 获取对应的Repository并保存 JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entity.getClass()); Object savedEntity = repo.save(entity); // 如果是板材,初始化库存 if (savedEntity instanceof Bancai) { initializeKucunForBancai((Bancai) savedEntity); } return Information.NewSuccess(savedEntity); } catch (Exception ex) { return Information.Newfail(500, "创建失败: " + ex.getMessage(), null); } } /** * 更新实体 * @param entity 包含ID的实体对象 * @return 更新结果 */ public Information updateEntity(Object entity) { if (entity == null) { return Information.Newfail(403, "参数为空", null); } try { // 获取ID字段 Field idField = entity.getClass().getDeclaredField("id"); idField.setAccessible(true); Object idValue = idField.get(entity); if (idValue == null) { return Information.Newfail(403, "ID为空", null); } // 获取Repository和现有实体 JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entity.getClass()); Object existingEntity = repo.findById((Serializable) idValue) .orElseThrow(() -> new RuntimeException("实体不存在")); // 复制非空属性并保存 copyNonNullProperties(entity, existingEntity); return Information.NewSuccess(repo.save(existingEntity)); } catch (Exception ex) { return Information.Newfail(500, "更新失败: " + ex.getMessage(), null); } } /** * 删除实体 * @param entity 要删除的实体 * @return 删除结果 */ public Information deleteEntity(EntityBasis entity) { if (entity == null) { return Information.NewFail("删除对象不能为空"); } try { String entityName = entity.getClass().getSimpleName().toLowerCase(); JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entityName); // 先加载完整实体(关键步骤) Object fullEntity = repo.findById(entity.getId()) .orElseThrow(() -> new EntityNotFoundException("实体不存在")); if(entity instanceof Bancai) { if(((Bancai)fullEntity).getKucun().getShuliang()>0) { return Information.NewFail("库存不为零,无法删除"); } } // 检查依赖关系 if (dependencyService.hasDependencies(entity.getClass(), entity.getId())) { return Information.NewFail("该记录已被引用,无法删除"); } // 使用实体对象删除(触发级联操作) repo.delete(fullEntity); return Information.NewSuccess("删除成功"); } catch (Exception e) { return Information.NewFail("删除错误: " + e.getMessage()); } } /** * 动态查询实体 * @param entity 包含查询条件的实体对象 * @return 查询结果 */ public <T> Information queryEntity(T entity) { if (entity == null) { return Information.NewFail("查询参数不能为空"); } try { JpaRepository<T, ?> repo = (JpaRepository<T, ?>) repositoryService.getJpaRepository(entity.getClass()); Example<T> example = Example.of(entity, ExampleMatcher.matching() .withIgnoreNullValues() .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)); return Information.NewSuccess(repo.findAll(example)); } catch (Exception e) { return Information.NewFail("查询失败: " + e.getMessage()); } } // ====================== 私有辅助方法 ====================== /** * 为板材初始化库存 * @param bancai 板材对象 */ private void initializeKucunForBancai(Bancai bancai) throws Exception { Kucun kucun = new Kucun(null, bancai, 0); bancai.setKucun(kucunRepository.save(kucun)); } /** * 处理实体关联关系 * @param entity 要处理的实体 */ private void handleAssociations(Object entity) throws Exception { for (Field field : entity.getClass().getDeclaredFields()) { field.setAccessible(true); Object value = field.get(entity); if (value == null) continue; // 处理 JPA 实体关联 if (value instanceof EntityBasis) { EntityBasis associated = (EntityBasis) value; JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(associated.getClass().getSimpleName().toLowerCase()); // 只处理已存在实体(不创建新关联) if (associated.getId() != null) { Object managedEntity = repo.findById(associated.getId()) .orElseThrow(() -> new RuntimeException("关联实体不存在")); field.set(entity, managedEntity); } } // 处理集合关联 else if (value instanceof Collection) { List<Object> managedEntities = new ArrayList<>(); for (Object item : (Collection<?>) value) { if (item instanceof EntityBasis) { EntityBasis eb = (EntityBasis) item; JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(eb.getClass().getSimpleName().toLowerCase()); if (eb.getId() != null) { managedEntities.add(repo.findById(eb.getId()) .orElseThrow(() -> new RuntimeException("关联实体不存在"))); } } } if (!managedEntities.isEmpty()) { field.set(entity, managedEntities); } } } } /** * 复制非空属性 * @param source 源对象 * @param target 目标对象 */ private void copyNonNullProperties(Object source, Object target) throws IllegalAccessException { for (Field field : source.getClass().getDeclaredFields()) { field.setAccessible(true); Object value = field.get(source); // 跳过关联字段和ID字段 if (value != null && !(value instanceof EntityBasis) && !(value instanceof Collection) && !field.getName().equals("id")) { try { Field targetField = target.getClass().getDeclaredField(field.getName()); targetField.setAccessible(true); targetField.set(target, value); } catch (NoSuchFieldException ignored) {} } } } }package com.kucun.controller; import com.fasterxml.jackson.databind.ObjectMapper; import com.kucun.Service.AppService; import com.kucun.data.entity.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.Collections; import java.util.HashMap; import java.util.Map; @RestController @RequestMapping("/app") public class AppController { // Java 8 兼容的实体类型映射 private static final Map<String, Class<?>> ENTITY_MAP; static { Map<String, Class<?>> map = new HashMap<>(); map.put("user", User.class); map.put("bancai", Bancai.class); map.put("caizi", Caizhi.class); map.put("mupi", Mupi.class); map.put("dingdan", Dingdan.class); map.put("zujian", Zujian.class); map.put("chanpin", Chanpin.class); map.put("dingdan_chanpin", Dingdan_chanpin.class); map.put("dingdan_chanpin_zujian", Dingdan_chanpin_zujian.class); map.put("chanpin_zujian", Chanpin_zujian.class); map.put("jinhuo", Jinhuo.class); map.put("kucun", Kucun.class); ENTITY_MAP = Collections.unmodifiableMap(map); } @Autowired private AppService appService; @Autowired private ObjectMapper objectMapper; // ====================== 数据查询 ====================== @GetMapping("/all") public Information getAllData() { return appService.getAllData(); } @GetMapping("/all/{entityType}") public Information getEntityData(@PathVariable String entityType) { return appService.getEntityData(entityType.toLowerCase()); } // ====================== CRUD操作 ====================== @PostMapping("/add/{entityType}") public Information addEntity( @PathVariable String entityType, @RequestBody Map<String, Object> requestBody ) { return handleEntityOperation(entityType, requestBody, "add"); } @PostMapping("/select/{entityType}") public Information queryEntity( @PathVariable String entityType, @RequestBody Map<String, Object> requestBody ) { return handleEntityOperation(entityType, requestBody, "select"); } @PostMapping("/delete/{entityType}") public Information deleteEntity( @PathVariable String entityType, @RequestBody Map<String, Object> requestBody ) { return handleEntityOperation(entityType, requestBody, "delete"); } @PostMapping("/update/{entityType}") public Information updateEntity( @PathVariable String entityType, @RequestBody Map<String, Object> requestBody ) { return handleEntityOperation(entityType, requestBody, "update"); } // ====================== 核心辅助方法 ====================== private Information handleEntityOperation( String entityType, Map<String, Object> requestBody, String operation ) { String normalizedType = entityType.toLowerCase(); Class<?> entityClass = ENTITY_MAP.get(normalizedType); if (entityClass == null) { return Information.NewFail("不支持的实体类型: " + entityType); } try { Object entity = objectMapper.convertValue(requestBody, entityClass); switch (operation) { case "add": return appService.addEntity(entity); case "select": return appService.queryEntity(entity); case "delete": // 确保实体实现了EntityBasis接口 if (entity instanceof EntityBasis) { return appService.deleteEntity((EntityBasis) entity); } else { return Information.NewFail("删除操作需要实体实现EntityBasis接口"); } case "update": return appService.updateEntity(entity); default: return Information.NewFail("无效的操作类型"); } } catch (Exception e) { return Information.NewFail(operation + "操作失败: " + e.getMessage()); } } }package com.kucun.Service; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.metamodel.*; import org.springframework.stereotype.Service; import java.io.Serializable; import java.util.*; import java.util.stream.Collectors; @Service public class EntityDependencyService { @PersistenceContext private EntityManager entityManager; private final Map<Class<?>, Set<Attribute<?, ?>>> associationCache = new HashMap<>(); /** * 检查实体是否被其他实体引用 * @param entityClass 实体类 * @param entityId 实体ID * @return 存在引用返回true */ public boolean hasDependencies(Class<?> entityClass, Serializable entityId) { Metamodel metamodel = entityManager.getMetamodel(); Set<EntityType<?>> entities = metamodel.getEntities(); for (EntityType<?> entityType : entities) { // 跳过自身(避免自引用检查) if (entityType.getJavaType().equals(entityClass)) continue; Set<Attribute<?, ?>> associations = getAssociationAttributes(entityType); for (Attribute<?, ?> attr : associations) { if (attr.getJavaType().isAssignableFrom(entityClass)) { if (isReferenced(entityType, attr, entityId)) { return true; } } } } return false; } /** * 获取实体所有关联属性(带缓存) */ private Set<Attribute<?, ?>> getAssociationAttributes(EntityType<?> entityType) { return associationCache.computeIfAbsent(entityType.getJavaType(), k -> entityType.getAttributes().stream() .filter(Attribute::isAssociation) .collect(Collectors.toSet()) ); } /** * 检查特定关联是否引用目标实体 */ private boolean isReferenced(EntityType<?> entityType, Attribute<?, ?> attribute, Serializable targetId) { String jpql = buildReferenceQuery(entityType, attribute); Long count = (Long) entityManager.createQuery(jpql) .setParameter("targetId", targetId) .getSingleResult(); return count > 0; } /** * 构建引用检查查询 */ private String buildReferenceQuery(EntityType<?> entityType, Attribute<?, ?> attribute) { String entityName = entityType.getName(); String attrName = attribute.getName(); if (attribute instanceof PluralAttribute) { return String.format("SELECT COUNT(e) FROM %s e WHERE :targetId MEMBER OF e.%s", entityName, attrName); } else { return String.format("SELECT COUNT(e) FROM %s e WHERE e.%s.id = :targetId", entityName, attrName); } } }package com.kucun.Service; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Service; @Service public class DynamicRepositoryService { private final Map<Class<?>, JpaRepository<?, ?>> repositoryMap = new HashMap<>(); private final Map<String, JpaRepository<?, ?>> repositoryNameMap = new HashMap<>(); public Map<String, JpaRepository<?, ?>> getRepositoryNameMap() { return repositoryNameMap; } public Map<Class<?>, JpaRepository<?, ?>> getRepositoryMap() { return repositoryMap; } public JpaRepository<?,?> getJpaRepository(String e){ // System.out.println("String:"+e+mapToString(repositoryNameMap)); return repositoryNameMap.get(e); } public JpaRepository<?,?> getJpaRepository(Class<?> e){ // System.out.println("Class:"+e+mapToString(repositoryMap)); // System.out.println("Class:"+e); return repositoryMap.get(e); } // 自动注入所有JpaRepository实例 @Autowired public void initRepositories(Map<String, JpaRepository<?, ?>> repositories) { repositories.forEach((name, repo) -> { // 获取代理类实现的接口 Class<?>[] interfaces = repo.getClass().getInterfaces(); for (Class<?> iface : interfaces) { // 扫描接口上的泛型信息 Type[] genericInterfaces = iface.getGenericInterfaces(); for (Type type : genericInterfaces) { if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; // 检查原始类型是否是JpaRepository if (pt.getRawType().equals(JpaRepository.class)) { Type[] args = pt.getActualTypeArguments(); if (args.length >= 2 && args[0] instanceof Class) { Class<?> entityClass = (Class<?>) args[0]; repositoryMap.put(entityClass, repo); String key = entityClass.getSimpleName().toLowerCase(); repositoryNameMap.put(key, repo); // 调试日志 System.out.printf("Mapped %s -> %s [key: %s]%n", entityClass.getName(), repo.getClass().getName(), key); } } } } // 检查接口本身的泛型签名(如果继承的是参数化接口) Type genericSuper = iface.getGenericSuperclass(); if (genericSuper instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) genericSuper; if (pt.getRawType().equals(JpaRepository.class)) { Type[] args = pt.getActualTypeArguments(); if (args.length >= 2 && args[0] instanceof Class) { Class<?> entityClass = (Class<?>) args[0]; repositoryMap.put(entityClass, repo); String key = entityClass.getSimpleName().toLowerCase(); repositoryNameMap.put(key, repo); // 调试日志 System.out.printf("Mapped %s -> %s [key: %s]%n", entityClass.getName(), repo.getClass().getName(), key); } } } } }); } // 通用保存方法 public <T> T saveEntity(T entity) { JpaRepository<T, ?> repo = (JpaRepository<T, ?>) repositoryMap.get(entity.getClass()); if (repo != null) { return repo.save(entity); } throw new IllegalArgumentException("Repository not found for " + entity.getClass()); } public static String mapToString(Map<?, ?> map) { if (map == null || map.isEmpty()) { return ""; } StringBuilder sb = new StringBuilder(); for (Map.Entry<?, ?> entry : map.entrySet()) { sb.append(entry.getKey()).append("=").append(entry.getValue()).append(","); } // 删除最后一个多余的逗号 if (sb.length() > 0) { sb.setLength(sb.length() - 1); } return sb.toString(); } }package com.kucun.data.entity; import java.lang.annotation.Annotation; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToOne; import javax.persistence.Table; import com.kucun.data.entity.DTO.*; import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.databind.annotation.JsonSerialize; /** * 板材 * @author Administrator * */ @Entity @Table(name="bancai") @JsonSerialize(using = FullEntitySerializer.class) public class Bancai implements EntityBasis { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "caizhi_id") // private Caizhi caizhi; @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "mupi1_id") private Mupi mupi1; @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "mupi2_id") private Mupi mupi2; private Double houdu; @OneToOne( cascade = CascadeType.ALL, orphanRemoval = true, // 添加此配置 fetch = FetchType.LAZY ) @JoinColumn(name = "kucun_id", referencedColumnName = "id") private Kucun kucun; public Kucun getKucun() { return kucun; } public void setKucun(Kucun kucun) { this.kucun = kucun; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Caizhi getCaizhi() { return caizhi; } public void setCaizhi(Caizhi caizhi) { this.caizhi = caizhi; } public Mupi getMupi1() { return mupi1; } public void setMupi1(Mupi mupi1) { this.mupi1 = mupi1; } public Mupi getMupi2() { return mupi2; } public void setMupi2(Mupi mupi2) { this.mupi2 = mupi2; } public Double getHoudu() { return houdu; } public void setHoudu(Double houdu) { this.houdu = houdu; } public Bancai(int id, Caizhi caizhi, Mupi mupi1, Mupi mupi2, Double houdu) { super(); this.id = id; this.caizhi = caizhi; this.mupi1 = mupi1; this.mupi2 = mupi2; this.houdu = houdu; } public Bancai() { super(); } } package com.kucun.data.entity; import java.util.List; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.UniqueConstraint; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.kucun.data.entity.DTO.FullEntitySerializer; /** * 板材材质 * @author Administrator * */ @Entity @Table(name="caizhi", uniqueConstraints = { @UniqueConstraint(columnNames = "name") }) @JsonSerialize(using = FullEntitySerializer.class) public class Caizhi extends SimpleEntity implements EntityBasis{ @OneToMany(mappedBy="caizhi") private List<Bancai> bancais; public Caizhi() { super(); } // 添加反向关联维护方法 public void addBancai(Bancai bancai) { bancais.add(bancai); bancai.setCaizhi(this); } // 添加移除方法 public void removeBancai(Bancai bancai) { bancais.remove(bancai); bancai.setCaizhi(null); } public List<Bancai> getBancais() { return bancais; } public void setBancais(List<Bancai> bancais) { this.bancais = bancais; } } package com.kucun.data.entity; import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.ManyToMany; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.UniqueConstraint; import org.hibernate.annotations.Type; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.kucun.data.entity.DTO.FullEntitySerializer; /** * 木皮 * @author Administrator * */ @Entity @Table(name="mupi", uniqueConstraints = { @UniqueConstraint(columnNames = "name") }) @JsonSerialize(using = FullEntitySerializer.class) public class Mupi extends SimpleEntity implements EntityBasis{ /** * 是否有油漆 */ @Column(name="you") @Type(type = "org.hibernate.type.BooleanType") private Boolean you; // 添加 OneToMany 映射 @OneToMany(mappedBy = "mupi1") // 指向 Bancai 中的 mupi1 字段 private List<Bancai> bancaisForMupi1; @OneToMany(mappedBy = "mupi2") // 指向 Bancai 中的 mupi2 字段 private List<Bancai> bancaisForMupi2; public List<Bancai> getBancaisForMupi1() { return bancaisForMupi1; } public void setBancaisForMupi1(List<Bancai> bancaisForMupi1) { this.bancaisForMupi1 = bancaisForMupi1; } public List<Bancai> getBancaisForMupi2() { return bancaisForMupi2; } public void setBancaisForMupi2(List<Bancai> bancaisForMupi2) { this.bancaisForMupi2 = bancaisForMupi2; } public Mupi() { super(); } public Boolean getYou() { return you; } public void setYou(Boolean you) { this.you = you; } } 2025-06-17 13:50:08.559 DEBUG 18340 --- [nio-8080-exec-7] o.s.web.servlet.DispatcherServlet : POST "/KuCun2/app/delete/bancai", parameters={} 2025-06-17 13:50:08.561 DEBUG 18340 --- [nio-8080-exec-7] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.kucun.controller.AppController#deleteEntity(String, Map) 2025-06-17 13:50:08.567 DEBUG 18340 --- [nio-8080-exec-7] m.m.a.RequestResponseBodyMethodProcessor : Read "application/json;charset=UTF-8" to [{id=14}] 2025-06-17 13:50:08.585 DEBUG 18340 --- [nio-8080-exec-7] org.hibernate.SQL : select bancai0_.id as id1_0_0_, bancai0_.caizhi_id as caizhi_i3_0_0_, bancai0_.houdu as houdu2_0_0_, bancai0_.kucun_id as kucun_id4_0_0_, bancai0_.mupi1_id as mupi5_0_0_, bancai0_.mupi2_id as mupi6_0_0_ from bancai bancai0_ where bancai0_.id=? Hibernate: select bancai0_.id as id1_0_0_, bancai0_.caizhi_id as caizhi_i3_0_0_, bancai0_.houdu as houdu2_0_0_, bancai0_.kucun_id as kucun_id4_0_0_, bancai0_.mupi1_id as mupi5_0_0_, bancai0_.mupi2_id as mupi6_0_0_ from bancai bancai0_ where bancai0_.id=? 2025-06-17 13:50:08.590 DEBUG 18340 --- [nio-8080-exec-7] m.m.a.RequestResponseBodyMethodProcessor : Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json] 2025-06-17 13:50:08.591 DEBUG 18340 --- [nio-8080-exec-7] m.m.a.RequestResponseBodyMethodProcessor : Writing [com.kucun.data.entity.Information@3dee3314] 2025-06-17 13:50:08.591 DEBUG 18340 --- [nio-8080-exec-7] o.s.web.servlet.DispatcherServlet : Completed 200 OK 删除失败:null

package com.example.kucun2.dataProcessing; import android.content.Context; import android.os.Handler; import android.os.Looper; import android.util.Log; import com.example.kucun2.entity.data.GsonFactory; import com.example.kucun2.entity.data.SynchronizableEntity; import com.example.kucun2.entity.data.SynchronizedList; import com.example.kucun2.function.MyAppFnction; import com.google.gson.Gson; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; /** 数据加载处理器 职责: 从服务器加载全量/增量数据 处理JSON解析和数据转换 更新数据存储并建立关联 提供加载状态回调 */ public class DataLoader { private static final String TAG = “DataLoader”; private final DataCore dataCore; private final DataAssociator associator; private final Gson gson = GsonFactory.createGson(); // 加载状态跟踪 private boolean isLoading = false; public DataLoader(DataCore dataCore, DataAssociator associator) { this.dataCore = dataCore; this.associator = associator; } /** 从服务器加载全量数据 @param context Android上下文 @param callback 加载结果回调 */ public void loadAllData(Context context, Data.LoadDataCallback callback) { // 主线程检查 if (Looper.myLooper() != Looper.getMainLooper()) { throw new IllegalStateException(“必须在主线程调用Data.loadAllData”); } // 防止重复加载 if (isLoading) { callback.onFailure(); return; } isLoading = true; dataCore.ensurePreservedObjects(); // 获取OkHttp客户端 OkHttpClient client = MyAppFnction.getClient(); // 构建请求 Request request = new Request.Builder() .url(MyAppFnction.getApiUrl(“api/data/all”)) .addHeader(“Authorization”, "Bearer " + Data.getUser().getToken()) .build(); // 异步执行请求 client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { isLoading = false; safeCallback(callback, false); Log.e(TAG, “数据加载失败”, e); } @Override public void onResponse(Call call, Response response) { try { if (!response.isSuccessful()) { throw new IOException("Unexpected code: " + response); } String jsonData = response.body().string(); parseAndAssignData(jsonData, context, callback); } catch (Exception e) { isLoading = false; safeCallback(callback, false); Log.e(TAG, "数据处理失败", e); } } }); } /** 加载增量更新数据 @param lastSyncTimestamp 上次同步时间戳 @param callback 加载结果回调 */ public void loadDeltaData(long lastSyncTimestamp, Data.LoadDataCallback callback) { // 构建增量请求 Request request = new Request.Builder() .url(MyAppFnction.getApiUrl(“api/data/delta?since=” + lastSyncTimestamp)) .addHeader(“Authorization”, "Bearer " + Data.getUser().getToken()) .build(); // 执行请求(类似loadAllData) } /** 解析JSON数据并更新到实体列表 */ private void parseAndAssignData( String jsonData, Context context, Data.LoadDataCallback callback ) { try { // 解析JSON数据 Data.AllDataResponse allData = gson.fromJson( jsonData, Data.AllDataResponse.class ); // 更新所有列表 updateAllLists(allData); // 建立实体关联 associator.automaticAssociation(); // 标记所有实体为已修改 Data.setAllEntitiesState(SynchronizableEntity.SyncState.MODIFIED); // 保存到本地存储 DataPersistence.saveToPreferences(context); // 回调成功 isLoading = false; safeCallback(callback, true); } catch (Exception e) { isLoading = false; safeCallback(callback, false); Log.e(TAG, “数据解析失败”, e); } } /** 更新所有实体列表 */ private void updateAllLists(Data.AllDataResponse allData) { updateList(dataCore.bancais, allData.bancais); updateList(dataCore.caizhis, allData.caizhis); updateList(dataCore.mupis, allData.mupis); updateList(dataCore.chanpins, allData.chanpins); updateList(dataCore.chanpin_zujians, allData.chanpin_zujians); updateList(dataCore.dingdans, allData.dingdans); updateList(dataCore.dingdan_chanpins, allData.dingdan_chanpins); updateList(dataCore.Dingdan_chanpin_zujians, allData.Dingdan_chanpin_zujians); updateList(dataCore.kucuns, allData.kucuns); updateList(dataCore.zujians, allData.zujians); updateList(dataCore.users, allData.users); updateList(dataCore.jinhuos, allData.jinhuos); } /** 更新单个实体列表(合并策略) */ private <T extends SynchronizableEntity> void updateList( SynchronizedList<T> existingList, List<T> newList ) { if (newList == null) return; // 创建ID映射表用于快速查找 Map<Long, T> existingMap = new HashMap<>(); for (T entity : existingList) { existingMap.put(entity.getId(), entity); } // 处理新数据:更新或添加 for (T newEntity : newList) { T existing = existingMap.get(newEntity.getId()); if (existing != null) { // 合并更新 existing.mergeFrom(newEntity); } else { // 添加新实体 existingList.add(newEntity); } } // 处理删除:标记不在新数据中的实体为删除 Set<Long> newIds = newList.stream() .map(SynchronizableEntity::getId) .collect(Collectors.toSet()); Iterator<T> iterator = existingList.iterator(); while (iterator.hasNext()) { T entity = iterator.next(); if (!newIds.contains(entity.getId())) { entity.setState(SynchronizableEntity.SyncState.DELETED); } } } /** 安全回调到主线程 */ private void safeCallback(Data.LoadDataCallback callback, boolean success) { new Handler(Looper.getMainLooper()).post(() -> { if (callback == null) return; if (success) callback.onSuccess(); else callback.onFailure(); }); } }package com.example.kucun2.function; import android.app.Application; import android.content.Context; import androidx.annotation.StringRes; import java.lang.reflect.Field; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.X509TrustManager; import okhttp3.OkHttpClient; public class MyAppFnction extends Application { private static MyAppFnction instance; public static OkHttpClient getClient() { return client; } private static OkHttpClient client; @Override public void onCreate() { super.onCreate(); instance = this; createSecureClient(this.getApplicationContext()); } public static String getStringResource(@StringRes int resId) { return instance.getString(resId); } public static String getStringResource(@StringRes int resId, Object... args) { return instance.getString(resId, args); } public static String getStringResource(String resourceType, String resourceName) { try { // 1. 构造完整的资源路径 String className = instance.getPackageName() + ".R$" + resourceType; // 2. 反射获取资源ID Class<?> resClass = Class.forName(className); Field field = resClass.getField(resourceName); int resId = field.getInt(null); // 静态字段获取资源ID // 3. 获取实际字符串资源 return instance.getResources().getString(resId); } catch (Exception e) { handleError(e); return null; // 或返回默认值 } } private static void handleError(Exception e) { // 异常处理逻辑 if (e instanceof ClassNotFoundException) { System.err.println("R类未找到: " + e.getMessage()); } else if (e instanceof NoSuchFieldException) { System.err.println("资源字段不存在: " + e.getMessage()); } else { e.printStackTrace(); } } public static void createSecureClient(Context context) { // 创建安全的SSL上下文 SSLContext sslContext = TLSUtils.createSSLContext(context, "selfsigned.crt"); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); X509TrustManager trustManager = TLSUtils.createTrustManager(context, "selfsigned.crt"); client = new OkHttpClient.Builder() .sslSocketFactory(socketFactory, trustManager) .hostnameVerifier((hostname, session) -> { // 开发环境直接返回true,生产环境应验证域名 return true; }) .build(); } } <string name=“url”>https://192.168.31.177:3000</string> <string name=“url_all”>/app/all</string> <string name=“url_bancis”>/app/bancai/all</string> <string name=“url_caizhis”>/app/caizhi/all</string> <string name=“url_mupis”>/app/mupi/all</string> <string name=“url_dingdans”>/app/dingdan/all</string> <string name=“url_chanpins”>/app/chanpin/all</string> <string name=“url_zujians”>/app/zujian/all</string> <string name="url_chanpin_zujians">/app/chanpin_zujian/all</string> <string name="url_dingdan_zujians">/app/dingdan_zujian/all</string> <string name="url_dingdan_chanpins">/app/dingdan_chanpin/all</string> <string name="url_jinhuos">/app/jinhuo/all</string> <string name="url_add_bancai">/app/bancai/add</string> <string name="url_add_dingdan">/app/dingdan/add</string> <string name="url_add_chanpin">/app/chanpin/add</string> <string name="url_add_zujian">/app/zujian/add</string> <string name="url_add_caizhi">/app/caizhi/add</string> <string name="url_add_mupi">/app/mupi/add</string> <string name="url_add_dingdan_chanpin">/app/dingdan_chanpi/add</string> <string name="url_add_dingdan_zujian">/app/dingdan_zujian/add</string> <string name="url_add_chanpin_zujian">/app/chanpin_zujian/add</string> <string name="url_add_jinhuo">/app/jinhuo/add</string> <string name="url_login">/user/login</string>api url标准化,url规则url_{增删改查}_实体类名小写,获取全部url_实体类名小写+s

package com.kucun.controller; import com.fasterxml.jackson.databind.ObjectMapper; import com.kucun.Service.AppService; import com.kucun.Service.DynamicRepositoryService; import com.kucun.data.entity.; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.web.bind.annotation.; import java.util.Date; import java.util.List; import java.util.Map; import javax.validation.Valid; @RestController @RequestMapping(“/app”) public class AppController { @Autowired private AppService appService; @Autowired private ObjectMapper objectMapper; private Map<String, Class<?>> ENTITY_MAP ; @Autowired public AppController( DynamicRepositoryService dynamicRepositoryService, AppService appService, ObjectMapper objectMapper ) { this.ENTITY_MAP = dynamicRepositoryService.getStringClassMap(); this.appService = appService; this.objectMapper = objectMapper; } // ====================== 数据查询 ====================== @GetMapping("/all") public Information getAllData( @RequestParam(value = "since",required=false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Date since ) { System.out.println("since:"+since); try { if(since == null) return appService.getAllData(); else return appService.getUpdatesSince(since); } catch (Exception e) { // TODO: handle exception return Information.NewFail(e.getMessage()); } } // 添加保存全部数据的API端点 @PostMapping("/save-all") public Information saveAllData(@RequestBody Map<String, List<?>> allData) { try { return appService.saveAllData(allData); } catch (Exception e) { return Information.NewFail("保存全部数据失败: " + e.getMessage()); } } @GetMapping("/all/{entityType}") public Information getEntityData(@PathVariable String entityType, @RequestParam(value = "since",required=false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Date since) { return appService.getEntityData(entityType.toLowerCase()); } // ====================== CRUD操作 ====================== @PostMapping("/add/{entityType}") public Information addEntity( @PathVariable String entityType, @RequestBody @Valid Map<String, Object> requestBody ) { return handleEntityOperation(entityType, requestBody, "add"); } @PostMapping("/select/{entityType}") public Information queryEntity( @PathVariable String entityType, @RequestBody Map<String, Object> requestBody ) { return handleEntityOperation(entityType, requestBody, "select"); } @PostMapping("/delete/{entityType}") public Information deleteEntity( @PathVariable String entityType, @RequestBody Map<String, Object> requestBody ) { return handleEntityOperation(entityType, requestBody, "delete"); } @PostMapping("/update/{entityType}") public Information updateEntity( @PathVariable String entityType, @RequestBody Map<String, Object> requestBody ) { return handleEntityOperation(entityType, requestBody, "update"); } // ====================== 核心辅助方法 ====================== private Information handleEntityOperation( String entityType, Map<String, Object> requestBody, String operation ) { String normalizedType = entityType.toLowerCase(); // 特殊处理 Dingdan_bancai if ("dingdan_bancai".equals(normalizedType)) { try { Dingdan_bancai entity = objectMapper.convertValue(requestBody, Dingdan_bancai.class); // 从请求体中提取用户ID并设置到临时字段 if (requestBody.containsKey("currentUserId")) { entity.setCurrentUserId(((Integer) requestBody.get("currentUserId"))); } return appService.handleDingdanBancaiOperation( entity, operation); } catch (Exception e) { return Information.NewFail(operation + "操作失败: " + e.getMessage()); } } Class<?> entityClass = ENTITY_MAP.get(normalizedType); if (entityClass == null) { return Information.NewFail("不支持的实体类型: " + entityType); } try { Object entity = objectMapper.convertValue(requestBody, entityClass); //System.out.println(Information.NewSuccess(requestBody).DataJson()); switch (operation) { case "add": return appService.addEntity(entity); case "select": return appService.queryEntity((EntityBasis) entity); case "delete": // 确保实体实现了EntityBasis接口 if (entity instanceof EntityBasis) { return appService.deleteEntity((EntityBasis) entity); } else { return Information.NewFail("删除操作需要实体实现EntityBasis接口"); } case "update": return appService.updateEntity(entity); default: return Information.NewFail("无效的操作类型"); } } catch (Exception e) { return Information.NewFail(operation + "操作失败: " + e.getMessage()); } } }package com.kucun.Service; import java.io.Serializable; import java.lang.reflect.Field; import java.util.*; import java.util.stream.Collectors; import javax.persistence.EntityNotFoundException; import javax.transaction.Transactional; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Example; import org.springframework.data.domain.ExampleMatcher; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Service; import com.kucun.data.entity.; import com.kucun.dataDo.; /** * * * */ @Service public class AppService { // 自动注入所有依赖 @Autowired private KucunRepository kucunRepository; @Autowired private DynamicRepositoryService repositoryService; @Autowired private EntityDependencyService dependencyService; /** * 获取所有实体类型的数据 * @return 包含所有实体数据的Map * * */ public Information getAllData() { Map<String, Object> response = new HashMap<>(); repositoryService.getRepositoryNameMap().forEach((key, repo) -> response.put(key + "s", repo.findAll()) ); return Information.NewSuccess(response); } /** * 获取自指定时间以来的所有更新 * @param since 时间戳 * @return 按实体类型分组的更新数据 */ public Information getUpdatesSince(Date since) { Map<String, List<?>> updates = new HashMap<>(); Map<String, CustomRepository<?, ?>> repoMap = repositoryService.getRepositoryNameMap(); repoMap.forEach((entityName, repo) -> { // 使用反射查询大于指定时间的记录 List<?> results = repositoryService.findUpdatedSince(entityName, since); if (!results.isEmpty()) { updates.put(entityName+'s', results); } }); return Information.NewSuccess(updates); } /** * 获取指定实体类型的所有数据 * @param entityName 实体名称 * @return 实体数据列表 * * */ public Information getEntityData(String entityName) { JpaRepository<?, ?> repo = repositoryService.getJpaRepository(entityName); return Information.NewSuccess(repo.findAll()); } /** * 添加新实体 * @param entity 要添加的实体对象 * @return 添加结果 * * */ public Information addEntity(@Valid Object entity) { try { // 处理关联字段 handleAssociations(entity); // 获取对应的Repository并保存 JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entity.getClass()); //System.out.println(Information.NewSuccess(entity).DataJson()); if(entity instanceof User) { if(((User) entity).getPass()!=null) { String psass=((User) entity).getPass(); ((User) entity).setPass(PasswordService.hashPassword(psass)); } } Object savedEntity = repo.save(entity); // 如果是板材,初始化库存 if (savedEntity instanceof Bancai) { initializeKucunForBancai((Bancai) savedEntity); } return Information.NewSuccess(savedEntity); } catch (Exception ex) { return Information.Newfail(500, "创建失败: " + ex.getMessage(), null); } } /** * 更新实体 * @param entity 包含ID的实体对象 * @return 更新结果 * * */ public Information updateEntity(Object entity) { if (entity == null) { return Information.Newfail(403, "参数为空", null); } // 获取ID字段 Field idField=null; try { idField = getIdField(entity); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { idField.setAccessible(true); Object idValue = idField.get(entity); if (idValue == null) { return Information.Newfail(403, "ID为空", null); } // 获取Repository和现有实体 JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entity.getClass()); Object existingEntity = repo.findById((Serializable) idValue) .orElseThrow(() -> new RuntimeException("实体不存在")); if(entity instanceof User) { if(((User) entity).getPass()!=null) { String psass=((User) entity).getPass(); ((User) entity).setPass(PasswordService.hashPassword(psass)); } } // 复制非空属性并保存 copyNonNullProperties(entity, existingEntity); return Information.NewSuccess(repo.save(existingEntity)); } catch (Exception ex) { ex.fillInStackTrace(); return Information.Newfail(500, "更新失败: " + ex.getMessage(), null); } } /** * 删除实体 * @param entity 要删除的实体 * @return 删除结果 */ public Information deleteEntity(EntityBasis entity) { if (entity == null) { return Information.NewFail("删除对象不能为空"); } try { String entityName = entity.getClass().getSimpleName().toLowerCase(); JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entityName); // 先加载完整实体(关键步骤) Object managedEntity = repo.findById(entity.getId()) .orElseThrow(() -> new EntityNotFoundException("实体不存在")); if(entity instanceof Bancai) { Kucun k=kucunRepository.findByBancai((Bancai)entity); if(k!=null&&k.getShuliang()>0) { return Information.NewFail("库存不为零,无法删除"); } if(k!=null) { Field deletedField = k.getClass().getDeclaredField("deleted"); deletedField.setAccessible(true); deletedField.set(k, true); Field deletedAtField = k.getClass().getDeclaredField("deletedAt"); deletedAtField.setAccessible(true); deletedAtField.set(k, new Date()); kucunRepository.save(k); } } // 检查依赖关系 if (dependencyService.hasDependencies(entity.getClass(), entity.getId())) { return Information.NewFail("该记录已被引用,无法删除"); } // 使用实体对象删除(触发级联操作) Field deletedField = managedEntity.getClass().getDeclaredField("deleted"); deletedField.setAccessible(true); deletedField.set(managedEntity, true); Field deletedAtField = managedEntity.getClass().getDeclaredField("deletedAt"); deletedAtField.setAccessible(true); deletedAtField.set(managedEntity, new Date()); repo.save(managedEntity); return Information.NewSuccess("删除成功"); } catch (Exception e) { return Information.NewFail("删除错误: " + e.getMessage()); } }/** * 动态查询实体 * @param entity 包含查询条件的实体对象 * @return 查询结果 */ public <T extends EntityBasis> Information queryEntity(T entity) { if (entity == null) { return Information.NewFail("查询参数不能为空"); } try { JpaRepository<T, ?> repo = (JpaRepository<T, ?>) repositoryService.getJpaRepository(entity.getClass()); // 创建基础查询条件 ExampleMatcher matcher = ExampleMatcher.matching() .withIgnoreNullValues() .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING); if(entity.getDeleted()==null) { // 添加软删除过滤条件 if (entity instanceof EntityBasis) { // 动态设置deleted=false条件 Field deletedField = EntityBasis.class.getDeclaredField("deleted"); deletedField.setAccessible(true); deletedField.set(entity, false); } } Example<T> example = Example.of(entity, matcher); return Information.NewSuccess(repo.findAll(example)); } catch (Exception e) { return Information.NewFail("查询失败: " + e.getMessage()); } } // ====================== 私有辅助方法 ====================== /** * 为板材初始化库存 * @param bancai 板材对象 */ private void initializeKucunForBancai(Bancai bancai) throws Exception { Kucun kucun = new Kucun(null, bancai, 0); bancai.setKucun(kucunRepository.save(kucun)); } /** * 处理实体关联关系 * @param entity 要处理的实体 */ private void handleAssociations(Object entity) throws Exception { for (Field field : entity.getClass().getDeclaredFields()) { field.setAccessible(true); Object value = field.get(entity); if (value == null) continue; // 处理 JPA 实体关联 if (value instanceof EntityBasis) { EntityBasis associated = (EntityBasis) value; JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(associated.getClass().getSimpleName().toLowerCase()); // 只处理已存在实体(不创建新关联) if (associated.getId() != null) { Object managedEntity = repo.findById(associated.getId()) .orElseThrow(() -> new Exception("关联实体不存在")); field.set(entity, managedEntity); } } // 处理集合关联 else if (value instanceof Collection) { List<Object> managedEntities = new ArrayList<>(); for (Object item : (Collection<?>) value) { if (item instanceof EntityBasis) { EntityBasis eb = (EntityBasis) item; JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(eb.getClass().getSimpleName().toLowerCase()); if (eb.getId() != null) { managedEntities.add(repo.findById(eb.getId()) .orElseThrow(() -> new Exception("关联实体不存在"))); } } } if (!managedEntities.isEmpty()) { field.set(entity, managedEntities); } } } } /** * 处理实体关联关系 * @param entity 要处理的实体 */ private void handleAssociationss(Object entity) throws Exception { for (Field field : entity.getClass().getDeclaredFields()) { field.setAccessible(true); Object value = field.get(entity); if(value instanceof EntityBasis) { } } } /** * 复制非空属性 * @param source 源对象 * @param target 目标对象 */ private void copyNonNullProperties(Object source, Object target) throws IllegalAccessException { for (Field field : source.getClass().getDeclaredFields()) { field.setAccessible(true); Object value = field.get(source); // 跳过关联字段和ID字段 if (value != null && !(value instanceof EntityBasis) && !(value instanceof Collection) && !field.getName().equals("id")) { try { Field targetField = target.getClass().getDeclaredField(field.getName()); targetField.setAccessible(true); targetField.set(target, value); } catch (NoSuchFieldException ignored) {} } } } /* * 获取实体类的id字段(支持父类查找) * @param entity 实体对象 * @return Field对象或null */ public static Field getIdField(Object entity) { if (entity == null) { return null; } Class<?> clazz = entity.getClass(); // 递归查找类及其父类的id字段 while (clazz != null && clazz != Object.class) { try { Field idField = clazz.getDeclaredField("id"); idField.setAccessible(true); return idField; } catch (NoSuchFieldException e) { // 继续向上查找父类 clazz = clazz.getSuperclass(); } catch (SecurityException e) { e.printStackTrace(); return null; } } return null; } // ====================== 专用方法处理 Dingdan_bancai ====================== @Transactional public Information handleDingdanBancaiOperation( Dingdan_bancai entity, String operation ) { try { // 获取对应的Repository JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(“dingdan_bancai”); switch (operation) { case "add": Dingdan_bancai savedEntity = (Dingdan_bancai) repo.save(entity); updateKucunAndCreateJinhuo(savedEntity, savedEntity.getShuliang()); return Information.NewSuccess(savedEntity); case "update": // 先获取现有实体以计算差异 Dingdan_bancai existing = (Dingdan_bancai) repo.findById(entity.getId()) .orElseThrow(() -> new EntityNotFoundException("实体不存在")); int quantityDifference = entity.getShuliang() - existing.getShuliang(); Dingdan_bancai updatedEntity = (Dingdan_bancai) repo.save(entity); if (quantityDifference != 0) { updateKucunAndCreateJinhuo(updatedEntity, quantityDifference); } return Information.NewSuccess(updatedEntity); default: return Information.NewFail("不支持的操作类型: " + operation); } } catch (Exception ex) { return Information.NewFail(operation + "操作失败: " + ex.getMessage()); } } // 更新库存并创建进货记录 private void updateKucunAndCreateJinhuo(Dingdan_bancai db, int quantityChange) { // 1. 更新库存 Bancai bancai = db.getBancai(); Kucun kucun = kucunRepository.findByBancai(bancai); if (kucun == null) { kucun = new Kucun(null, bancai, 0); } kucun.setShuliang(kucun.getShuliang() + quantityChange); kucunRepository.save(kucun); // 2. 创建进货记录 Jinhuo jinhuo = new Jinhuo(); jinhuo.setDingdan_bancai(db); jinhuo.setShuliang(quantityChange); jinhuo.setDate(new Date()); // 使用临时字段设置用户 if (db.getCurrentUserId() != null) { User user = new User(); user.setId(db.getCurrentUserId()); jinhuo.setUser(user); } ((JinhuoRepository)repositoryService.getJpaRepository(jinhuo.getClass())).save( jinhuo); } // … existing code … /** * 保存所有实体类型的数据 * @param allData 包含所有实体数据的Map,key为实体类型名+“s”,value为实体列表 * @return 保存结果 */ @Transactional public Information saveAllData(Map<String, List<?>> allData) { Map<String, Object> response = new HashMap<>(); allData.forEach((key, entities) -> { String entityName = key.endsWith("s") ? key.substring(0, key.length() - 1) : key; // 获取实体类类型 Class<?> entityClass = repositoryService.getEntityClass(entityName); if (entityClass != null) { // 类型安全转换 List<?> convertedList = entities.stream() .filter(entityClass::isInstance) .map(entityClass::cast) .collect(Collectors.toList()); // 保存实体 List<?> savedEntities = repositoryService.saveEntities( entityName, convertedList ); response.put(key, savedEntities); } else { response.put(key + "_error", "实体类型未注册"); } }); return Information.NewSuccess(response); } // … existing code … }---@startuml ' 基础类与接口 abstract class EntityBasis { + Integer id + Date lastUpdated + Boolean deleted + Date deletedAt + getId() + setId(Integer) } interface EntityBasisId { + getId() + setId(Integer) } abstract class SimpleEntity { + Integer id + String name } ' 实体类定义 class Mupi { + Boolean you + String name + List<Bancai> bancaisForMupi1 + List<Bancai> bancaisForMupi2 } class User { + String name + String andy + String pass + int role + int incumbency } class Chanpin_zujian { + Double one_howmany + Double zujianshu } class WechatUser { + String openid + String sessionKey + String nickname + String avatarUrl + String phoneNumber + Long userId + Date createTime + Integer status } class Kucun { + Integer shuliang } class Dingdan_chanpin { + Integer shuliang } class Information { + Integer Status + String text + Object data } class Zujian { + String name + List<Chanpin_zujian> chanping_zujian } class Dingdan_bancai { + Integer shuliang + Integer currentUserId } class Dingdan { + String number + Date xiadan + Date jiaohuo + List<Dingdan_chanpin> dingdan_chanpin } class Jinhuo { + Integer shuliang + Date date + String text + Integer theTypeOfOperation } class Caizhi { + String name + List<Bancai> bancai } class Bancai { + Double houdu } ' 继承关系 EntityBasis --|> EntityBasisId SimpleEntity --|> EntityBasisId Mupi --|> EntityBasis User --|> EntityBasis Chanpin_zujian --|> EntityBasis WechatUser --|> EntityBasis Kucun --|> EntityBasis Dingdan_chanpin --|> EntityBasis Zujian --|> EntityBasis Dingdan_bancai --|> EntityBasis Dingdan --|> EntityBasis Jinhuo --|> EntityBasis Caizhi --|> EntityBasis Bancai --|> EntityBasis ' 关联关系 ' 一对一 Bancai -- Kucun : 1:1 (kucun) ' 一对多/多对一 Chanpin "1" -- "*" Chanpin_zujian : 包含 (chanpin_zujian) Zujian "1" -- "*" Chanpin_zujian : 关联 (chanping_zujian) Bancai "1" -- "*" Chanpin_zujian : 被使用 (bancai) Dingdan "1" -- "*" Dingdan_chanpin : 包含 (dingdan_chanpin) Chanpin "1" -- "*" Dingdan_chanpin : 被订购 (chanpin) Dingdan "1" -- "*" Dingdan_bancai : 包含 (dingdan) Chanpin "1" -- "*" Dingdan_bancai : 关联 (chanpin) Zujian "1" -- "*" Dingdan_bancai : 关联 (zujian) Bancai "1" -- "*" Dingdan_bancai : 被订购 (bancai) User "1" -- "*" Jinhuo : 操作 (user) Dingdan_bancai "1" -- "*" Jinhuo : 关联 (dingdan_bancai) ' 单向关联 WechatUser -- User : 绑定 (userId) @enduml----用php脚本实现api,远程虚拟主机运行

大家在看

recommend-type

polkit-0.96-11.el6_10.2.x86_64.rpm离线升级包下载(Polkit漏洞CentOS6修复升级包)

CentOS 6.X版本专用 升级命令: rpm -Uvh polkit-0.96-11.el6_10.2.x86_64.rpm 或yum localinstall -y polkit-0.96-11.el6_10.2.x86_64.rpm 参考链接: https://ubuntu.com/security/CVE-2021-4034 https://access.redhat.com/security/cve/CVE-2021-4034 https://security-tracker.debian.org/tracker/CVE-2021-4034 https://www.qualys.com/2022/01/25/cve-2021-4034/pwnkit.txt
recommend-type

ray-optics:光学系统的几何光线追踪

射线光学 安装 要使用pip安装rayoptics ,请使用 > pip install rayoptics 或者,可以使用conda从conda - forge渠道安装rayoptics > conda install rayoptics --channel conda-forge 文献资料 射线光学位于“ 成像光学设计和分析工具 RayOptics是一个Python几何光学和成像光学库。 它为分析成像和相干光学系统提供了几何射线追踪基础。 在此基础上提供了许多标准的几何分析选项,例如横向射线和波前像差分析。 y-ybar图和镜头布局视图中近轴光线的图形编辑也支持光学系统的近轴布局。 支持导入Zemax .zmx和CODEV .seq文件。 RayOptics可用于Python脚本,Python和IPython外壳,Jupyter笔记本以及基于Qt的图形用户界面应用程序中。 笔记 该项
recommend-type

微信qq浏览器打开提示

自己的域名总是被举报,变红?搞一个遮罩呗! 跳转浏览器提示就OK了,亲测在PHP网站完美使用。 1.上传插件整个文件夹到/public目录。得到:/public/WxqqJump 2.修改/public/index.php文件。在第一行&lt;?php下新增代码 当不再使用或者需要临时关闭跳转时,只需//注销该行代码即可。
recommend-type

扑翼无人机准定常空气动力学及控制Matlab代码.rar

1.版本:matlab2014/2019a/2021a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 5.作者介绍:某大厂资深算法工程师,从事Matlab算法仿真工作10年;擅长智能优化算法、神经网络预测、信号处理、元胞自动机等多种领域的算法仿真实验,更多仿真源码、数据集定制私信+。
recommend-type

Pixhawk4飞控驱动.zip

已安装成功

最新推荐

recommend-type

【大学生电子设计】:备战2015全国大学生电子设计竞赛-信号源类赛题分析.pdf

【大学生电子设计】:备战2015全国大学生电子设计竞赛-信号源类赛题分析.pdf
recommend-type

湘潭大学人工智能专业2024级大一C语言期末考试题库项目-包含58个从头歌平台抓取并排版的C语言编程题目及解答-涵盖基础语法-数组操作-条件判断-循环结构-函数调用-指针应用等核心.zip

2025电赛预测湘潭大学人工智能专业2024级大一C语言期末考试题库项目_包含58个从头歌平台抓取并排版的C语言编程题目及解答_涵盖基础语法_数组操作_条件判断_循环结构_函数调用_指针应用等核心.zip
recommend-type

基于STM32的步进电机S型曲线与SpTA算法高效控制及其实现 T梯形算法 经典版

基于STM32平台的步进电机S型曲线和SpTA加减速控制算法。首先阐述了S型曲线控制算法的特点及其在STM32平台上的实现方法,包括设置启动频率、加速时间和最高速度等参数,以减少电机启动和停止时的冲击。接着讨论了T梯形算法与S型曲线的结合,通过精确的时间控制提高运动精度。然后重点讲解了SpTA算法,强调其自适应性强、不依赖PWM定时器个数,能够根据实际运行状态动态调整。文中提到一种高效的非DMA数据传输方式,提升了CPU效率并解决了外部中断时无法获取已输出PWM波形个数的问题。最后介绍了SpTA算法在多路电机控制方面的优势。 适合人群:从事嵌入式系统开发、自动化控制领域的工程师和技术人员,尤其是对步进电机控制有研究兴趣的人群。 使用场景及目标:适用于需要高精度和平滑控制的步进电机应用场合,如工业机器人、数控机床等领域。目标是帮助开发者掌握STM32平台下步进电机的先进控制算法,优化系统的实时性能和多电机协同控制能力。 其他说明:文章提供了详细的理论背景和技术细节,有助于读者深入理解并应用于实际项目中。
recommend-type

一个面向Android开发者的全面知识体系整理项目-包含Android基础-Framework解析-系统启动流程-四大组件原理-Handler-Binder-AMS-WMS等核心机.zip

python一个面向Android开发者的全面知识体系整理项目_包含Android基础_Framework解析_系统启动流程_四大组件原理_Handler_Binder_AMS_WMS等核心机.zip
recommend-type

Pansophica开源项目:智能Web搜索代理的探索

Pansophica开源项目是一个相对较新且具有创新性的智能Web搜索代理,它突破了传统搜索引擎的界限,提供了一种全新的交互方式。首先,我们来探讨“智能Web搜索代理”这一概念。智能Web搜索代理是一个软件程序或服务,它可以根据用户的查询自动执行Web搜索,并尝试根据用户的兴趣、历史搜索记录或其他输入来提供个性化的搜索结果。 Pansophica所代表的不仅仅是搜索结果的展示,它还强调了一个交互式的体验,在动态和交互式虚拟现实中呈现搜索结果。这种呈现方式与现有的搜索体验有着根本的不同。目前的搜索引擎,如Google、Bing和Baidu等,多以静态文本和链接列表的形式展示结果。而Pansophica通过提供一个虚拟现实环境,使得搜索者可以“扭转”视角,进行“飞行”探索,以及“弹网”来浏览不同的内容。这种多维度的交互方式使得信息的浏览变得更加快速和直观,有望改变用户与网络信息互动的方式。 接着,我们关注Pansophica的“开源”属性。所谓开源,指的是软件的源代码可以被公众获取,任何个人或组织都可以自由地使用、学习、修改和分发这些代码。开源软件通常由社区进行开发和维护,这样的模式鼓励了协作创新并减少了重复性劳动,因为全世界的开发者都可以贡献自己的力量。Pansophica项目作为开源软件,意味着其他开发者可以访问和使用其源代码,进一步改进和扩展其功能,甚至可以为Pansophica构建新的应用或服务。 最后,文件名称“Pansophica-src-1.3”表明了我们讨论的特定版本的Pansophica开源代码。数字“1.3”很可能指的是该版本号,表明这是Pansophica项目的第1.3个公开版本。这个版本号对于开发者来说很重要,因为它可以帮助他们追踪更新的进度、比较版本间的差异以及选择最适合其项目的版本。 综合以上信息,Pansophica开源项目不仅在搜索代理领域引入了创新的交互方式,而且通过开源的方式,提供了技术共享和协作的可能性。对于IT行业来说,开源项目是推动技术发展的重要力量,它激发了社区的活力,促进了知识的传播和技术的进步。通过构建一个开源社区,Pansophica可以吸引来自世界各地的开发者和研究人员,共同探索如何将搜索技术与交互式虚拟现实技术结合起来,为用户带来更加丰富和有效的信息检索体验。同时,Pansophica的开源性质也使其更容易适应未来技术的发展,随着社区的不断贡献和反馈,这一平台有望在功能和性能上得到持续的优化和增强。
recommend-type

跨平台内容提取无忧:coze工作流应对社交媒体挑战

# 1. 社交媒体内容提取的必要性与挑战 ## 1.1 内容提取的必要性 在数字时代,社交媒体内容是信息与数据流动的主干道,公司、个人和研究者都在寻求从这些信息中提取价值。无论是为了市场趋势分析、品牌监控、消费者洞察还是公共舆论监测,有效的社交媒体内容提取变得至关重要。这不仅有助于企业做出数据驱动的决策,也能使个人更好地理
recommend-type

vrrp主设备发送的免费arp

<think>好的,我现在需要回答用户关于VRRP主设备发送免费ARP的目的和工作原理的问题。首先,我得回忆一下VRRP的基本概念和工作机制。VRRP,虚拟路由冗余协议,主要用于在局域网中提供默认网关的冗余备份,确保网络的高可用性。主设备(Master)负责转发流量,而备用设备(Backup)则在主设备故障时接管工作。 用户的问题集中在主设备发送免费ARP的目的和机制上。根据引用[2],免费ARP用于通知下游设备虚拟MAC地址的变更。当主设备被选举出来后,它需要让局域网内的其他设备知道虚拟IP对应的MAC地址已经指向自己,这样流量才会被正确路由到主设备。免费ARP的作用应该就是更新这些设备的
recommend-type

为Ghost博客平台打造的Meteor流星包装使用指南

从给定文件信息中,我们可以提炼出以下IT知识点: ### 标题知识点:流星Ghost软件包 1. **流星Ghost软件包的用途**:流星Ghost软件包是专为Ghost博客平台设计的流星(Meteor)应用程序。流星是一个开源的全栈JavaScript平台,用于开发高性能和易于编写的Web应用程序。Ghost是一个开源博客平台,它提供了一个简单且专业的写作环境。 2. **软件包的作用**:流星Ghost软件包允许用户在流星平台上轻松集成Ghost博客。这样做的好处是可以利用流星的实时特性以及易于开发和部署的应用程序框架,同时还能享受到Ghost博客系统的便利和美观。 ### 描述知识点:流星Ghost软件包的使用方法 1. **软件包安装方式**:用户可以通过流星的命令行工具添加名为`mrt:ghost`的软件包。`mrt`是流星的一个命令行工具,用于添加、管理以及配置软件包。 2. **初始化Ghost服务器**:描述中提供了如何在服务器启动时运行Ghost的基本代码示例。这段代码使用了JavaScript的Promise异步操作,`ghost().then(function (ghostServer) {...})`这行代码表示当Ghost服务器初始化完成后,会在Promise的回调函数中提供一个Ghost服务器实例。 3. **配置Ghost博客**:在`then`方法中,首先会获取到Ghost服务器的配置对象`config`,用户可以在此处进行自定义设置,例如修改主题、配置等。 4. **启动Ghost服务器**:在配置完成之后,通过调用`ghostServer.start()`来启动Ghost服务,使其能够处理博客相关的请求。 5. **Web浏览器导航**:一旦流星服务器启动并运行,用户便可以通过Web浏览器访问Ghost博客平台。 ### 标签知识点:JavaScript 1. **JavaScript作为流星Ghost软件包的开发语言**:标签指出流星Ghost软件包是使用JavaScript语言开发的。JavaScript是一种在浏览器端广泛使用的脚本语言,它也是流星平台的基础编程语言。 2. **流星和Ghost共同使用的语言**:JavaScript同样也是Ghost博客平台的开发语言。这表明流星Ghost软件包可以无缝集成,因为底层技术栈相同。 ### 压缩包子文件的文件名称列表知识点:meteor-ghost-master 1. **版本控制和软件包结构**:文件名称`meteor-ghost-master`暗示了该软件包可能托管在像GitHub这样的版本控制系统上。文件名中的`master`通常指的是主分支或主版本。 2. **软件包的目录结构**:通过文件名称可以推断出该软件包可能拥有一个标准的流星软件包结构,包含了初始化、配置、运行等必要的模块和文件。 3. **软件包的维护状态**:由于文件名没有包含特定的版本号,我们无法直接得知软件包的最新更新情况。通常,软件包维护者会将最新的版本代码放在`master`分支上。 ### 总结 流星Ghost软件包提供了一个有效的解决方案,使得流星平台的开发者能够在他们的应用中添加Ghost博客功能。软件包的使用简便,通过流星的命令行工具安装,并通过JavaScript代码配置和启动Ghost服务。通过流星Ghost软件包,开发者能够享受流星的实时特性以及Ghost博客系统的便利性。此外,软件包的命名和结构也暗示了其维护和版本控制的模式,有助于开发者更好地理解如何使用和维护这一软件包。
recommend-type

抖音标题生成自动化:用coze工作流释放创意

# 1. 抖音标题生成自动化的重要性 随着社交媒体平台的崛起,内容的吸引力很大程度上取决于标题的创意与精准性。抖音作为一个日活亿级的短视频平台,高质量的标题能够有效提高视频的点击率,增加内容的传播。但是,人工撰写标题不仅耗时耗力,而且很难做到快速响应热点,自动化标题生成工具应运而生。coze工作流,作为一种实现自动化生成抖音标题的工具,其重要性不言而喻。它能够利用大数据分析和机器学习技术,提高标题的吸引
recommend-type

spss消费结构因子分析

<think>好的,我现在需要帮助用户在SPSS中进行消费结构的因子分析。首先,我要回忆一下因子分析的基本步骤和SPSS的操作流程。用户可能对SPSS不太熟悉,所以步骤要详细,同时需要结合他们提供的引用内容,特别是引用[2]中的适用条件和检验方法。 首先,用户提到了消费结构的数据,这可能包括多个变量,如食品、住房、交通等支出。因子分析适用于这种情况,可以降维并找出潜在因子。根据引用[2],需要检查样本量是否足够,变量间是否有相关性,以及KMO和Bartlett检验的结果。 接下来,我需要按照步骤组织回答:数据准备、适用性检验、因子提取、因子旋转、命名解释、计算得分。每个步骤都要简明扼要,说