mirror of https://github.com/certd/certd
chore: 插件编辑与运行测试beta
parent
c021dd03d3
commit
a0eeb17d73
|
@ -3,14 +3,23 @@ import { AbstractTaskPlugin } from "./api.js";
|
|||
import { pluginGroups } from "./group.js";
|
||||
|
||||
const onRegister = ({ key, value }: OnRegisterContext<AbstractTaskPlugin>) => {
|
||||
//如果有相同名字的先移除
|
||||
|
||||
for (const group of Object.values(pluginGroups)) {
|
||||
const index = group.plugins.findIndex(plugin => plugin.name === key);
|
||||
if (index > -1) {
|
||||
group.plugins.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
const group = value?.define?.group as string;
|
||||
if (group) {
|
||||
if (pluginGroups.hasOwnProperty(group)) {
|
||||
// @ts-ignore
|
||||
pluginGroups[group].plugins.push(value.define);
|
||||
} else {
|
||||
pluginGroups.other.plugins.push(value.define);
|
||||
return;
|
||||
}
|
||||
}
|
||||
pluginGroups.other.plugins.push(value.define);
|
||||
};
|
||||
export const pluginRegistry = createRegistry<AbstractTaskPlugin>("plugin", onRegister);
|
||||
|
|
|
@ -26,7 +26,6 @@ export function registerWorker(name: string, worker: any) {
|
|||
window.MonacoEnvironment = {
|
||||
//@ts-ignore
|
||||
getWorker(_, label) {
|
||||
debugger;
|
||||
const custom = WorkerBucket[label];
|
||||
if (custom) {
|
||||
return new custom();
|
||||
|
|
|
@ -83,17 +83,6 @@ const emitValue = lodashDebounce((value: any) => {
|
|||
emits("update:modelValue", value);
|
||||
}, props.debounce || 500);
|
||||
|
||||
// watch(
|
||||
// () => {
|
||||
// return props.modelValue;
|
||||
// },
|
||||
// (value: string) => {
|
||||
// if (instanceRef.value && value !== instanceRef.value.getValue()) {
|
||||
// // instanceRef.value.setValue(value);
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
|
||||
async function createEditor(ctx: EditorCodeCtx) {
|
||||
disposeEditor();
|
||||
const instance = monaco.editor.create(monacoRef.value, {
|
||||
|
@ -121,6 +110,9 @@ async function createEditor(ctx: EditorCodeCtx) {
|
|||
instanceRef = instance;
|
||||
ctx.instance = instance;
|
||||
emits("ready", ctx);
|
||||
if (props.modelValue) {
|
||||
instanceRef.setValue(props.modelValue);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
@ -224,6 +216,9 @@ watch(
|
|||
editor.setValue(newValue);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -49,7 +49,6 @@ export async function initWorkers() {
|
|||
} else if (label === "typescript" || label === "javascript") {
|
||||
return new tsWorker.default();
|
||||
} else if (label === "yaml" || label === "yml") {
|
||||
debugger;
|
||||
//@ts-ignore
|
||||
return new yamlWorker.default();
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ export default router;
|
|||
// // 多页控制 打开新的页面
|
||||
// const pageStore = usePageStore();
|
||||
// // for (const item of to.matched) {
|
||||
// // pageStore.keepAlivePush(item.name);
|
||||
// // pageStore.cachePush(item.name);
|
||||
// // }
|
||||
// pageStore.open(to);
|
||||
// // 更改标题
|
||||
|
|
|
@ -58,7 +58,7 @@ function transformOneResource(resource: any, parent: any) {
|
|||
}
|
||||
return {
|
||||
menu,
|
||||
route
|
||||
route,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ export const buildMenusAndRouters = (resources: any, parent: any = null) => {
|
|||
setIndex(menus);
|
||||
return {
|
||||
routes,
|
||||
menus
|
||||
menus,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ export const sysResources = [
|
|||
meta: {
|
||||
icon: "ion:earth-outline",
|
||||
permission: "sys:settings:view",
|
||||
cache: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -110,6 +111,7 @@ export const sysResources = [
|
|||
meta: {
|
||||
icon: "ion:extension-puzzle-outline",
|
||||
permission: "sys:settings:view",
|
||||
cache: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -121,6 +123,7 @@ export const sysResources = [
|
|||
isMenu: false,
|
||||
icon: "ion:extension-puzzle",
|
||||
permission: "sys:settings:view",
|
||||
cache: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -145,6 +148,7 @@ export const sysResources = [
|
|||
meta: {
|
||||
icon: "ion:golf-outline",
|
||||
permission: "sys:settings:view",
|
||||
cache: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -88,7 +88,7 @@ function wrapperMenus(menus: MenuRecordRaw[], deep: boolean = true) {
|
|||
? mapTree(menus, (item: any) => {
|
||||
return { ...cloneDeep(item), name: $t(item.name) };
|
||||
})
|
||||
: menus.map((item) => {
|
||||
: menus.map(item => {
|
||||
return { ...cloneDeep(item), name: $t(item.name) };
|
||||
});
|
||||
}
|
||||
|
@ -96,8 +96,8 @@ function wrapperMenus(menus: MenuRecordRaw[], deep: boolean = true) {
|
|||
function toggleSidebar() {
|
||||
updatePreferences({
|
||||
sidebar: {
|
||||
hidden: !preferences.sidebar.hidden
|
||||
}
|
||||
hidden: !preferences.sidebar.hidden,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -107,12 +107,12 @@ function clearPreferencesAndLogout() {
|
|||
|
||||
watch(
|
||||
() => preferences.app.layout,
|
||||
async (val) => {
|
||||
async val => {
|
||||
if (val === "sidebar-mixed-nav" && preferences.sidebar.hidden) {
|
||||
updatePreferences({
|
||||
sidebar: {
|
||||
hidden: false
|
||||
}
|
||||
hidden: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ watch(i18n.global.locale, refresh, { flush: "post" });
|
|||
|
||||
const slots: SetupContext["slots"] = useSlots();
|
||||
const headerSlots = computed(() => {
|
||||
return Object.keys(slots).filter((key) => key.startsWith("header-"));
|
||||
return Object.keys(slots).filter(key => key.startsWith("header-"));
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -20,14 +20,14 @@ const defaultPreferences: Preferences = {
|
|||
loginExpiredMode: "page",
|
||||
name: "",
|
||||
preferencesButtonPosition: "auto",
|
||||
watermark: false
|
||||
watermark: false,
|
||||
},
|
||||
breadcrumb: {
|
||||
enable: true,
|
||||
hideOnlyOne: false,
|
||||
showHome: false,
|
||||
showIcon: true,
|
||||
styleType: "normal"
|
||||
styleType: "normal",
|
||||
},
|
||||
copyright: {
|
||||
companyName: "greper",
|
||||
|
@ -36,33 +36,33 @@ const defaultPreferences: Preferences = {
|
|||
enable: false,
|
||||
icp: "",
|
||||
icpLink: "",
|
||||
settingShow: false
|
||||
settingShow: false,
|
||||
},
|
||||
footer: {
|
||||
enable: true,
|
||||
fixed: false
|
||||
fixed: false,
|
||||
},
|
||||
header: {
|
||||
enable: true,
|
||||
hidden: false,
|
||||
menuAlign: "start",
|
||||
mode: "fixed"
|
||||
mode: "fixed",
|
||||
},
|
||||
logo: {
|
||||
enable: true,
|
||||
source: "./static/images/logo/logo.svg"
|
||||
source: "./static/images/logo/logo.svg",
|
||||
},
|
||||
navigation: {
|
||||
accordion: true,
|
||||
split: true,
|
||||
styleType: "rounded"
|
||||
styleType: "rounded",
|
||||
},
|
||||
shortcutKeys: {
|
||||
enable: true,
|
||||
globalLockScreen: true,
|
||||
globalLogout: true,
|
||||
globalPreferences: true,
|
||||
globalSearch: true
|
||||
globalSearch: true,
|
||||
},
|
||||
sidebar: {
|
||||
autoActivateChild: true,
|
||||
|
@ -72,7 +72,7 @@ const defaultPreferences: Preferences = {
|
|||
expandOnHover: true,
|
||||
extraCollapse: false,
|
||||
hidden: false,
|
||||
width: 224
|
||||
width: 224,
|
||||
},
|
||||
tabbar: {
|
||||
draggable: true,
|
||||
|
@ -86,7 +86,7 @@ const defaultPreferences: Preferences = {
|
|||
showMaximize: true,
|
||||
showMore: true,
|
||||
styleType: "chrome",
|
||||
wheelable: true
|
||||
wheelable: true,
|
||||
},
|
||||
theme: {
|
||||
builtinType: "default",
|
||||
|
@ -97,13 +97,13 @@ const defaultPreferences: Preferences = {
|
|||
mode: "light",
|
||||
radius: "0.5",
|
||||
semiDarkHeader: false,
|
||||
semiDarkSidebar: false
|
||||
semiDarkSidebar: false,
|
||||
},
|
||||
transition: {
|
||||
enable: true,
|
||||
loading: false,
|
||||
name: "fade-slide",
|
||||
progress: true
|
||||
progress: true,
|
||||
},
|
||||
widget: {
|
||||
fullscreen: true,
|
||||
|
@ -113,8 +113,8 @@ const defaultPreferences: Preferences = {
|
|||
notification: false,
|
||||
refresh: true,
|
||||
sidebarToggle: true,
|
||||
themeToggle: true
|
||||
}
|
||||
themeToggle: true,
|
||||
},
|
||||
};
|
||||
|
||||
export { defaultPreferences };
|
||||
|
|
|
@ -45,7 +45,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
* Close tabs in bulk
|
||||
*/
|
||||
async _bulkCloseByPaths(paths: string[]) {
|
||||
this.tabs = this.tabs.filter((item) => {
|
||||
this.tabs = this.tabs.filter(item => {
|
||||
return !paths.includes(getTabPath(item));
|
||||
});
|
||||
|
||||
|
@ -60,7 +60,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
if (isAffixTab(tab)) {
|
||||
return;
|
||||
}
|
||||
const index = this.tabs.findIndex((item) => item.fullPath === fullPath);
|
||||
const index = this.tabs.findIndex(item => item.fullPath === fullPath);
|
||||
index !== -1 && this.tabs.splice(index, 1);
|
||||
},
|
||||
/**
|
||||
|
@ -85,7 +85,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
const toParams = {
|
||||
params: params || {},
|
||||
path,
|
||||
query: query || {}
|
||||
query: query || {},
|
||||
};
|
||||
await router.replace(toParams);
|
||||
},
|
||||
|
@ -99,7 +99,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
return;
|
||||
}
|
||||
|
||||
const tabIndex = this.tabs.findIndex((tab) => {
|
||||
const tabIndex = this.tabs.findIndex(tab => {
|
||||
return getTabPath(tab) === getTabPath(routeTab);
|
||||
});
|
||||
|
||||
|
@ -109,13 +109,13 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
const maxNumOfOpenTab = (routeTab?.meta?.maxNumOfOpenTab ?? -1) as number;
|
||||
// 如果动态路由层级大于 0 了,那么就要限制该路由的打开数限制了
|
||||
// 获取到已经打开的动态路由数, 判断是否大于某一个值
|
||||
if (maxNumOfOpenTab > 0 && this.tabs.filter((tab) => tab.name === routeTab.name).length >= maxNumOfOpenTab) {
|
||||
if (maxNumOfOpenTab > 0 && this.tabs.filter(tab => tab.name === routeTab.name).length >= maxNumOfOpenTab) {
|
||||
// 关闭第一个
|
||||
const index = this.tabs.findIndex((item) => item.name === routeTab.name);
|
||||
const index = this.tabs.findIndex(item => item.name === routeTab.name);
|
||||
index !== -1 && this.tabs.splice(index, 1);
|
||||
} else if (maxCount > 0 && this.tabs.length >= maxCount) {
|
||||
// 关闭第一个
|
||||
const index = this.tabs.findIndex((item) => !Reflect.has(item.meta, "affixTab") || !item.meta.affixTab);
|
||||
const index = this.tabs.findIndex(item => !Reflect.has(item.meta, "affixTab") || !item.meta.affixTab);
|
||||
index !== -1 && this.tabs.splice(index, 1);
|
||||
}
|
||||
this.tabs.push(tab);
|
||||
|
@ -125,7 +125,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
const mergedTab = {
|
||||
...currentTab,
|
||||
...tab,
|
||||
meta: { ...currentTab?.meta, ...tab.meta }
|
||||
meta: { ...currentTab?.meta, ...tab.meta },
|
||||
};
|
||||
if (currentTab) {
|
||||
const curMeta = currentTab.meta;
|
||||
|
@ -145,7 +145,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
* @zh_CN 关闭所有标签页
|
||||
*/
|
||||
async closeAllTabs(router: Router) {
|
||||
const newTabs = this.tabs.filter((tab) => isAffixTab(tab));
|
||||
const newTabs = this.tabs.filter(tab => isAffixTab(tab));
|
||||
this.tabs = newTabs.length > 0 ? newTabs : [...this.tabs].splice(0, 1);
|
||||
await this._goToDefaultTab(router);
|
||||
this.updateCacheTabs();
|
||||
|
@ -155,7 +155,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
* @param tab
|
||||
*/
|
||||
async closeLeftTabs(tab: TabDefinition) {
|
||||
const index = this.tabs.findIndex((item) => getTabPath(item) === getTabPath(tab));
|
||||
const index = this.tabs.findIndex(item => getTabPath(item) === getTabPath(tab));
|
||||
|
||||
if (index < 1) {
|
||||
return;
|
||||
|
@ -176,13 +176,13 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
* @param tab
|
||||
*/
|
||||
async closeOtherTabs(tab: TabDefinition) {
|
||||
const closePaths = this.tabs.map((item) => getTabPath(item));
|
||||
const closePaths = this.tabs.map(item => getTabPath(item));
|
||||
|
||||
const paths: string[] = [];
|
||||
|
||||
for (const path of closePaths) {
|
||||
if (path !== tab.fullPath) {
|
||||
const closeTab = this.tabs.find((item) => getTabPath(item) === path);
|
||||
const closeTab = this.tabs.find(item => getTabPath(item) === path);
|
||||
if (!closeTab) {
|
||||
continue;
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
* @param tab
|
||||
*/
|
||||
async closeRightTabs(tab: TabDefinition) {
|
||||
const index = this.tabs.findIndex((item) => getTabPath(item) === getTabPath(tab));
|
||||
const index = this.tabs.findIndex(item => getTabPath(item) === getTabPath(tab));
|
||||
|
||||
if (index !== -1 && index < this.tabs.length - 1) {
|
||||
const rightTabs = this.tabs.slice(index + 1);
|
||||
|
@ -227,7 +227,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
this.updateCacheTabs();
|
||||
return;
|
||||
}
|
||||
const index = this.getTabs.findIndex((item) => getTabPath(item) === getTabPath(currentRoute.value));
|
||||
const index = this.getTabs.findIndex(item => getTabPath(item) === getTabPath(currentRoute.value));
|
||||
|
||||
const before = this.getTabs[index - 1];
|
||||
const after = this.getTabs[index + 1];
|
||||
|
@ -252,7 +252,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
*/
|
||||
async closeTabByKey(key: string, router: Router) {
|
||||
const originKey = decodeURIComponent(key);
|
||||
const index = this.tabs.findIndex((item) => getTabPath(item) === originKey);
|
||||
const index = this.tabs.findIndex(item => getTabPath(item) === originKey);
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
* @param path
|
||||
*/
|
||||
getTabByPath(path: string) {
|
||||
return this.getTabs.find((item) => getTabPath(item) === path) as TabDefinition;
|
||||
return this.getTabs.find(item => getTabPath(item) === path) as TabDefinition;
|
||||
},
|
||||
/**
|
||||
* @zh_CN 新窗口打开标签页
|
||||
|
@ -283,7 +283,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
* @param tab
|
||||
*/
|
||||
async pinTab(tab: TabDefinition) {
|
||||
const index = this.tabs.findIndex((item) => getTabPath(item) === getTabPath(tab));
|
||||
const index = this.tabs.findIndex(item => getTabPath(item) === getTabPath(tab));
|
||||
if (index !== -1) {
|
||||
const oldTab = this.tabs[index];
|
||||
tab.meta.affixTab = true;
|
||||
|
@ -292,9 +292,9 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
this.tabs.splice(index, 1, tab);
|
||||
}
|
||||
// 过滤固定tabs,后面更改affixTabOrder的值的话可能会有问题,目前行464排序affixTabs没有设置值
|
||||
const affixTabs = this.tabs.filter((tab) => isAffixTab(tab));
|
||||
const affixTabs = this.tabs.filter(tab => isAffixTab(tab));
|
||||
// 获得固定tabs的index
|
||||
const newIndex = affixTabs.findIndex((item) => getTabPath(item) === getTabPath(tab));
|
||||
const newIndex = affixTabs.findIndex(item => getTabPath(item) === getTabPath(tab));
|
||||
// 交换位置重新排序
|
||||
await this.sortTabs(index, newIndex);
|
||||
},
|
||||
|
@ -310,7 +310,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
this.renderRouteView = false;
|
||||
startProgress();
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 200));
|
||||
await new Promise(resolve => setTimeout(resolve, 200));
|
||||
|
||||
this.excludeCachedTabs.delete(name as string);
|
||||
this.renderRouteView = true;
|
||||
|
@ -324,7 +324,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
if (tab?.meta?.newTabTitle) {
|
||||
return;
|
||||
}
|
||||
const findTab = this.tabs.find((item) => getTabPath(item) === getTabPath(tab));
|
||||
const findTab = this.tabs.find(item => getTabPath(item) === getTabPath(tab));
|
||||
if (findTab) {
|
||||
findTab.meta.newTabTitle = undefined;
|
||||
await this.updateCacheTabs();
|
||||
|
@ -348,7 +348,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
* @param title
|
||||
*/
|
||||
async setTabTitle(tab: TabDefinition, title: string) {
|
||||
const findTab = this.tabs.find((item) => getTabPath(item) === getTabPath(tab));
|
||||
const findTab = this.tabs.find(item => getTabPath(item) === getTabPath(tab));
|
||||
|
||||
if (findTab) {
|
||||
findTab.meta.newTabTitle = title;
|
||||
|
@ -389,7 +389,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
* @param tab
|
||||
*/
|
||||
async unpinTab(tab: TabDefinition) {
|
||||
const index = this.tabs.findIndex((item) => getTabPath(item) === getTabPath(tab));
|
||||
const index = this.tabs.findIndex(item => getTabPath(item) === getTabPath(tab));
|
||||
|
||||
if (index !== -1) {
|
||||
const oldTab = this.tabs[index];
|
||||
|
@ -399,7 +399,7 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
this.tabs.splice(index, 1, tab);
|
||||
}
|
||||
// 过滤固定tabs,后面更改affixTabOrder的值的话可能会有问题,目前行464排序affixTabs没有设置值
|
||||
const affixTabs = this.tabs.filter((tab) => isAffixTab(tab));
|
||||
const affixTabs = this.tabs.filter(tab => isAffixTab(tab));
|
||||
// 获得固定tabs的index,使用固定tabs的下一个位置也就是活动tabs的第一个位置
|
||||
const newIndex = affixTabs.length;
|
||||
// 交换位置重新排序
|
||||
|
@ -428,11 +428,11 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
cacheMap.add(name);
|
||||
}
|
||||
this.cachedTabs = cacheMap;
|
||||
}
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
affixTabs(): TabDefinition[] {
|
||||
const affixTabs = this.tabs.filter((tab) => isAffixTab(tab));
|
||||
const affixTabs = this.tabs.filter(tab => isAffixTab(tab));
|
||||
|
||||
return affixTabs.sort((a, b) => {
|
||||
const orderA = (a.meta?.affixTabOrder ?? 0) as number;
|
||||
|
@ -447,16 +447,16 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
return [...this.excludeCachedTabs];
|
||||
},
|
||||
getTabs(): TabDefinition[] {
|
||||
const normalTabs = this.tabs.filter((tab) => !isAffixTab(tab));
|
||||
const normalTabs = this.tabs.filter(tab => !isAffixTab(tab));
|
||||
return [...this.affixTabs, ...normalTabs].filter(Boolean);
|
||||
}
|
||||
},
|
||||
},
|
||||
persist: [
|
||||
// tabs不需要保存在localStorage
|
||||
{
|
||||
pick: ["tabs"],
|
||||
storage: sessionStorage
|
||||
}
|
||||
storage: sessionStorage,
|
||||
},
|
||||
],
|
||||
state: (): TabbarState => ({
|
||||
cachedTabs: new Set(),
|
||||
|
@ -464,8 +464,8 @@ export const useTabbarStore = defineStore("core-tabbar", {
|
|||
excludeCachedTabs: new Set(),
|
||||
renderRouteView: true,
|
||||
tabs: [],
|
||||
updateTime: Date.now()
|
||||
})
|
||||
updateTime: Date.now(),
|
||||
}),
|
||||
});
|
||||
|
||||
// 解决热更新问题
|
||||
|
@ -486,16 +486,16 @@ function cloneTab(route: TabDefinition): TabDefinition {
|
|||
return {
|
||||
...opt,
|
||||
matched: (matched
|
||||
? matched.map((item) => ({
|
||||
? matched.map(item => ({
|
||||
meta: item.meta,
|
||||
name: item.name,
|
||||
path: item.path
|
||||
path: item.path,
|
||||
}))
|
||||
: undefined) as RouteRecordNormalized[],
|
||||
meta: {
|
||||
...meta,
|
||||
newTabTitle: meta.newTabTitle
|
||||
}
|
||||
newTabTitle: meta.newTabTitle,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -513,7 +513,7 @@ function isAffixTab(tab: TabDefinition) {
|
|||
*/
|
||||
function isTabShown(tab: TabDefinition) {
|
||||
const matched = tab?.matched ?? [];
|
||||
return !tab.meta.hideInTab && matched.every((item) => !item.meta.hideInTab);
|
||||
return !tab.meta.hideInTab && matched.every(item => !item.meta.hideInTab);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -528,6 +528,6 @@ function routeToTab(route: RouteRecordNormalized) {
|
|||
return {
|
||||
meta: route.meta,
|
||||
name: route.name,
|
||||
path: route.path
|
||||
path: route.path,
|
||||
} as TabDefinition;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ const domain = computed(() => {
|
|||
});
|
||||
|
||||
function onUpdated(res: { uploadCert: any }) {
|
||||
debugger;
|
||||
emit("update:modelValue", res.uploadCert);
|
||||
const domains = getAllDomainsFromCrt(res.uploadCert.crt);
|
||||
emit("updated", { domains });
|
||||
|
@ -45,7 +44,6 @@ function onUpdated(res: { uploadCert: any }) {
|
|||
|
||||
const pipeline: any = inject("pipeline");
|
||||
function onUploadClick() {
|
||||
debugger;
|
||||
openUpdateCertDialog({
|
||||
onSubmit: onUpdated,
|
||||
});
|
||||
|
|
|
@ -30,20 +30,20 @@ import { Modal, notification } from "ant-design-vue";
|
|||
import * as api from "./api";
|
||||
|
||||
defineOptions({
|
||||
name: "PipelineManager"
|
||||
name: "PipelineManager",
|
||||
});
|
||||
|
||||
const certdFormRef = ref();
|
||||
const groupDictRef = dict({
|
||||
url: "/pi/pipeline/group/all",
|
||||
value: "id",
|
||||
label: "name"
|
||||
label: "name",
|
||||
});
|
||||
const selectedRowKeys = ref([]);
|
||||
const context: any = {
|
||||
certdFormRef,
|
||||
groupDictRef,
|
||||
selectedRowKeys
|
||||
selectedRowKeys,
|
||||
};
|
||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context });
|
||||
|
||||
|
@ -70,7 +70,7 @@ function batchDelete() {
|
|||
notification.success({ message: "删除成功" });
|
||||
await crudExpose.doRefresh();
|
||||
selectedRowKeys.value = [];
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -101,3 +101,11 @@ export async function SaveCommPluginConfigs(data: CommPluginConfig): Promise<voi
|
|||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export async function DoTest(req: { id: number; input: any }): Promise<void> {
|
||||
return await request({
|
||||
url: apiPrefix + "/doTest",
|
||||
method: "post",
|
||||
data: req,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
</span>
|
||||
</div>
|
||||
<div class="more">
|
||||
<a-button type="primary" :loading="saveLoading" @click="doSave">保存</a-button>
|
||||
<a-button class="mr-1" type="primary" :loading="saveLoading" @click="doSave">保存</a-button>
|
||||
<a-button type="primary" @click="doTest">测试运行</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<div class="pi-plugin-editor">
|
||||
|
@ -34,6 +35,7 @@ import { onMounted, provide, ref } from "vue";
|
|||
import { useRoute } from "vue-router";
|
||||
import * as api from "./api";
|
||||
import yaml from "js-yaml";
|
||||
import { notification } from "ant-design-vue";
|
||||
|
||||
const CertApplyPluginNames = ["CertApply", "CertApplyLego", "CertApplyUpload"];
|
||||
defineOptions({
|
||||
|
@ -48,39 +50,53 @@ async function getPlugin() {
|
|||
const pluginObj = await api.GetObj(id);
|
||||
if (!pluginObj.metadata) {
|
||||
pluginObj.metadata = yaml.dump({
|
||||
input: [
|
||||
{
|
||||
key: "cert",
|
||||
input: {
|
||||
cert: {
|
||||
title: "前置任务生成的证书",
|
||||
component: {
|
||||
name: "output-selector",
|
||||
from: [...CertApplyPluginNames],
|
||||
},
|
||||
},
|
||||
],
|
||||
output: [],
|
||||
},
|
||||
output: {},
|
||||
});
|
||||
} else {
|
||||
pluginObj.metadata = "";
|
||||
}
|
||||
plugin.value = pluginObj;
|
||||
}
|
||||
getPlugin();
|
||||
onMounted(async () => {});
|
||||
|
||||
onMounted(async () => {
|
||||
getPlugin();
|
||||
});
|
||||
|
||||
provide("get:plugin", () => {
|
||||
return plugin;
|
||||
});
|
||||
|
||||
const saveLoading = ref(false);
|
||||
function doSave() {
|
||||
async function doSave() {
|
||||
saveLoading.value = true;
|
||||
try {
|
||||
// api.Save(plugin.value);
|
||||
await api.UpdateObj(plugin.value);
|
||||
notification.success({
|
||||
message: "保存成功",
|
||||
});
|
||||
} finally {
|
||||
saveLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function doTest() {
|
||||
await doSave();
|
||||
const result = await api.DoTest({
|
||||
id: plugin.value.id,
|
||||
input: {},
|
||||
});
|
||||
notification.success({
|
||||
message: "测试已开始",
|
||||
description: result,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
|
|
@ -21,7 +21,7 @@ import { message, Modal } from "ant-design-vue";
|
|||
import { DeleteBatch } from "./api";
|
||||
|
||||
defineOptions({
|
||||
name: "SysPlugin"
|
||||
name: "SysPlugin",
|
||||
});
|
||||
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
|
||||
|
||||
|
@ -36,7 +36,7 @@ const handleBatchDelete = () => {
|
|||
message.info("删除成功");
|
||||
crudExpose.doRefresh();
|
||||
selectedRowKeys.value = [];
|
||||
}
|
||||
},
|
||||
});
|
||||
} else {
|
||||
message.error("请先勾选记录");
|
||||
|
|
|
@ -42,7 +42,12 @@ export class PluginController extends CrudController<PluginService> {
|
|||
|
||||
@Post('/update', { summary: 'sys:settings:edit' })
|
||||
async update(@Body(ALL) bean: any) {
|
||||
return super.update(bean);
|
||||
|
||||
const res = await super.update(bean);
|
||||
// 更新插件配置
|
||||
const info = await this.service.info(bean.id)
|
||||
await this.service.registerPlugin(info)
|
||||
return res
|
||||
}
|
||||
|
||||
@Post('/info', { summary: 'sys:settings:view' })
|
||||
|
|
|
@ -9,7 +9,7 @@ import { merge } from "lodash-es";
|
|||
import { accessRegistry, pluginRegistry } from "@certd/pipeline";
|
||||
import { dnsProviderRegistry } from "@certd/plugin-cert";
|
||||
import { logger } from "@certd/basic";
|
||||
|
||||
import yaml from 'js-yaml'
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class PluginService extends BaseService<PluginEntity> {
|
||||
|
@ -158,12 +158,14 @@ export class PluginService extends BaseService<PluginEntity> {
|
|||
author: author
|
||||
}
|
||||
});
|
||||
if (info.length > 0) {
|
||||
if (info&&info.length > 0) {
|
||||
const plugin = info[0];
|
||||
const AsyncFunction = Object.getPrototypeOf(async () => {}).constructor;
|
||||
const getPluginClass = new AsyncFunction(plugin.content);
|
||||
return await getPluginClass();
|
||||
const pluginClass = await getPluginClass({logger: logger});
|
||||
return new pluginClass()
|
||||
}
|
||||
throw new Error(`插件${pluginName}不存在`);
|
||||
}
|
||||
/**
|
||||
* 从数据库加载插件
|
||||
|
@ -177,28 +179,40 @@ export class PluginService extends BaseService<PluginEntity> {
|
|||
})
|
||||
});
|
||||
|
||||
|
||||
|
||||
for (const item of res) {
|
||||
const pluginName = item.author ? item.author +"/"+ item.name : item.name;
|
||||
let registry = null
|
||||
if(item.pluginType === 'access'){
|
||||
registry = accessRegistry;
|
||||
}else if (item.pluginType === 'plugin'){
|
||||
registry = pluginRegistry;
|
||||
}else if (item.pluginType === 'dnsProvider'){
|
||||
registry = dnsProviderRegistry
|
||||
}else {
|
||||
logger.warn(`插件${pluginName}类型错误:${item.pluginType}`)
|
||||
continue
|
||||
}
|
||||
|
||||
registry.register(pluginName, {
|
||||
define:item,
|
||||
target: ()=>{
|
||||
return this.getPluginTarget(pluginName);
|
||||
}
|
||||
});
|
||||
await this.registerPlugin(item);
|
||||
}
|
||||
}
|
||||
|
||||
async registerPlugin(plugin:PluginEntity){
|
||||
const metadata = yaml.load(plugin.metadata);
|
||||
const item = {
|
||||
...plugin,
|
||||
...metadata
|
||||
}
|
||||
delete item.metadata;
|
||||
delete item.content;
|
||||
if(item.author){
|
||||
item.name = item.author +"/"+ item.name;
|
||||
}
|
||||
let registry = null
|
||||
if(item.pluginType === 'access'){
|
||||
registry = accessRegistry;
|
||||
}else if (item.pluginType === 'plugin'){
|
||||
registry = pluginRegistry;
|
||||
}else if (item.pluginType === 'dnsProvider'){
|
||||
registry = dnsProviderRegistry
|
||||
}else {
|
||||
logger.warn(`插件${item.name}类型错误:${item.pluginType}`)
|
||||
return
|
||||
}
|
||||
|
||||
registry.register(item.name, {
|
||||
define:item,
|
||||
target: ()=>{
|
||||
return this.getPluginTarget(item.name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue