perf: 通知渠道支持测试按钮

pull/265/head
xiaojunnuo 2024-11-25 11:35:16 +08:00
parent 3af6d96e6e
commit b54ae272eb
13 changed files with 126 additions and 24 deletions

View File

@ -41,6 +41,10 @@ export type AccessContext = {
export abstract class BaseAccess implements IAccess { export abstract class BaseAccess implements IAccess {
ctx!: AccessContext; ctx!: AccessContext;
setCtx(ctx: AccessContext) {
this.ctx = ctx;
}
async onRequest(req: AccessRequestHandleReq) { async onRequest(req: AccessRequestHandleReq) {
if (!req.action) { if (!req.action) {
throw new Error("action is required"); throw new Error("action is required");

View File

@ -56,6 +56,6 @@ export function newAccess(type: string, input: any, ctx?: AccessContext) {
utils, utils,
}; };
} }
access.ctx = ctx; access.setCtx(ctx);
return access; return access;
} }

View File

@ -93,4 +93,19 @@ export abstract class BaseNotification implements INotification {
} }
throw new Error(`action ${req.action} not found`); throw new Error(`action ${req.action} not found`);
} }
async onTestRequest() {
await this.send({
userId: 0,
title: "测试通知",
content: "测试通知",
pipeline: {
id: 1,
title: "测试流水线",
} as any,
pipelineId: 1,
historyId: 1,
url: "http://www.baidu.com",
});
}
} }

View File

@ -44,13 +44,13 @@ export function newNotification(type: string, input: any, ctx: NotificationConte
throw new Error(`notification ${type} not found`); throw new Error(`notification ${type} not found`);
} }
// @ts-ignore // @ts-ignore
const access = new register.target(); const plugin = new register.target();
for (const key in input) { for (const key in input) {
access[key] = input[key]; plugin[key] = input[key];
} }
if (!ctx) { if (!ctx) {
throw new Error("ctx is required"); throw new Error("ctx is required");
} }
access.ctx = ctx; plugin.setCtx(ctx);
return access; return plugin;
} }

View File

@ -11,12 +11,15 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib"; import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
import { ref } from "vue"; import { ref, inject } from "vue";
defineOptions({ defineOptions({
name: "ApiTest" name: "ApiTest"
}); });
const getScope: any = inject("get:scope");
const getPluginType: any = inject("get:plugin:type");
const props = defineProps<{} & ComponentPropsType>(); const props = defineProps<{} & ComponentPropsType>();
const emit = defineEmits<{ const emit = defineEmits<{
@ -31,16 +34,20 @@ const doTest = async () => {
return; return;
} }
const { form } = getScope();
const pluginType = getPluginType();
message.value = ""; message.value = "";
hasError.value = false; hasError.value = false;
loading.value = true; loading.value = true;
debugger;
try { try {
const res = await doRequest( const res = await doRequest(
{ {
type: props.type, type: pluginType,
typeName: props.typeName, typeName: form.type,
action: props.action, action: props.action,
input: props.form input: form
}, },
{ {
onError(err: any) { onError(err: any) {
@ -50,9 +57,7 @@ const doTest = async () => {
showErrorNotify: false showErrorNotify: false
} }
); );
if (res && res.length > 0) {
message.value = "测试请求成功"; message.value = "测试请求成功";
}
} finally { } finally {
loading.value = false; loading.value = false;
} }

View File

@ -42,6 +42,9 @@ const emit = defineEmits<{
const attrs = useAttrs(); const attrs = useAttrs();
const getCurrentPluginDefine: any = inject("getCurrentPluginDefine"); const getCurrentPluginDefine: any = inject("getCurrentPluginDefine");
const getScope: any = inject("get:scope");
const getPluginType: any = inject("get:plugin:type");
const optionsRef = ref([]); const optionsRef = ref([]);
const message = ref(""); const message = ref("");
const hasError = ref(false); const hasError = ref(false);
@ -75,13 +78,16 @@ const getOptions = async () => {
hasError.value = false; hasError.value = false;
loading.value = true; loading.value = true;
optionsRef.value = []; optionsRef.value = [];
const { form } = getScope();
const pluginType = getPluginType();
try { try {
const res = await doRequest( const res = await doRequest(
{ {
type: props.type, type: pluginType,
typeName: props.typeName, typeName: form.type,
action: props.action, action: props.action,
input: props.form input: form
}, },
{ {
onError(err: any) { onError(err: any) {

View File

@ -1,9 +1,9 @@
import { request } from "/@/api/service"; import { request } from "/@/api/service";
export type ComponentPropsType = { export type ComponentPropsType = {
type: string; type?: string;
typeName: string; typeName?: string;
action?: string; action: string;
form: any; form?: any;
value?: any; value?: any;
}; };
export type RequestHandleReq<T = any> = { export type RequestHandleReq<T = any> = {
@ -15,7 +15,7 @@ export type RequestHandleReq<T = any> = {
}; };
export async function doRequest(req: RequestHandleReq, opts: any = {}) { export async function doRequest(req: RequestHandleReq, opts: any = {}) {
const url = req.type === "access" ? "/pi/handle/access" : "/pi/handle/plugin"; const url = `/pi/handle/${req.type}`;
const { typeName, action, data, input } = req; const { typeName, action, data, input } = req;
const res = await request({ const res = await request({
url, url,

View File

@ -19,7 +19,6 @@ defineOptions({
}); });
const props = defineProps<ComponentPropsType>(); const props = defineProps<ComponentPropsType>();
const emit = defineEmits<{ const emit = defineEmits<{
"update:value": any; "update:value": any;
}>(); }>();

View File

@ -6,6 +6,9 @@ import SecretPlainGetter from "/@/views/certd/access/access-selector/access/secr
export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) { export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) {
provide("accessApi", api); provide("accessApi", api);
provide("get:plugin:type", () => {
return "access";
});
const AccessTypeDictRef = dict({ const AccessTypeDictRef = dict({
url: "/pi/access/accessTypeDict" url: "/pi/access/accessTypeDict"
}); });

View File

@ -1,10 +1,13 @@
import { ColumnCompositionProps, dict } from "@fast-crud/fast-crud"; import { ColumnCompositionProps, compute, dict } from "@fast-crud/fast-crud";
import { computed, provide, ref, toRef } from "vue"; import { computed, provide, ref, toRef } from "vue";
import { useReference } from "/@/use/use-refrence"; import { useReference } from "/@/use/use-refrence";
import { forEach, get, merge, set } from "lodash-es"; import { forEach, get, merge, set } from "lodash-es";
export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) { export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) {
provide("notificationApi", api); provide("notificationApi", api);
provide("get:plugin:type", () => {
return "notification";
});
const notificationTypeDictRef = dict({ const notificationTypeDictRef = dict({
url: "/pi/notification/getTypeDict" url: "/pi/notification/getTypeDict"
}); });
@ -125,6 +128,26 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) {
}) })
} }
} as ColumnCompositionProps, } as ColumnCompositionProps,
test: {
title: "测试",
form: {
component: {
name: "api-test",
type: "notification",
typeName: compute(({ form }) => {
return form.type;
}),
action: "TestRequest",
form: compute(({ form }) => {
return form;
})
},
order: 999
},
column: {
show: false
}
},
setting: { setting: {
column: { show: false }, column: { show: false },
form: { form: {

View File

@ -222,6 +222,9 @@ export default {
provide("getCurrentPluginDefine", () => { provide("getCurrentPluginDefine", () => {
return currentPluginDefine; return currentPluginDefine;
}); });
provide("get:plugin:type", () => {
return "plugin";
});
function getContext() { function getContext() {
return { return {

View File

@ -1,11 +1,21 @@
import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core'; import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core';
import { Constants } from '@certd/lib-server'; import { Constants } from '@certd/lib-server';
import { AccessRequestHandleReq, ITaskPlugin, newAccess, pluginRegistry, PluginRequestHandleReq, TaskInstanceContext } from '@certd/pipeline'; import {
AccessRequestHandleReq,
ITaskPlugin,
newAccess,
newNotification,
NotificationRequestHandleReq,
pluginRegistry,
PluginRequestHandleReq,
TaskInstanceContext,
} from '@certd/pipeline';
import { BaseController } from '@certd/lib-server'; import { BaseController } from '@certd/lib-server';
import { AccessService } from '../../modules/pipeline/service/access-service.js'; import { AccessService } from '../../modules/pipeline/service/access-service.js';
import { EmailService } from '../../modules/basic/service/email-service.js'; import { EmailService } from '../../modules/basic/service/email-service.js';
import { AccessGetter } from '../../modules/pipeline/service/access-getter.js'; import { AccessGetter } from '../../modules/pipeline/service/access-getter.js';
import { http, HttpRequestConfig, logger, mergeUtils, utils } from '@certd/basic'; import { http, HttpRequestConfig, logger, mergeUtils, utils } from '@certd/basic';
import { NotificationService } from '../../modules/pipeline/service/notification-service.js';
@Provide() @Provide()
@Controller('/api/pi/handle') @Controller('/api/pi/handle')
@ -16,12 +26,18 @@ export class HandleController extends BaseController {
@Inject() @Inject()
emailService: EmailService; emailService: EmailService;
@Inject()
notificationService: NotificationService;
@Post('/access', { summary: Constants.per.authOnly }) @Post('/access', { summary: Constants.per.authOnly })
async accessRequest(@Body(ALL) body: AccessRequestHandleReq) { async accessRequest(@Body(ALL) body: AccessRequestHandleReq) {
let inputAccess = body.input.access; let inputAccess = body.input.access;
if (body.input.id > 0) { if (body.input.id > 0) {
const oldEntity = await this.accessService.info(body.input.id); const oldEntity = await this.accessService.info(body.input.id);
if (oldEntity) { if (oldEntity) {
if (oldEntity.userId !== this.getUserId()) {
throw new Error('access not found');
}
const param: any = { const param: any = {
type: body.typeName, type: body.typeName,
setting: JSON.stringify(body.input.access), setting: JSON.stringify(body.input.access),
@ -38,6 +54,34 @@ export class HandleController extends BaseController {
return this.ok(res); return this.ok(res);
} }
@Post('/notification', { summary: Constants.per.authOnly })
async notificationRequest(@Body(ALL) body: NotificationRequestHandleReq) {
const input = body.input.body;
// if (body.input.id > 0) {
// const oldEntity = await this.notificationService.info(body.input.id);
// if (oldEntity) {
// if (oldEntity.userId !== this.getUserId()) {
// throw new Error('notification not found');
// }
// const param: any = {
// type: body.typeName,
// setting: JSON.stringify(body.input.access),
// };
// }
// }
const notification = newNotification(body.typeName, input, {
http,
logger,
utils,
emailService: this.emailService,
});
const res = await notification.onRequest(body);
return this.ok(res);
}
@Post('/plugin', { summary: Constants.per.authOnly }) @Post('/plugin', { summary: Constants.per.authOnly })
async pluginRequest(@Body(ALL) body: PluginRequestHandleReq) { async pluginRequest(@Body(ALL) body: PluginRequestHandleReq) {
const userId = this.getUserId(); const userId = this.getUserId();

View File

@ -7,7 +7,7 @@ import { CertInfo } from '@certd/plugin-cert';
title: '部署到腾讯云CDN', title: '部署到腾讯云CDN',
icon: 'svg:icon-tencentcloud', icon: 'svg:icon-tencentcloud',
group: pluginGroups.tencent.key, group: pluginGroups.tencent.key,
desc: '可能不支持国际版', desc: '已废弃请使用v2版',
default: { default: {
strategy: { strategy: {
runStrategy: RunStrategy.SkipWhenSucceed, runStrategy: RunStrategy.SkipWhenSucceed,