pull/243/head
xiaojunnuo 2024-10-31 10:32:05 +08:00
parent f92935d93f
commit ee65c9f47d
10 changed files with 140 additions and 49 deletions

View File

@ -42,19 +42,20 @@ function setGlobalProxy(opts) {
}
class HttpError extends Error {
// eslint-disable-next-line constructor-super
constructor(error) {
super(error || error.message);
if (!error) {
return;
}
super(error.message);
if (error.message.indexOf('ssl3_get_record:wrong version number') >= 0) {
this.message = error.message;
if (this.message && this.message.indexOf('ssl3_get_record:wrong version number') >= 0) {
this.message = 'http协议错误服务端要求http协议请检查是否使用了https请求';
}
this.name = error.name;
this.code = error.code;
this.cause = error.cause;
if (error.response) {
this.status = error.response.status;
@ -62,6 +63,9 @@ class HttpError extends Error {
this.response = {
data: error.response.data,
};
if (!this.message) {
this.message = this.statusText;
}
}
let url = '';
@ -73,12 +77,18 @@ class HttpError extends Error {
params: error.config.params,
data: error.config.data,
};
url = error.config.baseURL + error.config.url;
url = (error.config.baseURL || '') + error.config.url;
}
if (url) {
this.message = `${this.message}:${url}`;
}
// const { stack, cause } = error;
delete this.cause;
delete this.stack;
// this.cause = cause;
// this.stack = stack;
delete error.stack;
delete error.cause;
delete error.response;
delete error.config;
delete error.request;

View File

@ -114,17 +114,19 @@ instance.interceptors.response.use(null, async (error) => {
const code = response ? `HTTP ${response.status}` : error.code;
log(`Caught ${code}, retry attempt ${config.retryAttempt}/${retryMaxAttempts} to URL ${config.url}`);
const retryAfter = (retryDefaultDelay * config.retryAttempt);
/* Attempt to parse Retry-After header, fallback to default delay */
let retryAfter = response ? parseRetryAfterHeader(response.headers['retry-after']) : 0;
const headerRetryAfter = response ? parseRetryAfterHeader(response.headers['retry-after']) : 0;
if (retryAfter > 0) {
log(`Found retry-after response header with value: ${response.headers['retry-after']}, waiting ${retryAfter} seconds`);
}
else {
retryAfter = (retryDefaultDelay * config.retryAttempt);
log(`Unable to locate or parse retry-after response header, waiting ${retryAfter} seconds`);
if (headerRetryAfter > 0) {
const waitMinutes = (headerRetryAfter / 60).toFixed(1);
log(`Found retry-after response header with value: ${response.headers['retry-after']}, waiting ${waitMinutes} minutes`);
log(JSON.stringify(response.data));
return Promise.reject(new Agents.HttpError(error));
}
log(`waiting ${retryAfter} seconds`);
/* Wait and retry the request */
await new Promise((resolve) => { setTimeout(resolve, (retryAfter * 1000)); });
return instance(config);

View File

@ -17,7 +17,7 @@ export class HttpError extends Error {
if (!error) {
return;
}
super(error.message);
super(error.message || error.response?.statusText);
if (error?.message?.indexOf('ssl3_get_record:wrong version number') >= 0) {
this.message = 'http协议错误服务端要求http协议请检查是否使用了https请求';
@ -25,7 +25,6 @@ export class HttpError extends Error {
this.name = error.name;
this.code = error.code;
this.cause = error.cause;
this.status = error.response?.status;
this.statusText = error.response?.statusText;
@ -38,7 +37,7 @@ export class HttpError extends Error {
};
let url = error.config?.url;
if (error.config?.baseURL) {
url = error.config?.baseURL + url;
url = (error.config?.baseURL || '') + url;
}
if (url) {
this.message = `${this.message} : url=${url}`;
@ -48,6 +47,9 @@ export class HttpError extends Error {
data: error.response?.data,
};
// const { stack, cause } = error;
// this.cause = cause;
// this.stack = stack;
delete error.response;
delete error.config;
delete error.request;

View File

@ -117,7 +117,8 @@ export class RunHistory {
}
logError(runnable: Runnable, e: Error) {
// @ts-ignore
delete e.stack;
delete e.cause;
const errorInfo = runnable.runnableType === "step" ? e : e.message;
this._loggers[runnable.id].error(`[${runnable.runnableType}] [${runnable.title}]<id:${runnable.id}> `, errorInfo);
}

View File

@ -6,23 +6,16 @@ const openedRef = ref(false);
function open() {
openedRef.value = true;
}
function close() {
openedRef.value = false;
}
function prev() {
console.log("prev");
}
function next() {
console.log("next");
}
const settingStore = useSettingStore();
const slots = defineSlots();
</script>
<template>
<div v-if="!settingStore.isComm" class="tutorial-button" @click="open">
<fs-icon icon="mingcute:question-line"></fs-icon>
<div class="ml-5">使用教程</div>
<div class="tutorial-button pointer" @click="open">
<template v-if="!slots.default">
<fs-icon icon="mingcute:question-line"></fs-icon>
<div class="ml-5">使用教程</div>
</template>
<slot></slot>
<a-modal v-model:open="openedRef" class="tutorial-modal" width="90%">
<template #title> 使用教程 </template>
<tutorial-steps v-if="openedRef" />

View File

@ -45,10 +45,7 @@ const steps = ref<Step[]>([
items: [
{
title: "教程演示内容",
descriptions: [
"1. 本教程演示如何全自动申请和更新证书部署证书到阿里云CDN和Nginx证书到期后自动续期自动部署",
"2. 演示流程:创建证书申请流水线 -> 添加部署任务 -> 运行测试 -> 设置定时执行和邮件通知"
]
descriptions: ["本教程演示如何自动申请证书并部署到Nginx上"]
},
{
image: "/static/doc/images/1-add.png",

View File

@ -28,7 +28,7 @@
<fs-icon :icon="menu.meta.icon"></fs-icon>
<span class="ml-5">{{ menu.title }} </span>
</div>
<tutorial-button class="flex-center header-btn" />
<tutorial-button v-if="!settingStore.isComm" class="flex-center header-btn" />
<vip-button class="flex-center header-btn" mode="nav" />
</div>
<div class="header-right header-buttons">

View File

@ -5,21 +5,44 @@
<a-avatar size="large" :src="userStore?.userInfo?.avatar"></a-avatar>
</div>
<div class="text">
<div>您好{{ userStore?.userInfo?.nickName || userStore?.userInfo?.username }}</div>
<div>
<a-tag color="green" class="flex-inline"> <fs-icon icon="ion:time-outline" class="mr-5"></fs-icon> {{ now }}</a-tag>
<div class="left">
<div>
<span>您好{{ userStore?.userInfo?.nickName || userStore?.userInfo?.username }} 欢迎使用 {{ siteInfo.title }} </span>
</div>
<div>
<a-tag color="green" class="flex-inline"> <fs-icon icon="ion:time-outline" class="mr-5"></fs-icon> {{ now }}</a-tag>
</div>
</div>
</div>
<div class="suggest"></div>
<div class="suggest">
<div>
<tutorial-button class="flex-center">
<a-tag color="blue" class="flex-center">
仅需3步让你的证书永不过期 <fs-icon class="font-size-16 ml-5" icon="mingcute:question-line"></fs-icon
></a-tag>
</tutorial-button>
<simple-steps></simple-steps>
</div>
</div>
</div>
<div v-if="!settingStore.isComm" class="warning">
<a-alert type="warning" show-icon>
<template #message>
证书和授权为敏感信息不要使用来历不明的在线Certd服务和镜像请务必私有化部署使用保护数据安全认准官方版本发布渠道
<a class="ml-5 flex-inline" href="https://gitee.com/certd/certd" target="_blank">gitee</a>
<a class="ml-5 flex-inline" href="https://github.com/certd/certd" target="_blank">github</a>
<a class="ml-5 flex-inline" href="https://certd.docmirror.cn" target="_blank">帮助文档</a>
</template>
</a-alert>
</div>
<div class="statistic-data m-20">
<a-row :gutter="20">
<a-col :span="6">
<statistic-card title="流水线数量"></statistic-card>
<statistic-card title="提醒"> </statistic-card>
</a-col>
<a-col :span="6">
<statistic-card title="运行次数"></statistic-card>
<statistic-card title="流水线数量"></statistic-card>
</a-col>
<a-col :span="6">
<statistic-card title="最近运行"></statistic-card>
@ -27,6 +50,11 @@
<a-col :span="6">
<statistic-card title="最近到期证书"></statistic-card>
</a-col>
<!-- <a-col :span="12">-->
<!-- <statistic-card title="3步自动部署">-->
<!-- <simple-steps></simple-steps>-->
<!-- </statistic-card>-->
<!-- </a-col>-->
</a-row>
</div>
@ -56,16 +84,25 @@
<script lang="ts" setup>
import { FsIcon } from "@fast-crud/fast-crud";
import SimpleSteps from "./simple-steps.vue";
defineOptions({
name: "DashboardUser"
});
import { useUserStore } from "/@/store/modules/user";
import { computed, onMounted, ref } from "vue";
import { computed, onMounted, Ref, ref } from "vue";
import dayjs from "dayjs";
import StatisticCard from "/@/views/framework/home/dashboard/statistic-card.vue";
import * as pluginApi from "/@/views/certd/pipeline/api.plugin";
import { PluginGroups } from "/@/views/certd/pipeline/pipeline/type";
import TutorialButton from "/@/components/tutorial/index.vue";
import { useSettingStore } from "/@/store/modules/settings";
import { SiteInfo } from "/@/api/modules/api.basic";
const version = ref(import.meta.env.VITE_APP_VERSION);
const settingStore = useSettingStore();
const siteInfo: Ref<SiteInfo> = computed(() => {
return settingStore.siteInfo;
});
const userStore = useUserStore();
const now = computed(() => {
@ -85,23 +122,39 @@ onMounted(async () => {
<style lang="less">
.dashboard-user {
.warning {
.ant-alert {
border-left: 0;
border-right: 0;
border-radius: 0;
}
}
.header-profile {
display: flex;
align-items: center;
padding: 20px;
background-color: #fff;
.avatar {
margin-right: 20px;
}
.text {
flex: 1;
display: flex;
flex-direction: column;
div {
margin-bottom: 10px;
flex-direction: row;
.left {
display: flex;
flex-direction: column;
justify-content: center;
> div {
margin: 2px;
}
}
}
}
.notice {
padding: 20px;
}
.plugin-list {
margin: 0 20px;

View File

@ -0,0 +1,31 @@
<template>
<a-steps :current="3" class="mt-10" size="small" :items="steps" @click="goPipeline"></a-steps>
</template>
<script lang="ts" setup>
import { useRouter } from "vue-router";
type Step = {
title: string;
description?: string;
};
import { ref } from "vue";
const steps = ref<Step[]>([
{
title: "创建证书流水线"
},
{
title: "添加部署任务"
},
{
title: "定时运行"
}
]);
const router = useRouter();
function goPipeline() {
router.push({ path: "/certd/pipeline" });
}
</script>

View File

@ -7,12 +7,13 @@
<div class="more"></div>
</div>
<div class="content">
<div class="statistic">
<div v-if="!slots.default" class="statistic">
<div class="value">80</div>
</div>
<slot></slot>
</div>
<div class="footer">
<div class="icon-text"><fs-icon icon="ion:settings-outline" /> 管理流水线</div>
<div class="icon-text"><fs-icon icon="ion:settings-outline" />管理流水线</div>
</div>
</div>
</a-card>
@ -23,6 +24,7 @@ import { FsIcon } from "@fast-crud/fast-crud";
const props = defineProps<{
title: string;
}>();
const slots = defineSlots();
</script>
<style lang="less">
.statistic-card {