mirror of https://github.com/certd/certd
docs(guide): 更新常见问题解答
- 新增 ping 域名的故障排查步骤 - 添加查看容器日志的方法 - 补充 IPv6网络配置的说明pull/409/head
parent
d9a9f1c25c
commit
06f8514bc1
|
@ -18,6 +18,14 @@ services:
|
||||||
# - 8.8.4.4
|
# - 8.8.4.4
|
||||||
```
|
```
|
||||||
|
|
||||||
|
如果仍然有问题,按如下步骤检查是否能够ping通域名
|
||||||
|
```shell
|
||||||
|
docker exec -it certd /bin/sh
|
||||||
|
ping www.baidu.com
|
||||||
|
ping gg.px.certd.handfree.work
|
||||||
|
ping app.handfree.work
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## 2. 连接IPv6超时
|
## 2. 连接IPv6超时
|
||||||
docker-compose 需要放开IPv6网络的配置
|
docker-compose 需要放开IPv6网络的配置
|
||||||
|
@ -43,4 +51,17 @@ networks:
|
||||||
|
|
||||||
## 4. 没有服务器配置文件,请检查是否开启了外网映射!
|
## 4. 没有服务器配置文件,请检查是否开启了外网映射!
|
||||||
宝塔网站证书部署报错:`Error: 没有服务器配置文件,请检查是否开启了外网映射!`
|
宝塔网站证书部署报错:`Error: 没有服务器配置文件,请检查是否开启了外网映射!`
|
||||||
解决方案:先手动在宝塔网站中设置一次证书
|
解决方案:先手动在宝塔网站中设置一次证书
|
||||||
|
|
||||||
|
|
||||||
|
## 5. 如何查看容器日志
|
||||||
|
```shell
|
||||||
|
docker logs -f --tail 200 certd
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,10 @@ onErrorCaptured(e => {
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await settingStore.checkUrlBound();
|
await settingStore.checkUrlBound();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function goGithub() {
|
||||||
|
window.open("https://github.com/certd/certd");
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -63,14 +67,14 @@ onMounted(async () => {
|
||||||
<LockScreen :avatar @to-login="handleLogout" />
|
<LockScreen :avatar @to-login="handleLogout" />
|
||||||
</template>
|
</template>
|
||||||
<template #header-right-0>
|
<template #header-right-0>
|
||||||
<div class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full hidden md:block">
|
<div v-if="!settingStore.isComm" class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full hidden md:block">
|
||||||
<tutorial-button v-if="!settingStore.isComm" class="flex-center header-btn" />
|
<tutorial-button class="flex-center header-btn" />
|
||||||
</div>
|
</div>
|
||||||
<div class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full">
|
<div class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full">
|
||||||
<vip-button class="flex-center header-btn" mode="nav" />
|
<vip-button class="flex-center header-btn" mode="nav" />
|
||||||
</div>
|
</div>
|
||||||
<div class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full">
|
<div v-if="!settingStore.isComm" class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full">
|
||||||
<fs-icon icon="ion:logo-github" />
|
<fs-button shape="circle" type="text" icon="ion:logo-github" :text="null" @click="goGithub" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
|
|
@ -18,11 +18,11 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "LayoutHeader"
|
name: "LayoutHeader",
|
||||||
});
|
});
|
||||||
|
|
||||||
withDefaults(defineProps<Props>(), {
|
withDefaults(defineProps<Props>(), {
|
||||||
theme: "light"
|
theme: "light",
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{ clearPreferencesAndLogout: [] }>();
|
const emit = defineEmits<{ clearPreferencesAndLogout: [] }>();
|
||||||
|
@ -39,42 +39,42 @@ const rightSlots = computed(() => {
|
||||||
if (preferences.widget.globalSearch) {
|
if (preferences.widget.globalSearch) {
|
||||||
list.push({
|
list.push({
|
||||||
index: REFERENCE_VALUE,
|
index: REFERENCE_VALUE,
|
||||||
name: "global-search"
|
name: "global-search",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preferencesButtonPosition.value.header) {
|
if (preferencesButtonPosition.value.header) {
|
||||||
list.push({
|
list.push({
|
||||||
index: REFERENCE_VALUE + 10,
|
index: REFERENCE_VALUE + 10,
|
||||||
name: "preferences"
|
name: "preferences",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (preferences.widget.themeToggle) {
|
if (preferences.widget.themeToggle) {
|
||||||
list.push({
|
list.push({
|
||||||
index: REFERENCE_VALUE + 20,
|
index: REFERENCE_VALUE + 20,
|
||||||
name: "theme-toggle"
|
name: "theme-toggle",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (preferences.widget.languageToggle) {
|
if (preferences.widget.languageToggle) {
|
||||||
list.push({
|
list.push({
|
||||||
index: REFERENCE_VALUE + 30,
|
index: REFERENCE_VALUE + 30,
|
||||||
name: "language-toggle"
|
name: "language-toggle",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (preferences.widget.fullscreen) {
|
if (preferences.widget.fullscreen) {
|
||||||
list.push({
|
list.push({
|
||||||
index: REFERENCE_VALUE + 40,
|
index: REFERENCE_VALUE + 40,
|
||||||
name: "fullscreen"
|
name: "fullscreen",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (preferences.widget.notification) {
|
if (preferences.widget.notification) {
|
||||||
list.push({
|
list.push({
|
||||||
index: REFERENCE_VALUE + 50,
|
index: REFERENCE_VALUE + 50,
|
||||||
name: "notification"
|
name: "notification",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(slots).forEach((key) => {
|
Object.keys(slots).forEach(key => {
|
||||||
const name = key.split("-");
|
const name = key.split("-");
|
||||||
if (key.startsWith("header-right")) {
|
if (key.startsWith("header-right")) {
|
||||||
list.push({ index: Number(name[2]), name: key });
|
list.push({ index: Number(name[2]), name: key });
|
||||||
|
@ -89,11 +89,11 @@ const leftSlots = computed(() => {
|
||||||
if (preferences.widget.refresh) {
|
if (preferences.widget.refresh) {
|
||||||
list.push({
|
list.push({
|
||||||
index: 0,
|
index: 0,
|
||||||
name: "refresh"
|
name: "refresh",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(slots).forEach((key) => {
|
Object.keys(slots).forEach(key => {
|
||||||
const name = key.split("-");
|
const name = key.split("-");
|
||||||
if (key.startsWith("header-left")) {
|
if (key.startsWith("header-left")) {
|
||||||
list.push({ index: Number(name[2]), name: key });
|
list.push({ index: Number(name[2]), name: key });
|
||||||
|
@ -108,7 +108,7 @@ function clearPreferencesAndLogout() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<template v-for="slot in leftSlots.filter((item) => item.index < REFERENCE_VALUE)" :key="slot.name">
|
<template v-for="slot in leftSlots.filter(item => item.index < REFERENCE_VALUE)" :key="slot.name">
|
||||||
<slot :name="slot.name">
|
<slot :name="slot.name">
|
||||||
<template v-if="slot.name === 'refresh'">
|
<template v-if="slot.name === 'refresh'">
|
||||||
<VbenIconButton class="my-0 mr-1 rounded-md" @click="refresh">
|
<VbenIconButton class="my-0 mr-1 rounded-md" @click="refresh">
|
||||||
|
@ -120,7 +120,7 @@ function clearPreferencesAndLogout() {
|
||||||
<div class="flex-center hidden lg:block">
|
<div class="flex-center hidden lg:block">
|
||||||
<slot name="breadcrumb"></slot>
|
<slot name="breadcrumb"></slot>
|
||||||
</div>
|
</div>
|
||||||
<template v-for="slot in leftSlots.filter((item) => item.index > REFERENCE_VALUE)" :key="slot.name">
|
<template v-for="slot in leftSlots.filter(item => item.index > REFERENCE_VALUE)" :key="slot.name">
|
||||||
<slot :name="slot.name"></slot>
|
<slot :name="slot.name"></slot>
|
||||||
</template>
|
</template>
|
||||||
<div :class="`menu-align-${preferences.header.menuAlign}`" class="flex h-full min-w-0 flex-1 items-center">
|
<div :class="`menu-align-${preferences.header.menuAlign}`" class="flex h-full min-w-0 flex-1 items-center">
|
||||||
|
|
|
@ -9,15 +9,15 @@ import { preferences, updatePreferences } from "/@/vben/preferences";
|
||||||
import { VbenDropdownRadioMenu, VbenIconButton } from "/@/vben//shadcn-ui";
|
import { VbenDropdownRadioMenu, VbenIconButton } from "/@/vben//shadcn-ui";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "LanguageToggle"
|
name: "LanguageToggle",
|
||||||
});
|
});
|
||||||
|
|
||||||
async function handleUpdate(value: string) {
|
async function handleUpdate(value: string) {
|
||||||
const locale = value as SupportedLanguagesType;
|
const locale = value as SupportedLanguagesType;
|
||||||
updatePreferences({
|
updatePreferences({
|
||||||
app: {
|
app: {
|
||||||
locale
|
locale,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
await loadLocaleMessages(locale);
|
await loadLocaleMessages(locale);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,11 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "ThemeToggleButton"
|
name: "ThemeToggleButton",
|
||||||
});
|
});
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
type: "normal"
|
type: "normal",
|
||||||
});
|
});
|
||||||
|
|
||||||
const isDark = defineModel<boolean>();
|
const isDark = defineModel<boolean>();
|
||||||
|
@ -29,13 +29,13 @@ const bindProps = computed(() => {
|
||||||
|
|
||||||
return type === "normal"
|
return type === "normal"
|
||||||
? {
|
? {
|
||||||
variant: "heavy" as const
|
variant: "heavy" as const,
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
class: "rounded-full",
|
class: "rounded-full",
|
||||||
size: "icon" as const,
|
size: "icon" as const,
|
||||||
style: { padding: "7px" },
|
style: { padding: "7px" },
|
||||||
variant: "icon" as const
|
variant: "icon" as const,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -59,12 +59,12 @@ function toggleTheme(event: MouseEvent) {
|
||||||
const clipPath = [`circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`];
|
const clipPath = [`circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`];
|
||||||
document.documentElement.animate(
|
document.documentElement.animate(
|
||||||
{
|
{
|
||||||
clipPath: isDark.value ? [...clipPath].reverse() : clipPath
|
clipPath: isDark.value ? [...clipPath].reverse() : clipPath,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
duration: 450,
|
duration: 450,
|
||||||
easing: "ease-in",
|
easing: "ease-in",
|
||||||
pseudoElement: isDark.value ? "::view-transition-old(root)" : "::view-transition-new(root)"
|
pseudoElement: isDark.value ? "::view-transition-old(root)" : "::view-transition-new(root)",
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,16 +10,16 @@ import { ToggleGroup, ToggleGroupItem, VbenTooltip } from "/@/vben//shadcn-ui";
|
||||||
import ThemeButton from "./theme-button.vue";
|
import ThemeButton from "./theme-button.vue";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "ThemeToggle"
|
name: "ThemeToggle",
|
||||||
});
|
});
|
||||||
|
|
||||||
withDefaults(defineProps<{ shouldOnHover?: boolean }>(), {
|
withDefaults(defineProps<{ shouldOnHover?: boolean }>(), {
|
||||||
shouldOnHover: false
|
shouldOnHover: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
function handleChange(isDark: boolean) {
|
function handleChange(isDark: boolean) {
|
||||||
updatePreferences({
|
updatePreferences({
|
||||||
theme: { mode: isDark ? "dark" : "light" }
|
theme: { mode: isDark ? "dark" : "light" },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,18 +29,18 @@ const PRESETS = [
|
||||||
{
|
{
|
||||||
icon: Sun,
|
icon: Sun,
|
||||||
name: "light",
|
name: "light",
|
||||||
title: $t("preferences.theme.light")
|
title: $t("preferences.theme.light"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: MoonStar,
|
icon: MoonStar,
|
||||||
name: "dark",
|
name: "dark",
|
||||||
title: $t("preferences.theme.dark")
|
title: $t("preferences.theme.dark"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: SunMoon,
|
icon: SunMoon,
|
||||||
name: "auto",
|
name: "auto",
|
||||||
title: $t("preferences.followSystem")
|
title: $t("preferences.followSystem"),
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
|
@ -49,7 +49,7 @@ const PRESETS = [
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<ThemeButton :model-value="isDark" type="icon" @update:model-value="handleChange" />
|
<ThemeButton :model-value="isDark" type="icon" @update:model-value="handleChange" />
|
||||||
</template>
|
</template>
|
||||||
<ToggleGroup :model-value="preferences.theme.mode" class="gap-2" type="single" variant="outline" @update:model-value="(val) => updatePreferences({ theme: { mode: val as ThemeModeType } })">
|
<ToggleGroup :model-value="preferences.theme.mode" class="gap-2" type="single" variant="outline" @update:model-value="val => updatePreferences({ theme: { mode: val as ThemeModeType } })">
|
||||||
<ToggleGroupItem v-for="item in PRESETS" :key="item.name" :value="item.name">
|
<ToggleGroupItem v-for="item in PRESETS" :key="item.name" :value="item.name">
|
||||||
<component :is="item.icon" class="size-5" />
|
<component :is="item.icon" class="size-5" />
|
||||||
</ToggleGroupItem>
|
</ToggleGroupItem>
|
||||||
|
|
|
@ -18,7 +18,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
disabled: false,
|
disabled: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
size: "default",
|
size: "default",
|
||||||
variant: "default"
|
variant: "default",
|
||||||
});
|
});
|
||||||
|
|
||||||
const isDisabled = computed(() => {
|
const isDisabled = computed(() => {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { ButtonVariants } from '../../ui';
|
import type { ButtonVariants } from "../../ui";
|
||||||
import type { VbenButtonProps } from './button';
|
import type { VbenButtonProps } from "./button";
|
||||||
|
|
||||||
import { computed, useSlots } from 'vue';
|
import { computed, useSlots } from "vue";
|
||||||
|
|
||||||
import { cn } from '/@/vben/shared/utils';
|
import { cn } from "/@/vben/shared/utils";
|
||||||
|
|
||||||
import { VbenTooltip } from '../tooltip';
|
import { VbenTooltip } from "../tooltip";
|
||||||
import VbenButton from './button.vue';
|
import VbenButton from "./button.vue";
|
||||||
|
|
||||||
interface Props extends VbenButtonProps {
|
interface Props extends VbenButtonProps {
|
||||||
class?: any;
|
class?: any;
|
||||||
|
@ -15,7 +15,7 @@ interface Props extends VbenButtonProps {
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
tooltip?: string;
|
tooltip?: string;
|
||||||
tooltipDelayDuration?: number;
|
tooltipDelayDuration?: number;
|
||||||
tooltipSide?: 'bottom' | 'left' | 'right' | 'top';
|
tooltipSide?: "bottom" | "left" | "right" | "top";
|
||||||
variant?: ButtonVariants;
|
variant?: ButtonVariants;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
disabled: false,
|
disabled: false,
|
||||||
onClick: () => {},
|
onClick: () => {},
|
||||||
tooltipDelayDuration: 200,
|
tooltipDelayDuration: 200,
|
||||||
tooltipSide: 'bottom',
|
tooltipSide: "bottom",
|
||||||
variant: 'icon',
|
variant: "icon",
|
||||||
});
|
});
|
||||||
|
|
||||||
const slots = useSlots();
|
const slots = useSlots();
|
||||||
|
@ -33,30 +33,13 @@ const showTooltip = computed(() => !!slots.tooltip || !!props.tooltip);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VbenButton
|
<VbenButton v-if="!showTooltip" :class="cn('rounded-full', props.class)" :disabled="disabled" :variant="variant" size="icon" @click="onClick">
|
||||||
v-if="!showTooltip"
|
|
||||||
:class="cn('rounded-full', props.class)"
|
|
||||||
:disabled="disabled"
|
|
||||||
:variant="variant"
|
|
||||||
size="icon"
|
|
||||||
@click="onClick"
|
|
||||||
>
|
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</VbenButton>
|
</VbenButton>
|
||||||
|
|
||||||
<VbenTooltip
|
<VbenTooltip v-else :delay-duration="tooltipDelayDuration" :side="tooltipSide">
|
||||||
v-else
|
|
||||||
:delay-duration="tooltipDelayDuration"
|
|
||||||
:side="tooltipSide"
|
|
||||||
>
|
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<VbenButton
|
<VbenButton :class="cn('rounded-full', props.class)" :disabled="disabled" :variant="variant" size="icon" @click="onClick">
|
||||||
:class="cn('rounded-full', props.class)"
|
|
||||||
:disabled="disabled"
|
|
||||||
:variant="variant"
|
|
||||||
size="icon"
|
|
||||||
@click="onClick"
|
|
||||||
>
|
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</VbenButton>
|
</VbenButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import {Inject, Provide, Scope, ScopeEnum} from "@midwayjs/core";
|
import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core";
|
||||||
import {BaseService, PageReq} from "@certd/lib-server";
|
import { BaseService, PageReq } from "@certd/lib-server";
|
||||||
import {PluginEntity} from "../entity/plugin.js";
|
import { PluginEntity } from "../entity/plugin.js";
|
||||||
import {InjectEntityModel} from "@midwayjs/typeorm";
|
import { InjectEntityModel } from "@midwayjs/typeorm";
|
||||||
import {Repository} from "typeorm";
|
import { Repository } from "typeorm";
|
||||||
import {isComm} from "@certd/plus-core";
|
import { isComm } from "@certd/plus-core";
|
||||||
import {BuiltInPluginService} from "../../pipeline/service/builtin-plugin-service.js";
|
import { BuiltInPluginService } from "../../pipeline/service/builtin-plugin-service.js";
|
||||||
import {merge} from "lodash-es";
|
import { merge } from "lodash-es";
|
||||||
import {accessRegistry, notificationRegistry, pluginRegistry} from "@certd/pipeline";
|
import { accessRegistry, notificationRegistry, pluginRegistry } from "@certd/pipeline";
|
||||||
import {dnsProviderRegistry} from "@certd/plugin-cert";
|
import { dnsProviderRegistry } from "@certd/plugin-cert";
|
||||||
import {logger} from "@certd/basic";
|
import { logger } from "@certd/basic";
|
||||||
import yaml from "js-yaml";
|
import yaml from "js-yaml";
|
||||||
import {getDefaultAccessPlugin, getDefaultDeployPlugin, getDefaultDnsPlugin} from "./default-plugin.js";
|
import { getDefaultAccessPlugin, getDefaultDeployPlugin, getDefaultDnsPlugin } from "./default-plugin.js";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
|
@ -254,9 +254,6 @@ export class PluginService extends BaseService<PluginEntity> {
|
||||||
}).constructor;
|
}).constructor;
|
||||||
// const script = await this.compile(plugin.content);
|
// const script = await this.compile(plugin.content);
|
||||||
const script = plugin.content;
|
const script = plugin.content;
|
||||||
const {MaoyunClient} = await import("@certd/plugin-plus")
|
|
||||||
const a :any ={}
|
|
||||||
new MaoyunClient(a)
|
|
||||||
const getPluginClass = new AsyncFunction(script);
|
const getPluginClass = new AsyncFunction(script);
|
||||||
return await getPluginClass({logger: logger});
|
return await getPluginClass({logger: logger});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
Loading…
Reference in New Issue