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\%{ .w-50\%{
width: 50%; width: 50%;
}
.ant-drawer-content-wrapper {
max-width: 90vw;
} }

View File

@ -1,4 +1,5 @@
import { request } from "/src/api/service"; import { request } from "/src/api/service";
import { CertInfo } from "/@/views/certd/pipeline/api";
const apiPrefix = "/monitor/cert"; const apiPrefix = "/monitor/cert";
export const certInfoApi = { export const certInfoApi = {
@ -53,5 +54,12 @@ export const certInfoApi = {
method: "post", method: "post",
data: body 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 dayjs from "dayjs";
import { useUserStore } from "/@/store/modules/user"; import { useUserStore } from "/@/store/modules/user";
import { useRouter } from "vue-router"; 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 { export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const { t } = useI18n(); const { t } = useI18n();
@ -30,6 +34,26 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
}; };
const { openCrudFormDialog } = useFormWrapper(); const { openCrudFormDialog } = useFormWrapper();
const router = useRouter(); 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 { return {
crudOptions: { crudOptions: {
request: { request: {
@ -120,6 +144,15 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
fixed: "right", fixed: "right",
buttons: { buttons: {
view: { show: false }, view: { show: false },
viewCert: {
order: 3,
title: "查看证书",
type: "link",
icon: "ph:certificate",
async click({ row }) {
await viewCert(row);
}
},
copy: { show: false }, copy: { show: false },
edit: { show: false }, edit: { show: false },
remove: { show: false } remove: { show: false }

View File

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

View File

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

View File

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

View File

@ -1036,7 +1036,6 @@ export default defineComponent({
height: 30px; height: 30px;
border: 1px solid #eee; border: 1px solid #eee;
border-right: 0; border-right: 0;
z-index: 10000;
border-radius: 5px 0 0 5px; border-radius: 5px 0 0 5px;
display: flex; display: flex;
justify-content: center; 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>{{ product.intro }}</div>
<div class="flex-o mt-5"> <div class="flex-o mt-5">
<span class="label">规格</span> <span class="label">规格</span>
<span class="flex-o">流水线<suite-value class="ml-5" :model-value="product.content.maxPipelineCount" unit="条" /></span> <span class="flex-o flex-wrap">
<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.maxPipelineCount" unit="条" /></span>
<span class="flex-o">部署次数<suite-value class="ml-5" :model-value="product.content.maxDeployCount" 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>
<div class="flex-o mt-5"> <div class="flex-o mt-5">
@ -210,6 +212,7 @@ defineExpose({
text-align: right; text-align: right;
margin-right: 5px; margin-right: 5px;
color: #686868; color: #686868;
flex: none;
} }
} }

View File

@ -95,4 +95,12 @@ export class CertInfoController extends CrudController<CertInfoService> {
return this.ok(res); 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);
}
} }