Skip to content

Commit 7e0eef7

Browse files
authored
Merge pull request #97 from gitxiaofeng/master
feature:历史版本功能查看
2 parents 615832b + 1d8485c commit 7e0eef7

File tree

7 files changed

+191
-9
lines changed

7 files changed

+191
-9
lines changed

case-server/pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,14 @@
151151
<artifactId>httpclient</artifactId>
152152
<version>4.5.5</version>
153153
</dependency>
154+
155+
<!-- json patch组件 -->
156+
<dependency>
157+
<groupId>com.flipkart.zjsonpatch</groupId>
158+
<artifactId>zjsonpatch</artifactId>
159+
<version>0.4.11</version>
160+
</dependency>
161+
154162
</dependencies>
155163

156164
<build>

case-server/src/main/java/com/xiaoju/framework/controller/BackupController.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.xiaoju.framework.controller;
22

3+
import com.fasterxml.jackson.databind.JsonNode;
34
import com.xiaoju.framework.constants.enums.StatusCode;
45
import com.xiaoju.framework.entity.exception.CaseServerException;
56
import com.xiaoju.framework.entity.persistent.CaseBackup;
@@ -43,6 +44,19 @@ public Response<List<CaseBackup>> getBackupByCaseId(@RequestParam @NotNull(messa
4344
return Response.success(caseBackupService.getBackupByCaseId(caseId, beginTime, endTime));
4445
}
4546

47+
/**
48+
* 查询某个用例所有的备份记录
49+
*
50+
* @param caseId1 用例备份id1
51+
* @param caseId2 用例备份id2
52+
* @return 响应体
53+
*/
54+
@GetMapping(value = "/getCaseDiff")
55+
public Response<JsonNode> getCaseDiff(@RequestParam @NotNull(message = "备份id1") Long caseId1,
56+
@RequestParam @NotNull(message = "备份id2") Long caseId2) {
57+
return Response.success(caseBackupService.getCaseDiff(caseId1, caseId2));
58+
}
59+
4660
/**
4761
* 删除某个用例所有的备份记录
4862
*

case-server/src/main/java/com/xiaoju/framework/controller/WebController.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ public String login(){
2323
return "index";
2424
}
2525

26+
@RequestMapping("/history/*")
27+
public String history(){
28+
return "index";
29+
}
30+
31+
@RequestMapping("/caseManager/historyContrast/*/*")
32+
public String historyContrast(){
33+
return "index";
34+
}
35+
2636
@RequestMapping("/case/caseList/1")
2737
public String index(HttpServletRequest request){
2838
return "index";

case-server/src/main/java/com/xiaoju/framework/mapper/CaseBackupMapper.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ List<CaseBackup> selectByCaseId(@Param("caseId") Long caseId,
3030
@Param("beginTime") Date beginTime,
3131
@Param("endTime") Date endTime);
3232

33+
CaseBackup selectByBackupId(@Param("id") Long id);
34+
3335
/**
3436
* 删除一批备份记录
3537
*

case-server/src/main/java/com/xiaoju/framework/service/CaseBackupService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.xiaoju.framework.service;
22

3+
import com.fasterxml.jackson.databind.JsonNode;
34
import com.xiaoju.framework.entity.persistent.CaseBackup;
45

56
import java.util.List;
@@ -38,4 +39,6 @@ public interface CaseBackupService {
3839
* @return int
3940
*/
4041
int deleteBackup(Long caseId);
42+
43+
JsonNode getCaseDiff(Long backupId1, Long backupId2);
4144
}

case-server/src/main/java/com/xiaoju/framework/service/impl/CaseBackupServiceImpl.java

Lines changed: 147 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
package com.xiaoju.framework.service.impl;
22

3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import com.fasterxml.jackson.databind.node.ArrayNode;
6+
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
7+
import com.fasterxml.jackson.databind.node.ObjectNode;
8+
import com.flipkart.zjsonpatch.JsonDiff;
9+
import com.flipkart.zjsonpatch.JsonPatch;
310
import com.xiaoju.framework.entity.persistent.CaseBackup;
411
import com.xiaoju.framework.mapper.CaseBackupMapper;
512
import com.xiaoju.framework.service.CaseBackupService;
@@ -8,10 +15,16 @@
815
import org.slf4j.LoggerFactory;
916
import org.springframework.stereotype.Service;
1017
import org.springframework.transaction.annotation.Transactional;
18+
import java.util.regex.Matcher;
19+
import java.util.regex.Pattern;
1120

1221
import javax.annotation.Resource;
13-
import java.util.Date;
14-
import java.util.List;
22+
import java.io.IOException;
23+
import java.lang.reflect.Field;
24+
import java.util.*;
25+
26+
import static com.flipkart.zjsonpatch.DiffFlags.ADD_EXPLICIT_REMOVE_ADD_ON_REPLACE;
27+
import static com.flipkart.zjsonpatch.DiffFlags.ADD_ORIGINAL_VALUE_ON_REPLACE;
1528

1629
/**
1730
* 备份记录
@@ -33,12 +46,19 @@ public synchronized CaseBackup insertBackup(CaseBackup caseBackup) {
3346
List<CaseBackup> caseBackups = caseBackupMapper.selectByCaseId(caseBackup.getCaseId(), null, null);
3447

3548
// 如果当前已有,则直接返回
36-
// todo: 此处应该是比较json或者base字段信息,此处可能存在json字段位置不一致导致的字符串不一致问题。
37-
if (caseBackups.size() > 0 &&
38-
caseBackups.get(0).getCaseContent().equals(caseBackup.getCaseContent()) &&
39-
caseBackups.get(0).getRecordContent().equals(caseBackup.getRecordContent())) {
40-
LOGGER.info("当前内容已经保存过了,不再重复保存。");
41-
return caseBackups.get(0);
49+
// todo 此处还是用版本信息控制更加合理
50+
ObjectMapper jsonMapper = new ObjectMapper();
51+
try {
52+
if (caseBackups.size() > 0 &&
53+
JsonDiff.asJson(jsonMapper.readTree(caseBackups.get(0).getCaseContent()),
54+
jsonMapper.readTree(caseBackup.getCaseContent())).size() == 0 &&
55+
JsonDiff.asJson(jsonMapper.readTree(caseBackups.get(0).getRecordContent()),
56+
jsonMapper.readTree(caseBackup.getRecordContent())).size() == 0) {
57+
LOGGER.info("当前内容已经保存过了,不再重复保存。");
58+
return caseBackups.get(0);
59+
}
60+
} catch (IOException e) {
61+
LOGGER.info("json转换异常. 数据继续备份", e);
4262
}
4363

4464
int ret = caseBackupMapper.insert(caseBackup);
@@ -53,9 +73,127 @@ public synchronized CaseBackup insertBackup(CaseBackup caseBackup) {
5373
return caseBackup;
5474
}
5575

76+
@Override
77+
public JsonNode getCaseDiff(Long backupId2, Long backupId1) {
78+
ObjectMapper jsonMapper = new ObjectMapper();
79+
CaseBackup caseBackup1 = caseBackupMapper.selectByBackupId(backupId1);
80+
CaseBackup caseBackup2 = caseBackupMapper.selectByBackupId(backupId2);
81+
82+
try {
83+
JsonNode content1 = jsonMapper.readTree(caseBackup1.getCaseContent());
84+
JsonNode content2 = jsonMapper.readTree(caseBackup2.getCaseContent());
85+
ArrayNode patches = (ArrayNode) JsonDiff.asJson(content1, content2, EnumSet.of(ADD_ORIGINAL_VALUE_ON_REPLACE));
86+
87+
JsonNodeFactory FACTORY = JsonNodeFactory.instance;
88+
ArrayNode patchesNew = FACTORY.arrayNode();
89+
ObjectNode retJson = FACTORY.objectNode();
90+
Iterator<JsonNode> it = patches.elements();
91+
92+
while (it.hasNext()) {
93+
JsonNode element = it.next();
94+
String op = element.get("op").textValue();
95+
if (op.equals("replace")) {
96+
if (element.get("path").textValue().endsWith("base")) {
97+
continue;
98+
}
99+
ObjectNode node1 = element.deepCopy();
100+
101+
if(!element.get("path").textValue().endsWith("image") && !element.get("path").textValue().contains("imageSize")) {
102+
node1.remove("value");
103+
node1.put("value", "旧内容:" + element.get("fromValue").textValue() + "\n新内容:" + element.get("value").textValue());
104+
}
105+
patchesNew.add(node1);
106+
ObjectNode node2 = FACTORY.objectNode();
107+
node2.put("op", "add");
108+
String srcPath = element.get("path").textValue();
109+
110+
node2.put("path", srcPath.substring(0, srcPath.lastIndexOf('/')) + "/background");
111+
node2.put("value", "#d6f0ff");
112+
patchesNew.add(node2);
113+
} else if (op.equals("add")) {
114+
ObjectNode node1 = element.deepCopy();
115+
traverse(node1, "add");
116+
117+
patchesNew.add(node1);
118+
119+
} else if (op.equals("remove")) {
120+
patchesNew.add(element);
121+
ObjectNode node1 = element.deepCopy();
122+
node1.remove("op");
123+
node1.put("op", "add");
124+
traverse(node1, "remove");
125+
patchesNew.add(node1);
126+
127+
} else {
128+
LOGGER.info("op is: " + element.toString());
129+
}
130+
}
131+
JsonNode target = JsonPatch.apply((JsonNode) patchesNew, content1);
132+
133+
retJson.set("content", target);
134+
ArrayNode cardJson = FACTORY.arrayNode();
135+
ObjectNode backup1 = FACTORY.objectNode();
136+
backup1.put("user", caseBackup1.getCreator());
137+
backup1.put("time", caseBackup1.getGmtCreated().toString());
138+
ObjectNode backup2 = FACTORY.objectNode();
139+
backup2.put("user", caseBackup2.getCreator());
140+
backup2.put("time", caseBackup2.getGmtCreated().toString());
141+
cardJson.add(backup1);
142+
cardJson.add(backup2);
143+
144+
retJson.set("backupinfo", cardJson);
145+
146+
return retJson;
147+
148+
} catch (Exception e) {
149+
LOGGER.error("json mapper read tree exception. ", e);
150+
return null;
151+
}
152+
153+
}
154+
155+
private void traverse(JsonNode node, String op) {
156+
Iterator<JsonNode> iterator = node.iterator();
157+
158+
while (iterator.hasNext()) {
159+
JsonNode n = iterator.next();
160+
if (n.size() > 0) {
161+
if (n.has("id")) {
162+
if (op.equals("add")) {
163+
((ObjectNode) n).put("background", "#ddfade");
164+
} else {
165+
((ObjectNode) n).put("background", "#ffe7e7");
166+
}
167+
}
168+
traverse(n, op);
169+
} else {
170+
// System.out.println(n.toString());
171+
}
172+
}
173+
174+
}
56175
@Override
57176
public List<CaseBackup> getBackupByCaseId(Long caseId, String beginTime, String endTime) {
58-
return caseBackupMapper.selectByCaseId(caseId, transferTime(beginTime), transferTime(endTime));
177+
List<CaseBackup> backupsSrc = caseBackupMapper.selectByCaseId(caseId, transferTime(beginTime), transferTime(endTime));
178+
List<CaseBackup> backups = new ArrayList<>();
179+
String pattern = "\"base\":(\\d+).*";
180+
Pattern r = Pattern.compile(pattern);
181+
Integer compareVersion = 0;
182+
for (CaseBackup cb:backupsSrc) {
183+
Matcher m = r.matcher(cb.getCaseContent());
184+
if (m.find()) {
185+
Integer currentVersion = Integer.valueOf(m.group(1));
186+
if (!currentVersion.equals(compareVersion)) {
187+
backups.add(cb);
188+
compareVersion = currentVersion;
189+
} else {
190+
LOGGER.error("base信息一致。过滤信息。base: " + currentVersion);
191+
}
192+
} else {
193+
LOGGER.error("未找到base信息。用例内容是:" + cb.getCaseContent());
194+
}
195+
}
196+
return backups;
59197
}
60198

61199
@Override

case-server/src/main/resources/com/xiaoju/framework/mapper/CaseBackupMapper.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@
3131
order by id desc
3232
</select>
3333

34+
<select id="selectByBackupId" parameterType="java.lang.Long" resultMap="BaseResultMap">
35+
select
36+
<include refid="Base_Column_List" />
37+
from case_backup
38+
where id = #{id,jdbcType=BIGINT}
39+
</select>
40+
3441
<delete id="updateByCaseId" parameterType="java.lang.Long">
3542
update case_backup set is_delete =1
3643
where case_id = #{case_id,jdbcType=BIGINT} and is_delete = 0

0 commit comments

Comments
 (0)