diff --git a/.gitignore b/.gitignore index a1c2a23..16be3b7 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* + +.idea/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c5c3627 --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +## 禅道java版sdk工具包 +基于禅道开源版18.1封装的java版sdk工具包,对于高版本的是否兼容还需要测试 + +### 功能描述 +利用禅道开放的第三方应用接口,封装的java版sdk工具包,可通过java代码的方式创建项目、执行、任务等常用接口。 +大部分接口是直接使用的禅道开放的接口,小部分接口是通过模拟浏览器的方式实现的。 + +### 免责声明 +SDK源码编写完成后仅简单应用了项目、执行、任务的创建、开始、关闭等功能,未进行大规模测试。 +此仓库的源码是从项目上剥离出来的源码,使用时请备份数据,并进行严格测试,确保安全后再上线使用。 + +### 开发环境 +jdk 8+ + +### 构建工具 +Maven 3+ + +### 编译命令 +``` +mvn package +``` +如果编译报错,可以尝试更换maven版本或使用最新maven版本 + +### 使用说明 +#### 引用方式 +1. 直接引入jar包 +2. 引入源码 + +#### 创建凭证 +使用禅道管理员账号登录,依次找到左侧菜单栏【后台】-【二次开发】-【应用】-【添加应用】 +得到代号+密钥就是接入凭证 + +#### 创建管理账号 +创建一个专门的管理账号,拥有管理员权限。例如我创建的是pms账号 + +#### 使用方法 +参考 ClientTest.java + +##### 版本说明 +###### v0.0.1-SNAPSHOT +1. 项目的创建、删除、修改、开始、激活、关闭 +2. 执行的创建、删除、开始、激活、关闭 +3. 任务的创建、删除、开始、激活、关闭、完成 +4. 用户的获取 + +### 联系方式 +E-Mail:wangbing@wbsite.xyz \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..c1ee6b1 --- /dev/null +++ b/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + + com.tzcmcc.zentao.sdk + zentao-java-sdk + 0.0.1-SNAPSHOT + zentao-java-sdk + zentao-java-sdk + jar + + + UTF-8 + UTF-8 + 1.8 + true + + + + + + aliyun + Aliyun Repository + default + https://maven.aliyun.com/repository/public + + + + + + aliyun + Aliyun Repository + https://maven.aliyun.com/repository/public + default + + + + + + + cn.hutool + hutool-all + 5.8.0.M2 + + + + + org.jsoup + jsoup + 1.10.2 + + + + junit + junit + 4.13.2 + test + + + + + + ${project.artifactId}-${project.version} + + src/main/java + + src/test/java + + diff --git a/src/main/java/xyz/wbsite/zentao/sdk/Constant.java b/src/main/java/xyz/wbsite/zentao/sdk/Constant.java new file mode 100644 index 0000000..087a473 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/Constant.java @@ -0,0 +1,15 @@ +package xyz.wbsite.zentao.sdk; + +/** + * 常用常量 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class Constant { + + public final static String SUCCESS_KEY = "success"; + + public final static String LOGIN_OVERTIME = "登录已超时"; +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/ZentaoClient.java b/src/main/java/xyz/wbsite/zentao/sdk/ZentaoClient.java new file mode 100644 index 0000000..d0badfb --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/ZentaoClient.java @@ -0,0 +1,105 @@ +package xyz.wbsite.zentao.sdk; + +import xyz.wbsite.zentao.sdk.user.ent.ZtUser; +import xyz.wbsite.zentao.sdk.user.req.ZtUserListAllRequest; +import xyz.wbsite.zentao.sdk.user.rsp.ZtUserListAllResponse; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 禅道客户端 + *

+ * 基于开源版本18.1开发 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZentaoClient { + + /** + * 普通禅道账户 + */ + private static Map cache = new ConcurrentHashMap<>(); + + /** + * 普通禅道账户 + */ + private final ZentaoInstance managerInstance; + + + /** + * 禅道服务地址 + */ + private final String serviceUrl; + + /** + * 禅道服务接入code + */ + private final String serviceCode; + + /** + * 禅道服务接入key + */ + private final String serviceKey; + + /** + * 禅道客户端构造器 + * + * @param serviceUrl 禅道服务地址 + * @param serviceCode 禅道服务接入code + * @param serviceKey 禅道服务接入key + * @param managerAccount 管理账户 + */ + public ZentaoClient(String serviceUrl, String serviceCode, String serviceKey, String managerAccount) { + this.serviceUrl = serviceUrl; + this.serviceCode = serviceCode; + this.serviceKey = serviceKey; + this.managerInstance = new ZentaoInstance(this, managerAccount); + } + + /** + * 查询所有账户信息 + *

+ * 要求managerAccount账户有管理员权限 + */ + public List listAllUser() { + ZtUserListAllResponse ztUserListAllResponse = managerInstance.getZtUserService().listAll(new ZtUserListAllRequest()); + if (!ztUserListAllResponse.isSuccess()) { + throw new IllegalArgumentException(ztUserListAllResponse.getMessage()); + } + return ztUserListAllResponse.getResult(); + } + + /** + * 普通账号进入 + */ + public ZentaoInstance loginAs(String account) { + if (cache.containsKey(account)) { + return cache.get(account); + } + cache.put(account, new ZentaoInstance(this, account)); + return cache.get(account); + } + + /** + * 项目管理账号进入 + */ + public ZentaoInstance loginAsPms() { + return managerInstance; + } + + public String getServiceUrl() { + return serviceUrl; + } + + public String getServiceCode() { + return serviceCode; + } + + public String getServiceKey() { + return serviceKey; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/ZentaoInstance.java b/src/main/java/xyz/wbsite/zentao/sdk/ZentaoInstance.java new file mode 100644 index 0000000..1c3e8ed --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/ZentaoInstance.java @@ -0,0 +1,165 @@ +package xyz.wbsite.zentao.sdk; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.http.HttpStatus; +import cn.hutool.http.HttpUtil; +import cn.hutool.log.StaticLog; +import xyz.wbsite.zentao.sdk.execution.ZtExecutionService; +import xyz.wbsite.zentao.sdk.project.ZtProjectService; +import xyz.wbsite.zentao.sdk.task.ZtTaskService; +import xyz.wbsite.zentao.sdk.user.ZtUserService; + +/** + * 禅道客户端实例 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZentaoInstance { + + /** + * 客户端 + */ + private ZentaoClient client; + + /** + * 模拟登录账户 + */ + private String account; + /** + * 登录信息 + */ + private String zentaosid; + private static final int DEFAULT_CONNECT_TIMEOUT = 3 * 1000; + private static final int DEFAULT_READ_TIMEOUT = 10 * 1000; + private final ZtProjectService ztProjectService = new ZtProjectService(this); + private final ZtExecutionService ztExecutionService = new ZtExecutionService(this); + private final ZtTaskService ztTaskService = new ZtTaskService(this); + private final ZtUserService ztUserService = new ZtUserService(this); + + public ZentaoInstance(ZentaoClient client, String account) { + this.client = client; + this.account = account; + } + + public ZtProjectService getZtProjectService() { + return ztProjectService; + } + + public ZtExecutionService getZtExecutionService() { + return ztExecutionService; + } + + public ZtTaskService getZtTaskService() { + return ztTaskService; + } + + public ZtUserService getZtUserService() { + return ztUserService; + } + + private boolean login(String account) { + String time = String.valueOf(System.currentTimeMillis() / 1000); + String token = SecureUtil.md5(client.getServiceCode() + client.getServiceKey() + time); + String url = StrUtil.format(client.getServiceUrl() + "/api.php?m=user&f=apilogin&account={}&code={}&time={}&token={}", account, client.getServiceCode(), time, token); + HttpRequest request = HttpUtil.createGet(url); + HttpResponse response = request.execute(); + if (HttpStatus.HTTP_OK != response.getStatus()) { + System.err.println("请求失败"); + return false; + } else { + this.zentaosid = response.getCookieValue("zentaosid"); + StaticLog.info("禅道登录凭证:{}", this.zentaosid); + } + return true; + } + + /** + * 检查状态 + * + * @return 登录状态是否正常 + */ + public synchronized boolean checkStatus() { + try { + HttpRequest httpRequest = createTestUrl(); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + return false; + } + String body = execute.body(); + String string = Convert.unicodeToStr(body); + if (!StrUtil.contains(string, Constant.LOGIN_OVERTIME)) { + return true; + } + } catch (Exception ignored) { + + } + // 登录状态异常后尝试登录 + return login(account); + } + + public HttpRequest createTestUrl() { + String fullUrl = client.getServiceUrl(); + HttpRequest request = HttpUtil.createGet(fullUrl); + setDefault(request, fullUrl); + request.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"); + request.header("Upgrade-Insecure-Requests", "1"); + return request; + } + + public HttpRequest createGet(String url) { + checkStatus(); + String fullUrl = client.getServiceUrl() + url; + HttpRequest request = HttpUtil.createGet(fullUrl); + setDefault(request, fullUrl); + return request; + } + + public HttpRequest createGetForHtml(String url) { + checkStatus(); + String fullUrl = client.getServiceUrl() + url; + HttpRequest request = HttpUtil.createGet(fullUrl); + setDefault(request, fullUrl); + request.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"); + request.header("Upgrade-Insecure-Requests", "1"); + return request; + } + + public HttpRequest createPost(String url) { + checkStatus(); + String fullUrl = client.getServiceUrl() + url; + HttpRequest request = HttpUtil.createPost(fullUrl); + setDefault(request, fullUrl); + return request; + } + + public HttpRequest createPostForHtml(String url) { + checkStatus(); + String fullUrl = client.getServiceUrl() + url; + HttpRequest request = HttpUtil.createPost(fullUrl); + setDefault(request, fullUrl); + request.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"); + request.header("Upgrade-Insecure-Requests", "1"); + return request; + } + + public void setDefault(HttpRequest request, String url) { + request.setConnectionTimeout(DEFAULT_CONNECT_TIMEOUT); + request.setReadTimeout(DEFAULT_READ_TIMEOUT); + request.header("Accept", "application/json, text/javascript, */*; q=0.01"); + request.header("Accept-Encoding", "gzip, deflate"); + request.header("Accept-Language", "zh-CN,zh;q=0.9"); + request.header("Connection", "keep-alive"); + request.header("Host", client.getServiceUrl().replaceAll("http[s]?://", "")); + request.header("Origin", client.getServiceUrl()); + request.header("Referer", url); + request.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"); + request.header("X-Requested-With", "XMLHttpRequest"); + request.cookie("zentaosid=" + this.zentaosid); + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/execution/ZtExecutionService.java b/src/main/java/xyz/wbsite/zentao/sdk/execution/ZtExecutionService.java new file mode 100644 index 0000000..f1d7c87 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/execution/ZtExecutionService.java @@ -0,0 +1,407 @@ +package xyz.wbsite.zentao.sdk.execution; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpException; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.http.HttpStatus; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import cn.hutool.log.StaticLog; +import xyz.wbsite.zentao.sdk.Constant; +import xyz.wbsite.zentao.sdk.ZentaoInstance; +import xyz.wbsite.zentao.sdk.execution.ent.ZtExecution; +import xyz.wbsite.zentao.sdk.execution.req.ZtExecutionActivateRequest; +import xyz.wbsite.zentao.sdk.execution.req.ZtExecutionCloseRequest; +import xyz.wbsite.zentao.sdk.execution.req.ZtExecutionCreateRequest; +import xyz.wbsite.zentao.sdk.execution.req.ZtExecutionDeleteRequest; +import xyz.wbsite.zentao.sdk.execution.req.ZtExecutionStartRequest; +import xyz.wbsite.zentao.sdk.execution.rsp.ZtExecutionActivateResponse; +import xyz.wbsite.zentao.sdk.execution.rsp.ZtExecutionCloseResponse; +import xyz.wbsite.zentao.sdk.execution.rsp.ZtExecutionCreateResponse; +import xyz.wbsite.zentao.sdk.execution.rsp.ZtExecutionDeleteResponse; +import xyz.wbsite.zentao.sdk.execution.rsp.ZtExecutionGetResponse; +import xyz.wbsite.zentao.sdk.execution.rsp.ZtExecutionStartResponse; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +/** + * 执行/迭代服务 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtExecutionService { + + private ZentaoInstance zentaoInstance; + + public ZtExecutionService(ZentaoInstance zentaoInstance) { + this.zentaoInstance = zentaoInstance; + } + + /** + * 创建执行 + */ + public ZtExecutionCreateResponse create(ZtExecutionCreateRequest projectCreateRequest) { + ZtExecutionCreateResponse response = new ZtExecutionCreateResponse(); + try { + String url = StrUtil.format("/execution-create-{}-0-0-productID=0,branchID=0.json", projectCreateRequest.getProject()); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createPost(url); + httpRequest.form("project", projectCreateRequest.getProject()); + httpRequest.form("name", projectCreateRequest.getName()); + httpRequest.form("code", projectCreateRequest.getCode()); + httpRequest.form("begin", projectCreateRequest.getBegin()); + httpRequest.form("end", projectCreateRequest.getEnd()); + httpRequest.form("delta", projectCreateRequest.getDelta()); + httpRequest.form("days", projectCreateRequest.getDays()); + httpRequest.form("lifetime", projectCreateRequest.getLifetime()); + httpRequest.form("status", "wait"); + httpRequest.form("plans[][]", ""); + httpRequest.form("team", projectCreateRequest.getTeam()); + httpRequest.form("teams", projectCreateRequest.getTeams()); + httpRequest.form("PO", projectCreateRequest.getPo()); + httpRequest.form("QD", projectCreateRequest.getQd()); + httpRequest.form("PM", projectCreateRequest.getPm()); + httpRequest.form("RD", projectCreateRequest.getRd()); + for (String teamMember : projectCreateRequest.getTeamMembers()) { + httpRequest.form("teamMembers[]", teamMember); + } + httpRequest.form("desc", projectCreateRequest.getDesc()); + httpRequest.form("acl", projectCreateRequest.getAcl()); + httpRequest.form("uid", RandomUtil.randomString(13)); + + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = Convert.unicodeToStr(execute.body()); + // 返回 {"result":"success","message":"保存成功","id":"366"} + StaticLog.info(body); + if (body.contains(Constant.SUCCESS_KEY)) { + JSONObject entries = JSONUtil.parseObj(body); + response.setId(Convert.toInt(entries.get("id"))); + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } + } catch (HttpException e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 关闭执行 + */ + public ZtExecutionStartResponse start(ZtExecutionStartRequest projectStartRequest) { + ZtExecutionStartResponse response = new ZtExecutionStartResponse(); + try { + String url = StrUtil.format("/execution-start-{}.json", projectStartRequest.getExecutionId()); + StaticLog.info(url); + HttpRequest request = zentaoInstance.createPost(url); + request.form("status", "doing"); + request.form("realBegan", projectStartRequest.getRealBegan()); + request.form("comment", projectStartRequest.getComment()); + request.form("uid", RandomUtil.randomString(13)); + HttpResponse execute = request.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = Convert.unicodeToStr(execute.body()); + StaticLog.info(body); + // 返回的是html + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } catch (HttpException e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 关闭执行 + */ + public ZtExecutionCloseResponse close(ZtExecutionCloseRequest projectCloseRequest) { + ZtExecutionCloseResponse response = new ZtExecutionCloseResponse(); + try { + String url = StrUtil.format("/execution-close-{}.html", projectCloseRequest.getExecutionId()); + StaticLog.info(url); + HttpRequest request = zentaoInstance.createPost(url); + request.form("status", "closed"); + request.form("realEnd", projectCloseRequest.getRealEnd()); + request.form("comment", projectCloseRequest.getComment()); + request.form("uid", RandomUtil.randomString(13)); + HttpResponse execute = request.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = execute.body(); + StaticLog.info(Convert.unicodeToStr(body)); + // 返回的是html + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } catch (Exception e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 激活执行 + */ + public ZtExecutionActivateResponse activate(ZtExecutionActivateRequest projectActivateRequest) { + ZtExecutionActivateResponse response = new ZtExecutionActivateResponse(); + try { + String url = StrUtil.format("/execution-close-{}.html", projectActivateRequest.getExecutionId()); + StaticLog.info(url); + HttpRequest request = zentaoInstance.createPost(url); + request.form("begin", projectActivateRequest.getBegin()); + request.form("end", projectActivateRequest.getEnd()); + request.form("readjustTime", projectActivateRequest.getReadjustTime()); + request.form("status", "doing"); + request.form("comment", projectActivateRequest.getComment()); + request.form("uid", RandomUtil.randomString(13)); + HttpResponse execute = request.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = execute.body(); + StaticLog.info(Convert.unicodeToStr(body)); + // 返回的是html + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } catch (Exception e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 激活执行 + */ + public ZtExecutionDeleteResponse delete(ZtExecutionDeleteRequest projectDeleteRequest) { + ZtExecutionDeleteResponse response = new ZtExecutionDeleteResponse(); + try { + String url = StrUtil.format("/execution-delete-{}.html", projectDeleteRequest.getExecutionId()); + StaticLog.info(url); + HttpRequest request = zentaoInstance.createPost(url); + HttpResponse execute = request.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = execute.body(); + StaticLog.info(Convert.unicodeToStr(body)); + // 返回的是html + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } catch (Exception e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 设置查询条件 + *

+ * 禅道查询条件是设置在session中的,所有查询之前先设置参数 + */ + private boolean setQuery(int projectId, String fieldName, String fieldValue) { + try { + String url = StrUtil.format("/search-buildQuery.html"); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createPost(url); + httpRequest.form("fieldname", ""); + httpRequest.form("fieldid", ""); + httpRequest.form("fieldstatus", "0"); + httpRequest.form("fieldproject", "0"); + httpRequest.form("fieldPM", ""); + httpRequest.form("fieldopenedBy", ""); + httpRequest.form("fieldopenedDate", ""); + httpRequest.form("fieldbegin", ""); + httpRequest.form("fieldend", ""); + httpRequest.form("fieldrealBegan", ""); + httpRequest.form("fieldrealEnd", ""); + httpRequest.form("fieldclosedBy", ""); + httpRequest.form("fieldlastEditedDate", ""); + httpRequest.form("fieldclosedDate", ""); + httpRequest.form("fieldteamCount", ""); + httpRequest.form("andOr1", "AND"); + httpRequest.form("field1", fieldName); + httpRequest.form("operator1", "="); + httpRequest.form("value1", fieldValue); + httpRequest.form("andOr2", "and"); + httpRequest.form("field2", "id"); + httpRequest.form("operator2", "="); + httpRequest.form("value2", ""); + httpRequest.form("andOr3", "and"); + httpRequest.form("field3", "status"); + httpRequest.form("operator3", "="); + httpRequest.form("value3", "0"); + httpRequest.form("groupAndOr", "and"); + httpRequest.form("andOr4", "AND"); + httpRequest.form("field4", "project"); + httpRequest.form("operator4", "="); + httpRequest.form("value4", projectId); + httpRequest.form("andOr5", "and"); + httpRequest.form("field5", "PM"); + httpRequest.form("operator5", "="); + httpRequest.form("value5", ""); + httpRequest.form("andOr6", "and"); + httpRequest.form("field6", "openedBy"); + httpRequest.form("operator6", "="); + httpRequest.form("value6", ""); + httpRequest.form("module", "execution"); + httpRequest.form("actionURL", "/execution-all-bySearch-order_asc-0-myQueryID.html"); + httpRequest.form("groupItems", "3"); + httpRequest.form("formType", "lite"); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + return false; + } + String body = Convert.unicodeToStr(execute.body()); + StaticLog.info(body); + return execute.getStatus() == HttpStatus.HTTP_OK; + } catch (Exception e) { + StaticLog.error(e); + } + return false; + } + + /** + * 通过执行名称获取执行 + */ + public ZtExecutionGetResponse getByName(int projectId, String name) { + ZtExecutionGetResponse response = new ZtExecutionGetResponse(); + try { + boolean setQuery = setQuery(projectId, "name", name); + if (!setQuery) { + response.setSuccess(false); + response.setMessage("设置查询参数失败"); + return response; + } + HttpRequest httpRequest = zentaoInstance.createGetForHtml("/execution-all-bySearch-order_asc-0-myQueryID.html"); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = execute.body(); + Document parse = Jsoup.parse(body); + Elements trs = parse.select(".main-table .sortable tr"); + if (trs.size() == 1) { + Element tr = trs.get(0); + ZtExecution ztExecution = new ZtExecution(); + ztExecution.setId(Convert.toInt(tr.select(".c-id").text())); + ztExecution.setName(tr.select(".c-name").attr("title")); + ztExecution.setCode(tr.select(".c-code").attr("title")); + ztExecution.setProjectId(projectId); + ztExecution.setProjectName(tr.select(".c-project").attr("title")); + ztExecution.setPm(tr.select(".c-PM").text()); + ztExecution.setStatus(tr.select(".c-status").text()); + ztExecution.setProgress(tr.select(".c-progress").text()); + ztExecution.setBegin(tr.select(".c-begin").text()); + ztExecution.setEnd(tr.select(".c-end").text()); + ztExecution.setEstimate(tr.select(".c-estimate").text()); + ztExecution.setConsumed(tr.select(".c-consumed").text()); + ztExecution.setLeft(tr.select(".c-left").text()); + response.setSuccess(true); + response.setMessage("请求成功"); + response.setResult(ztExecution); + return response; + } + StaticLog.info(body); + response.setMessage("无数据"); + return response; + } catch (HttpException e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 通过项目编码获取项目 + */ + public ZtExecutionGetResponse getByCode(int projectId, String code) { + ZtExecutionGetResponse response = new ZtExecutionGetResponse(); + try { + boolean setQuery = setQuery(projectId, "code", code); + if (!setQuery) { + response.setSuccess(false); + response.setMessage("设置查询参数失败"); + return response; + } + HttpRequest httpRequest = zentaoInstance.createGetForHtml("/execution-all-bySearch-order_asc-0-myQueryID.html"); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = execute.body(); + Document parse = Jsoup.parse(body); + Elements trs = parse.select(".main-table .sortable tr"); + if (trs.size() == 1) { + Element tr = trs.get(0); + ZtExecution ztExecution = new ZtExecution(); + ztExecution.setId(Convert.toInt(tr.select(".c-id").text())); + ztExecution.setName(tr.select(".c-name").attr("title")); + ztExecution.setCode(tr.select(".c-code").attr("title")); + ztExecution.setProjectId(projectId); + ztExecution.setProjectName(tr.select(".c-project").attr("title")); + ztExecution.setPm(tr.select(".c-PM").text()); + ztExecution.setStatus(tr.select(".c-status").text()); + ztExecution.setProgress(tr.select(".c-progress").text()); + ztExecution.setBegin(tr.select(".c-begin").text()); + ztExecution.setEnd(tr.select(".c-end").text()); + ztExecution.setEstimate(tr.select(".c-estimate").text()); + ztExecution.setConsumed(tr.select(".c-consumed").text()); + ztExecution.setLeft(tr.select(".c-left").text()); + response.setSuccess(true); + response.setMessage("请求成功"); + response.setResult(ztExecution); + return response; + } + StaticLog.info(body); + response.setMessage("无数据"); + return response; + } catch (HttpException e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/execution/ent/ZtExecution.java b/src/main/java/xyz/wbsite/zentao/sdk/execution/ent/ZtExecution.java new file mode 100644 index 0000000..cce6cb4 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/execution/ent/ZtExecution.java @@ -0,0 +1,168 @@ +package xyz.wbsite.zentao.sdk.execution.ent; + +/** + * 禅道执行信息 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtExecution { + + /** + * 执行ID + */ + private int id; + /** + * 执行名称 + */ + private String name; + /** + * 执行代号 + */ + private String code; + /** + * 项目ID + */ + private int projectId; + /** + * 项目名称 + */ + private String projectName; + /** + * 执行产品经理 + */ + private String pm; + /** + * 执行状态 + */ + private String status; + /** + * 进度 + */ + private String progress; + /** + * 计划开始时间 + */ + private String begin; + /** + * 计划完成时间 + */ + private String end; + /** + * 预计工时 + */ + private String estimate; + /** + * 消耗工时 + */ + private String consumed; + /** + * 剩余工时 + */ + private String left; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public int getProjectId() { + return projectId; + } + + public void setProjectId(int projectId) { + this.projectId = projectId; + } + + public String getProjectName() { + return projectName; + } + + public void setProjectName(String projectName) { + this.projectName = projectName; + } + + public String getPm() { + return pm; + } + + public void setPm(String pm) { + this.pm = pm; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getProgress() { + return progress; + } + + public void setProgress(String progress) { + this.progress = progress; + } + + public String getBegin() { + return begin; + } + + public void setBegin(String begin) { + this.begin = begin; + } + + public String getEnd() { + return end; + } + + public void setEnd(String end) { + this.end = end; + } + + public String getEstimate() { + return estimate; + } + + public void setEstimate(String estimate) { + this.estimate = estimate; + } + + public String getConsumed() { + return consumed; + } + + public void setConsumed(String consumed) { + this.consumed = consumed; + } + + public String getLeft() { + return left; + } + + public void setLeft(String left) { + this.left = left; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/execution/req/ZtExecutionActivateRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/execution/req/ZtExecutionActivateRequest.java new file mode 100644 index 0000000..0593279 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/execution/req/ZtExecutionActivateRequest.java @@ -0,0 +1,64 @@ +package xyz.wbsite.zentao.sdk.execution.req; + +/** + * 禅道执行激活请求 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtExecutionActivateRequest { + + private int executionId; + + private String begin; + + private String end; + + /** + * 是否重新调整时间 0/1 + */ + private String readjustTime; + + private String comment; + + public int getExecutionId() { + return executionId; + } + + public void setExecutionId(int executionId) { + this.executionId = executionId; + } + + public String getBegin() { + return begin; + } + + public void setBegin(String begin) { + this.begin = begin; + } + + public String getEnd() { + return end; + } + + public void setEnd(String end) { + this.end = end; + } + + public String getReadjustTime() { + return readjustTime; + } + + public void setReadjustTime(String readjustTime) { + this.readjustTime = readjustTime; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/execution/req/ZtExecutionCloseRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/execution/req/ZtExecutionCloseRequest.java new file mode 100644 index 0000000..7a6ee4a --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/execution/req/ZtExecutionCloseRequest.java @@ -0,0 +1,41 @@ +package xyz.wbsite.zentao.sdk.execution.req; + +/** + * 禅道执行关闭请求 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtExecutionCloseRequest { + + private int executionId; + + private String comment; + + private String realEnd; + + public int getExecutionId() { + return executionId; + } + + public void setExecutionId(int executionId) { + this.executionId = executionId; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public String getRealEnd() { + return realEnd; + } + + public void setRealEnd(String realEnd) { + this.realEnd = realEnd; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/execution/req/ZtExecutionCreateRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/execution/req/ZtExecutionCreateRequest.java new file mode 100644 index 0000000..05e2c32 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/execution/req/ZtExecutionCreateRequest.java @@ -0,0 +1,222 @@ +package xyz.wbsite.zentao.sdk.execution.req; + +import java.util.List; + +/** + * 禅道执行创建请求 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtExecutionCreateRequest { + + private int project; + private String name; + private String code; + /** + * 开始日期2023-11-09 + */ + private String begin; + /** + * 结束日期2024-11-07 + */ + private String end; + /** + * 总耗时天数 + */ + private int delta; + /** + * 可用工作日 + */ + private int days; + /** + * 执行类型short/long/ops + */ + private String lifetime; + /** + * 团队名称可空 + */ + private String team; + /** + * 需要复制得团队,和团队名称必填一个 + * 值为zt_project的id + */ + private int teams; + /** + * 需求负责人 + */ + private String po; + /** + * 测试负责人 + */ + private String qd; + /** + * 迭代负责人 + */ + private String pm; + /** + * 发布负责人 + */ + private String rd; + /** + * 团队成员 + */ + private List teamMembers; + /** + * 执行描述 + */ + private String desc; + /** + * 访问控制private/open + */ + private String acl; + /** + * 权限控制extend/reset + */ + private String auth; + + public int getProject() { + return project; + } + + public void setProject(int project) { + this.project = project; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getBegin() { + return begin; + } + + public void setBegin(String begin) { + this.begin = begin; + } + + public String getEnd() { + return end; + } + + public void setEnd(String end) { + this.end = end; + } + + public int getDelta() { + return delta; + } + + public void setDelta(int delta) { + this.delta = delta; + } + + public int getDays() { + return days; + } + + public void setDays(int days) { + this.days = days; + } + + public String getLifetime() { + return lifetime; + } + + public void setLifetime(String lifetime) { + this.lifetime = lifetime; + } + + public String getTeam() { + return team; + } + + public void setTeam(String team) { + this.team = team; + } + + public int getTeams() { + return teams; + } + + public void setTeams(int teams) { + this.teams = teams; + } + + public String getPo() { + return po; + } + + public void setPo(String po) { + this.po = po; + } + + public String getQd() { + return qd; + } + + public void setQd(String qd) { + this.qd = qd; + } + + public String getPm() { + return pm; + } + + public void setPm(String pm) { + this.pm = pm; + } + + public String getRd() { + return rd; + } + + public void setRd(String rd) { + this.rd = rd; + } + + public List getTeamMembers() { + return teamMembers; + } + + public void setTeamMembers(List teamMembers) { + this.teamMembers = teamMembers; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public String getAcl() { + return acl; + } + + public void setAcl(String acl) { + this.acl = acl; + } + + public String getAuth() { + return auth; + } + + public void setAuth(String auth) { + this.auth = auth; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/execution/req/ZtExecutionDeleteRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/execution/req/ZtExecutionDeleteRequest.java new file mode 100644 index 0000000..56559f9 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/execution/req/ZtExecutionDeleteRequest.java @@ -0,0 +1,21 @@ +package xyz.wbsite.zentao.sdk.execution.req; + +/** + * 禅道执行删除请求 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtExecutionDeleteRequest { + + private int executionId; + + public int getExecutionId() { + return executionId; + } + + public void setExecutionId(int executionId) { + this.executionId = executionId; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/execution/req/ZtExecutionStartRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/execution/req/ZtExecutionStartRequest.java new file mode 100644 index 0000000..2213b1d --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/execution/req/ZtExecutionStartRequest.java @@ -0,0 +1,41 @@ +package xyz.wbsite.zentao.sdk.execution.req; + +/** + * 禅道执行启动请求 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtExecutionStartRequest { + + private int executionId; + + private String comment; + + private String realBegan; + + public int getExecutionId() { + return executionId; + } + + public void setExecutionId(int executionId) { + this.executionId = executionId; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public String getRealBegan() { + return realBegan; + } + + public void setRealBegan(String realBegan) { + this.realBegan = realBegan; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionActivateResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionActivateResponse.java new file mode 100644 index 0000000..24a450b --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionActivateResponse.java @@ -0,0 +1,36 @@ +package xyz.wbsite.zentao.sdk.execution.rsp; + +/** + * 禅道执行激活响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtExecutionActivateResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionCloseResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionCloseResponse.java new file mode 100644 index 0000000..8ca0694 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionCloseResponse.java @@ -0,0 +1,36 @@ +package xyz.wbsite.zentao.sdk.execution.rsp; + +/** + * 禅道执行关闭响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtExecutionCloseResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionCreateResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionCreateResponse.java new file mode 100644 index 0000000..dd28ddf --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionCreateResponse.java @@ -0,0 +1,48 @@ +package xyz.wbsite.zentao.sdk.execution.rsp; + +/** + * 禅道执行创建响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtExecutionCreateResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + /** + * 执行id + */ + private int id; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionDeleteResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionDeleteResponse.java new file mode 100644 index 0000000..c548564 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionDeleteResponse.java @@ -0,0 +1,36 @@ +package xyz.wbsite.zentao.sdk.execution.rsp; + +/** + * 禅道执行删除响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtExecutionDeleteResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionGetResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionGetResponse.java new file mode 100644 index 0000000..c0109e0 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionGetResponse.java @@ -0,0 +1,50 @@ +package xyz.wbsite.zentao.sdk.execution.rsp; + +import xyz.wbsite.zentao.sdk.execution.ent.ZtExecution; + +/** + * 检索执行 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtExecutionGetResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + /** + * 执行 + */ + private ZtExecution result; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public ZtExecution getResult() { + return result; + } + + public void setResult(ZtExecution result) { + this.result = result; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionStartResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionStartResponse.java new file mode 100644 index 0000000..2ee4484 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/execution/rsp/ZtExecutionStartResponse.java @@ -0,0 +1,36 @@ +package xyz.wbsite.zentao.sdk.execution.rsp; + +/** + * 禅道执行启动响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtExecutionStartResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/project/ZtProjectService.java b/src/main/java/xyz/wbsite/zentao/sdk/project/ZtProjectService.java new file mode 100644 index 0000000..1feacdb --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/project/ZtProjectService.java @@ -0,0 +1,443 @@ +package xyz.wbsite.zentao.sdk.project; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpException; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.http.HttpStatus; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import cn.hutool.log.StaticLog; +import xyz.wbsite.zentao.sdk.Constant; +import xyz.wbsite.zentao.sdk.ZentaoInstance; +import xyz.wbsite.zentao.sdk.project.ent.ZtProject; +import xyz.wbsite.zentao.sdk.project.req.ZtProjectActivateRequest; +import xyz.wbsite.zentao.sdk.project.req.ZtProjectCloseRequest; +import xyz.wbsite.zentao.sdk.project.req.ZtProjectCreateRequest; +import xyz.wbsite.zentao.sdk.project.req.ZtProjectDeleteRequest; +import xyz.wbsite.zentao.sdk.project.req.ZtProjectEditRequest; +import xyz.wbsite.zentao.sdk.project.req.ZtProjectStartRequest; +import xyz.wbsite.zentao.sdk.project.rsp.ZtProjectActivateResponse; +import xyz.wbsite.zentao.sdk.project.rsp.ZtProjectCloseResponse; +import xyz.wbsite.zentao.sdk.project.rsp.ZtProjectCreateResponse; +import xyz.wbsite.zentao.sdk.project.rsp.ZtProjectDeleteResponse; +import xyz.wbsite.zentao.sdk.project.rsp.ZtProjectEditResponse; +import xyz.wbsite.zentao.sdk.project.rsp.ZtProjectGetResponse; +import xyz.wbsite.zentao.sdk.project.rsp.ZtProjectStartResponse; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +/** + * 禅道项目接口服务 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtProjectService { + + private ZentaoInstance zentaoInstance; + + public ZtProjectService(ZentaoInstance zentaoInstance) { + this.zentaoInstance = zentaoInstance; + } + + /** + * 创建项目 + */ + public ZtProjectCreateResponse create(ZtProjectCreateRequest request) { + ZtProjectCreateResponse response = new ZtProjectCreateResponse(); + try { + String url = StrUtil.format("/project-create-{}-0-0-productID=0,branchID=0.json", request.getModel()); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createPost(url); + httpRequest.contentType("application/x-www-form-urlencoded; charset=UTF-8"); + httpRequest.form("parent", request.getParent()); + httpRequest.form("name", request.getName()); + httpRequest.form("code", request.getCode()); + httpRequest.form("multiple", request.getMultiple()); + httpRequest.form("hasProduct", request.getHasProduct()); + httpRequest.form("PM", request.getPm()); + httpRequest.form("budget", NumberUtil.decimalFormat("#.00", Convert.toDouble(request.getBudget(), 0D))); + httpRequest.form("budgetUnit", request.getBudgetUnit()); + httpRequest.form("begin", request.getBegin()); + httpRequest.form("end", request.getEnd()); + httpRequest.form("days", request.getDays()); + httpRequest.form("products[0]", request.getProducts()); + httpRequest.form("productName", request.getProductName()); + httpRequest.form("desc", request.getDesc()); + httpRequest.form("acl", request.getAcl()); + httpRequest.form("auth", request.getAuth()); + httpRequest.form("model", request.getModel()); + httpRequest.form("uid", RandomUtil.randomString(13)); + + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = Convert.unicodeToStr(execute.body()); + //{"result":"success","message":"保存成功","id":"355"} + StaticLog.info(body); + if (body.contains(Constant.SUCCESS_KEY)) { + JSONObject entries = JSONUtil.parseObj(body); + response.setId(Convert.toInt(entries.get("id"))); + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } + } catch (HttpException e) { + throw new RuntimeException(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 更新项目 + */ + public ZtProjectEditResponse edit(ZtProjectEditRequest request) { + ZtProjectEditResponse response = new ZtProjectEditResponse(); + try { + String url = StrUtil.format("/project-edit-{}-view.json", request.getId()); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createPostForHtml(url); + httpRequest.form("parent", request.getParent()); + httpRequest.form("name", request.getName()); + httpRequest.form("code", request.getCode()); + httpRequest.form("PM", request.getPm()); + httpRequest.form("budget", NumberUtil.decimalFormat("#.00", Convert.toDouble(request.getBudget(), 0D))); + httpRequest.form("budgetUnit", request.getBudgetUnit()); + httpRequest.form("future", request); + httpRequest.form("begin", request.getBegin()); + httpRequest.form("end", request.getEnd()); + httpRequest.form("days", request.getDays()); + httpRequest.form("desc", request.getDesc()); + httpRequest.form("acl", request.getAcl()); + httpRequest.form("auth", request.getAuth()); + httpRequest.form("model", request.getModel()); + httpRequest.form("delta", request.getDelta()); + httpRequest.form("uid", RandomUtil.randomString(13)); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = Convert.unicodeToStr(execute.body()); + //{"result":"success","message":"保存成功","locate":"/project-view-363.json"} + StaticLog.info(body); + if (body.contains(Constant.SUCCESS_KEY)) { + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } + } catch (Exception e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 启动项目 + */ + public ZtProjectStartResponse start(ZtProjectStartRequest request) { + ZtProjectStartResponse response = new ZtProjectStartResponse(); + try { + String url = StrUtil.format("/project-start-{}.html", request.getProjectId()); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createPost(url); + httpRequest.form("status", "doing"); + httpRequest.form("realBegan", request.getRealBegan()); + httpRequest.form("comment", request.getComment()); + httpRequest.form("uid", RandomUtil.randomString(13)); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = Convert.unicodeToStr(execute.body()); + StaticLog.info(body); + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } catch (Exception e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 关闭项目 + */ + public ZtProjectCloseResponse close(ZtProjectCloseRequest request) { + ZtProjectCloseResponse response = new ZtProjectCloseResponse(); + try { + String url = StrUtil.format("/project-close-{}.html", request.getProjectId()); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createPost(url); + httpRequest.form("status", "closed"); + httpRequest.form("realEnd", request.getRealEnd()); + httpRequest.form("comment", request.getComment()); + httpRequest.form("uid", RandomUtil.randomString(13)); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = Convert.unicodeToStr(execute.body()); + StaticLog.info(body); + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } catch (Exception e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 激活项目 + */ + public ZtProjectActivateResponse activate(ZtProjectActivateRequest request) { + ZtProjectActivateResponse response = new ZtProjectActivateResponse(); + try { + String url = StrUtil.format("/project-close-{}.html", request.getProjectId()); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createPost(url); + httpRequest.form("begin", request.getBegin()); + httpRequest.form("end", request.getEnd()); + httpRequest.form("readjustTime", request.getReadjustTime()); + httpRequest.form("status", "doing"); + httpRequest.form("comment", request.getComment()); + httpRequest.form("uid", RandomUtil.randomString(13)); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = Convert.unicodeToStr(execute.body()); + StaticLog.info(body); + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } catch (Exception e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 删除项目 + */ + public ZtProjectDeleteResponse delete(ZtProjectDeleteRequest request) { + ZtProjectDeleteResponse response = new ZtProjectDeleteResponse(); + try { + String url = StrUtil.format("/project-delete-{}-yes-browse.html", request.getProjectId()); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createPost(url); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = Convert.unicodeToStr(execute.body()); + StaticLog.info(body); + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } catch (Exception e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 设置查询条件 + *

+ * 禅道查询条件是设置在session中的,所有查询之前先设置参数 + */ + private boolean setQuery(String fieldName, String fieldValue) { + try { + String url = StrUtil.format("/search-buildQuery.html"); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createPost(url); + httpRequest.form("fieldname", ""); + httpRequest.form("fieldcode", ""); + httpRequest.form("fieldid", ""); + httpRequest.form("fieldmodel", ""); + httpRequest.form("fieldhasProduct", ""); + httpRequest.form("fieldparent", "0"); + httpRequest.form("fieldstatus", ""); + httpRequest.form("fielddesc", ""); + httpRequest.form("fieldPM", ""); + httpRequest.form("fieldopenedDate", ""); + httpRequest.form("fieldbegin", ""); + httpRequest.form("fieldend", ""); + httpRequest.form("fieldrealBegan", ""); + httpRequest.form("fieldrealEnd", ""); + httpRequest.form("fieldopenedBy", ""); + httpRequest.form("fieldclosedBy", ""); + httpRequest.form("fieldlastEditedDate", ""); + httpRequest.form("fieldclosedDate", ""); + httpRequest.form("andOr1", "AND"); + httpRequest.form("field1", fieldName); + httpRequest.form("operator1", "="); + httpRequest.form("value1", fieldValue); + httpRequest.form("andOr2", "and"); + httpRequest.form("field2", "code"); + httpRequest.form("operator2", "="); + httpRequest.form("value2", ""); + httpRequest.form("andOr3", "and"); + httpRequest.form("field3", "id"); + httpRequest.form("operator3", "="); + httpRequest.form("value3", ""); + httpRequest.form("groupAndOr", "and"); + httpRequest.form("andOr4", "AND"); + httpRequest.form("field4", "model"); + httpRequest.form("operator4", "="); + httpRequest.form("value4", ""); + httpRequest.form("andOr5", "and"); + httpRequest.form("field5", "hasProduct"); + httpRequest.form("operator5", "="); + httpRequest.form("value5", ""); + httpRequest.form("andOr6", "and"); + httpRequest.form("field6", "parent"); + httpRequest.form("operator6", "="); + httpRequest.form("value6", 0); + httpRequest.form("module", "project"); + httpRequest.form("actionURL", "/project-browse-0-bySearch-myQueryID.html"); + httpRequest.form("groupItems", "3"); + httpRequest.form("formType", "lite"); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + return false; + } + String body = Convert.unicodeToStr(execute.body()); + StaticLog.info(body); + return execute.getStatus() == HttpStatus.HTTP_OK; + } catch (Exception e) { + StaticLog.error(e); + } + return false; + } + + /** + * 通过项目名称获取项目 + */ + public ZtProjectGetResponse getByName(String name) { + ZtProjectGetResponse response = new ZtProjectGetResponse(); + try { + boolean setQuery = setQuery("name", name); + if (!setQuery) { + response.setSuccess(false); + response.setMessage("设置查询参数失败"); + return response; + } + HttpRequest httpRequest = zentaoInstance.createGetForHtml("/project-browse-0-bySearch-myQueryID.html"); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = execute.body(); + Document parse = Jsoup.parse(body); + Elements trs = parse.select(".main-table .sortable tr"); + if (trs.size() == 1) { + Element tr = trs.get(0); + ZtProject ztProject = new ZtProject(); + ztProject.setId(Convert.toInt(tr.select(".c-id").text())); + ztProject.setName(tr.select(".c-name").attr("title")); + ztProject.setStatus(tr.select(".c-status").text()); + ztProject.setPm(tr.select(".c-PM").text()); + ztProject.setBudget(tr.select(".c-budget").text()); + ztProject.setBegin(tr.select(".c-begin").text()); + ztProject.setEnd(tr.select(".c-end").text()); + ztProject.setProgress(tr.select(".c-progress").text()); + response.setSuccess(true); + response.setMessage("请求成功"); + response.setResult(ztProject); + return response; + } + StaticLog.info(body); + response.setMessage("无数据"); + return response; + } catch (HttpException e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 通过项目编码获取项目 + */ + public ZtProjectGetResponse getByCode(String code) { + ZtProjectGetResponse response = new ZtProjectGetResponse(); + try { + boolean setQuery = setQuery("code", code); + if (!setQuery) { + response.setSuccess(false); + response.setMessage("设置查询参数失败"); + return response; + } + HttpRequest httpRequest = zentaoInstance.createGetForHtml("/project-browse-0-bySearch-myQueryID.html"); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = execute.body(); + Document parse = Jsoup.parse(body); + Elements trs = parse.select(".main-table .sortable tr"); + if (trs.size() == 1) { + Element tr = trs.get(0); + ZtProject ztProject = new ZtProject(); + ztProject.setId(Convert.toInt(tr.select(".c-id").text())); + ztProject.setName(tr.select(".c-name").attr("title")); + ztProject.setStatus(tr.select(".c-status").text()); + ztProject.setPm(tr.select(".c-PM").text()); + ztProject.setBudget(tr.select(".c-budget").text()); + ztProject.setBegin(tr.select(".c-begin").text()); + ztProject.setEnd(tr.select(".c-end").text()); + ztProject.setProgress(tr.select(".c-progress").text()); + response.setSuccess(true); + response.setMessage("请求成功"); + response.setResult(ztProject); + return response; + } + StaticLog.info(body); + response.setMessage("无数据"); + return response; + } catch (HttpException e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/project/ent/ZtProject.java b/src/main/java/xyz/wbsite/zentao/sdk/project/ent/ZtProject.java new file mode 100644 index 0000000..3d9b6c9 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/project/ent/ZtProject.java @@ -0,0 +1,108 @@ +package xyz.wbsite.zentao.sdk.project.ent; + +/** + * 禅道项目信息 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtProject { + + /** + * 项目ID + */ + private int id; + /** + * 项目名称 + */ + private String name; + /** + * 项目状态 + */ + private String status; + /** + * 项目产品经理 + */ + private String pm; + /** + * 预算 + */ + private String budget; + /** + * 计划开始时间 + */ + private String begin; + /** + * 计划完成时间 + */ + private String end; + /** + * 进度 + */ + private String progress; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getPm() { + return pm; + } + + public void setPm(String pm) { + this.pm = pm; + } + + public String getBudget() { + return budget; + } + + public void setBudget(String budget) { + this.budget = budget; + } + + public String getBegin() { + return begin; + } + + public void setBegin(String begin) { + this.begin = begin; + } + + public String getEnd() { + return end; + } + + public void setEnd(String end) { + this.end = end; + } + + public String getProgress() { + return progress; + } + + public void setProgress(String progress) { + this.progress = progress; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectActivateRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectActivateRequest.java new file mode 100644 index 0000000..a767081 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectActivateRequest.java @@ -0,0 +1,65 @@ +package xyz.wbsite.zentao.sdk.project.req; + +/** + * 禅道项目激活请求 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtProjectActivateRequest { + + private int projectId; + + private String begin; + + private String end; + + /** + * 是否重新调整时间 0/1 + */ + private String readjustTime; + + private String comment; + + + public int getProjectId() { + return projectId; + } + + public void setProjectId(int projectId) { + this.projectId = projectId; + } + + public String getBegin() { + return begin; + } + + public void setBegin(String begin) { + this.begin = begin; + } + + public String getEnd() { + return end; + } + + public void setEnd(String end) { + this.end = end; + } + + public String getReadjustTime() { + return readjustTime; + } + + public void setReadjustTime(String readjustTime) { + this.readjustTime = readjustTime; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectCloseRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectCloseRequest.java new file mode 100644 index 0000000..f20b889 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectCloseRequest.java @@ -0,0 +1,41 @@ +package xyz.wbsite.zentao.sdk.project.req; + +/** + * 禅道项目关闭请求 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtProjectCloseRequest { + + private int projectId; + + private String comment; + + private String realEnd; + + public int getProjectId() { + return projectId; + } + + public void setProjectId(int projectId) { + this.projectId = projectId; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public String getRealEnd() { + return realEnd; + } + + public void setRealEnd(String realEnd) { + this.realEnd = realEnd; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectCreateRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectCreateRequest.java new file mode 100644 index 0000000..c8806fc --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectCreateRequest.java @@ -0,0 +1,229 @@ +package xyz.wbsite.zentao.sdk.project.req; + + +/** + * 禅道项目创建请求 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtProjectCreateRequest { + + /** + * 父项目 + */ + private String parent; + /** + * 项目名称 + */ + private String name; + /** + * 项目代号 + */ + private String code; + /** + * 启用迭代(0:不启用,1:启用) + */ + private String multiple; + /** + * 是否产品型项目(0:没有关联产品,1:关联产品) + */ + private String hasProduct; + /** + * 产品经理账户 + */ + private String pm; + /** + * 预算(金额) + */ + private String budget; + /** + * 预算单位CNY + */ + private String budgetUnit; + /** + * 预算待定(值为空或1) + */ + private String future; + /** + * 项目开始时间 yyyy-MM-dd + */ + private String begin; + /** + * 项目结束时间 yyyy-MM-dd + */ + private String end; + /** + * 可用工作日 + */ + private int days; + /** + * 关联产品 + */ + private String products; + /** + * 关联产品名称 + */ + private String productName; + /** + * 项目描述 + */ + private String desc; + /** + * 访问控制private/open + */ + private String acl; + /** + * 权限控制extend/reset + */ + private String auth; + /** + * 项目管理方式scrum/waterfall/kanban + */ + private String model; + + public String getParent() { + return parent; + } + + public void setParent(String parent) { + this.parent = parent; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getMultiple() { + return multiple; + } + + public void setMultiple(String multiple) { + this.multiple = multiple; + } + + public String getHasProduct() { + return hasProduct; + } + + public void setHasProduct(String hasProduct) { + this.hasProduct = hasProduct; + } + + public String getPm() { + return pm; + } + + public void setPm(String pm) { + this.pm = pm; + } + + public String getBudget() { + return budget; + } + + public void setBudget(String budget) { + this.budget = budget; + } + + public String getBudgetUnit() { + return budgetUnit; + } + + public void setBudgetUnit(String budgetUnit) { + this.budgetUnit = budgetUnit; + } + + public String getFuture() { + return future; + } + + public void setFuture(String future) { + this.future = future; + } + + public String getBegin() { + return begin; + } + + public void setBegin(String begin) { + this.begin = begin; + } + + public String getEnd() { + return end; + } + + public void setEnd(String end) { + this.end = end; + } + + public int getDays() { + return days; + } + + public void setDays(int days) { + this.days = days; + } + + public String getProducts() { + return products; + } + + public void setProducts(String products) { + this.products = products; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public String getAcl() { + return acl; + } + + public void setAcl(String acl) { + this.acl = acl; + } + + public String getAuth() { + return auth; + } + + public void setAuth(String auth) { + this.auth = auth; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectDeleteRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectDeleteRequest.java new file mode 100644 index 0000000..2f4e6fe --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectDeleteRequest.java @@ -0,0 +1,21 @@ +package xyz.wbsite.zentao.sdk.project.req; + +/** + * 禅道项目删除请求 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtProjectDeleteRequest { + + private int projectId; + + public int getProjectId() { + return projectId; + } + + public void setProjectId(int projectId) { + this.projectId = projectId; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectEditRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectEditRequest.java new file mode 100644 index 0000000..f198fee --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectEditRequest.java @@ -0,0 +1,205 @@ +package xyz.wbsite.zentao.sdk.project.req; + +/** + * 禅道项目更新响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtProjectEditRequest { + + /** + * 项目ID + */ + private int id; + /** + * 父项目ID + */ + private String parent; + /** + * 项目名称 + */ + private String name; + /** + * 项目代号 + */ + private String code; + /** + * 产品经理账户 + */ + private String pm; + /** + * 是否待定(1待定) + */ + private String future; + /** + * 预算 + */ + private String budget; + /** + * 预算单位CNY + */ + private String budgetUnit; + /** + * 项目开始时间 yyyy-MM-dd + */ + private String begin; + /** + * 项目结束时间 yyyy-MM-dd + */ + private String end; + /** + * 可用工作日 + */ + private int days; + /** + * delta + */ + private int delta; + /** + * 项目描述 + */ + private String desc; + /** + * 访问控制private/open + */ + private String acl; + /** + * 权限控制extend/reset + */ + private String auth; + /** + * 项目管理方式scrum/waterfall/kanban + */ + private String model; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getParent() { + return parent; + } + + public void setParent(String parent) { + this.parent = parent; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + + public String getPm() { + return pm; + } + + public void setPm(String pm) { + this.pm = pm; + } + + public String getBudget() { + return budget; + } + + public void setBudget(String budget) { + this.budget = budget; + } + + public String getBudgetUnit() { + return budgetUnit; + } + + public void setBudgetUnit(String budgetUnit) { + this.budgetUnit = budgetUnit; + } + + public String getBegin() { + return begin; + } + + public void setBegin(String begin) { + this.begin = begin; + } + + public String getEnd() { + return end; + } + + public void setEnd(String end) { + this.end = end; + } + + public int getDays() { + return days; + } + + public void setDays(int days) { + this.days = days; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public String getAcl() { + return acl; + } + + public void setAcl(String acl) { + this.acl = acl; + } + + public String getAuth() { + return auth; + } + + public void setAuth(String auth) { + this.auth = auth; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public int getDelta() { + return delta; + } + + public void setDelta(int delta) { + this.delta = delta; + } + + public String getFuture() { + return future; + } + + public void setFuture(String future) { + this.future = future; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectStartRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectStartRequest.java new file mode 100644 index 0000000..d5036b6 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/project/req/ZtProjectStartRequest.java @@ -0,0 +1,41 @@ +package xyz.wbsite.zentao.sdk.project.req; + +/** + * 禅道项目启动响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtProjectStartRequest { + + private int projectId; + + private String comment; + + private String realBegan; + + public int getProjectId() { + return projectId; + } + + public void setProjectId(int projectId) { + this.projectId = projectId; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public String getRealBegan() { + return realBegan; + } + + public void setRealBegan(String realBegan) { + this.realBegan = realBegan; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectActivateResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectActivateResponse.java new file mode 100644 index 0000000..1289c2f --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectActivateResponse.java @@ -0,0 +1,36 @@ +package xyz.wbsite.zentao.sdk.project.rsp; + +/** + * 项目激活响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtProjectActivateResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectCloseResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectCloseResponse.java new file mode 100644 index 0000000..6196b8d --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectCloseResponse.java @@ -0,0 +1,36 @@ +package xyz.wbsite.zentao.sdk.project.rsp; + +/** + * 项目关闭响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtProjectCloseResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectCreateResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectCreateResponse.java new file mode 100644 index 0000000..bc5bc38 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectCreateResponse.java @@ -0,0 +1,50 @@ +package xyz.wbsite.zentao.sdk.project.rsp; + +/** + * 项目创建结果响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtProjectCreateResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + + /** + * + * 项目id + */ + private int id; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectDeleteResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectDeleteResponse.java new file mode 100644 index 0000000..8b0b0bf --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectDeleteResponse.java @@ -0,0 +1,36 @@ +package xyz.wbsite.zentao.sdk.project.rsp; + +/** + * 禅道项目删除响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtProjectDeleteResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectEditResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectEditResponse.java new file mode 100644 index 0000000..d3db91b --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectEditResponse.java @@ -0,0 +1,36 @@ +package xyz.wbsite.zentao.sdk.project.rsp; + +/** + * 项目信息更新响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtProjectEditResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectGetResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectGetResponse.java new file mode 100644 index 0000000..82931a3 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectGetResponse.java @@ -0,0 +1,48 @@ +package xyz.wbsite.zentao.sdk.project.rsp; + +import xyz.wbsite.zentao.sdk.project.ent.ZtProject; + +/** + * 检索项目 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtProjectGetResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + + private ZtProject result; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public ZtProject getResult() { + return result; + } + + public void setResult(ZtProject result) { + this.result = result; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectStartResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectStartResponse.java new file mode 100644 index 0000000..0a4a444 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/project/rsp/ZtProjectStartResponse.java @@ -0,0 +1,49 @@ +package xyz.wbsite.zentao.sdk.project.rsp; + +/** + * 项目启动响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtProjectStartResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + + /** + * 项目id + */ + private int id; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/task/ZtTaskService.java b/src/main/java/xyz/wbsite/zentao/sdk/task/ZtTaskService.java new file mode 100644 index 0000000..4787f8e --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/task/ZtTaskService.java @@ -0,0 +1,450 @@ +package xyz.wbsite.zentao.sdk.task; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpException; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.http.HttpStatus; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import cn.hutool.log.StaticLog; +import xyz.wbsite.zentao.sdk.Constant; +import xyz.wbsite.zentao.sdk.ZentaoInstance; +import xyz.wbsite.zentao.sdk.task.ent.ZtTask; +import xyz.wbsite.zentao.sdk.task.req.ZtTaskCloseRequest; +import xyz.wbsite.zentao.sdk.task.req.ZtTaskCreateRequest; +import xyz.wbsite.zentao.sdk.task.req.ZtTaskDeleteRequest; +import xyz.wbsite.zentao.sdk.task.req.ZtTaskFinishRequest; +import xyz.wbsite.zentao.sdk.task.req.ZtTaskStartRequest; +import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskCloseResponse; +import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskCreateResponse; +import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskDeleteResponse; +import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskFinishResponse; +import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskGetResponse; +import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskStartResponse; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +/** + * 禅道任务服务 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtTaskService { + + private ZentaoInstance zentaoInstance; + + public ZtTaskService(ZentaoInstance zentaoInstance) { + this.zentaoInstance = zentaoInstance; + } + + /** + * 创建任务 + */ + public ZtTaskCreateResponse create(ZtTaskCreateRequest ztTaskCreateRequest) { + ZtTaskCreateResponse response = new ZtTaskCreateResponse(); + try { + String url = StrUtil.format("/task-create-{}-0-0.json", ztTaskCreateRequest.getExecution()); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createPost(url); + httpRequest.form("execution", ztTaskCreateRequest.getExecution()); + httpRequest.form("type", ztTaskCreateRequest.getType()); + httpRequest.form("module", ztTaskCreateRequest.getModule()); + httpRequest.form("assignedTo[]", StrUtil.join(",", ztTaskCreateRequest.getAssignedTo())); + httpRequest.form("teamMember", ztTaskCreateRequest.getTeamMember()); + httpRequest.form("multiple", ztTaskCreateRequest.getMultiple()); + httpRequest.form("mode", ztTaskCreateRequest.getMode()); + httpRequest.form("status", "wait"); + httpRequest.form("story", ztTaskCreateRequest.getStory()); + httpRequest.form("color", ztTaskCreateRequest.getColor()); + httpRequest.form("name", ztTaskCreateRequest.getName()); + httpRequest.form("storyEstimate", ztTaskCreateRequest.getStoryEstimate()); + httpRequest.form("storyDesc", ztTaskCreateRequest.getStoryDesc()); + httpRequest.form("storyPri", ztTaskCreateRequest.getStoryPri()); + httpRequest.form("pri", ztTaskCreateRequest.getPri()); + httpRequest.form("estimate", ztTaskCreateRequest.getEstimate()); + httpRequest.form("desc", ztTaskCreateRequest.getDesc()); + httpRequest.form("estStarted", ztTaskCreateRequest.getEstStarted()); + httpRequest.form("deadline", ztTaskCreateRequest.getDeadline()); + httpRequest.form("after", "toTaskList"); + httpRequest.form("team[]", ""); + httpRequest.form("teamSource[]", ""); + httpRequest.form("teamEstimate[]", ""); + if (CollUtil.isNotEmpty(ztTaskCreateRequest.getMailtos())) { + for (String mailto : ztTaskCreateRequest.getMailtos()) { + httpRequest.form("mailto[]", mailto); + } + } + httpRequest.form("uid", RandomUtil.randomString(13)); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = Convert.unicodeToStr(execute.body()); + StaticLog.info(body); + // {"result":"success","message":"保存成功","id":"1891"} + if (body.contains(Constant.SUCCESS_KEY)) { + JSONObject entries = JSONUtil.parseObj(body); + response.setId(Convert.toInt(entries.get("id"))); + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } else { + response.setSuccess(false); + response.setMessage(JSONUtil.parseObj(body).getStr("message")); + return response; + } + } catch (HttpException e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 关闭执行 + */ + public ZtTaskStartResponse start(ZtTaskStartRequest projectStartRequest) { + ZtTaskStartResponse response = new ZtTaskStartResponse(); + try { + String url = StrUtil.format("/task-start-{}.html", projectStartRequest.getTaskId()); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createPost(url); + httpRequest.form("assignedTo", projectStartRequest.getAssignedTo()); + httpRequest.form("realStarted", projectStartRequest.getRealStarted()); + httpRequest.form("consumed", projectStartRequest.getConsumed()); + httpRequest.form("left", projectStartRequest.getLeft()); + httpRequest.form("status", "doing"); + httpRequest.form("comment", projectStartRequest.getComment()); + httpRequest.form("uid", RandomUtil.randomString(13)); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = Convert.unicodeToStr(execute.body()); + // 返回html + StaticLog.info(body); + } catch (HttpException e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 完成任务 + */ + public ZtTaskFinishResponse finish(ZtTaskFinishRequest ztTaskFinishRequest) { + ZtTaskFinishResponse response = new ZtTaskFinishResponse(); + try { + String url = StrUtil.format("/task-finish-{}.html", ztTaskFinishRequest.getTaskId()); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createPost(url); + httpRequest.form("currentConsumed", ztTaskFinishRequest.getCurrentConsumed()); + httpRequest.form("consumed", ztTaskFinishRequest.getConsumed()); + httpRequest.form("assignedTo", ztTaskFinishRequest.getAssignedTo()); + httpRequest.form("realStarted", ztTaskFinishRequest.getRealStarted()); + httpRequest.form("finishedDate", ztTaskFinishRequest.getFinishedDate()); + httpRequest.form("status", "done"); + httpRequest.form("comment", ztTaskFinishRequest.getComment()); + httpRequest.form("uid", RandomUtil.randomString(13)); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = Convert.unicodeToStr(execute.body()); + StaticLog.info(body); + if (body.contains(Constant.SUCCESS_KEY)) { + JSONObject entries = JSONUtil.parseObj(body); + response.setId(Convert.toInt(entries.get("id"))); + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } + } catch (HttpException e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 关闭任务 + */ + public ZtTaskCloseResponse close(ZtTaskCloseRequest projectCloseRequest) { + ZtTaskCloseResponse response = new ZtTaskCloseResponse(); + try { + String url = StrUtil.format("/task-close-{}.html", projectCloseRequest.getTaskId()); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createPost(url); + httpRequest.form("status", "closed"); + httpRequest.form("comment", projectCloseRequest.getComment()); + httpRequest.form("uid", RandomUtil.randomString(13)); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = Convert.unicodeToStr(execute.body()); + StaticLog.info(body); + if (body.contains(Constant.SUCCESS_KEY)) { + JSONObject entries = JSONUtil.parseObj(body); + response.setId(Convert.toInt(entries.get("id"))); + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } + } catch (HttpException e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 删除执行 + */ + public ZtTaskDeleteResponse delete(ZtTaskDeleteRequest projectDeleteRequest) { + ZtTaskDeleteResponse response = new ZtTaskDeleteResponse(); + try { + String url = StrUtil.format("/task-delete-{}.html", projectDeleteRequest.getTaskId()); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createPost(url); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = Convert.unicodeToStr(execute.body()); + StaticLog.info(body); + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } catch (HttpException e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 设置查询条件 + *

+ * 禅道查询条件是设置在session中的,所有查询之前先设置参数 + */ + private boolean setQuery(int executionId, String fieldName, String fieldValue) { + try { + String url = StrUtil.format("/search-buildQuery.html"); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createPost(url); + httpRequest.form("fieldname", ""); + httpRequest.form("fieldstatus", ""); + httpRequest.form("fielddesc", ""); + httpRequest.form("fieldassignedTo", ""); + httpRequest.form("fieldpri", 0); + httpRequest.form("fieldexecution", ""); + httpRequest.form("fieldmodule", "ZERO"); + httpRequest.form("fieldestimate", ""); + httpRequest.form("fieldleft", ""); + httpRequest.form("fieldconsumed", ""); + httpRequest.form("fieldtype", ""); + httpRequest.form("fieldfromBug", ""); + httpRequest.form("fieldclosedReason", ""); + httpRequest.form("fieldopenedBy", ""); + httpRequest.form("fieldfinishedBy", ""); + httpRequest.form("fieldclosedBy", ""); + httpRequest.form("fieldcanceledBy", ""); + httpRequest.form("fieldlastEditedBy", ""); + httpRequest.form("fieldmailto", ""); + httpRequest.form("fieldopenedDate", ""); + httpRequest.form("fielddeadline", ""); + httpRequest.form("fieldestStarted", ""); + httpRequest.form("fieldrealStarted", ""); + httpRequest.form("fieldassignedDate", ""); + httpRequest.form("fieldfinishedDate", ""); + httpRequest.form("fieldclosedDate", ""); + httpRequest.form("fieldcanceledDate", ""); + httpRequest.form("fieldlastEditedDate", ""); + httpRequest.form("fieldactivatedDate", ""); + httpRequest.form("fieldid", ""); + httpRequest.form("andOr1", "AND"); + httpRequest.form("field1", fieldName); + httpRequest.form("operator1", "="); + httpRequest.form("value1", fieldValue); + httpRequest.form("andOr2", "and"); + httpRequest.form("field2", "id"); + httpRequest.form("operator2", "="); + httpRequest.form("value2", ""); + httpRequest.form("andOr3", "and"); + httpRequest.form("field3", "status"); + httpRequest.form("operator3", "="); + httpRequest.form("value3", ""); + httpRequest.form("groupAndOr", "and"); + httpRequest.form("andOr4", "AND"); + httpRequest.form("field4", "desc"); + httpRequest.form("operator4", "include"); + httpRequest.form("value4", ""); + httpRequest.form("andOr5", "and"); + httpRequest.form("field5", "assignedTo"); + httpRequest.form("operator5", "="); + httpRequest.form("value5", ""); + httpRequest.form("andOr6", "and"); + httpRequest.form("field6", "pri"); + httpRequest.form("operator6", "="); + httpRequest.form("value6", 0); + httpRequest.form("module", "task"); + httpRequest.form("actionURL", StrUtil.format("/execution-task-{}-bySearch-myQueryID.html", executionId)); + httpRequest.form("groupItems", "3"); + httpRequest.form("formType", "lite"); + StaticLog.info(JSONUtil.toJsonStr(httpRequest.form())); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + return false; + } + String body = Convert.unicodeToStr(execute.body()); + StaticLog.info(body); + return execute.getStatus() == HttpStatus.HTTP_OK; + } catch (Exception e) { + StaticLog.error(e); + } + return false; + } + + /** + * 通过任务名称获取任务 + * + * @param executionId 执行ID + * @param taskId 任务ID + * @return 任务获取响应 + */ + public ZtTaskGetResponse getById(int executionId, int taskId) { + ZtTaskGetResponse response = new ZtTaskGetResponse(); + try { + boolean setQuery = setQuery(executionId, "id", String.valueOf(taskId)); + if (!setQuery) { + response.setSuccess(false); + response.setMessage("设置查询参数失败"); + return response; + } + String url = StrUtil.format("/execution-task-{}-bySearch-myQueryID.html", executionId); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createGetForHtml(url); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = execute.body(); + Document parse = Jsoup.parse(body); + Elements trs = parse.select("#taskList tbody tr"); + if (trs.size() == 1) { + Element tr = trs.get(0); + ZtTask ztTask = new ZtTask(); + ztTask.setId(Convert.toInt(tr.select(".c-id").text())); + ztTask.setName(tr.select(".c-name").attr("title")); + ztTask.setStatus(tr.select(".c-status").text()); + ztTask.setPri(tr.select(".c-pri").text()); + ztTask.setAssignedTo(tr.select(".c-assignedTo").text()); + ztTask.setStatus(tr.select(".c-status").text()); + ztTask.setFinishedBy(tr.select(".c-finishedBy").text()); + ztTask.setProgress(tr.select("c-deadline").text()); + ztTask.setProgress(tr.select("c-estimate").text()); + ztTask.setProgress(tr.select("c-consumed").text()); + ztTask.setProgress(tr.select("c-left").text()); + ztTask.setProgress(tr.select("c-progress").text()); + response.setSuccess(true); + response.setMessage("请求成功"); + response.setResult(ztTask); + return response; + } + StaticLog.info(body); + response.setMessage("无数据"); + return response; + } catch (HttpException e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + + /** + * 通过任务名称获取任务 + * + * @param executionId 执行ID + * @param name 任务名称 + * @return 任务获取响应 + */ + public ZtTaskGetResponse getByName(int executionId, String name) { + ZtTaskGetResponse response = new ZtTaskGetResponse(); + try { + boolean setQuery = setQuery(executionId, "name", name); + if (!setQuery) { + response.setSuccess(false); + response.setMessage("设置查询参数失败"); + return response; + } + String url = StrUtil.format("/execution-task-{}-bySearch-myQueryID.html", executionId); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createGetForHtml(url); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = execute.body(); + Document parse = Jsoup.parse(body); + Elements trs = parse.select("#taskList tbody tr"); + if (trs.size() == 1) { + Element tr = trs.get(0); + ZtTask ztTask = new ZtTask(); + ztTask.setId(Convert.toInt(tr.select(".c-id").text())); + ztTask.setName(tr.select(".c-name").attr("title")); + ztTask.setStatus(tr.select(".c-status").text()); + ztTask.setPri(tr.select(".c-pri").text()); + ztTask.setAssignedTo(tr.select(".c-assignedTo").text()); + ztTask.setStatus(tr.select(".c-status").text()); + ztTask.setFinishedBy(tr.select(".c-finishedBy").text()); + ztTask.setProgress(tr.select("c-deadline").text()); + ztTask.setProgress(tr.select("c-estimate").text()); + ztTask.setProgress(tr.select("c-consumed").text()); + ztTask.setProgress(tr.select("c-left").text()); + ztTask.setProgress(tr.select("c-progress").text()); + response.setSuccess(true); + response.setMessage("请求成功"); + response.setResult(ztTask); + return response; + } + StaticLog.info(body); + response.setMessage("无数据"); + return response; + } catch (HttpException e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/task/ent/ZtTask.java b/src/main/java/xyz/wbsite/zentao/sdk/task/ent/ZtTask.java new file mode 100644 index 0000000..f1151a1 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/task/ent/ZtTask.java @@ -0,0 +1,144 @@ +package xyz.wbsite.zentao.sdk.task.ent; + +/** + * 禅道任务信息 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtTask { + + /** + * 任务ID + */ + private int id; + /** + * 任务名称 + */ + private String name; + /** + * 任务等级 + */ + private String pri; + /** + * 指派人 + */ + private String assignedTo; + /** + * 任务状态 + */ + private String status; + /** + * 任务完成人 + */ + private String finishedBy; + /** + * 结束日期 + */ + private String deadline; + /** + * 预计工时 + */ + private String estimate; + /** + * 消耗工时 + */ + private String consumed; + /** + * 剩余工时 + */ + private String left; + /** + * 进度 + */ + private String progress; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPri() { + return pri; + } + + public void setPri(String pri) { + this.pri = pri; + } + + public String getAssignedTo() { + return assignedTo; + } + + public void setAssignedTo(String assignedTo) { + this.assignedTo = assignedTo; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getFinishedBy() { + return finishedBy; + } + + public void setFinishedBy(String finishedBy) { + this.finishedBy = finishedBy; + } + + public String getDeadline() { + return deadline; + } + + public void setDeadline(String deadline) { + this.deadline = deadline; + } + + public String getEstimate() { + return estimate; + } + + public void setEstimate(String estimate) { + this.estimate = estimate; + } + + public String getConsumed() { + return consumed; + } + + public void setConsumed(String consumed) { + this.consumed = consumed; + } + + public String getLeft() { + return left; + } + + public void setLeft(String left) { + this.left = left; + } + + public String getProgress() { + return progress; + } + + public void setProgress(String progress) { + this.progress = progress; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskActivateRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskActivateRequest.java new file mode 100644 index 0000000..ca58ae6 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskActivateRequest.java @@ -0,0 +1,72 @@ +package xyz.wbsite.zentao.sdk.task.req; + +/** + * 禅道任务执行请求 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtTaskActivateRequest { + + /** + * 执行id + */ + private int executionId; + /** + * 开始日期 + */ + private String begin; + /** + * 结束日期 + */ + private String end; + /** + * 是否重新调整时间 0/1 + */ + private boolean readjustTime; + /** + * 备注 + */ + private String comment; + + public int getExecutionId() { + return executionId; + } + + public void setExecutionId(int executionId) { + this.executionId = executionId; + } + + public String getBegin() { + return begin; + } + + public void setBegin(String begin) { + this.begin = begin; + } + + public String getEnd() { + return end; + } + + public void setEnd(String end) { + this.end = end; + } + + public boolean isReadjustTime() { + return readjustTime; + } + + public void setReadjustTime(boolean readjustTime) { + this.readjustTime = readjustTime; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskCloseRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskCloseRequest.java new file mode 100644 index 0000000..b21f205 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskCloseRequest.java @@ -0,0 +1,31 @@ +package xyz.wbsite.zentao.sdk.task.req; + +/** + * 禅道任务关闭请求 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtTaskCloseRequest { + + private int taskId; + + private String comment; + + public int getTaskId() { + return taskId; + } + + public void setTaskId(int taskId) { + this.taskId = taskId; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskCreateRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskCreateRequest.java new file mode 100644 index 0000000..d40a237 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskCreateRequest.java @@ -0,0 +1,238 @@ +package xyz.wbsite.zentao.sdk.task.req; + +import java.util.List; + +/** + * 禅道任务创建请求 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtTaskCreateRequest { + + /** + * 执行ID + */ + private int execution; + + /** + * 任务类型devel/design/request/test/study/discuss/ui/affair/misc + */ + private String type; + + /** + * 所属模块ID,可默认0 + */ + private String module; + + /** + * 指派 + */ + private List assignedTo; + + /** + * 指派多人时设置 + */ + private String teamMember; + + /** + * 是否多人任务,1表示是 + */ + private String multiple; + /** + * 开发模式linear/multi,多人任务时指定 + */ + private String mode; + /** + * 关联需求 + */ + private String story; + private String storyEstimate; + private String storyDesc; + private String storyPri; + /** + * 任务颜色 + */ + private String color; + /** + * 任务标题 + */ + private String name; + /** + * 优先级1-4,从高到低 + */ + private String pri; + /** + * 预计时间(小时)整数或小数 + */ + private String estimate; + /** + * 任务描述 + */ + private String desc; + /** + * 预计开始时间yyyy-MM-dd + */ + private String estStarted; + /** + * 预计结束日期yyyy-MM-dd + */ + private String deadline; + /** + * 抄送人 + */ + private List mailtos; + + public int getExecution() { + return execution; + } + + public void setExecution(int execution) { + this.execution = execution; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getModule() { + return module; + } + + public void setModule(String module) { + this.module = module; + } + + public List getAssignedTo() { + return assignedTo; + } + + public void setAssignedTo(List assignedTo) { + this.assignedTo = assignedTo; + } + + public String getTeamMember() { + return teamMember; + } + + public void setTeamMember(String teamMember) { + this.teamMember = teamMember; + } + + public String getMultiple() { + return multiple; + } + + public void setMultiple(String multiple) { + this.multiple = multiple; + } + + public String getMode() { + return mode; + } + + public void setMode(String mode) { + this.mode = mode; + } + + public String getStory() { + return story; + } + + public void setStory(String story) { + this.story = story; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getStoryEstimate() { + return storyEstimate; + } + + public void setStoryEstimate(String storyEstimate) { + this.storyEstimate = storyEstimate; + } + + public String getStoryDesc() { + return storyDesc; + } + + public void setStoryDesc(String storyDesc) { + this.storyDesc = storyDesc; + } + + public String getStoryPri() { + return storyPri; + } + + public void setStoryPri(String storyPri) { + this.storyPri = storyPri; + } + + public String getPri() { + return pri; + } + + public void setPri(String pri) { + this.pri = pri; + } + + public String getEstimate() { + return estimate; + } + + public void setEstimate(String estimate) { + this.estimate = estimate; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public String getEstStarted() { + return estStarted; + } + + public void setEstStarted(String estStarted) { + this.estStarted = estStarted; + } + + public String getDeadline() { + return deadline; + } + + public void setDeadline(String deadline) { + this.deadline = deadline; + } + + public List getMailtos() { + return mailtos; + } + + public void setMailtos(List mailtos) { + this.mailtos = mailtos; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskDeleteRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskDeleteRequest.java new file mode 100644 index 0000000..d6316fc --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskDeleteRequest.java @@ -0,0 +1,21 @@ +package xyz.wbsite.zentao.sdk.task.req; + +/** + * 禅道任务删除请求 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtTaskDeleteRequest { + + private int taskId; + + public int getTaskId() { + return taskId; + } + + public void setTaskId(int taskId) { + this.taskId = taskId; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskFinishRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskFinishRequest.java new file mode 100644 index 0000000..b12e68e --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskFinishRequest.java @@ -0,0 +1,95 @@ +package xyz.wbsite.zentao.sdk.task.req; + +/** + * 禅道任务完成请求 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtTaskFinishRequest { + /** + * 任务ID + */ + private int taskId; + /** + * 本次消耗 + */ + private int currentConsumed; + /** + * 之前消耗 + */ + private String consumed; + /** + * 指派 + */ + private String assignedTo; + /** + * 实际开始 + */ + private String realStarted; + /** + * 实际完成 + */ + private String finishedDate; + /** + * 备注 + */ + private String comment; + + public int getTaskId() { + return taskId; + } + + public void setTaskId(int taskId) { + this.taskId = taskId; + } + + public int getCurrentConsumed() { + return currentConsumed; + } + + public void setCurrentConsumed(int currentConsumed) { + this.currentConsumed = currentConsumed; + } + + public String getConsumed() { + return consumed; + } + + public void setConsumed(String consumed) { + this.consumed = consumed; + } + + public String getAssignedTo() { + return assignedTo; + } + + public void setAssignedTo(String assignedTo) { + this.assignedTo = assignedTo; + } + + public String getRealStarted() { + return realStarted; + } + + public void setRealStarted(String realStarted) { + this.realStarted = realStarted; + } + + public String getFinishedDate() { + return finishedDate; + } + + public void setFinishedDate(String finishedDate) { + this.finishedDate = finishedDate; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskStartRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskStartRequest.java new file mode 100644 index 0000000..407c4bd --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/task/req/ZtTaskStartRequest.java @@ -0,0 +1,83 @@ +package xyz.wbsite.zentao.sdk.task.req; + +/** + * 禅道任务启动请求 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtTaskStartRequest { + /** + * 任务ID + */ + private int taskId; + /** + * 指派给 + */ + private String assignedTo; + /** + * 2023-11-10 10:09:26 + */ + private String realStarted; + /** + * 总计消耗(小时) + */ + private String consumed; + /** + * 预计剩余(小时) + */ + private String left; + /** + * 备注 + */ + private String comment; + + public int getTaskId() { + return taskId; + } + + public void setTaskId(int taskId) { + this.taskId = taskId; + } + + public String getAssignedTo() { + return assignedTo; + } + + public void setAssignedTo(String assignedTo) { + this.assignedTo = assignedTo; + } + + public String getRealStarted() { + return realStarted; + } + + public void setRealStarted(String realStarted) { + this.realStarted = realStarted; + } + + public String getConsumed() { + return consumed; + } + + public void setConsumed(String consumed) { + this.consumed = consumed; + } + + public String getLeft() { + return left; + } + + public void setLeft(String left) { + this.left = left; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskActivateResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskActivateResponse.java new file mode 100644 index 0000000..b998dc4 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskActivateResponse.java @@ -0,0 +1,48 @@ +package xyz.wbsite.zentao.sdk.task.rsp; + +/** + * 禅道任务激活响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtTaskActivateResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + /** + * 任务ID + */ + private int id; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskCloseResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskCloseResponse.java new file mode 100644 index 0000000..aea1fda --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskCloseResponse.java @@ -0,0 +1,48 @@ +package xyz.wbsite.zentao.sdk.task.rsp; + +/** + * 禅道任务关闭响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtTaskCloseResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + /** + * 任务ID + */ + private int id; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskCreateResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskCreateResponse.java new file mode 100644 index 0000000..e0eddb9 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskCreateResponse.java @@ -0,0 +1,47 @@ +package xyz.wbsite.zentao.sdk.task.rsp; + +/** + * 禅道任务关闭响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtTaskCreateResponse { + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + /** + * 任务ID + */ + private int id; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskDeleteResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskDeleteResponse.java new file mode 100644 index 0000000..087414d --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskDeleteResponse.java @@ -0,0 +1,36 @@ +package xyz.wbsite.zentao.sdk.task.rsp; + +/** + * 禅道任务删除响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtTaskDeleteResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskFinishResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskFinishResponse.java new file mode 100644 index 0000000..8192cb1 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskFinishResponse.java @@ -0,0 +1,48 @@ +package xyz.wbsite.zentao.sdk.task.rsp; + +/** + * 禅道任务完成响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtTaskFinishResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + /** + * 任务ID + */ + private int id; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskGetResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskGetResponse.java new file mode 100644 index 0000000..e1094ac --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskGetResponse.java @@ -0,0 +1,50 @@ +package xyz.wbsite.zentao.sdk.task.rsp; + +import xyz.wbsite.zentao.sdk.task.ent.ZtTask; + +/** + * 检索任务 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtTaskGetResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + /** + * 任务信息 + */ + private ZtTask result; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public ZtTask getResult() { + return result; + } + + public void setResult(ZtTask result) { + this.result = result; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskStartResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskStartResponse.java new file mode 100644 index 0000000..0765823 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/task/rsp/ZtTaskStartResponse.java @@ -0,0 +1,48 @@ +package xyz.wbsite.zentao.sdk.task.rsp; + +/** + * 禅道任务启动响应 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtTaskStartResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + /** + * 任务ID + */ + private int id; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/user/ZtUserService.java b/src/main/java/xyz/wbsite/zentao/sdk/user/ZtUserService.java new file mode 100644 index 0000000..0a10cf9 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/user/ZtUserService.java @@ -0,0 +1,86 @@ +package xyz.wbsite.zentao.sdk.user; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpException; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.http.HttpStatus; +import cn.hutool.log.StaticLog; +import xyz.wbsite.zentao.sdk.ZentaoInstance; +import xyz.wbsite.zentao.sdk.user.ent.ZtUser; +import xyz.wbsite.zentao.sdk.user.req.ZtUserListAllRequest; +import xyz.wbsite.zentao.sdk.user.rsp.ZtUserListAllResponse; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.util.ArrayList; +import java.util.List; + +/** + * 禅道用户服务 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtUserService { + + private ZentaoInstance zentaoInstance; + + public ZtUserService(ZentaoInstance client) { + this.zentaoInstance = client; + } + + public ZtUserListAllResponse listAll(ZtUserListAllRequest request) { + ZtUserListAllResponse response = new ZtUserListAllResponse(); + try { + List result = new ArrayList<>(); + int currentPage = 1; + while (true) { + String url = StrUtil.format("/company-browse-inside-0-bydept-id-32-2000-{}.html", currentPage); + StaticLog.info(url); + HttpRequest httpRequest = zentaoInstance.createGetForHtml(url); + HttpResponse execute = httpRequest.execute(); + if (HttpStatus.HTTP_OK != execute.getStatus()) { + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } + String body = execute.body(); + Document parse = Jsoup.parse(body); + Elements trs = parse.select(".main-table #userList tbody tr"); + for (Element tr : trs) { + ZtUser ztUser = new ZtUser(); + ztUser.setId(Convert.toInt(tr.select(".c-id").text())); + ztUser.setName(tr.child(1).attr("title")); + ztUser.setAccount(tr.child(2).text()); + ztUser.setPosition(tr.child(3).text()); + ztUser.setEmail(tr.child(4).text()); + ztUser.setSex(tr.child(5).text()); + ztUser.setPhone(tr.child(6).text()); + ztUser.setQq(tr.child(7).text()); + ztUser.setLastLoginDate(tr.child(8).text()); + ztUser.setAccessTimes(Convert.toInt(tr.child(9).text(), 0)); + result.add(ztUser); + } + if (trs.size() < 2000) { + break; + } + // 继续获取下一页数据 + currentPage++; + } + response.setResult(result); + response.setSuccess(true); + response.setMessage("请求成功"); + return response; + } catch (HttpException e) { + StaticLog.error(e); + } + response.setSuccess(false); + response.setMessage("请求失败"); + return response; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/user/ent/ZtUser.java b/src/main/java/xyz/wbsite/zentao/sdk/user/ent/ZtUser.java new file mode 100644 index 0000000..fb0a616 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/user/ent/ZtUser.java @@ -0,0 +1,144 @@ +package xyz.wbsite.zentao.sdk.user.ent; + +/** + * 禅道用户 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtUser { + + /** + * 账户ID + */ + private int id; + /** + * 姓名 + */ + private String name; + /** + * 账户 + */ + private String account; + /** + * 职位 + */ + private String position; + /** + * 邮箱 + */ + private String email; + /** + * 性别 + */ + private String sex; + /** + * 手机号码 + */ + private String mobile; + /** + * 电话号码 + */ + private String phone; + /** + * QQ + */ + private String qq; + /** + * 最后登录 + */ + private String lastLoginDate; + /** + * 接入次数 + */ + private int accessTimes; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getSex() { + return sex; + } + + public void setSex(String sex) { + this.sex = sex; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getQq() { + return qq; + } + + public void setQq(String qq) { + this.qq = qq; + } + + public String getLastLoginDate() { + return lastLoginDate; + } + + public void setLastLoginDate(String lastLoginDate) { + this.lastLoginDate = lastLoginDate; + } + + public int getAccessTimes() { + return accessTimes; + } + + public void setAccessTimes(int accessTimes) { + this.accessTimes = accessTimes; + } +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/user/req/ZtUserListAllRequest.java b/src/main/java/xyz/wbsite/zentao/sdk/user/req/ZtUserListAllRequest.java new file mode 100644 index 0000000..ba206f1 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/user/req/ZtUserListAllRequest.java @@ -0,0 +1,12 @@ +package xyz.wbsite.zentao.sdk.user.req; + +/** + * 查询所有账户信息 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtUserListAllRequest { + +} diff --git a/src/main/java/xyz/wbsite/zentao/sdk/user/rsp/ZtUserListAllResponse.java b/src/main/java/xyz/wbsite/zentao/sdk/user/rsp/ZtUserListAllResponse.java new file mode 100644 index 0000000..b8108d6 --- /dev/null +++ b/src/main/java/xyz/wbsite/zentao/sdk/user/rsp/ZtUserListAllResponse.java @@ -0,0 +1,50 @@ +package xyz.wbsite.zentao.sdk.user.rsp; + +import xyz.wbsite.zentao.sdk.user.ent.ZtUser; + +import java.util.List; + +/** + * 查询所有账户信息 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class ZtUserListAllResponse { + + /** + * 成功标志 + */ + private boolean success; + /** + * 消息 + */ + private String message; + + private List result; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public List getResult() { + return result; + } + + public void setResult(List result) { + this.result = result; + } +} diff --git a/src/test/java/xyz/wbsite/zentao/sdk/ClientTest.java b/src/test/java/xyz/wbsite/zentao/sdk/ClientTest.java new file mode 100644 index 0000000..5f824cc --- /dev/null +++ b/src/test/java/xyz/wbsite/zentao/sdk/ClientTest.java @@ -0,0 +1,218 @@ +package xyz.wbsite.zentao.sdk; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateField; +import cn.hutool.core.date.DateUtil; +import cn.hutool.json.JSONUtil; +import xyz.wbsite.zentao.sdk.execution.req.ZtExecutionCreateRequest; +import xyz.wbsite.zentao.sdk.execution.req.ZtExecutionStartRequest; +import xyz.wbsite.zentao.sdk.execution.rsp.ZtExecutionCreateResponse; +import xyz.wbsite.zentao.sdk.execution.rsp.ZtExecutionStartResponse; +import xyz.wbsite.zentao.sdk.project.req.ZtProjectActivateRequest; +import xyz.wbsite.zentao.sdk.project.req.ZtProjectCloseRequest; +import xyz.wbsite.zentao.sdk.project.req.ZtProjectCreateRequest; +import xyz.wbsite.zentao.sdk.project.req.ZtProjectDeleteRequest; +import xyz.wbsite.zentao.sdk.project.req.ZtProjectEditRequest; +import xyz.wbsite.zentao.sdk.project.req.ZtProjectStartRequest; +import xyz.wbsite.zentao.sdk.project.rsp.ZtProjectActivateResponse; +import xyz.wbsite.zentao.sdk.project.rsp.ZtProjectCloseResponse; +import xyz.wbsite.zentao.sdk.project.rsp.ZtProjectCreateResponse; +import xyz.wbsite.zentao.sdk.project.rsp.ZtProjectDeleteResponse; +import xyz.wbsite.zentao.sdk.project.rsp.ZtProjectEditResponse; +import xyz.wbsite.zentao.sdk.project.rsp.ZtProjectStartResponse; +import xyz.wbsite.zentao.sdk.task.req.ZtTaskCloseRequest; +import xyz.wbsite.zentao.sdk.task.req.ZtTaskCreateRequest; +import xyz.wbsite.zentao.sdk.task.req.ZtTaskDeleteRequest; +import xyz.wbsite.zentao.sdk.task.req.ZtTaskFinishRequest; +import xyz.wbsite.zentao.sdk.task.req.ZtTaskStartRequest; +import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskCloseResponse; +import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskCreateResponse; +import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskDeleteResponse; +import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskFinishResponse; +import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskGetResponse; +import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskStartResponse; +import org.junit.Test; + +import java.util.Collections; + +/** + * 禅道客户端测试 + *

+ * 基于开源版本18.1开发 + * + * @since 1.8 + */ +public class ClientTest { + + @Test + public void test() { + // 初始化客户端 + ZentaoClient client = new ZentaoClient("http://127.0.0.1:80", "******", "********************************", "pms"); + ZentaoInstance instance = client.loginAsPms(); + + // 创建项目 + ZtProjectCreateRequest ztProjectCreateRequest = new ZtProjectCreateRequest(); + ztProjectCreateRequest.setParent("0"); + ztProjectCreateRequest.setName("测试项目"); + ztProjectCreateRequest.setCode("测试项目"); + ztProjectCreateRequest.setMultiple("1"); + ztProjectCreateRequest.setHasProduct("0"); + ztProjectCreateRequest.setPm(""); + ztProjectCreateRequest.setBudget("1000"); + ztProjectCreateRequest.setBudgetUnit("CNY"); + ztProjectCreateRequest.setBegin(DateUtil.date().toString("yyyy-MM-dd")); + ztProjectCreateRequest.setEnd(DateUtil.date().offset(DateField.DAY_OF_MONTH, 27).toString("yyyy-MM-dd")); + ztProjectCreateRequest.setDays(21); + ztProjectCreateRequest.setProducts("0"); + ztProjectCreateRequest.setProductName(""); + ztProjectCreateRequest.setDesc(""); + ztProjectCreateRequest.setAcl("open"); + ztProjectCreateRequest.setAuth("extend"); + ztProjectCreateRequest.setModel("scrum"); + ZtProjectCreateResponse createProjectResponse = instance.getZtProjectService().create(ztProjectCreateRequest); + System.out.println(JSONUtil.toJsonPrettyStr(createProjectResponse)); + + // 编辑项目 + ZtProjectEditRequest ztProjectEditRequest = new ZtProjectEditRequest(); + ztProjectEditRequest.setId(createProjectResponse.getId()); + ztProjectEditRequest.setParent("0"); + ztProjectEditRequest.setName("测试项目"); + ztProjectEditRequest.setCode("测试项目"); + ztProjectEditRequest.setPm(""); + ztProjectEditRequest.setBudget("1000"); + ztProjectEditRequest.setBudgetUnit("CNY"); + ztProjectEditRequest.setBegin(DateUtil.date().toString("yyyy-MM-dd")); + ztProjectEditRequest.setEnd(DateUtil.date().offset(DateField.DAY_OF_MONTH, 27).toString("yyyy-MM-dd")); + ztProjectEditRequest.setDays(21); + ztProjectEditRequest.setDesc(""); + ztProjectEditRequest.setAcl("open"); + ztProjectEditRequest.setAuth("extend"); + ztProjectEditRequest.setModel("scrum"); + ZtProjectEditResponse ztProjectEditResponse = instance.getZtProjectService().edit(ztProjectEditRequest); + System.out.println(JSONUtil.toJsonPrettyStr(ztProjectEditResponse)); + + // 开始项目 + ZtProjectStartRequest ztProjectStartRequest = new ZtProjectStartRequest(); + ztProjectStartRequest.setProjectId(createProjectResponse.getId()); + ztProjectStartRequest.setComment(""); + ztProjectStartRequest.setRealBegan(DateUtil.today()); + ZtProjectStartResponse startProjectResponse = instance.getZtProjectService().start(ztProjectStartRequest); + System.out.println(JSONUtil.toJsonPrettyStr(startProjectResponse)); + + // 创建执行(模块1) + { + ZtExecutionCreateRequest ztExecutionCreateRequest = new ZtExecutionCreateRequest(); + ztExecutionCreateRequest.setProject(createProjectResponse.getId()); + ztExecutionCreateRequest.setName("测试项目-模块1"); + ztExecutionCreateRequest.setCode("测试项目-模块1"); + ztExecutionCreateRequest.setBegin(DateUtil.date().toString("yyyy-MM-dd")); + ztExecutionCreateRequest.setEnd(DateUtil.date().offset(DateField.DAY_OF_MONTH, 6).toString("yyyy-MM-dd")); + ztExecutionCreateRequest.setDelta(7); + ztExecutionCreateRequest.setDays(5); + ztExecutionCreateRequest.setLifetime("short"); + ztExecutionCreateRequest.setTeam(""); + ztExecutionCreateRequest.setTeams(createProjectResponse.getId()); + ztExecutionCreateRequest.setPo(""); + ztExecutionCreateRequest.setQd(""); + ztExecutionCreateRequest.setPm(""); + ztExecutionCreateRequest.setRd(""); + ztExecutionCreateRequest.setTeamMembers(CollUtil.newArrayList("")); + ztExecutionCreateRequest.setDesc(""); + ztExecutionCreateRequest.setAcl("open"); + ztExecutionCreateRequest.setAuth("extend"); + ZtExecutionCreateResponse ztExecutionCreateResponse = instance.getZtExecutionService().create(ztExecutionCreateRequest); + System.out.println(JSONUtil.toJsonPrettyStr(ztExecutionCreateResponse)); + + // 开始执行(模块1) + ZtExecutionStartRequest ztExecutionStartRequest = new ZtExecutionStartRequest(); + ztExecutionStartRequest.setExecutionId(ztExecutionCreateResponse.getId()); + ztExecutionStartRequest.setComment(""); + ztExecutionStartRequest.setRealBegan(DateUtil.today()); + ZtExecutionStartResponse ztExecutionStartResponse = instance.getZtExecutionService().start(ztExecutionStartRequest); + System.out.println(JSONUtil.toJsonPrettyStr(ztExecutionStartResponse)); + + { + // 创建测试任务1 + ZtTaskCreateRequest ztTaskCreateRequest = new ZtTaskCreateRequest(); + ztTaskCreateRequest.setExecution(ztExecutionCreateResponse.getId()); + ztTaskCreateRequest.setType("devel"); + ztTaskCreateRequest.setModule("0"); + ztTaskCreateRequest.setAssignedTo(Collections.emptyList()); + ztTaskCreateRequest.setTeamMember(""); + ztTaskCreateRequest.setMultiple(""); + ztTaskCreateRequest.setMode(""); + ztTaskCreateRequest.setStory(""); + ztTaskCreateRequest.setStoryEstimate(""); + ztTaskCreateRequest.setStoryDesc(""); + ztTaskCreateRequest.setStoryPri(""); + ztTaskCreateRequest.setColor("#ff0000"); + ztTaskCreateRequest.setName("测试任务1"); + ztTaskCreateRequest.setPri("1"); + ztTaskCreateRequest.setEstimate("1"); + ztTaskCreateRequest.setDesc("任务描述"); + ztTaskCreateRequest.setEstStarted(DateUtil.date().toString("yyyy-MM-dd")); + ztTaskCreateRequest.setDeadline(DateUtil.date().toString("yyyy-MM-dd")); + ztTaskCreateRequest.setMailtos(Collections.emptyList()); + ZtTaskCreateResponse ztTaskCreateResponse = instance.getZtTaskService().create(ztTaskCreateRequest); + System.out.println(JSONUtil.toJsonPrettyStr(ztTaskCreateResponse)); + + ZtTaskGetResponse ztTaskGetResponse = instance.getZtTaskService().getByName(ztExecutionCreateResponse.getId(), "测试任务1"); + // 开始任务 + ZtTaskStartRequest ztTaskStartRequest = new ZtTaskStartRequest(); + ztTaskStartRequest.setTaskId(ztTaskGetResponse.getResult().getId()); + ztTaskStartRequest.setAssignedTo(""); + ztTaskStartRequest.setRealStarted(DateUtil.date().toString("yyyy-MM-dd HH:mm:ss")); + ztTaskStartRequest.setConsumed(ztTaskGetResponse.getResult().getConsumed()); + ztTaskStartRequest.setLeft(ztTaskGetResponse.getResult().getLeft()); + ztTaskStartRequest.setComment("备注"); + ZtTaskStartResponse ztTaskStartResponse = instance.getZtTaskService().start(ztTaskStartRequest); + System.out.println(JSONUtil.toJsonPrettyStr(ztTaskStartResponse)); + + // 完成任务 + ZtTaskFinishRequest ztTaskFinishRequest = new ZtTaskFinishRequest(); + ztTaskFinishRequest.setTaskId(ztTaskGetResponse.getResult().getId()); + ztTaskFinishRequest.setAssignedTo(""); + ztTaskFinishRequest.setRealStarted(DateUtil.date().toString("yyyy-MM-dd HH:mm:ss")); + ztTaskFinishRequest.setConsumed(ztTaskGetResponse.getResult().getConsumed()); + ztTaskFinishRequest.setComment("备注"); + ZtTaskFinishResponse ztTaskFinishResponse = instance.getZtTaskService().finish(ztTaskFinishRequest); + System.out.println(JSONUtil.toJsonPrettyStr(ztTaskFinishResponse)); + + // 关闭任务 + ZtTaskCloseRequest ztTaskCloseRequest = new ZtTaskCloseRequest(); + ztTaskCloseRequest.setTaskId(ztTaskCreateResponse.getId()); + ztTaskCloseRequest.setComment("备注"); + ZtTaskCloseResponse ztTaskCloseResponse = instance.getZtTaskService().close(ztTaskCloseRequest); + System.out.println(JSONUtil.toJsonPrettyStr(ztTaskCloseResponse)); + + // 删除任务 + ZtTaskDeleteRequest ztTaskDeleteRequest = new ZtTaskDeleteRequest(); + ztTaskDeleteRequest.setTaskId(ztTaskCreateResponse.getId()); + ZtTaskDeleteResponse ztTaskDeleteResponse = instance.getZtTaskService().delete(ztTaskDeleteRequest); + System.out.println(JSONUtil.toJsonPrettyStr(ztTaskDeleteResponse)); + } + } + + // 关闭项目 + ZtProjectCloseRequest ztProjectCloseRequest = new ZtProjectCloseRequest(); + ztProjectCloseRequest.setProjectId(createProjectResponse.getId()); + ztProjectCloseRequest.setComment(""); + ztProjectCloseRequest.setRealEnd(DateUtil.today()); + ZtProjectCloseResponse closeProjectResponse = instance.getZtProjectService().close(ztProjectCloseRequest); + System.out.println(JSONUtil.toJsonPrettyStr(closeProjectResponse)); + + // 激活项目 + ZtProjectActivateRequest ztProjectActivateRequest = new ZtProjectActivateRequest(); + ztProjectActivateRequest.setProjectId(createProjectResponse.getId()); + ztProjectActivateRequest.setComment(""); + ztProjectActivateRequest.setBegin(DateUtil.today()); + ZtProjectActivateResponse activateProjectResponse = instance.getZtProjectService().activate(ztProjectActivateRequest); + System.out.println(JSONUtil.toJsonPrettyStr(activateProjectResponse)); + + // 删除项目 + ZtProjectDeleteRequest ztProjectDeleteRequest = new ZtProjectDeleteRequest(); + ztProjectDeleteRequest.setProjectId(createProjectResponse.getId()); + ZtProjectDeleteResponse ztProjectDeleteResponse = instance.getZtProjectService().delete(ztProjectDeleteRequest); + System.out.println(JSONUtil.toJsonPrettyStr(ztProjectDeleteResponse)); + } +}