feat(sj_1.0.0): 通知人配置完成钉钉新增

This commit is contained in:
opensnail 2024-04-18 16:36:11 +08:00
parent 75f5193fc3
commit 297b12a4a0
8 changed files with 152 additions and 40 deletions

View File

@ -557,10 +557,16 @@ const local: App.I18n.Schema = {
description: 'Please enter Describe', description: 'Please enter Describe',
notifyAttribute: 'Please enter Attribute information', notifyAttribute: 'Please enter Attribute information',
recipientName: 'Please enter Recipient name', recipientName: 'Please enter Recipient name',
notifyType: 'lease select Notification type' notifyType: 'lease select Notification type',
dingdingAts: "请输入被{'@'}人手机号或钉钉号",
qiYeWechatAts: "请输入被{'@'}人企业微信用户id",
larkAts: "请输入被{'@'}人open_id",
webhookUrl: '请输入URL'
}, },
addNotifyRecipient: 'Add Notify recipients', addNotifyRecipient: 'Add Notify recipients',
editNotifyRecipient: 'Add Notify recipients' editNotifyRecipient: 'Add Notify recipients',
ats: "{'@'}通知人",
webhookUrl: '通知地址'
} }
}, },
form: { form: {

View File

@ -553,10 +553,16 @@ const local: App.I18n.Schema = {
description: '请输入描述', description: '请输入描述',
notifyAttribute: '请输入属性信息', notifyAttribute: '请输入属性信息',
recipientName: '请输入接收人名称', recipientName: '请输入接收人名称',
notifyType: '请选择通知类型' notifyType: '请选择通知类型',
dingdingAts: "请输入被{'@'}人手机号或钉钉号",
qiYeWechatAts: "请输入被{'@'}人企业微信用户id",
larkAts: "请输入被{'@'}人open_id",
webhookUrl: '请输入URL'
}, },
addNotifyRecipient: '新增通知接收人', addNotifyRecipient: '新增通知接收人',
editNotifyRecipient: '编辑通知接收人' editNotifyRecipient: '编辑通知接收人',
ats: "{'@'}通知人",
webhookUrl: '通知地址'
} }
}, },
form: { form: {

View File

@ -39,7 +39,7 @@ export function fetchGetNotifyRecipientList(params?: Api.NotifyRecipient.NotifyR
/** add notify recipient */ /** add notify recipient */
export function fetchAddNotifyRecipient(data: Api.NotifyRecipient.NotifyRecipient) { export function fetchAddNotifyRecipient(data: Api.NotifyRecipient.NotifyRecipient) {
return request<boolean>({ return request<boolean>({
url: '/notify-config', url: '/notify-recipient',
method: 'post', method: 'post',
data data
}); });
@ -48,7 +48,7 @@ export function fetchAddNotifyRecipient(data: Api.NotifyRecipient.NotifyRecipien
/** edit notify recipient */ /** edit notify recipient */
export function fetchEditNotifyRecipient(data: Api.NotifyRecipient.NotifyRecipient) { export function fetchEditNotifyRecipient(data: Api.NotifyRecipient.NotifyRecipient) {
return request<boolean>({ return request<boolean>({
url: '/notify-config', url: '/notify-recipient',
method: 'put', method: 'put',
data data
}); });

16
src/typings/api.d.ts vendored
View File

@ -557,13 +557,22 @@ declare namespace Api {
/** 接收人名称 */ /** 接收人名称 */
recipientName: string; recipientName: string;
/** 通知类型 */ /** 通知类型 */
notifyType: string; notifyType: AlarmType;
/** 属性信息 */ /** 属性信息 */
notifyAttribute: string; notifyAttribute?: string;
/** 描述 */ /** 描述 */
description: string; description: string;
}>; }>;
/** dingDing Notify */
type DingDingNotify = Common.CommonRecord<{
/** 接收人名称 */
webhookUrl: string;
/** 通知类型 */
ats: string[];
}> &
NotifyRecipient;
/** notifyRecipient search params */ /** notifyRecipient search params */
type NotifyRecipientParams = CommonType.RecordNullable< type NotifyRecipientParams = CommonType.RecordNullable<
Pick<Api.NotifyRecipient.NotifyRecipient, 'recipientName' | 'notifyType' | 'notifyAttribute' | 'description'> & Pick<Api.NotifyRecipient.NotifyRecipient, 'recipientName' | 'notifyType' | 'notifyAttribute' | 'description'> &
@ -572,5 +581,8 @@ declare namespace Api {
/** notifyRecipient list */ /** notifyRecipient list */
type NotifyRecipientList = Common.PaginatingQueryRecord<NotifyRecipient>; type NotifyRecipientList = Common.PaginatingQueryRecord<NotifyRecipient>;
/** 1: 钉钉通知 2: 邮件通知 3: 企业通知 4: 飞书 */
type AlarmType = 1 | 2 | 3 | 4;
} }
} }

View File

@ -729,9 +729,15 @@ declare namespace App {
notifyAttribute: string; notifyAttribute: string;
recipientName: string; recipientName: string;
notifyType: string; notifyType: string;
dingdingAts: string;
qiYeWechatAts: string;
larkAts: string;
webhookUrl: string;
}; };
addNotifyRecipient: string; addNotifyRecipient: string;
editNotifyRecipient: string; editNotifyRecipient: string;
ats: string;
webhookUrl: string;
}; };
}; };
form: { form: {

View File

@ -51,6 +51,7 @@ declare module 'vue' {
NDrawer: typeof import('naive-ui')['NDrawer'] NDrawer: typeof import('naive-ui')['NDrawer']
NDrawerContent: typeof import('naive-ui')['NDrawerContent'] NDrawerContent: typeof import('naive-ui')['NDrawerContent']
NDropdown: typeof import('naive-ui')['NDropdown'] NDropdown: typeof import('naive-ui')['NDropdown']
NDynamicTags: typeof import('naive-ui')['NDynamicTags']
NEmpty: typeof import('naive-ui')['NEmpty'] NEmpty: typeof import('naive-ui')['NEmpty']
NFlex: typeof import('naive-ui')['NFlex'] NFlex: typeof import('naive-ui')['NFlex']
NForm: typeof import('naive-ui')['NForm'] NForm: typeof import('naive-ui')['NForm']

View File

@ -0,0 +1,76 @@
<script setup lang="ts">
import { reactive } from 'vue';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import { $t } from '@/locales';
defineOptions({
name: 'DingDingForm'
});
interface Emits {
(e: 'fetchAdd', model: Api.NotifyRecipient.NotifyRecipient): void;
}
const emit = defineEmits<Emits>();
const { formRef, validate } = useNaiveForm();
const { defaultRequiredRule } = useFormRules();
type Model = Pick<
Api.NotifyRecipient.DingDingNotify,
'id' | 'recipientName' | 'notifyType' | 'webhookUrl' | 'ats' | 'description'
>;
const model: Model = reactive(createDefaultModel());
function createDefaultModel(): Model {
return {
id: '',
recipientName: '',
notifyType: 1,
webhookUrl: '',
ats: [],
description: ''
};
}
type RuleKey = Extract<keyof Model, 'recipientName' | 'notifyType' | 'webhookUrl' | 'ats' | 'description'>;
const rules: Record<RuleKey, App.Global.FormRule> = {
recipientName: defaultRequiredRule,
notifyType: defaultRequiredRule,
description: defaultRequiredRule,
webhookUrl: defaultRequiredRule,
ats: defaultRequiredRule
};
const buildNotifyAttribute = (webhookUrl: string, ats: string[]) => {
return JSON.stringify({ webhookUrl, ats });
};
async function save() {
await validate();
const { id, recipientName, notifyType, webhookUrl, ats, description } = model;
const notifyAttribute = buildNotifyAttribute(webhookUrl, ats);
emit('fetchAdd', { id, recipientName, notifyType, notifyAttribute, description });
}
defineExpose({
save
});
</script>
<template>
<NForm ref="formRef" :model="model" :rules="rules">
<NFormItem :label="$t('page.notifyRecipient.recipientName')" path="recipientName">
<NInput v-model:value="model.recipientName" :placeholder="$t('page.notifyRecipient.form.recipientName')" />
</NFormItem>
<NFormItem :label="$t('page.notifyRecipient.webhookUrl')" path="webhookUrl">
<NInput v-model:value="model.webhookUrl" :placeholder="$t('page.notifyRecipient.form.webhookUrl')" />
</NFormItem>
<NFormItem :label="$t('page.notifyRecipient.ats')" path="ats">
<NDynamicTags v-model:value="model.ats" :placeholder="$t('page.notifyRecipient.form.dingdingAts')" />
</NFormItem>
</NForm>
</template>
<style scoped></style>

View File

@ -1,14 +1,17 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, reactive, watch } from 'vue'; import { computed, reactive, ref, watch } from 'vue';
import { useFormRules, useNaiveForm } from '@/hooks/common/form'; import { useNaiveForm } from '@/hooks/common/form';
import OperateDrawer from '@/components/common/operate-drawer.vue'; import OperateDrawer from '@/components/common/operate-drawer.vue';
import { $t } from '@/locales'; import { $t } from '@/locales';
import { fetchAddNotifyRecipient, fetchEditNotifyRecipient } from '@/service/api'; import { fetchAddNotifyRecipient } from '@/service/api';
import DingDingForm from './dingding-form.vue';
defineOptions({ defineOptions({
name: 'NotifyRecipientOperateDrawer' name: 'NotifyRecipientOperateDrawer'
}); });
const DingDingRef = ref();
interface Props { interface Props {
/** the type of operation */ /** the type of operation */
operateType: NaiveUI.TableOperateType; operateType: NaiveUI.TableOperateType;
@ -28,8 +31,7 @@ const visible = defineModel<boolean>('visible', {
default: false default: false
}); });
const { formRef, validate, restoreValidation } = useNaiveForm(); const { restoreValidation } = useNaiveForm();
const { defaultRequiredRule } = useFormRules();
const title = computed(() => { const title = computed(() => {
const titles: Record<NaiveUI.TableOperateType, string> = { const titles: Record<NaiveUI.TableOperateType, string> = {
@ -49,20 +51,18 @@ const model: Model = reactive(createDefaultModel());
function createDefaultModel(): Model { function createDefaultModel(): Model {
return { return {
recipientName: '', recipientName: '',
notifyType: '', notifyType: 1,
notifyAttribute: '', notifyAttribute: '',
description: '' description: ''
}; };
} }
type RuleKey = Extract<keyof Model, 'recipientName' | 'notifyType' | 'notifyAttribute' | 'description'>; // const rules: Record<RuleKey, App.Global.FormRule> = {
// recipientName: defaultRequiredRule,
const rules: Record<RuleKey, App.Global.FormRule> = { // notifyType: defaultRequiredRule,
recipientName: defaultRequiredRule, // notifyAttribute: defaultRequiredRule,
notifyType: defaultRequiredRule, // description: defaultRequiredRule
notifyAttribute: defaultRequiredRule, // };
description: defaultRequiredRule
};
function handleUpdateModelWhenEdit() { function handleUpdateModelWhenEdit() {
if (props.operateType === 'add') { if (props.operateType === 'add') {
@ -75,27 +75,24 @@ function handleUpdateModelWhenEdit() {
} }
} }
function closeDrawer() {
visible.value = false;
}
async function handleSubmit() { async function handleSubmit() {
await validate();
// request // request
if (props.operateType === 'add') { if (props.operateType === 'add') {
const { recipientName, notifyAttribute, notifyType, description } = model; DingDingRef.value?.save();
fetchAddNotifyRecipient({ recipientName, notifyAttribute, notifyType, description });
} }
if (props.operateType === 'edit') { if (props.operateType === 'edit') {
const { id, recipientName, notifyAttribute, notifyType, description } = model; console.log('更新');
fetchEditNotifyRecipient({ id, recipientName, notifyAttribute, notifyType, description });
} }
window.$message?.success($t('common.updateSuccess')); window.$message?.success($t('common.updateSuccess'));
closeDrawer();
emit('submitted'); emit('submitted');
} }
const dingDingFetchAdd = (dingDingModel: Api.NotifyRecipient.NotifyRecipient) => {
const { recipientName, notifyAttribute, notifyType, description } = dingDingModel;
fetchAddNotifyRecipient({ recipientName, notifyAttribute, notifyType, description });
};
watch(visible, () => { watch(visible, () => {
if (visible.value) { if (visible.value) {
handleUpdateModelWhenEdit(); handleUpdateModelWhenEdit();
@ -106,14 +103,22 @@ watch(visible, () => {
<template> <template>
<OperateDrawer v-model="visible" :title="title" @handle-submit="handleSubmit"> <OperateDrawer v-model="visible" :title="title" @handle-submit="handleSubmit">
<NForm ref="formRef" :model="model" :rules="rules"> <NTabs type="segment" animated>
<NFormItem :label="$t('page.notifyRecipient.recipientName')" path="recipientName"> <NTabPane name="dingding" tab="钉钉">
<NInput v-model:value="model.recipientName" :placeholder="$t('page.notifyRecipient.form.recipientName')" /> <DingDingForm ref="DingDingRef" @fetch-add="dingDingFetchAdd" />
</NFormItem> </NTabPane>
<NFormItem :label="$t('page.notifyRecipient.notifyType')" path="recipientName"> <NTabPane name="feishu" tab="飞书"></NTabPane>
<NSelect v-model:value="model.notifyType" :placeholder="$t('page.notifyRecipient.form.notifyType')" clearable /> <NTabPane name="email" tab="企业微信">
</NFormItem> <NFormItem :label="$t('page.notifyRecipient.recipientName')" path="recipientName">
</NForm> <NInput v-model:value="model.recipientName" :placeholder="$t('page.notifyRecipient.form.recipientName')" />
</NFormItem>
</NTabPane>
<NTabPane name="email" tab="邮箱">
<NFormItem :label="$t('page.notifyRecipient.recipientName')" path="recipientName">
<NInput v-model:value="model.recipientName" :placeholder="$t('page.notifyRecipient.form.recipientName')" />
</NFormItem>
</NTabPane>
</NTabs>
<template #footer> <template #footer>
<NSpace :size="16"> <NSpace :size="16">
<NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton> <NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>