| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- <template>
- <ElTabs class="tabs" v-model="activeTab">
- <ElTabPane label="流水线" name="pipeline">
- <ElTable :data="pipelines" width="100%">
- <ElTableColumn
- prop="id"
- label="ID"
- align="center"
- width="60"
- ></ElTableColumn>
- <ElTableColumn
- prop="name"
- label="名称"
- align="center"
- width="180"
- ></ElTableColumn>
- <ElTableColumn
- prop="username"
- label="最近执行人"
- align="center"
- width="180"
- ></ElTableColumn>
- <ElTableColumn
- label="最近执行时间"
- align="center"
- :formatter="(row) => timeFormatter(row, 'startTime')"
- ></ElTableColumn>
- <ElTableColumn
- prop="result"
- label="执行状态"
- align="center"
- width="100"
- :filters="[{ text: '成功', value: '成功' }, { text: '失败', value: '失败' }]"
- :filter-method="(value, row) => {
- return row.result === value;
- }"
- filter-placement="bottom-end"
- >
- <template #default="scope">
- <template v-if="scope.row.result === '成功'">
- <ElTag type="success">{{scope.row.result}}</ElTag>
- </template>
- <template v-else-if="scope.row.result === '失败'">
- <ElTag type="danger">{{scope.row.result}}</ElTag>
- </template>
- <template v-else-if="scope.row.result === '执行中'">
- <ElTag>{{scope.row.result}}<i class="el-icon-loading"></i></ElTag>
- </template>
- <template v-else>
- <ElTag type="warning">未知状态</ElTag>
- </template>
- </template>
- </ElTableColumn>
- <ElTableColumn
- label="详情"
- align="center"
- >
- <template #default="scope">
- <ElButton
- @click="handleClick('detail', scope.row.id)"
- type="text"
- size="small"
- :disabled="scope.row.result==='执行中'"
- >最近执行详情</ElButton>
- <ElButton @click="handleClick('history', scope.row.id)" type="text" size="small">历史</ElButton>
- </template>
- </ElTableColumn>
- <ElTableColumn
- align="center"
- >
- <template #header>
- <span>操作</span>
- <ElButton @click="handleClick('create')" type="text" class="add-button">新建</ElButton>
- </template>
- <template #default="scope">
- <ElButton @click="handleClick('trigger', scope.row.id)" type="text" size="small">触发</ElButton>
- <ElButton @click="handleClick('edit', scope.row.id)" type="text" size="small">编辑</ElButton>
- <ElButton @click="handleClick('delete', scope.row.id)" type="text" size="small">删除</ElButton>
- </template>
- </ElTableColumn>
- </ElTable>
- <ElDialog v-model="showPipelineDetailModal" destroy-on-close>
- <template #title>最近一次流水线构建的执行结果详情</template>
- <pre class="pipeline-detail">{{detail}}</pre>
- </ElDialog>
- <ElDialog v-model="showPipelineHistoryModal" destroy-on-close>
- <template #title>流水线构建历史</template>
- <ElTable
- :data="pipelineHistory"
- :default-sort="{
- props: 'id',
- }"
- height="400"
- >
- <ElTableColumn type="expand">
- <template #default="scope">
- <pre class="pipeline-detail">{{scope.row.details}}</pre>
- </template>
- </ElTableColumn>
- <ElTableColumn
- prop="id"
- label="构建ID"
- align="center"
- width="100"
- ></ElTableColumn>
- <ElTableColumn
- prop="pipelineId"
- label="流水线ID"
- align="center"
- width="100"
- ></ElTableColumn>
- <ElTableColumn
- prop="username"
- label="触发人"
- align="center"
- width="180"
- ></ElTableColumn>
- <ElTableColumn
- label="执行时间"
- align="center"
- :formatter="(row) => timeFormatter(row, 'startTime')"
- ></ElTableColumn>
- </ElTable>
- </ElDialog>
- <ElDialog
- v-model="showPipelineEditModal"
- :before-close="(done) => {
- jsonValid=true;
- done();
- }"
- destroy-on-close
- >
- <template #title>
- <span>编辑流水线配置</span>
- <span class="button-group">
- <ElButton type="text">脚本教程</ElButton>
- <ElButton type="text">模板详解</ElButton>
- </span>
- </template>
- <ElInput
- type="textarea"
- :rows="16"
- placeholder="请输入流水线配置"
- @input="lintJson"
- v-model="pipelineConfig">
- ></ElInput>
- <pre v-if="!jsonValid" :innerText="hint"></pre>
- <template #footer>
- <span class="dialog-footer">
- <el-button type="primary" @click="handlePipelineUpdateConfirm" :disabled="!jsonValid">确 定</el-button>
- </span>
- </template>
- </ElDialog>
- <ElDialog
- v-model="showPipelineCreateModal"
- :before-close="(done) => {
- $refs['createPipelineForm'].resetFields();
- done();
- }"
- destroy-on-close
- >
- <template #title>创建流水线</template>
- <ElForm
- :model="createPipelineForm"
- ref="createPipelineForm"
- label-position="top"
- label-suffix=":"
- class="create-pipeline-form"
- >
- <ElFormItem label="名称" prop="name" required>
- <ElInput v-model="createPipelineForm.name" placeholder="请输入流水线名称"></ElInput>
- </ElFormItem>
- <ElFormItem label="模板" prop="template" required>
- <ElSelect v-model="createPipelineForm.template" placeholder="请选择模板">
- <ElOption
- v-for="(template, index) in templates"
- :key="index" :label="template"
- :value="template"
- ></ElOption>
- </ElSelect>
- </ElFormItem>
- </ElForm>
- <template #footer>
- <span class="dialog-footer">
- <el-button type="primary" @click="handlePipelineCreateConfirm">确 定</el-button>
- </span>
- </template>
- </ElDialog>
- </ElTabPane>
- <ElTabPane label="部署产物" name="production">
- <ElTable :data="productions" width="100%">
- <ElTableColumn
- prop="id"
- label="ID"
- align="center"
- width="60"
- ></ElTableColumn>
- <ElTableColumn
- prop="name"
- label="名称"
- align="center"
- ></ElTableColumn>
- <ElTableColumn
- prop="pipelineId"
- label="流水线ID"
- align="center"
- width="100"
- ></ElTableColumn>
- <ElTableColumn
- label="部署时间"
- align="center"
- :formatter="(row) => timeFormatter(row, 'deployedTime')"
- ></ElTableColumn>
- <ElTableColumn
- label="URL"
- align="center"
- >
- <template #default="scope">
- <ElButton type="text" @click="open(scope.row.accessUrl, '_blank')">
- {{scope.row.accessUrl}}
- </ElButton>
- </template>
- </ElTableColumn>
- <ElTableColumn
- label="运行状态"
- align="center"
- >
- <template #default="scope">
- <template v-if="scope.row.status === '正常'">
- <ElTag type="success">{{scope.row.status}}</ElTag>
- </template>
- <template v-else>
- <ElTag type="danger">{{scope.row.status}}</ElTag>
- </template>
- </template>
- </ElTableColumn>
- <ElTableColumn>
- <template #default="scope">
- <ElButton type="text" @click="deleteProduction(scope.row.id)">
- <i class="el-icon-delete-solid"></i>
- </ElButton>
- </template>
- </ElTableColumn>
- </ElTable>
- </ElTabPane>
- </ElTabs>
- </template>
- <script>
- import jsonlint from '@/utils/jsonlint';
- import { PipelineAPI } from '@/api';
- import debounce from '@/utils/debounce';
- export default {
- data() {
- return {
- activeTab: 'pipeline',
- pipelines: [],
- productions: [],
- showPipelineCreateModal: false,
- showPipelineEditModal: false,
- showPipelineHistoryModal: false,
- showPipelineDetailModal: false,
- detail: '',
- pipelineHistory: [],
- pipelineConfig: '',
- jsonValid: true,
- editingPipelineId: -1,
- templates: ['Java项目', 'MySQL'],
- createPipelineForm: {
- name: '',
- template: '',
- },
- };
- },
- async mounted() {
- this.pipelines = await PipelineAPI.getPipelinesByProjectId(this.$store.state.workspace.currentProjectId);
- this.productions = await PipelineAPI.getDeploymentsByProjectId(this.$store.state.workspace.currentProjectId);
- },
- methods: {
- timeFormatter: (row, property) => `${row[property].year}/${row[property].month}/${row[property].day} `
- + `${row[property].hours}:${row[property].minutes}:${row[property].seconds}`,
- async handleClick(action, id) {
- switch (action) {
- case 'create': {
- this.showPipelineCreateModal = true;
- break;
- }
- case 'trigger': {
- await PipelineAPI.triggerDeployment({
- projectId: this.$store.state.workspace.currentProjectId,
- pipelineId: id,
- });
- this.productions = await PipelineAPI.getDeploymentsByProjectId(this.$store.state.workspace.currentProjectId);
- break;
- }
- case 'detail': {
- this.showPipelineDetailModal = true;
- this.detail = Array.prototype.find.call(this.pipelines, (pipeline) => pipeline.id === id).details;
- break;
- }
- case 'history': {
- this.showPipelineHistoryModal = true;
- this.pipelineHistory = await PipelineAPI.getPipelineHistory({
- projectId: this.$store.state.workspace.currentProjectId,
- pipelineId: id,
- });
- break;
- }
- case 'edit': {
- this.showPipelineEditModal = true;
- this.editingPipelineId = id;
- this.pipelineConfig = await PipelineAPI.getPipeline({
- projectId: this.$store.state.workspace.currentProjectId,
- pipelineId: id,
- }).configJson || '{}';
- break;
- }
- case 'delete': {
- PipelineAPI.deletePipeline({
- projectId: this.$store.state.workspace.currentProjectId,
- pipelineId: id,
- });
- break;
- }
- default: {
- console.warn('Unknown type of action.');
- }
- }
- },
- // eslint-disable-next-line func-names
- // FIXME: debounce效果有点问题,待排查
- lintJson: debounce(function (value) {
- try {
- const result = jsonlint.parse(value);
- this.pipelineConfig = JSON.stringify(result, null, ' ');
- this.jsonValid = true;
- } catch (e) {
- this.jsonValid = false;
- this.hint = e;
- }
- }, 500),
- async handlePipelineUpdateConfirm() {
- await PipelineAPI.updatePipeline({
- projectId: this.$store.state.workspace.currentProjectId,
- pipelineId: this.editingPipelineId,
- configJson: JSON.stringify(JSON.parse(this.pipelineConfig)),
- });
- this.showPipelineEditModal = false;
- },
- async handlePipelineCreateConfirm() {
- this.$refs.createPipelineForm.validate(async (valid) => {
- if (valid) {
- await PipelineAPI.createPipeline({
- projectId: this.$store.state.workspace.currentProjectId,
- pipelineId: this.editingPipelineId,
- name: this.createPipelineForm.name,
- templateName: this.createPipelineForm.template,
- });
- this.showPipelineCreateModal = false;
- }
- });
- },
- open(url, target) {
- window.open(url, target);
- },
- async deleteProduction(id) {
- await PipelineAPI.deleteInstance(id);
- },
- },
- };
- </script>
- <style scoped>
- .tabs {
- width: 80%;
- margin: auto auto;
- }
- .add-button {
- margin-left: 14px;
- }
- .pipeline-detail {
- width: 100%;
- word-break: break-word;
- white-space: pre-wrap;
- }
- .create-pipeline-form {
- width: 60%;
- margin: 0 auto;
- }
- .button-group {
- margin-left: 40px;
- }
- </style>
|