Commit 86952a4d authored by 胡慧's avatar 胡慧

迁移pipeline页面

parent 5aeb9a71
...@@ -2,7 +2,8 @@ module.exports = { ...@@ -2,7 +2,8 @@ module.exports = {
NODE_ENV: '"development"', NODE_ENV: '"development"',
ENV_CONFIG: '"dev"', ENV_CONFIG: '"dev"',
// QA_API: '"http://172.30.220.22:3003"', // QA_API: '"http://172.30.220.22:3003"',
QA_API: '"http://127.0.0.1:3003"', // QA_API: '"http://127.0.0.1:3003"',
QA_API: '"http://qaapi.liangkebang.com"',
TESTDATA_API: '"http://172.30.220.22:3333"', TESTDATA_API: '"http://172.30.220.22:3333"',
// PIPELINE_API:'"http://pipes.liangkebang.com"', PIPELINE_API:'"http://pipes.liangkebang.com"'
} }
...@@ -34,7 +34,8 @@ ...@@ -34,7 +34,8 @@
"url": "https://github.com/PanJiaChen/vue-element-admin/issues" "url": "https://github.com/PanJiaChen/vue-element-admin/issues"
}, },
"dependencies": { "dependencies": {
"axios": "0.18.0", "ace-builds": "^1.4.5",
"axios": "^0.19.0",
"clipboard": "1.7.1", "clipboard": "1.7.1",
"codemirror": "5.39.2", "codemirror": "5.39.2",
"driver.js": "0.8.1", "driver.js": "0.8.1",
...@@ -54,10 +55,12 @@ ...@@ -54,10 +55,12 @@
"showdown": "1.8.6", "showdown": "1.8.6",
"sortablejs": "1.7.0", "sortablejs": "1.7.0",
"tui-editor": "1.2.7", "tui-editor": "1.2.7",
"v-charts": "^1.19.0",
"vue": "2.5.17", "vue": "2.5.17",
"vue-count-to": "1.0.13", "vue-count-to": "1.0.13",
"vue-i18n": "7.3.2", "vue-i18n": "7.3.2",
"vue-router": "3.0.2", "vue-router": "3.0.2",
"vue-schart": "^1.0.0",
"vue-splitpane": "1.0.2", "vue-splitpane": "1.0.2",
"vuedraggable": "^2.16.0", "vuedraggable": "^2.16.0",
"vuex": "3.0.1", "vuex": "3.0.1",
...@@ -109,14 +112,14 @@ ...@@ -109,14 +112,14 @@
"serve-static": "1.13.2", "serve-static": "1.13.2",
"shelljs": "0.8.2", "shelljs": "0.8.2",
"svg-sprite-loader": "3.8.0", "svg-sprite-loader": "3.8.0",
"svgo": "1.0.5", "svgo": "^1.3.0",
"uglifyjs-webpack-plugin": "1.2.7", "uglifyjs-webpack-plugin": "1.2.7",
"url-loader": "1.0.1", "url-loader": "1.0.1",
"vue-loader": "15.3.0", "vue-loader": "15.3.0",
"vue-style-loader": "4.1.2", "vue-style-loader": "4.1.2",
"vue-template-compiler": "2.5.17", "vue-template-compiler": "2.5.17",
"webpack": "4.16.5", "webpack": "4.16.5",
"webpack-bundle-analyzer": "2.13.1", "webpack-bundle-analyzer": "^3.4.1",
"webpack-cli": "3.1.0", "webpack-cli": "3.1.0",
"webpack-dev-server": "3.1.14", "webpack-dev-server": "3.1.14",
"webpack-merge": "4.1.4" "webpack-merge": "4.1.4"
......
...@@ -59,3 +59,72 @@ export function getFlow() { ...@@ -59,3 +59,72 @@ export function getFlow() {
method: 'get' method: 'get'
}) })
} }
export function saveAdapter(data) {
return request({
url: '/manage/adapter',
method: 'post',
data
})
}
export function getAdapter(id) {
return request({
url: `/manage/adapter/list/${id}`,
method: 'get'
})
}
export function deleteAdapter(id) {
return request({
url: `/manage/adapter/${id}`,
method: 'delete'
})
}
export function getAdapters() {
return request({
url: '/manage/adapter/list',
method: 'get'
})
}
export function getPipelines() {
return request({
url: '/manage/pipeline/list/flow',
method: 'get'
})
}
export function fetchPipelineEntitys(page, count, data) {
return request({
url: `/manage/pipeline/entity/list/${page}/${count}`,
method: 'post',
data
})
}
export function findHook(params) {
return request({
url: `/manage/pipeline//hook/find/${params}`,
method: 'get'
})
}
export function getPipelineEntity(id) {
return request({
url: `/manage/pipeline/entity/${id}`,
method: 'get'
})
}
export function getPipelineEntityTaskResult(pipelineEntityid, stageIndex, taskIndex) {
return request({
url: `/manage/pipeline/task/detail/${pipelineEntityid}/${stageIndex}/${taskIndex}`,
method: 'get'
})
}
export function getLogs(id, start, end) {
return request({
url: `/task/exec/log/${id}/${start}/${end}`,
method: 'get'
})
}
export function getQualiSonar(data) {
return request({
url: `/manage/quali/detail`,
method: 'post',
data
})
}
...@@ -34,4 +34,3 @@ export function updateApplication(data) { ...@@ -34,4 +34,3 @@ export function updateApplication(data) {
data data
}) })
} }
...@@ -18,6 +18,7 @@ import './icons' // icon ...@@ -18,6 +18,7 @@ import './icons' // icon
import './errorLog' // error log import './errorLog' // error log
import './permission' // permission control import './permission' // permission control
import './mock' // simulation data import './mock' // simulation data
import ace from 'ace-builds'
import * as filters from './filters' // global filters import * as filters from './filters' // global filters
...@@ -26,6 +27,8 @@ Vue.use(Element, { ...@@ -26,6 +27,8 @@ Vue.use(Element, {
i18n: (key, value) => i18n.t(key, value) i18n: (key, value) => i18n.t(key, value)
}) })
Vue.use(ace)
// register global utility filters. // register global utility filters.
Object.keys(filters).forEach(key => { Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key]) Vue.filter(key, filters[key])
......
...@@ -236,6 +236,46 @@ export const asyncRouterMap = [ ...@@ -236,6 +236,46 @@ export const asyncRouterMap = [
component: () => import('@/views/pipeline/manager'), component: () => import('@/views/pipeline/manager'),
name: 'manager', name: 'manager',
meta: { title: '流水线管理', icon: '' } meta: { title: '流水线管理', icon: '' }
},
{
path: 'adapter',
component: () => import('@/views/pipeline/adapter'),
name: 'adapter',
meta: { title: '流水线适配', icon: '' }
},
{
path: 'job',
component: () => import('@/views/pipeline/job'),
name: 'job',
meta: { title: 'Job实例', icon: '' }
},
{
path: 'jobDetail',
component: () => import('@/views/pipeline/jobDetail'),
name: 'jobDetail',
meta: { title: 'Job实例详情', icon: '' },
hidden: true
},
{
path: 'taskConsole',
component: () => import('@/views/pipeline/taskConsole'),
name: 'taskConsole',
meta: { title: 'taskConsole日志', icon: '' },
hidden: true
},
{
path: 'hookInfo',
component: () => import('@/views/pipeline/hookInfo'),
name: 'hookInfo',
meta: { title: 'hookInfo', icon: '' },
hidden: true
},
{
path: 'qualiSonar',
component: () => import('@/views/pipeline/qualiSonar'),
name: 'qualiSonar',
meta: { title: 'qualiSonar', icon: '' },
hidden: true
} }
] ]
}, },
......
<template>
<div class="app-container">
<h3 style="overflow:hidden;">
Pipeline Adapter
<el-button type="primary" style="margin-right:40px;float:right" icon="el-icon-edit" @click="handleCreate">新建</el-button>
</h3>
<el-table
v-loading="listLoading"
:data="adapters"
border
fit
highlight-current-row
style="width: 100%;">
<el-table-column type="index" align="center" width="65"/>
<el-table-column label="name" prop="name" align="center"/>
<el-table-column label="hook uri" prop="id" width="350" align="center"/>
<el-table-column prop="description" label="description" align="center"/>
<el-table-column prop="user" label="user" align="center"/>
<el-table-column label="ops" align="center" width="180">
<template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleUpdate(scope.row)">{{ $t('table.edit') }}</el-button>
<el-button v-if="scope.row.status!=='deleted'" size="mini" type="danger" @click="handleDelete(scope.row)">{{ $t('table.delete') }}
</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog :title="dialogStatus" :visible.sync="dialogFormVisible" width="50%">
<el-form ref="dataForm" :rules="rules" :model="currentAdapter" label-position="left" label-width="100px" style="width: 90%; margin-left:40px;">
<el-form-item label="name" prop="name" >
<el-input v-model="currentAdapter.name"/>
</el-form-item>
<el-form-item label="description" prop="description" style="width:100%">
<el-input v-model="currentAdapter.description"/>
</el-form-item>
<div >
<div style="width:100%;margin-bottom:20px" >
<el-button type="primary" style="width:20%" @click="newAdapter()"> + 新建</el-button>
</div>
<div v-for="(obj, index) in currentAdapter.triggerPipelines" :key="index" style="width:110%;margin-bottom:20px" >
<label style="margin-right:20px"/>
<el-input v-model="obj.name" placeholder="请输入名称" style="width:30%"/>
<label style="margin:1px"/>
<el-button type="primary" size="mini" icon="el-icon-edit" style="margin:5px" @click="handelScript(obj,index)">script</el-button>
<el-select v-model="obj.pipelineId" value-key="id" style="width:30%">
<el-option v-for="item in pipes" :value="item.id" :label="item.name" :key="item.id" />
</el-select>
<el-button :disabled="index===0?true:false" style="margin-left:5px" @click="currentAdapter.triggerPipelines.splice(index, 1)">删除</el-button>
</div>
</div>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">{{ $t('table.cancel') }}</el-button>
<el-button type="primary" @click="createData()">{{ $t('table.confirm') }}</el-button>
</div>
</el-dialog>
<el-dialog :visible.sync="dialogDeleteVisible" :data="currentAdapter" width="30%" title="删除">
<span >
确定要删除{{ currentAdapter.name }}吗?
</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogDeleteVisible = false">{{ $t('table.cancel') }}</el-button>
<el-button type="primary" @click="deleteData">{{ $t('table.confirm') }}</el-button>
</span>
</el-dialog>
<div v-show="modalshow&&dialogFormVisible" class="modal" @focusout="saveScript">
<pre id="enditor" />
</div>
</div>
</template>
<script>
import { getAdapters, saveAdapter, getFlow, deleteAdapter } from '@/api/pipeline'
import waves from '@/directive/waves' // Waves directive
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
import ace from 'ace-builds/src-noconflict/ace'
import 'ace-builds/webpack-resolver' // 在 webpack 环境中使用必须要导入
import 'ace-builds/src-noconflict/theme-twilight' // 默认设置的主题
import 'ace-builds/src-noconflict/mode-javascript' // 默认设置的语言模式
export default {
name: 'ComplexTable',
components: { Pagination },
directives: { waves },
filters: {
},
data() {
return {
id: 0,
pipes: [],
triggerPipelines: [],
adapters: [],
hook_uri: '',
listLoading: true,
dialogStatus: '',
dialogFormVisible: false,
dialogDeleteVisible: false,
rules: {
name: [{ required: true, message: '请输入', trigger: 'blur' }],
description: [{ required: true, message: '请输入', trigger: 'blur' }]
},
currentAdapter: {
name: '',
description: '',
triggerPipelines: [{ name: '', pipelineId: '', script: '' }]
},
modalshow: false,
cont: '',
editor: null,
thescript: {}
}
},
computed: {
},
watch: {
},
created() {
this.getAdapters()
this.getFlow()
},
mounted() {
this.editor = ace.edit('enditor', {
maxLines: 40, // 最大行数,超过会自动出现滚动条
minLines: 20, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小
fontSize: 14, // 编辑器内字体大小
tabSize: 4, // 制表符设置为 4 个空格大小
theme: 'ace/theme/twilight', // 默认设置的主题
mode: 'ace/mode/groovy'
})
},
methods: {
getAdapters() {
getAdapters({}).then(res => {
this.listLoading = false
this.adapters = res.data.data
}).catch(() => {
this.listLoading = false
})
},
newAdapter() {
this.currentAdapter.triggerPipelines.push({ name: '', pipelineId: '', script: '' })
},
resetTemp() {
this.currentAdapter = {
name: '',
description: '',
triggerPipelines: [{ name: '', pipelineId: '', script: '' }]
}
},
handleCreate() {
this.resetTemp()
this.dialogStatus = '新建'
this.dialogFormVisible = true
this.modalshow = false
},
createData() {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
if (this.dialogStatus === '新建') {
this.triggerPipelines.forEach((item) => {
if (item.name === '' || item.pipelineId === '') {
this.$notify({
title: 'error',
message: '请仔细检查名称及流水线是否填写正确',
type: 'error',
duration: 2000
})
}
})
saveAdapter(this.currentAdapter).then(res => {
this.dialogFormVisible = false
if (res.data.code === '0000') {
this.getAdapters()
this.$notify({
title: '成功',
message: '保存成功',
type: 'success',
duration: 2000
})
}
})
} else {
saveAdapter(this.currentAdapter).then(res => {
this.dialogFormVisible = false
if (res.data.code === '0000') {
this.getAdapters()
this.$notify({
title: '成功',
message: '保存成功',
type: 'success',
duration: 2000
})
}
})
}
}
})
},
getFlow() {
getFlow().then(res => {
for (const index in res.data.data) {
const item = res.data.data[index]
this.pipes.push({ id: item.id, name: item.name })
}
})
},
handelScript(obj) {
this.modalshow = true
this.editor.setValue(obj.script)
this.thescript = obj
},
handleDelete(row) {
this.dialogDeleteVisible = true
this.row = row
},
saveScript() {
this.thescript.script = this.editor.getValue()
},
deleteData() {
deleteAdapter(this.row.id).then(res => {
this.dialogDeleteVisible = false
if (res.data.code === '0000') {
this.getAdapters()
this.$notify({
title: '成功',
message: '删除成功',
type: 'success',
duration: 2000
})
}
})
},
handleUpdate(row) {
this.currentAdapter = Object.assign({}, row)
this.dialogStatus = '编辑'
this.dialogFormVisible = true
this.modalshow = false
}
}
}
</script>
<style>
.modal {
position: absolute;
height:100%;
width:400px;
bacground:#fff;
z-index:9999;
right:20px;
top:20px;
}
</style>
...@@ -265,6 +265,7 @@ export default { ...@@ -265,6 +265,7 @@ export default {
} }
})) }))
this.refs[repo].push({ id: '0', name: '请选择' }) this.refs[repo].push({ id: '0', name: '请选择' })
console.log(this.refs)
this.refs[repo].reverse() this.refs[repo].reverse()
} }
}) })
...@@ -280,8 +281,8 @@ export default { ...@@ -280,8 +281,8 @@ export default {
createData() { createData() {
this.$refs['dataForm'].validate((valid) => { this.$refs['dataForm'].validate((valid) => {
if (valid) { if (valid) {
// 数组清洗整合,
this.temp.repos.forEach(item => { this.temp.repos.forEach(item => {
console.log(item)
this.repos.forEach(value => { this.repos.forEach(value => {
if (item.repository === value.project_name) { if (item.repository === value.project_name) {
this.$set(item, 'type', value.type) this.$set(item, 'type', value.type)
......
<template>
<div class="app-container">
<h3 style="overflow:hidden;">
hook info
</h3>
<el-form ref="hookInfo" :model="hookInfo" label-width="120px">
<el-form-item label="id" prop="id" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.id"/>
</el-form-item>
<el-form-item label="gitRepositoryId" prop="gitRepositoryId" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.gitRepositoryId"/>
</el-form-item>
<el-form-item label="gitRefId" prop="gitRefId" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.gitRefId"/>
</el-form-item>
<el-form-item label="objectKind" prop="objectKind" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.objectKind"/>
</el-form-item>
<el-form-item label="userId" prop="userId" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.userId"/>
</el-form-item>
<el-form-item label="userEmail" prop="userEmail" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.userEmail"/>
</el-form-item>
<el-form-item label="userName" prop="userName" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.userName"/>
</el-form-item>
<el-form-item label="projectId" prop="projectId" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.projectId"/>
</el-form-item>
<el-form-item label="ref" prop="ref" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.ref"/>
</el-form-item>
<el-form-item label="totalCommitsCount" prop="totalCommitsCount" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.totalCommitsCount"/>
</el-form-item>
<el-form-item label="before" prop="before" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.before"/>
</el-form-item>
<el-form-item label="after" prop="after" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.after"/>
</el-form-item>
<el-form-item label="checkoutSha" prop="checkoutSha" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.checkoutSha"/>
</el-form-item>
<el-form-item label="repository" prop="repository" style="width: 50%;">
<div style="border:1px solid #ddd;border-radius: 4px" >
<div v-for="(value ,key) in hookInfo.repository" :key="key">
<pre style="margin-left:10px">{{ key }} :{{ value }}</pre>
</div>
</div>
</el-form-item>
<el-form-item label="commit 1" prop="commits" style="width: 80%;">
<div style="border:1px solid #ddd;border-radius: 4px;width:80%;" >
<div v-for="item in hookInfo.commits" :key="item.id" class="ace-container">
<pre style="margin-left:10px">{{ item }}</pre>
</div>
</div>
</el-form-item>
<el-form-item label="createTime" prop="createTime" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.createTime"/>
</el-form-item>
<el-form-item label="updateTime" prop="updateTime" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.updateTime"/>
</el-form-item>
<el-form-item label="logicDel" prop="logicDel" style="width: 50%;">
<el-input :disabled="true" v-model="hookInfo.logicDel"/>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { findHook } from '@/api/pipeline'
export default {
data() {
return {
hookInfo: {}
}
},
created() {
this.findHook()
},
mounted() {
},
methods: {
findHook() {
// 获取gitHookReceiveId
this.gitHookReceiveId = this.$route.query.gitHookReceiveId
findHook(this.gitHookReceiveId).then(res => {
this.listLoading = false
this.hookInfo = res.data.data
}).catch(() => {
this.listLoading = false
})
}
}
}
</script>
<template>
<div class="app-container">
<h3 style="overflow:hidden;">
执行实例
</h3>
<el-table
v-loading="listLoading"
:data="jobs"
border
fit
highlight-current-row
style="width: 100%;">
<el-table-column type="index" align="center" width="65"/>
<el-table-column label="项目" prop="gitRepositoryName" align="center"/>
<el-table-column :formatter="replaceRef" label="分支" prop="gitRefName" align="center"/>
<el-table-column prop="triggerUser" label="触发者" align="center"/>
<el-table-column prop="status" label="状态" align="center">
<template slot-scope="scope">
<i :class="scope.row.statusIcon" />
</template>
</el-table-column>
<el-table-column prop="progress" label="进度" align="center"/>
<el-table-column :formatter="formatDate" prop="createTime" label="触发时间" align="center"/>
<el-table-column label="操作" align="center" width="250">
<template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleInfo(scope.row)">详情</el-button>
<el-button size="mini" type="primary" icon="el-icon-news" @click="handleHook(scope.row)">hook info</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination :current-page="page" :total="1000" background layout="prev, pager, next" style="margin-top:20px" @current-change="handleCurrentChange"/>
</div>
</template>
<script>
import { fetchPipelineEntitys } from '@/api/pipeline'
import moment from 'moment'
export default {
filters: {
},
data() {
return {
jobs: [],
listLoading: true,
pageCount: 10,
page: 1,
runtime: { runtime: 'run' }
}
},
computed: {
},
watch: {
},
created() {
this.fetchPipelineEntitys()
},
methods: {
handleCurrentChange(val) {
this.page = val
this.fetchPipelineEntitys()
},
fetchPipelineEntitys() {
fetchPipelineEntitys(this.page, this.pageCount, this.runtime).then(res => {
this.listLoading = false
this.jobs = res.data.data.data
this.jobs.map(item => {
item.progress = item.stageStep + ' - ' + item.stageTaskStep
switch (item.status) {
case 'end':
item.statusIcon = 'el-icon-success'
break
case 'fail':
item.statusIcon = 'el-icon-error'
break
case 'run':
item.statusIcon = 'el-icon-loading'
break
}
})
}).catch(() => {
this.listLoading = false
})
},
formatDate(row, val) {
const pattern = 'YYYY-MM-DD HH:mm:ss'
return moment(row.createTime).format(pattern)
},
replaceRef(row) {
return row.gitRefName ? row.gitRefName.replace('refs/heads/', '') : ''
},
handleInfo(row) {
this.$router.push({ name: 'jobDetail', query: { pipelineId: row.id }})
},
handleHook(row) {
this.$router.push({ name: 'hookInfo', query: { gitHookReceiveId: row.gitHookReceiveId }})
}
}
}
</script>
<template>
<el-container style="height: 400px; border-bottom: 5px solid #B3C0D1">
<el-aside width="500px" style="text-align: center; padding-top: 85px; border-right: 5px solid #B3C0D1">
<el-progress :percentage="percentage" :width="220" type="circle" />
</el-aside>
<el-container>
<el-header style="text-align: right; font-size: 12px" />
<el-main>
<el-table :data="pipes">
<el-table-column prop="name" label="name" width="180">
<template slot-scope="scope">
<i class="el-icon-star-off" style="color: red"/>
<span style="margin-left: 10px">{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column prop="status" label="status" width="120"/>
<el-table-column label="构建日志" width="140">
<template slot-scope="scope">
<el-button
type="primary"
icon="el-icon-info"
size="mini"
@click="handleConsole(scope.row.detailId,scope.row.status)"/>
</template>
</el-table-column>
<el-table-column label="构建结果" width="120">
<template slot-scope="scope">
<el-button
type="primary"
icon="el-icon-news"
size="mini"
@click="handleResult(scope.$index, scope.row)"/>
</template>
</el-table-column>
<el-table-column :formatter="formatDate" prop="updateTime" label="构建时间" width="160"/>
</el-table>
<el-dialog :visible.sync="dialogResultVisible" title="Task Result Info" >
<el-container style="height: 100px; border: 1px #eee">
<el-aside width="600px" style="padding-top: 20px">
<h2>Time 1 success </h2>
</el-aside>
<el-container>
<el-main>
<template slot-scope="scope">
<el-button
type="text"
icon="el-icon-info"
size="medium"
style= "text-align: center"
@click="handleConsole(grid.id, grid.status)"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<el-popover
placement="right"
width="400"
trigger="click">
<el-table :data="gridData">
<el-table-column width="150" prop="name" label="类型"/>
<el-table-column width="100" prop="value" label="结果"/>
</el-table>
<el-button
slot="reference"
type="text"
icon="el-icon-more"
size="medium"
style= "text-align: center;"/>
</el-popover>
</template>
</el-main>
</el-container>
</el-container>
</el-dialog>
</el-main>
</el-container>
</el-container>
</template>
<style>
.el-header {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333
}
</style>
<script>
import { getPipelineEntity, getPipelineEntityTaskResult } from '@/api/pipeline'
import moment from 'moment'
export default {
data() {
return {
pipes: [],
listLoading: true,
pipelineId: '',
detailId: '',
dialogResultVisible: false,
dialogStatus: '',
percentage: 0,
stageIndex: 0,
taskIndex: 0,
gridData: [],
grid: {}
}
},
computed: {
},
watch: {
},
created() {
this.getPipelineEntity()
},
methods: {
getPipelineEntity() {
// 获取PipelineId
this.pipelineId = this.$route.query.pipelineId
// 根据pipelineId获取详情数据
getPipelineEntity(this.pipelineId).then(res => {
this.listLoading = false
var count = 0
for (var stage in res.data.data.stages) {
for (var task in res.data.data.stages[stage].tasks) {
this.pipes.push(res.data.data.stages[1].tasks[task])
if (res.data.data.stages[1].tasks[task].status === 'success') {
count++
}
this.percentage = count / task * 100
}
}
}).catch(() => {
this.listLoading = false
})
},
formatDate(row, val) {
var pattern = 'YYYY-MM-DD HH:mm:ss'
return moment(row.updateTime).format(pattern)
},
handleConsole(id, status) {
this.$router.push({ name: 'taskConsole', query: { detailId: id, status: status }})
},
handleResult(row) {
this.row = row
this.dialogResultVisible = true
this.pipelineId = this.$route.query.pipelineId
this.taskIndex = this.row + 1
this.stageIndex = 1
getPipelineEntityTaskResult(this.pipelineId, this.stageIndex, this.taskIndex).then(res => {
this.gridData = res.data.data[0].info
this.grid = res.data.data[0]
})
}
}
}
</script>
...@@ -169,7 +169,11 @@ export default { ...@@ -169,7 +169,11 @@ export default {
this.listLoading = false this.listLoading = false
}) })
}, },
handleInfo(row) {
const startDate = this.formartTime(this.dateRange[0])
const endDate = this.formartTime(this.dateRange[1])
this.$router.push({ name: 'qualiSonar', query: { repository: row.repository, startDate: startDate, endDate: endDate }})
},
formartTime(date) { formartTime(date) {
return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}` return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`
}, },
......
<template>
<div class="app-container">
<h3 style="overflow:hidden;">
Sonar扫描结果
</h3>
<el-tabs v-model="activeName" type="card" @tab-click="handleClick">
<el-tab-pane label="BUGS" name="bugs">BUGS</el-tab-pane>
<el-tab-pane label="坏味道" name="codeSmells">坏味道</el-tab-pane>
<el-tab-pane label="覆盖率" name="coverage">覆盖率</el-tab-pane>
<el-tab-pane label="重复密度" name="duplicatedLinesDensity">重复密度</el-tab-pane>
<el-tab-pane label="代码行数" name="ncloc">代码行数</el-tab-pane>
</el-tabs>
<ve-line
:data="chartDatas"
:settings="chartSettings" />
</div>
</template>
<script>
import { getQualiSonar } from '@/api/pipeline'
import VeLine from 'v-charts/lib/line'
import 'v-charts/lib/style.css'
export default {
components: { VeLine },
data() {
return {
activeName: 'bugs',
repository: '',
listLoading: '',
chartDatas: {
columns: [],
rows: []
},
chartSettings: {
area: true
},
chartData: {
bugs: { columns: ['日期', 'BUGS'], rows: [] },
codeSmells: { columns: ['日期', '坏味道'], rows: [] },
coverage: { columns: ['日期', '覆盖率'], rows: [] },
duplicatedLinesDensity: { columns: ['日期', '重复密度'], rows: [] },
ncloc: { columns: ['日期', '代码行数'], rows: [] }
}
}
},
created() {
this.getQualiSonar()
},
methods: {
getQualiSonar() {
this.repository = this.$route.query.repository
this.startDate = this.$route.query.startDate
this.endDate = this.$route.query.endDate
getQualiSonar({
repository: this.repository,
type: 'sonar',
startDate: this.startDate,
endDate: this.endDate
}).then(res => {
this.listLoading = false
const data = res.data.data.sonar || {}
this.formetChartData('bugs', data.dates, data.bugs)
this.formetChartData('codeSmells', data.dates, data.codeSmells)
this.formetChartData('coverage', data.dates, data.coverage)
this.formetChartData('duplicatedLinesDensity', data.dates, data.duplicatedLinesDensity)
this.formetChartData('ncloc', data.dates, data.ncloc)
this.chartDatas = this.chartData['bugs']
})
},
formetChartData(key, dates, keyList) {
const name = {
bugs: 'BUGS',
codeSmells: '坏味道',
coverage: '覆盖率',
duplicatedLinesDensity: '重复密度',
ncloc: '代码行数'
}
for (const v of dates) {
this.chartData[key]['rows'].push({ '日期': v })
}
const arr = this.chartData[key]['rows']
for (let i = 0; i < arr.length; i++) {
arr[i][name[key]] = keyList[i]
}
},
handleClick() {
this.chartDatas = this.chartData[this.activeName]
}
}
}
</script>
<template>
<div class="app-container">
<h3 style="overflow:hidden;">
console
</h3>
<pre
style="border:1px solid #ccc; border-top:none;border-bottom:none; padding: 10px; white-space: pre-wrap;word-wrap: break-word;"
v-html="logs"/>
</div>
</template>
<style>
pre{
font-family:Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;
}
</style>
<script>
import { getLogs } from '@/api/pipeline'
export default {
data() {
return {
id: '',
start: 1,
end: 200,
logs: ''
}
},
created() {
this.getLogs()
},
methods: {
getLogs() {
this.id = this.$route.query.detailId
this.status = this.$route.query.status
getLogs(this.id, this.start, this.end).then(res => {
this.listLoading = false
this.logs = res.data
}
).catch(() => {
this.listLoading = false
})
}
}
}
</script>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment