Просмотр исходного кода

[新增]编译、部署数据接口

soleil 7 лет назад
Родитель
Сommit
ca7a93999d

+ 23 - 3
src/api/codehw.js

@@ -50,6 +50,17 @@ export const getBuildDetail = buildId => {
   return request(`${CODE_HOMEWORK_MODULE}/build/${buildId}`);
 };
 
+/**
+ * 获得最近n个构建的信息
+ * @param {string|number} buildId
+ * @return {Promise<{id:string,data:BuildSerializerType[]}>}
+ */
+export const getLatestBuildInfoList = (projectId, limit) => {
+  return request(
+    `${CODE_HOMEWORK_MODULE}/project/${projectId}/build/record?limit=${limit}`
+  );
+};
+
 /**
  * 获得一次部署的详细信息
  * @param {string|number} deployId
@@ -59,6 +70,15 @@ export const getDeployDetail = deployId => {
   return request(`${CODE_HOMEWORK_MODULE}/deploy/${deployId}`);
 };
 
+/**
+ * 获得一次部署的日志信息
+ * @param {string|number} deployId
+ * @return {Promise<{id:string,data:string}>}
+ */
+export const getDeployLogInfo = deployId => {
+  return request(`${CODE_HOMEWORK_MODULE}/deploy/log/${deployId}`);
+};
+
 /**
  * 获得一次单元测试的详细信息
  * @param {string|number} unitId
@@ -90,15 +110,15 @@ export const getAvailableMirrorList = ({ homeworkId, projectId }) => {
 /**
  * TODO: arguments 不被允许
  * 触发一次部署
- * @param {string|number} homeworkId
+ * @param {string|number} replicas
  * @param {string|number} projectId
  * @param {string|number} mirrorId
  * @return {Promise<{data:{success:boolean}}>}
  */
-export const makeDeploy = ({ homeworkId, projectId, mirrorId }) => {
+export const makeDeploy = ({ projectId, mirrorId, replicas }) => {
   return request(`${CODE_HOMEWORK_MODULE}/deploy`, {
     method: "POST",
-    body: { homeworkId, projectId, mirrorId }
+    body: { replicas, projectId, mirrorId }
   });
 };
 

+ 213 - 21
src/views/student/Code/ProjectDetail/DeployDetail.vue

@@ -1,15 +1,31 @@
 <template>
   <div class="data-table">
     <section>
+      <div class="mirror-subtitle" v-if="deployStatus != 'RUNNING'">
+        选择镜像
+      </div>
+      <div class="select-mirror" v-if="deployStatus != 'RUNNING'">
+        <div class="latest-build">
+          <div class="test-item" :key="item.id" v-for="item in latestBuildList">
+            <div>
+              <b-radio v-model="radio" :native-value="item.id"> </b-radio>
+              <strong>构建ID: #</strong> {{ item.id }}
+              <span style="padding-left: 10px">
+                <strong>镜像ID: #</strong> {{ item.mirrorId }}
+              </span>
+            </div>
+          </div>
+        </div>
+      </div>
       <button
-        :class="['button', 'block', 'is-link', { 'is-loading': isActive }]"
-        @click="isActive = !isActive"
+        :class="['button', 'block', 'is-link', { 'is-loading': isRunning }]"
+        @click="startDeploy"
       >
         开始部署
       </button>
       <b-message
         title="部署进行中..."
-        :active.sync="isActive"
+        :active.sync="isRunning"
         type="is-warning"
       >
         部署已经开始,一次部署需要大约5-10分钟,请5-10分钟后刷新页面获取部署结果
@@ -17,51 +33,224 @@
     </section>
     <!--部署记录-->
     <div class="deploy-list">
-      <div class="subtitle">部署结果</div>
+      <div class="subtitle">
+        {{ isRunning ? "当前部署情况" : "上次部署结果" }}
+      </div>
       <div class="deploy-item">本次部署ID: #{{ deployInfo.id }}</div>
-      <div class="deploy-item">本次部署时间: 2019-01-14 15:05</div>
       <div class="deploy-item">
-        部署结果:
-        <div class="tag is-success">部署成功</div>
+        本次部署创建时间: {{ handleTime(deployInfo.createdAt) }}
       </div>
-      <div class="deploy-item">
-        <div class="subtitle">项目部署地址</div>
-        <a :href="`http://${deployInfo.pageUrl}`" target="_blank">查看详情</a>
+      <div class="deploy-item" v-if="deployInfo.endAt">
+        本次部署结束时间: {{ handleTime(deployInfo.endAt) }}
       </div>
       <div class="deploy-item">
-        <div class="subtitle">配置信息</div>
-        <div>暂无项目配置信息</div>
+        部署结果:
+        <div :class="['tag', type(deployInfo.status)]">
+          {{ deployInfo.status }}
+        </div>
       </div>
+      <div class="subtitle">项目部署地址</div>
+      <div class="deploy-item">{{ deployInfo.url }}</div>
       <div class="deploy-item">
         <div class="subtitle">部署输出信息</div>
-        <div class="code-section">
-          <div class="code-content">{{ deployInfo.deployMessage }}</div>
+        <a
+          class="button is-small is-info"
+          @click="unfoldDeployLogInfo = !unfoldDeployLogInfo"
+        >
+          {{ unfoldDeployLogInfo ? "收起部署详细信息" : "查看部署详细信息" }}</a
+        >
+        <div class="code-section" v-show="unfoldDeployLogInfo">
+          <div class="code-content">{{ deployLog }}</div>
         </div>
-        <!--<div class="code-section">{{deployInfo.deployMessage}}</div>-->
       </div>
     </div>
   </div>
 </template>
 <script>
-// import { getDeployDetail } from "@/api/codehw";
+import {
+  getDeployDetail,
+  getDeployLogInfo,
+  getLatestBuildInfoList,
+  makeDeploy
+} from "@/api/codehw";
 
 export default {
   data() {
     return {
       isActive: false,
-      deployInfo: {}
+      isRunning: false,
+      deployStatus: "",
+      deployInfo: {},
+      haveDeployRecord: false,
+      deployLog: "",
+      unfoldDeployLogInfo: false,
+      latestBuildList: [],
+      radio: -1
     };
   },
+  props: {
+    projectDetail: {
+      type: Object,
+      default: () => {}
+    },
+    detailLoading: {
+      type: Boolean,
+      default: false
+    }
+  },
+  watch: {
+    projectDetail: function(newVal) {
+      //获取最新一次部署详细信息
+      if (newVal.latestDeploy.id) {
+        this.haveDeployRecord = true;
+        this.getLatestDeployInfo(newVal.latestDeploy.id);
+        // this.getLatestDeployInfo(17);
+        this.getDeployLogInfo(this.projectDetail.latestDeploy.id);
+        this.getLatestBuildInfo(this.projectDetail && this.projectDetail.id, 5);
+        //this.getLatestBuildInfo(95,5);
+      }
+    }
+  },
   mounted() {
-    // getDeployDetail(123).then(res => {
-    //   console.log(res.data);
-    //   this.deployInfo = res.data;
-    // });
+    if (this.projectDetail.latestDeploy) {
+      this.getLatestDeployInfo(this.projectDetail.latestDeploy.id);
+      this.getDeployLogInfo(this.projectDetail.latestDeploy.id);
+      //this.getLatestDeployInfo(17);
+      this.getLatestBuildInfo(this.projectDetail && this.projectDetail.id, 5);
+      // this.getLatestBuildInfo(95,5);
+    }
+  },
+  methods: {
+    //获取最新一次部署详细信息
+    getLatestDeployInfo(deployId) {
+      getDeployDetail(deployId)
+        .then(res => {
+          this.deployInfo = res.data;
+          this.deployStatus = res.data.status;
+          let isRunning = this.deployStatus == "RUNNING" ? true : false;
+          this.isRunning = isRunning;
+        })
+        .catch(e => {
+          this.$toast.open({
+            message: e.message || "服务器未知错误",
+            type: "is-danger"
+          });
+        });
+    },
+    //处理时间格式
+    handleTime(time) {
+      if (!time) {
+        return "";
+      }
+      return time.replace("T", " ") + "ms";
+    },
+    //开始部署
+    startDeploy() {
+      if (this.radio == -1) {
+        this.$toast.open({
+          message: "请先选择镜像",
+          type: "is-danger"
+        });
+        return;
+      } else {
+        let mirrorId = this.getSelectedMirrorId();
+        //触发部署
+        makeDeploy(this.projectDetail.id, mirrorId, 1)
+          .then(res => {
+            console.log(res);
+            this.$toast.open({
+              message: "开始部署",
+              type: "is-success"
+            });
+            this.isRunning = true;
+          })
+          .then(e => {
+            this.$toast.open({
+              message: e.message || "服务器未知错误",
+              type: "is-danger"
+            });
+          });
+      }
+    },
+    //获取最近n个构建的信息
+    getLatestBuildInfo(buildId, limit) {
+      getLatestBuildInfoList(buildId, limit)
+        .then(res => {
+          this.latestBuildList = res.data;
+        })
+        .catch(e => {
+          this.$toast.open({
+            message: e.message || "服务器未知错误",
+            type: "is-danger"
+          });
+        });
+    },
+    //获取部署日志
+    getDeployLogInfo(deployId) {
+      getDeployLogInfo(deployId)
+        .then(res => {
+          this.deployLog = res.data;
+        })
+        .catch(e => {
+          this.$toast.open({
+            message: e.message || "服务器未知错误",
+            type: "is-danger"
+          });
+        });
+    },
+    //部署类型
+    type(value) {
+      if (value == "FAILURE") {
+        return "is-danger";
+      } else if (value == "RUNNING") {
+        return "is-warning";
+      } else if (value == "SUCCESS") {
+        return "is-success";
+      } else {
+        return "";
+      }
+    },
+    //选择镜像ID
+    getSelectedMirrorId() {
+      for (let item in this.latestBuildList) {
+        if (item.id == this.radio) {
+          return item.mirrorId;
+        }
+      }
+    }
   }
 };
 </script>
 <style lang="scss" scoped>
 @import "../../../../assets/scss/app";
+.mirror-subtitle {
+  font-size: 1.25rem;
+  width: 100%;
+  font-weight: bold;
+  padding-bottom: 10px;
+  border-bottom: 1px solid #dbdbdb;
+}
+.select-mirror {
+  width: 100%;
+  display: flex;
+  .latest-build {
+    width: 100%;
+  }
+}
+.test-item {
+  width: 100%;
+  padding: $default-margin $default-margin-between;
+  margin: 0 -#{$default-margin-between};
+  cursor: pointer;
+}
+/*.test-item:hover,*/
+/*.test-item:nth-child(even):hover {*/
+/*background-color: #dde3ef;*/
+/*}*/
+
+.test-item:nth-child(even) {
+  background-color: rgba(244, 247, 252, 0.6);
+}
 .deploy-list {
   margin-top: 1.5rem;
   .deploy-item {
@@ -71,6 +260,9 @@ export default {
       margin-left: 10px;
       margin-right: 10px;
     }
+    a {
+      margin-bottom: 10px;
+    }
   }
   .subtitle {
     margin-top: 1.5rem;

+ 1 - 1
src/views/student/Code/ProjectDetail/index.vue

@@ -31,7 +31,7 @@
       </template>
       <template slot="content">
         <strong>git 地址 : </strong>
-        <a :href="projectDetail.url">{{ projectDetail.url }}</a>
+        <a :href="projectDetail.url" target="_blank">{{ projectDetail.url }}</a>
       </template>
     </page-header>
     <page-body>