pull/361/head
xiaojunnuo 2025-03-11 23:11:24 +08:00
parent 5b8d5dd975
commit f07724372d
9 changed files with 90 additions and 22 deletions

View File

@ -295,4 +295,9 @@ h1, h2, h3, h4, h5, h6 {
.w-50\%{
width: 50%;
}
.ant-drawer-content-wrapper {
max-width: 90vw;
}

View File

@ -1,4 +1,5 @@
import { request } from "/src/api/service";
import { CertInfo } from "/@/views/certd/pipeline/api";
const apiPrefix = "/monitor/cert";
export const certInfoApi = {
@ -53,5 +54,12 @@ export const certInfoApi = {
method: "post",
data: body
});
},
async GetCert(id: number): Promise<CertInfo> {
return await request({
url: apiPrefix + "/getCert",
method: "post",
params: { id: id }
});
}
};

View File

@ -5,6 +5,10 @@ import { certInfoApi } from "./api";
import dayjs from "dayjs";
import { useUserStore } from "/@/store/modules/user";
import { useRouter } from "vue-router";
import { useModal } from "/@/use/use-modal";
import * as api from "/@/views/certd/pipeline/api";
import { notification } from "ant-design-vue";
import CertView from "/@/views/certd/pipeline/cert-view.vue";
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const { t } = useI18n();
@ -30,6 +34,26 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
};
const { openCrudFormDialog } = useFormWrapper();
const router = useRouter();
const model = useModal();
const viewCert = async (row: any) => {
const cert = await api.GetCert(row.id);
if (!cert) {
notification.error({ message: "证书还未生成,请先运行流水线" });
return;
}
model.success({
title: "查看证书",
maskClosable: true,
okText: "关闭",
width: 800,
content: () => {
return <CertView cert={cert}></CertView>;
}
});
};
return {
crudOptions: {
request: {
@ -120,6 +144,15 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
fixed: "right",
buttons: {
view: { show: false },
viewCert: {
order: 3,
title: "查看证书",
type: "link",
icon: "ph:certificate",
async click({ row }) {
await viewCert(row);
}
},
copy: { show: false },
edit: { show: false },
remove: { show: false }

View File

@ -29,6 +29,17 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
return {
crudOptions: {
settings: {
plugins: {
mobile: {
props: {
rowHandle: {
width: 160
}
}
}
}
},
request: {
pageRequest,
addRequest,

View File

@ -1,12 +1,5 @@
<template>
<a-drawer
v-model:open="notificationDrawerVisible"
placement="right"
:closable="true"
width="600px"
class="pi-notification-form"
@after-open-change="notificationDrawerOnAfterVisibleChange"
>
<a-drawer v-model:open="notificationDrawerVisible" placement="right" :closable="true" width="600px" class="pi-notification-form" @after-open-change="notificationDrawerOnAfterVisibleChange">
<template #title>
<div>
编辑通知
@ -59,11 +52,7 @@
rules: [{ required: true, message: '此项必填' }]
}"
/>
<pi-notification-form-email
v-if="currentNotification.type === 'email'"
ref="optionsRef"
v-model:options="currentNotification.options"
></pi-notification-form-email>
<pi-notification-form-email v-if="currentNotification.type === 'email'" ref="optionsRef" v-model:options="currentNotification.options"></pi-notification-form-email>
<fs-form-item
v-else

View File

@ -1,10 +1,13 @@
<template>
<a-modal v-model:open="taskModal.open" class="pi-task-view" title="任务日志" style="width: 80%" v-bind="taskModal">
<a-tabs v-model:active-key="activeKey" tab-position="left" animated>
<a-tabs v-model:active-key="activeKey" :tab-position="tabPosition" animated>
<a-tab-pane v-for="item of detail.nodes" :key="item.node.id">
<template #tab>
<div class="tab-title" :title="item.node.title">
<span class="tab-title-text">{{ item.type }} {{ item.node.title }}</span>
<span class="tab-title-text flex items-center">
<fs-icon icon="ion:chevron-forward-circle" class="text-md mr-1"></fs-icon>
{{ item.node.title }}
</span>
<pi-status-show :status="item.node.status?.result" type="icon"></pi-status-show>
</div>
</template>
@ -22,6 +25,7 @@
import { computed, inject, nextTick, Ref, ref, watch } from "vue";
import { RunHistory } from "../../type";
import PiStatusShow from "/@/views/certd/pipeline/pipeline/component/status-show.vue";
import { usePreferences } from "/@/vben/preferences";
export default {
name: "PiTaskView",
@ -35,6 +39,13 @@ export default {
},
cancelText: "关闭"
});
const { isMobile } = usePreferences();
const tabPosition = computed(() => {
if (isMobile.value) {
return "top";
}
return "left";
});
const detail = ref({ nodes: [] });
const activeKey = ref();
@ -129,7 +140,8 @@ export default {
taskModal,
activeKey,
taskViewOpen,
taskViewClose
taskViewClose,
tabPosition
};
}
};
@ -141,8 +153,8 @@ export default {
display: flex;
.tab-title-text {
display: inline-block;
width: 180px;
display: flex;
max-width: 180px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;

View File

@ -1036,7 +1036,6 @@ export default defineComponent({
height: 30px;
border: 1px solid #eee;
border-right: 0;
z-index: 10000;
border-radius: 5px 0 0 5px;
display: flex;
justify-content: center;

View File

@ -5,9 +5,11 @@
<div class="flex-o mt-5"><span class="label">说明</span>{{ product.intro }}</div>
<div class="flex-o mt-5">
<span class="label">规格</span>
<span class="flex-o">流水线<suite-value class="ml-5" :model-value="product.content.maxPipelineCount" unit="条" /></span>
<span class="flex-o">域名<suite-value class="ml-5" :model-value="product.content.maxDomainCount" unit="个" /></span>
<span class="flex-o">部署次数<suite-value class="ml-5" :model-value="product.content.maxDeployCount" unit="次" /></span>
<span class="flex-o flex-wrap">
<span class="flex-o">流水线<suite-value class="ml-5" :model-value="product.content.maxPipelineCount" unit="条" /></span>
<span class="flex-o">域名<suite-value class="ml-5" :model-value="product.content.maxDomainCount" unit="个" /></span>
<span class="flex-o">部署次数<suite-value class="ml-5" :model-value="product.content.maxDeployCount" unit="次" /></span>
</span>
</div>
<div class="flex-o mt-5">
@ -210,6 +212,7 @@ defineExpose({
text-align: right;
margin-right: 5px;
color: #686868;
flex: none;
}
}

View File

@ -95,4 +95,12 @@ export class CertInfoController extends CrudController<CertInfoService> {
return this.ok(res);
}
@Post('/getCert', { summary: Constants.per.authOnly })
async getCert(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId());
const certInfoEntity = await this.service.info(id);
const certInfo = JSON.parse(certInfoEntity.certInfo);
return this.ok(certInfo);
}
}