fix: 场景联动-执行动作
This commit is contained in:
parent
db0d033588
commit
ca7d9cba0a
|
@ -17,6 +17,8 @@ export default {
|
||||||
getHistory: (data: any, id: string) => post(`/notify/history/config/${id}/_query`, data),
|
getHistory: (data: any, id: string) => post(`/notify/history/config/${id}/_query`, data),
|
||||||
// 获取所有平台用户
|
// 获取所有平台用户
|
||||||
getPlatformUsers: (data: any) => post<any>(`/user/_query/no-paging`, data),
|
getPlatformUsers: (data: any) => post<any>(`/user/_query/no-paging`, data),
|
||||||
|
// 获取所有关系
|
||||||
|
getRelationUsers: (data: any) => post<any>(`/relation/_query/no-paging`, data),
|
||||||
// 钉钉部门
|
// 钉钉部门
|
||||||
dingTalkDept: (id: string) => get<any>(`/notifier/dingtalk/corp/${id}/departments/tree`),
|
dingTalkDept: (id: string) => get<any>(`/notifier/dingtalk/corp/${id}/departments/tree`),
|
||||||
// 钉钉部门人员
|
// 钉钉部门人员
|
||||||
|
@ -38,5 +40,9 @@ export default {
|
||||||
//通知类型
|
//通知类型
|
||||||
queryMessageType: () => get(`/notifier/config/types`),
|
queryMessageType: () => get(`/notifier/config/types`),
|
||||||
// 不分页-列表
|
// 不分页-列表
|
||||||
queryListNoPaging: (data: any) => post(`/notifier/config/_query/no-paging?paging=false`, data)
|
queryListNoPaging: (data: any) => post(`/notifier/config/_query/no-paging?paging=false`, data),
|
||||||
|
//
|
||||||
|
queryDingTalkUsers: (id: string) => get<any>(`/notifier/dingtalk/corp/${id}/users?sorts[0].name='name'&sorts[0].order=asc`),
|
||||||
|
//
|
||||||
|
queryWechatUsers: (id: string) => get<any>(`/notifier/wechat/corp/${id}/users?sorts[0].name='name'&sorts[0].order=asc`),
|
||||||
}
|
}
|
|
@ -19,3 +19,6 @@ export const _action = (id: string, type: '_disable' | '_enable') => server.put(
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const _execute = (id: string) => server.post(`/scene/${id}/_execute`);
|
export const _execute = (id: string) => server.post(`/scene/${id}/_execute`);
|
||||||
|
|
||||||
|
// 内置参数
|
||||||
|
export const queryBuiltInParams = (data: any, params?: any) => server.post(`/scene/parse-variables`, data, params);
|
|
@ -1,11 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
|
<div>
|
||||||
|
<Action :thenOptions="data.branches ? data?.branches[0].then : []" :name="0" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts" setup>
|
||||||
export default {
|
import { useSceneStore } from '@/store/scene'
|
||||||
name: 'inex'
|
import Action from '../action/index.vue'
|
||||||
}
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
||||||
|
const sceneStore = useSceneStore()
|
||||||
|
const { data } = storeToRefs(sceneStore)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<a-input-number
|
<a-input-number
|
||||||
style="max-width: 220px"
|
style="max-width: 220px"
|
||||||
placeholder="请输入时间"
|
placeholder="请输入时间"
|
||||||
v-model:value="value"
|
v-model:value="_value"
|
||||||
:precision="3"
|
:precision="3"
|
||||||
:min="0"
|
:min="0"
|
||||||
:max="6535"
|
:max="6535"
|
||||||
|
@ -32,6 +32,18 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onlyMessage } from '@/utils/comm';
|
import { onlyMessage } from '@/utils/comm';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
time: 0,
|
||||||
|
unit: 'seconds',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const timeUnitEnum = {
|
const timeUnitEnum = {
|
||||||
seconds: '秒',
|
seconds: '秒',
|
||||||
minutes: '分',
|
minutes: '分',
|
||||||
|
@ -40,24 +52,38 @@ const timeUnitEnum = {
|
||||||
|
|
||||||
const emit = defineEmits(['cancel', 'save']);
|
const emit = defineEmits(['cancel', 'save']);
|
||||||
|
|
||||||
const value = ref<number>(0);
|
const _value = ref<number>(props.value.time);
|
||||||
const unit = ref<'seconds' | 'minutes' | 'hours'>('seconds');
|
const unit = ref<'seconds' | 'minutes' | 'hours'>(
|
||||||
|
props.value?.unit || 'seconds',
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(newVal) => {
|
||||||
|
_value.value = newVal?.time || 0
|
||||||
|
unit.value = newVal?.unit || 'seconds'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
deep: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
emit('cancel');
|
emit('cancel');
|
||||||
};
|
};
|
||||||
const onOk = () => {
|
const onOk = () => {
|
||||||
if (unref(value) || unref(value) === 0) {
|
if (unref(_value) || unref(_value) === 0) {
|
||||||
} else {
|
} else {
|
||||||
onlyMessage('请输入时间', 'error');
|
onlyMessage('请输入时间', 'error');
|
||||||
}
|
}
|
||||||
emit(
|
emit(
|
||||||
'save',
|
'save',
|
||||||
{
|
{
|
||||||
time: value.value,
|
time: _value.value,
|
||||||
unit: unit.value,
|
unit: unit.value,
|
||||||
},
|
},
|
||||||
{ name: `${value.value} ${timeUnitEnum[unit.value]}后,执行后续动作` },
|
{ name: `${_value.value} ${timeUnitEnum[unit.value]}后,执行后续动作` },
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
|
@ -1,3 +1,631 @@
|
||||||
<template>
|
<template>
|
||||||
<div>ITEM</div>
|
<div class="actions-item-warp">
|
||||||
|
<div class="actions-item">
|
||||||
|
<div class="item-options-warp">
|
||||||
|
<div class="item-options-type" @click="onAdd">
|
||||||
|
<img
|
||||||
|
style="width: 18px"
|
||||||
|
:src="
|
||||||
|
iconMap.get(
|
||||||
|
data?.executor === 'alarm'
|
||||||
|
? data?.alarm?.mode
|
||||||
|
: data?.executor,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="item-options-content"
|
||||||
|
v-if="data?.executor === 'alarm'"
|
||||||
|
>
|
||||||
|
<template v-if="data?.alarm?.mode === 'trigger'">
|
||||||
|
满足条件后将触发<a-button
|
||||||
|
type="link"
|
||||||
|
@click.stop="triggerVisible = true"
|
||||||
|
>关联此场景的告警</a-button
|
||||||
|
>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
满足条件后将解除<a-button
|
||||||
|
type="link"
|
||||||
|
@click.stop="triggerVisible = true"
|
||||||
|
>关联此场景的告警</a-button
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="item-options-content"
|
||||||
|
v-else-if="data?.executor === 'notify'"
|
||||||
|
@click="onType('notify')"
|
||||||
|
>
|
||||||
|
<template v-if="data?.notify?.notifyType === 'dingTalk'">
|
||||||
|
<template
|
||||||
|
v-if="options?.provider === 'dingTalkRobotWebHook'"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
通过<span class="notify-text-highlight"
|
||||||
|
>群机器人消息</span
|
||||||
|
>
|
||||||
|
发送
|
||||||
|
<span class="notify-text-highlight">
|
||||||
|
{{
|
||||||
|
options?.templateName ||
|
||||||
|
data?.notify?.templateId
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div>
|
||||||
|
通过
|
||||||
|
<span class="notify-text-highlight">
|
||||||
|
<img
|
||||||
|
style="width: 18px"
|
||||||
|
:src="
|
||||||
|
itemNotifyIconMap.get(
|
||||||
|
data?.notify?.notifyType,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
钉钉
|
||||||
|
</span>
|
||||||
|
向<span class="notify-text-highlight">{{
|
||||||
|
options?.orgName || ''
|
||||||
|
}}</span>
|
||||||
|
<span class="notify-text-highlight">{{
|
||||||
|
options?.sendTo || ''
|
||||||
|
}}</span>
|
||||||
|
发送
|
||||||
|
<span class="notify-text-highlight">
|
||||||
|
{{
|
||||||
|
options?.templateName ||
|
||||||
|
data?.notify?.templateId
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="data?.notify?.notifyType === 'weixin'">
|
||||||
|
<div>
|
||||||
|
通过
|
||||||
|
<span class="notify-text-highlight">
|
||||||
|
<img
|
||||||
|
style="width: 18px"
|
||||||
|
:src="
|
||||||
|
itemNotifyIconMap.get(
|
||||||
|
data?.notify?.notifyType,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
微信
|
||||||
|
</span>
|
||||||
|
向<span class="notify-text-highlight">{{
|
||||||
|
options?.orgName || ''
|
||||||
|
}}</span>
|
||||||
|
<span class="notify-text-highlight">{{
|
||||||
|
options?.sendTo || ''
|
||||||
|
}}</span>
|
||||||
|
<span class="notify-text-highlight">{{
|
||||||
|
options?.tagName || ''
|
||||||
|
}}</span>
|
||||||
|
发送
|
||||||
|
<span class="notify-text-highlight">
|
||||||
|
{{
|
||||||
|
options?.templateName ||
|
||||||
|
data?.notify?.templateId
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="data?.notify?.notifyType === 'email'">
|
||||||
|
<div>
|
||||||
|
通过
|
||||||
|
<span class="notify-text-highlight">
|
||||||
|
<img
|
||||||
|
style="width: 18px"
|
||||||
|
:src="
|
||||||
|
itemNotifyIconMap.get(
|
||||||
|
data?.notify?.notifyType,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
邮件
|
||||||
|
</span>
|
||||||
|
向<span class="notify-text-highlight">{{
|
||||||
|
options?.sendTo || ''
|
||||||
|
}}</span>
|
||||||
|
发送
|
||||||
|
<span class="notify-text-highlight">
|
||||||
|
{{
|
||||||
|
options?.templateName ||
|
||||||
|
data?.notify?.templateId
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="data?.notify?.notifyType === 'voice'">
|
||||||
|
<div>
|
||||||
|
通过
|
||||||
|
<span class="notify-text-highlight">
|
||||||
|
<img
|
||||||
|
style="width: 18px"
|
||||||
|
:src="
|
||||||
|
itemNotifyIconMap.get(
|
||||||
|
data?.notify?.notifyType,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
语音
|
||||||
|
</span>
|
||||||
|
向<span class="notify-text-highlight">{{
|
||||||
|
options?.sendTo || ''
|
||||||
|
}}</span>
|
||||||
|
发送
|
||||||
|
<span class="notify-text-highlight">
|
||||||
|
{{
|
||||||
|
options?.templateName ||
|
||||||
|
data?.notify?.templateId
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="data?.notify?.notifyType === 'sms'">
|
||||||
|
<div>
|
||||||
|
通过
|
||||||
|
<span class="notify-text-highlight">
|
||||||
|
<img
|
||||||
|
style="width: 18px"
|
||||||
|
:src="
|
||||||
|
itemNotifyIconMap.get(
|
||||||
|
data?.notify?.notifyType,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
短信
|
||||||
|
</span>
|
||||||
|
向<span class="notify-text-highlight">{{
|
||||||
|
options?.sendTo || ''
|
||||||
|
}}</span>
|
||||||
|
发送
|
||||||
|
<span class="notify-text-highlight">
|
||||||
|
{{
|
||||||
|
options?.templateName ||
|
||||||
|
data?.notify?.templateId
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template
|
||||||
|
v-else-if="data?.notify?.notifyType === 'webhook'"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
通过
|
||||||
|
<span class="notify-text-highlight">
|
||||||
|
<img
|
||||||
|
style="width: 18px"
|
||||||
|
:src="
|
||||||
|
itemNotifyIconMap.get(
|
||||||
|
data?.notify?.notifyType,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
webhook
|
||||||
|
</span>
|
||||||
|
发送
|
||||||
|
<span>{{
|
||||||
|
options?.templateName ||
|
||||||
|
data?.notify?.templateId
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="item-options-content"
|
||||||
|
v-else-if="data?.executor === 'delay'"
|
||||||
|
@click="onType('delay')"
|
||||||
|
>
|
||||||
|
{{ options?.name }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="item-options-content"
|
||||||
|
v-else-if="data?.executor === 'device'"
|
||||||
|
@click="onType('device')"
|
||||||
|
>
|
||||||
|
<template v-if="data?.device?.selector === 'fixed'">
|
||||||
|
<div>
|
||||||
|
<AIcon
|
||||||
|
:type="
|
||||||
|
typeIconMap[
|
||||||
|
data?.device?.message?.messageType ||
|
||||||
|
'INVOKE_FUNCTION'
|
||||||
|
]
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<span style="padding-left: 4px">{{
|
||||||
|
data?.options?.type
|
||||||
|
}}</span>
|
||||||
|
<AIcon
|
||||||
|
type="icon-mubiao"
|
||||||
|
style="padding-right: 2px"
|
||||||
|
/>
|
||||||
|
{{
|
||||||
|
`${data?.options?.name} ${
|
||||||
|
data?.options?.properties
|
||||||
|
}
|
||||||
|
${
|
||||||
|
(
|
||||||
|
isBoolean(
|
||||||
|
data?.options?.propertiesValue,
|
||||||
|
)
|
||||||
|
? true
|
||||||
|
: data?.options?.propertiesValue
|
||||||
|
)
|
||||||
|
? `为 ${data?.options?.propertiesValue}`
|
||||||
|
: ''
|
||||||
|
}`
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="data?.device?.selector === 'tag'">
|
||||||
|
<div>
|
||||||
|
<AIcon
|
||||||
|
:type="
|
||||||
|
typeIconMap[
|
||||||
|
data?.device?.message?.messageType ||
|
||||||
|
'INVOKE_FUNCTION'
|
||||||
|
]
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
{{ data?.options?.type }}
|
||||||
|
<span
|
||||||
|
v-for="i in data?.options?.taglist || []"
|
||||||
|
:key="i.value"
|
||||||
|
>
|
||||||
|
{{ i.type }}
|
||||||
|
{{ i.name }}为{{ i.value }}
|
||||||
|
</span>
|
||||||
|
的{{ data?.options?.productName }}
|
||||||
|
{{ data?.options?.properties }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="data?.device?.selector === 'relation'">
|
||||||
|
<div>
|
||||||
|
<AIcon
|
||||||
|
:type="
|
||||||
|
typeIconMap[
|
||||||
|
data?.device?.message?.messageType ||
|
||||||
|
'INVOKE_FUNCTION'
|
||||||
|
]
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
{{ data?.options?.type }}与<span>{{
|
||||||
|
data?.options?.triggerName
|
||||||
|
}}</span
|
||||||
|
>具有相同 {{ data?.options?.relationName }}的{{
|
||||||
|
data?.options?.productName
|
||||||
|
}}设备的
|
||||||
|
{{ data?.options?.properties }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<a-button v-else @click="onAdd">点击配置执行动作</a-button>
|
||||||
|
</div>
|
||||||
|
<div class="item-number">{{ name + 1 }}</div>
|
||||||
|
<a-popconfirm title="确认删除?" @confirm="onDelete">
|
||||||
|
<div class="item-delete">
|
||||||
|
<AIcon type="DeleteOutlined" />
|
||||||
|
</div>
|
||||||
|
</a-popconfirm>
|
||||||
|
</div>
|
||||||
|
<template v-if="!isLast && type === 'serial'">
|
||||||
|
<div class="actions-item-filter-warp">
|
||||||
|
<!-- filter-border -->
|
||||||
|
满足此条件后执行后续动作
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<!-- 编辑 -->
|
||||||
|
<template v-if="visible">
|
||||||
|
<Modal
|
||||||
|
:name="name"
|
||||||
|
:branchGroup="branchGroup"
|
||||||
|
:branchesName="branchesName"
|
||||||
|
:data="data"
|
||||||
|
@cancel="onClose"
|
||||||
|
@save="onSave"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template>
|
||||||
|
<ActionTypeComponent
|
||||||
|
v-bind="props"
|
||||||
|
v-if="!!actionType"
|
||||||
|
:actionType="actionType"
|
||||||
|
@save="onPropsOk"
|
||||||
|
@cancel="onPropsCancel"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { getImage } from '@/utils/comm';
|
||||||
|
import { isBoolean } from 'lodash-es';
|
||||||
|
import { PropType } from 'vue';
|
||||||
|
import { ActionsType, ParallelType } from '../../../typings';
|
||||||
|
import Modal from '../Modal/index.vue';
|
||||||
|
import ActionTypeComponent from '../Modal/ActionTypeComponent.vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
branchesName: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
branchGroup: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: Object as PropType<ActionsType>,
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: Object as PropType<ParallelType>,
|
||||||
|
},
|
||||||
|
parallel: {
|
||||||
|
type: Boolean,
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
isLast: {
|
||||||
|
type: Boolean,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['delete', 'update']);
|
||||||
|
|
||||||
|
const iconMap = new Map();
|
||||||
|
iconMap.set('trigger', getImage('/scene/action-bind-icon.png'));
|
||||||
|
iconMap.set('notify', getImage('/scene/action-notify-icon.png'));
|
||||||
|
iconMap.set('device', getImage('/scene/action-device-icon.png'));
|
||||||
|
iconMap.set('relieve', getImage('/scene/action-unbind-icon.png'));
|
||||||
|
iconMap.set('delay', getImage('/scene/action-delay-icon.png'));
|
||||||
|
|
||||||
|
const itemNotifyIconMap = new Map();
|
||||||
|
itemNotifyIconMap.set(
|
||||||
|
'dingTalk',
|
||||||
|
getImage('/scene/notify-item-img/dingtalk.png'),
|
||||||
|
);
|
||||||
|
itemNotifyIconMap.set('weixin', getImage('/scene/notify-item-img/weixin.png'));
|
||||||
|
itemNotifyIconMap.set('email', getImage('/scene/notify-item-img/email.png'));
|
||||||
|
itemNotifyIconMap.set('voice', getImage('/scene/notify-item-img/voice.png'));
|
||||||
|
itemNotifyIconMap.set('sms', getImage('/scene/notify-item-img/sms.png'));
|
||||||
|
itemNotifyIconMap.set(
|
||||||
|
'webhook',
|
||||||
|
getImage('/scene/notify-item-img/webhook.png'),
|
||||||
|
);
|
||||||
|
|
||||||
|
const typeIconMap = {
|
||||||
|
READ_PROPERTY: 'icon-zhihangdongzuodu',
|
||||||
|
INVOKE_FUNCTION: 'icon-zhihangdongzuoxie-1',
|
||||||
|
WRITE_PROPERTY: 'icon-zhihangdongzuoxie',
|
||||||
|
};
|
||||||
|
|
||||||
|
const visible = ref<boolean>(false);
|
||||||
|
const triggerVisible = ref<boolean>(false);
|
||||||
|
const actionType = ref('');
|
||||||
|
|
||||||
|
const onDelete = () => {
|
||||||
|
emit('delete');
|
||||||
|
};
|
||||||
|
|
||||||
|
const onClose = () => {
|
||||||
|
visible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSave = (data: ActionsType, options?: any) => {
|
||||||
|
emit('update', data, options);
|
||||||
|
// setTimeout(() => {
|
||||||
|
// getParams();
|
||||||
|
// }, 10);
|
||||||
|
visible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onAdd = () => {
|
||||||
|
visible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onType = (_type: string) => {
|
||||||
|
actionType.value = _type
|
||||||
|
}
|
||||||
|
|
||||||
|
const onPropsOk = (data: ActionsType, options?: any) => {
|
||||||
|
emit('update', data, options);
|
||||||
|
// setTimeout(() => {
|
||||||
|
// getParams();
|
||||||
|
// }, 10);
|
||||||
|
actionType.value = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPropsCancel = () => {
|
||||||
|
actionType.value = '';
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.deleteBtn() {
|
||||||
|
position: absolute;
|
||||||
|
top: -10px;
|
||||||
|
right: -10px;
|
||||||
|
display: none;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
color: #999;
|
||||||
|
line-height: 20px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.show {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f3f3f3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions-item {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
padding: 16px;
|
||||||
|
border: 1px dashed #999;
|
||||||
|
border-radius: 2px;
|
||||||
|
|
||||||
|
.item-options-warp {
|
||||||
|
display: inline-flex;
|
||||||
|
height: 48px;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
.item-options-type {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 48px;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-radius: 6px 0 0 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-options-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 8px;
|
||||||
|
background: #fafafa;
|
||||||
|
border-radius: 0 6px 6px 0;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
div {
|
||||||
|
padding: 6px 10px;
|
||||||
|
color: #333;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 22px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 22px;
|
||||||
|
|
||||||
|
.notify-text-highlight {
|
||||||
|
margin-left: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notify-img-highlight {
|
||||||
|
margin: 0 10px;
|
||||||
|
color: rgba(0, 0, 0, 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-number {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 16px;
|
||||||
|
font-weight: 800;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-delete {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
color: #e50012;
|
||||||
|
background-color: rgba(229, 0, 18, 0.1);
|
||||||
|
border-radius: 50%;
|
||||||
|
transform: translate(50%, -50%);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(#e50012, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions-item-filter-warp {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
padding: 2px 0;
|
||||||
|
border: 1px dashed #999;
|
||||||
|
border-radius: 30px;
|
||||||
|
|
||||||
|
&.filter-border {
|
||||||
|
padding: 2px 16px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions-item-filter-overflow {
|
||||||
|
display: flex;
|
||||||
|
padding-top: 4px;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: visible;
|
||||||
|
row-gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terms-params {
|
||||||
|
// display: inline-block;
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
// &:not(:first-child) {
|
||||||
|
// margin-bottom: 16px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
.terms-params-warp {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terms-params-content {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border: unset;
|
||||||
|
row-gap: 16px;
|
||||||
|
|
||||||
|
.terms-params-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-form-item {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
&:not(:first-child) {
|
||||||
|
.ant-form-item-explain-error {
|
||||||
|
padding-left: 80px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.term-type-warp {
|
||||||
|
// display: inline-block;
|
||||||
|
width: 50px;
|
||||||
|
margin: 0 16px;
|
||||||
|
|
||||||
|
.term-type {
|
||||||
|
padding-top: 4px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,19 +1,43 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="action-list-content">
|
<div class="action-list-content">
|
||||||
|
<template v-for="(item, index) in actions" :key="item.key">
|
||||||
|
<Item
|
||||||
|
:parallel="parallel"
|
||||||
|
:data="item"
|
||||||
|
:branchesName="branchesName"
|
||||||
|
:branchGroup="parallel ? 1 : 0"
|
||||||
|
:name="index"
|
||||||
|
:type="type"
|
||||||
|
:isLast="index === actions.length - 1"
|
||||||
|
:options="item.options"
|
||||||
|
@delete="_delete(item.key || '')"
|
||||||
|
@update="(data, options) => _update(data, options, item)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
<div class="actions-add-list" :class="{ 'border': props.actions.length }">
|
<div class="actions-add-list" :class="{ 'border': props.actions.length }">
|
||||||
<j-button type="primary" ghost style="width: 100%" @click="onAdd">
|
<j-button type="primary" ghost style="width: 100%" @click="onAdd">
|
||||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||||
添加执行动作
|
添加执行动作
|
||||||
</j-button>
|
</j-button>
|
||||||
</div>
|
</div>
|
||||||
<Modal v-if="visible" @cancel="visible = false" />
|
<Modal
|
||||||
|
v-if="visible"
|
||||||
|
@cancel="onCancel"
|
||||||
|
:parallel="parallel"
|
||||||
|
:name="actions.length"
|
||||||
|
:branchGroup="parallel ? 1 : 0"
|
||||||
|
@save="onSave"
|
||||||
|
:branchesName="branchesName"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { PropType } from 'vue';
|
import { PropType } from 'vue';
|
||||||
import { ActionsType, ParallelType } from '../../../typings';
|
import { ActionsType, ParallelType } from '../../../typings';
|
||||||
import Modal from '../Modal/index.vue'
|
import Modal from '../Modal/index.vue';
|
||||||
|
import Item from './Item.vue';
|
||||||
|
import { pick } from 'lodash';
|
||||||
|
|
||||||
interface ListProps {
|
interface ListProps {
|
||||||
branchesName: number;
|
branchesName: number;
|
||||||
|
@ -35,12 +59,38 @@ const props = defineProps({
|
||||||
parallel: Boolean,
|
parallel: Boolean,
|
||||||
});
|
});
|
||||||
|
|
||||||
const visible = ref<boolean>(false)
|
const emit = defineEmits(['delete', 'add']);
|
||||||
|
|
||||||
|
const visible = ref<boolean>(false);
|
||||||
|
|
||||||
const onAdd = () => {
|
const onAdd = () => {
|
||||||
visible.value = true
|
visible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSave = (data: any, options?: any) => {
|
||||||
|
const { type, ...extra } = data;
|
||||||
|
const item: ActionsType = {
|
||||||
|
...extra,
|
||||||
|
key: data.key,
|
||||||
|
options,
|
||||||
|
};
|
||||||
|
emit('add', item)
|
||||||
|
visible.value = false
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
visible.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const _delete = (_key: string) => {
|
||||||
|
emit('delete', _key)
|
||||||
|
}
|
||||||
|
|
||||||
|
const _update = (data: ActionsType, options: any, item: any) => {
|
||||||
|
const olData = pick(item, ['terms']);
|
||||||
|
emit('add', {...olData, ...data, options})
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<template v-if="actionType === 'device'">
|
||||||
|
<Device v-bind="props" :value="data?.device" @cancel="onCancel" @save="onPropsOk" />
|
||||||
|
</template>
|
||||||
|
<template v-else-if="actionType === 'notify'">
|
||||||
|
<Notify v-bind="props" :value="data?.notify" @cancel="onCancel" @save="onPropsOk" />
|
||||||
|
</template>
|
||||||
|
<template v-else-if="actionType === 'delay'">
|
||||||
|
<Delay :value="data?.delay" @cancel="onCancel" @save="onPropsOk" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { PropType } from 'vue';
|
||||||
|
import { ActionsType } from '../../../typings';
|
||||||
|
import Delay from '../Delay/index.vue';
|
||||||
|
import Notify from '../Notify/index.vue';
|
||||||
|
import Device from '../Device/index.vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
branchesName: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
branchGroup: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: Object as PropType<ActionsType>,
|
||||||
|
},
|
||||||
|
parallel: {
|
||||||
|
type: Boolean,
|
||||||
|
},
|
||||||
|
actionType: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['cancel', 'save']);
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
emit('cancel');
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPropsOk = (data: any, options: any) => {
|
||||||
|
const _data = {
|
||||||
|
type: props.actionType,
|
||||||
|
executor: props.actionType,
|
||||||
|
key: props?.data?.key || `${props.actionType}_${new Date().getTime()}`,
|
||||||
|
device: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
emit('save', { ..._data }, options);
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -25,24 +25,51 @@
|
||||||
float="right"
|
float="right"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<template v-if="actionType === 'device'">
|
<ActionTypeComponent
|
||||||
<Device @cancel="onCancel" @save="onPropsOk" />
|
v-bind="props"
|
||||||
</template>
|
v-if="!!actionType"
|
||||||
<template v-else-if="actionType === 'notify'">
|
:actionType="actionType"
|
||||||
<Notify @cancel="onCancel" @save="onPropsOk" />
|
@save="onPropsOk"
|
||||||
</template>
|
@cancel="onPropsCancel"
|
||||||
<template v-else-if="actionType === 'delay'">
|
/>
|
||||||
<Delay @cancel="onCancel" @save="onPropsOk" />
|
|
||||||
</template>
|
|
||||||
</a-form>
|
</a-form>
|
||||||
</j-modal>
|
</j-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { getImage } from '@/utils/comm';
|
import { getImage } from '@/utils/comm';
|
||||||
import Delay from '../Delay/index.vue'
|
import Delay from '../Delay/index.vue';
|
||||||
import Notify from '../Notify/index.vue'
|
import Notify from '../Notify/index.vue';
|
||||||
import Device from '../Device/index.vue'
|
import Device from '../Device/index.vue';
|
||||||
|
import { PropType } from 'vue';
|
||||||
|
import { ActionsType } from '../../../typings';
|
||||||
|
import ActionTypeComponent from './ActionTypeComponent.vue'
|
||||||
|
import { randomString } from '@/utils/utils';
|
||||||
|
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
branchesName: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
branchGroup: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: Object as PropType<ActionsType>,
|
||||||
|
default: () => ({
|
||||||
|
key: randomString()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
parallel: {
|
||||||
|
type: Boolean,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['cancel', 'save']);
|
const emit = defineEmits(['cancel', 'save']);
|
||||||
|
|
||||||
|
@ -81,25 +108,42 @@ const options = [
|
||||||
|
|
||||||
const actionForm = ref();
|
const actionForm = ref();
|
||||||
const formModel = reactive({
|
const formModel = reactive({
|
||||||
type: '',
|
type: 'device',
|
||||||
});
|
});
|
||||||
|
|
||||||
const actionType = ref<string>('')
|
const actionType = ref<string>('');
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.data,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal?.executor) {
|
||||||
|
formModel.type = (newVal?.executor === 'alarm' ? newVal?.alarm?.mode : newVal?.executor) as string
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
deep: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const onOk = () => {
|
||||||
|
actionForm.value.validate().then((values: any) => {
|
||||||
|
actionType.value = values?.type;
|
||||||
|
if (values?.type === 'relieve' || values?.type === 'trigger') {
|
||||||
|
emit('save', { ...props.data, executor: 'alarm', alarm: { mode: values.type } }, {});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
emit('cancel');
|
emit('cancel');
|
||||||
};
|
};
|
||||||
const onOk = () => {
|
|
||||||
actionForm.value.validate().then((values: any) => {
|
const onPropsOk = (data: any, options?: any) => {
|
||||||
actionType.value = values?.type
|
emit('save', { ...data, executor: data.type }, options);
|
||||||
if (values?.type === 'relieve' || values?.type === 'trigger') {
|
actionType.value = ''
|
||||||
// emit('save');
|
|
||||||
// props.save({ ...props.data, executor: 'alarm', alarm: { mode: values.type } }, {});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPropsOk = (data: any, option: any) => {
|
const onPropsCancel = () => {
|
||||||
console.log(data, option)
|
actionType.value = ''
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
|
@ -7,16 +7,12 @@
|
||||||
class="search"
|
class="search"
|
||||||
/>
|
/>
|
||||||
<div style="height: 400px; overflow-y: auto">
|
<div style="height: 400px; overflow-y: auto">
|
||||||
<JTable
|
<JProTable
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:request="ConfigApi.list"
|
:request="(e) => ConfigApi.list({
|
||||||
model="CARD"
|
...e,
|
||||||
:bodyStyle="{
|
|
||||||
paddingRight: 0,
|
|
||||||
paddingLeft: 0,
|
|
||||||
}"
|
|
||||||
:defaultParams="{
|
|
||||||
terms: [
|
terms: [
|
||||||
|
...e?.terms,
|
||||||
{
|
{
|
||||||
terms: [
|
terms: [
|
||||||
{
|
{
|
||||||
|
@ -27,11 +23,15 @@
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
sorts: [{ name: 'id', value: props.value }, { name: 'createTime', order: 'desc' }],
|
||||||
|
})"
|
||||||
|
model="CARD"
|
||||||
|
:bodyStyle="{
|
||||||
|
paddingRight: 0,
|
||||||
|
paddingLeft: 0,
|
||||||
}"
|
}"
|
||||||
:params="params"
|
:params="params"
|
||||||
:gridColumn="2"
|
:gridColumn="2"
|
||||||
:gridColumns="[2, 2, 2]"
|
|
||||||
:rowSelection="{
|
:rowSelection="{
|
||||||
selectedRowKeys: _selectedRowKeys,
|
selectedRowKeys: _selectedRowKeys,
|
||||||
}"
|
}"
|
||||||
|
@ -82,7 +82,7 @@
|
||||||
</template>
|
</template>
|
||||||
</CardBox>
|
</CardBox>
|
||||||
</template>
|
</template>
|
||||||
</JTable>
|
</JProTable>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -175,4 +175,9 @@ watch(
|
||||||
padding-right: 0px;
|
padding-right: 0px;
|
||||||
padding-left: 0px;
|
padding-left: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.logo{
|
||||||
|
width: 88px;
|
||||||
|
height: 88px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -7,20 +7,16 @@
|
||||||
class="search"
|
class="search"
|
||||||
/>
|
/>
|
||||||
<div style="height: 400px; overflow-y: auto">
|
<div style="height: 400px; overflow-y: auto">
|
||||||
<JTable
|
<JProTable
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:request="(e) => TemplateApi.getListByConfigId(props.notifierId, e)"
|
:request="(e) => handleData(e)"
|
||||||
model="CARD"
|
model="CARD"
|
||||||
:bodyStyle="{
|
:bodyStyle="{
|
||||||
paddingRight: 0,
|
paddingRight: 0,
|
||||||
paddingLeft: 0,
|
paddingLeft: 0,
|
||||||
}"
|
}"
|
||||||
:defaultParams="{
|
|
||||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
|
||||||
}"
|
|
||||||
:params="params"
|
:params="params"
|
||||||
:gridColumn="2"
|
:gridColumn="2"
|
||||||
:gridColumns="[2, 2, 2]"
|
|
||||||
:rowSelection="{
|
:rowSelection="{
|
||||||
selectedRowKeys: _selectedRowKeys,
|
selectedRowKeys: _selectedRowKeys,
|
||||||
}"
|
}"
|
||||||
|
@ -71,7 +67,7 @@
|
||||||
</template>
|
</template>
|
||||||
</CardBox>
|
</CardBox>
|
||||||
</template>
|
</template>
|
||||||
</JTable>
|
</JProTable>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -142,6 +138,27 @@ const handleClick = (dt: any) => {
|
||||||
emit('update:value', dt.id);
|
emit('update:value', dt.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleData = async (e: any) => {
|
||||||
|
const sorts = [
|
||||||
|
{ name: 'id', value: props.value },
|
||||||
|
{ name: 'createTime', order: 'desc' },
|
||||||
|
];
|
||||||
|
const resp = await TemplateApi.getListByConfigId(props.notifierId, {
|
||||||
|
...e,
|
||||||
|
sorts: sorts,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
code: resp.message,
|
||||||
|
result: {
|
||||||
|
data: resp.result ? resp.result : [],
|
||||||
|
pageIndex: 0,
|
||||||
|
pageSize: resp.result.length,
|
||||||
|
total: resp.result.length,
|
||||||
|
},
|
||||||
|
status: resp.status,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.value,
|
() => props.value,
|
||||||
(newValue) => {
|
(newValue) => {
|
||||||
|
@ -164,4 +181,9 @@ watch(
|
||||||
padding-right: 0px;
|
padding-right: 0px;
|
||||||
padding-left: 0px;
|
padding-left: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
width: 88px;
|
||||||
|
height: 88px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -42,6 +42,7 @@ watch(
|
||||||
);
|
);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
loading.value = true
|
||||||
notice.queryMessageType().then((resp) => {
|
notice.queryMessageType().then((resp) => {
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
options.value = (resp.result as any[]).map((item) => {
|
options.value = (resp.result as any[]).map((item) => {
|
||||||
|
@ -52,6 +53,7 @@ onMounted(() => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
loading.value = false
|
||||||
});
|
});
|
||||||
notifyType.value = props.value
|
notifyType.value = props.value
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,38 +5,44 @@
|
||||||
ref="formRef"
|
ref="formRef"
|
||||||
:model="modelRef"
|
:model="modelRef"
|
||||||
>
|
>
|
||||||
<template v-for="item in variableDefinitions" :key="item.id">
|
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:name="item.id"
|
:name="`${item?.id}`"
|
||||||
:label="item.name"
|
:label="item?.name"
|
||||||
:rules="[{ required: true, message: `请输入${item.name}` }]"
|
v-for="item in variableDefinitions"
|
||||||
|
:key="item.id"
|
||||||
|
:required="getType(item) !== 'file' ? true : false"
|
||||||
|
:rules="[
|
||||||
|
{
|
||||||
|
validator: (_rule, value) => checkValue(_rule, value, item),
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
]"
|
||||||
>
|
>
|
||||||
<User
|
<User
|
||||||
|
:notify="notify"
|
||||||
v-if="getType(item) === 'user'"
|
v-if="getType(item) === 'user'"
|
||||||
v-model="modelRef[`${item.id}`]"
|
v-model:value="modelRef[item.id]"
|
||||||
/>
|
/>
|
||||||
<Org
|
<Org
|
||||||
|
:notify="notify"
|
||||||
v-else-if="getType(item) === 'org'"
|
v-else-if="getType(item) === 'org'"
|
||||||
v-model="modelRef[`${item.id}`]"
|
v-model:value="modelRef[item.id]"
|
||||||
/>
|
/>
|
||||||
<Tag
|
<Tag
|
||||||
|
:notify="notify"
|
||||||
v-else-if="getType(item) === 'tag'"
|
v-else-if="getType(item) === 'tag'"
|
||||||
v-model="modelRef[`${item.id}`]"
|
v-model:value="modelRef[item.id]"
|
||||||
/>
|
/>
|
||||||
<InputFile
|
<InputFile
|
||||||
v-else-if="getType(item) === 'file'"
|
v-else-if="getType(item) === 'file'"
|
||||||
v-model="modelRef[`${item.id}`]"
|
v-model:value="modelRef[item.id]"
|
||||||
/>
|
/>
|
||||||
<a-input
|
<a-input
|
||||||
v-else-if="getType(item) === 'link'"
|
v-else-if="getType(item) === 'link'"
|
||||||
v-model="modelRef[`${item.id}`]"
|
v-model:value="modelRef[item.id]"
|
||||||
/>
|
|
||||||
<BuildIn
|
|
||||||
v-else
|
|
||||||
v-model="modelRef[`${item.id}`]"
|
|
||||||
/>
|
/>
|
||||||
|
<BuildIn v-else :item="item" v-model:value="modelRef[item.id]" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</template>
|
|
||||||
</a-form>
|
</a-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -46,25 +52,103 @@ import Org from './variableItem/Org.vue';
|
||||||
import Tag from './variableItem/Tag.vue';
|
import Tag from './variableItem/Tag.vue';
|
||||||
import InputFile from './variableItem/InputFile.vue';
|
import InputFile from './variableItem/InputFile.vue';
|
||||||
import User from './variableItem/User.vue';
|
import User from './variableItem/User.vue';
|
||||||
|
import { PropType } from 'vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
variableDefinitions: {
|
variableDefinitions: {
|
||||||
type: Array,
|
type: Array as PropType<any>,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
|
notify: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
|
|
||||||
const modelRef = reactive({});
|
const modelRef = reactive({});
|
||||||
|
|
||||||
Object.assign(formRef, props.value);
|
watchEffect(() => {
|
||||||
|
Object.assign(modelRef, props.value);
|
||||||
|
});
|
||||||
|
|
||||||
const getType = (item: any) => {
|
const getType = (item: any) => {
|
||||||
return item.expands?.businessType || item.type;
|
return item.expands?.businessType || item.type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const checkValue = (_rule: any, value: any, item: any) => {
|
||||||
|
const type = item.expands?.businessType || item?.type;
|
||||||
|
if (type === 'file') {
|
||||||
|
return Promise.resolve();
|
||||||
|
} else if (type === 'link') {
|
||||||
|
if (!value) {
|
||||||
|
return Promise.reject(new Error('请输入' + item.name));
|
||||||
|
} else if (value.length > 64) {
|
||||||
|
return Promise.reject(new Error('最多64个字符'));
|
||||||
|
}
|
||||||
|
} else if (type === 'tag' && !value) {
|
||||||
|
return Promise.reject(new Error('请选择' + item.name));
|
||||||
|
} else if (['date', 'org'].includes(type)) {
|
||||||
|
if (!value) {
|
||||||
|
return Promise.reject(new Error('请选择' + item.name));
|
||||||
|
} else {
|
||||||
|
if (value?.source === 'upper') {
|
||||||
|
if (!value.upperKey) {
|
||||||
|
return Promise.reject(new Error('请选择' + item.name));
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!value.value) {
|
||||||
|
return Promise.reject(new Error('请选择' + item.name));
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (value.source === 'fixed' && !value.value) {
|
||||||
|
return Promise.reject(new Error('请输入' + item.name));
|
||||||
|
} else if (value.source === 'relation' && !value.value && !value.relation) {
|
||||||
|
return Promise.reject(new Error('请选择' + item.name));
|
||||||
|
} else if (value.source === 'upper' && !value.upperKey) {
|
||||||
|
return Promise.reject(new Error('请选择' + item.name));
|
||||||
|
} else if (type === 'user') {
|
||||||
|
if (props.notify.notifyType === 'email') {
|
||||||
|
if (Array.isArray(value.value)) {
|
||||||
|
if (!value.value.length) {
|
||||||
|
return Promise.reject(new Error('请输入收件人'));
|
||||||
|
}
|
||||||
|
const reg =
|
||||||
|
/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
|
||||||
|
const flag = value.value.every((it: string) => {
|
||||||
|
return reg.test(it);
|
||||||
|
});
|
||||||
|
if (!flag) {
|
||||||
|
return Promise.reject(new Error('请输入正确的邮箱地址'));
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
props.notify.notifyType &&
|
||||||
|
['sms', 'voice'].includes(props?.notify?.notifyType)
|
||||||
|
) {
|
||||||
|
const reg = /^[1][3-9]\d{9}$/;
|
||||||
|
if (!reg.test(value.value)) {
|
||||||
|
return Promise.reject(new Error('请输入正确的手机号码'));
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
};
|
||||||
</script>
|
</script>
|
|
@ -33,12 +33,18 @@
|
||||||
</template>
|
</template>
|
||||||
<template v-if="current === 1">
|
<template v-if="current === 1">
|
||||||
<a-form-item name="notifierId">
|
<a-form-item name="notifierId">
|
||||||
<NotifyConfig v-model:value="formModel.notifierId" :notifyType="formModel.notifyType" />
|
<NotifyConfig
|
||||||
|
v-model:value="formModel.notifierId"
|
||||||
|
:notifyType="formModel.notifyType"
|
||||||
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="current === 2">
|
<template v-if="current === 2">
|
||||||
<a-form-item name="templateId">
|
<a-form-item name="templateId">
|
||||||
<NotifyTemplate v-model:value="formModel.templateId" :notifierId="formModel.notifierId" />
|
<NotifyTemplate
|
||||||
|
v-model:value="formModel.templateId"
|
||||||
|
:notifierId="formModel.notifierId"
|
||||||
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="current === 3">
|
<template v-if="current === 3">
|
||||||
|
@ -46,6 +52,7 @@
|
||||||
<VariableDefinitions
|
<VariableDefinitions
|
||||||
:variableDefinitions="variable"
|
:variableDefinitions="variable"
|
||||||
v-model:value="formModel.variables"
|
v-model:value="formModel.variables"
|
||||||
|
:notify="formModel"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</template>
|
</template>
|
||||||
|
@ -55,8 +62,12 @@
|
||||||
<a-space>
|
<a-space>
|
||||||
<j-button v-if="current === 0" @click="onCancel">取消</j-button>
|
<j-button v-if="current === 0" @click="onCancel">取消</j-button>
|
||||||
<j-button v-if="current > 0" @click="prev">上一步</j-button>
|
<j-button v-if="current > 0" @click="prev">上一步</j-button>
|
||||||
<j-button v-if="current < 3" type="primary" @click="next">下一步</j-button>
|
<j-button v-if="current < 3" type="primary" @click="next"
|
||||||
<j-button v-if="current === 3" type="primary" @click="onOk">确定</j-button>
|
>下一步</j-button
|
||||||
|
>
|
||||||
|
<j-button v-if="current === 3" type="primary" @click="onOk"
|
||||||
|
>确定</j-button
|
||||||
|
>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
</j-modal>
|
</j-modal>
|
||||||
|
@ -69,6 +80,22 @@ import NotifyTemplate from './NotifyTemplate.vue';
|
||||||
import VariableDefinitions from './VariableDefinitions.vue';
|
import VariableDefinitions from './VariableDefinitions.vue';
|
||||||
import { onlyMessage } from '@/utils/comm';
|
import { onlyMessage } from '@/utils/comm';
|
||||||
import Template from '@/api/notice/template';
|
import Template from '@/api/notice/template';
|
||||||
|
import { PropType } from 'vue';
|
||||||
|
import { NotifyProps } from '../../../typings';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
value: {
|
||||||
|
type: Object as PropType<Partial<NotifyProps>>,
|
||||||
|
default: () => undefined,
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['cancel', 'save']);
|
const emit = defineEmits(['cancel', 'save']);
|
||||||
|
|
||||||
|
@ -78,33 +105,42 @@ const formModel = reactive({
|
||||||
notifyType: '',
|
notifyType: '',
|
||||||
notifierId: '',
|
notifierId: '',
|
||||||
templateId: '',
|
templateId: '',
|
||||||
variables: [],
|
variables: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
const variable = ref([]);
|
const variable = ref([]);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(newVal) => {
|
||||||
|
Object.assign(formModel, newVal);
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
const jumpStep = async (val: number) => {
|
const jumpStep = async (val: number) => {
|
||||||
if (val === 0) {
|
if (val === 0) {
|
||||||
current.value = val;
|
current.value = val;
|
||||||
} else if (val === 1) {
|
} else if (val === 1) {
|
||||||
|
console.log(formModel)
|
||||||
if (formModel.notifyType) {
|
if (formModel.notifyType) {
|
||||||
current.value = val
|
current.value = val;
|
||||||
} else {
|
} else {
|
||||||
onlyMessage('请选择通知方式', 'error');
|
onlyMessage('请选择通知方式', 'error');
|
||||||
}
|
}
|
||||||
} else if (val === 2) {
|
} else if (val === 2) {
|
||||||
if (formModel.notifierId) {
|
if (formModel.notifierId) {
|
||||||
current.value = val
|
current.value = val;
|
||||||
} else {
|
} else {
|
||||||
onlyMessage('请选择通知配置', 'error');
|
onlyMessage('请选择通知配置', 'error');
|
||||||
}
|
}
|
||||||
} else if (val === 3) {
|
} else if (val === 3) {
|
||||||
formModel.templateId = '1628943618904956928'
|
formModel.templateId = '1628943618904956928';
|
||||||
if (formModel.templateId) {
|
if (formModel.templateId) {
|
||||||
const resp = await Template.getTemplateDetail(formModel.templateId);
|
const resp = await Template.getTemplateDetail(formModel.templateId);
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
variable.value = resp.result?.variableDefinitions || [];
|
variable.value = resp.result?.variableDefinitions || [];
|
||||||
current.value = val
|
current.value = val;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
onlyMessage('请选择通知模板', 'error');
|
onlyMessage('请选择通知模板', 'error');
|
||||||
|
@ -113,7 +149,7 @@ const jumpStep = async (val: number) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const onChange = (cur: number) => {
|
const onChange = (cur: number) => {
|
||||||
jumpStep(cur)
|
jumpStep(cur);
|
||||||
};
|
};
|
||||||
|
|
||||||
const prev = () => {
|
const prev = () => {
|
||||||
|
@ -121,7 +157,7 @@ const prev = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const next = async () => {
|
const next = async () => {
|
||||||
jumpStep(current.value + 1)
|
jumpStep(current.value + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
|
|
|
@ -1,3 +1,163 @@
|
||||||
<template>
|
<template>
|
||||||
build-in
|
<a-input-group compact>
|
||||||
|
<a-select
|
||||||
|
:options="[
|
||||||
|
{ label: '手动输入', value: 'fixed' },
|
||||||
|
{ label: '内置参数', value: 'upper' },
|
||||||
|
]"
|
||||||
|
style="width: 120px"
|
||||||
|
:value="value?.source"
|
||||||
|
@change="sourceChange"
|
||||||
|
/>
|
||||||
|
<template v-if="source === 'upper'">
|
||||||
|
<a-tree-select
|
||||||
|
v-model:value="upperKey"
|
||||||
|
:treeData="builtInList"
|
||||||
|
placeholder="请选择参数"
|
||||||
|
style="width: calc(100% - 120px)"
|
||||||
|
>
|
||||||
|
<template #title="{ name, description }">
|
||||||
|
<a-space>
|
||||||
|
{{ name }}
|
||||||
|
<spn style="color: grey; margin-left: 5px">{{ description }}</spn>
|
||||||
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
|
</a-tree-select>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<a-date-picker
|
||||||
|
:value="value.value"
|
||||||
|
allowClear
|
||||||
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
style="width: calc(100% - 120px)"
|
||||||
|
v-if="item.type === 'date'"
|
||||||
|
@change="(_, dateString) => itemOnChange(dateString)"
|
||||||
|
/>
|
||||||
|
<a-input-number
|
||||||
|
:value="value.value"
|
||||||
|
allowClear
|
||||||
|
style="width: calc(100% - 120px)"
|
||||||
|
v-else-if="item.type === 'number'"
|
||||||
|
:placeholder="`请输入${item.name}`"
|
||||||
|
@change="itemOnChange"
|
||||||
|
/>
|
||||||
|
<a-input
|
||||||
|
:value="value.value"
|
||||||
|
allowClear
|
||||||
|
style="width: calc(100% - 120px)"
|
||||||
|
v-else
|
||||||
|
:placeholder="`请输入${item.name}`"
|
||||||
|
@change="(e) => itemOnChange(e.target.value)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</a-input-group>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { queryBuiltInParams } from '@/api/rule-engine/scene';
|
||||||
|
import { useSceneStore } from '@/store/scene';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
||||||
|
const sceneStore = useSceneStore();
|
||||||
|
const { data } = storeToRefs(sceneStore);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
source: 'fixed',
|
||||||
|
value: undefined,
|
||||||
|
upperKey: undefined,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:value']);
|
||||||
|
|
||||||
|
const source = computed(() => {
|
||||||
|
return props.value?.source || 'fixed';
|
||||||
|
});
|
||||||
|
|
||||||
|
const builtInList = ref<any[]>([]);
|
||||||
|
const upperKey = ref();
|
||||||
|
|
||||||
|
const sourceChange = (val: any) => {
|
||||||
|
emit('update:value', {
|
||||||
|
...props.value,
|
||||||
|
source: val,
|
||||||
|
value: undefined,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const itemOnChange = (val: any) => {
|
||||||
|
emit('update:value', {
|
||||||
|
...props.value,
|
||||||
|
value: val,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const treeDataFilter = (arr: any[], type: string) => {
|
||||||
|
if (Array.isArray(arr) && arr.length) {
|
||||||
|
const list: any[] = [];
|
||||||
|
arr.map((item: any) => {
|
||||||
|
if (item.children) {
|
||||||
|
const children = treeDataFilter(item.children, type);
|
||||||
|
if (children.length) {
|
||||||
|
list.push({
|
||||||
|
...item,
|
||||||
|
title: item.name,
|
||||||
|
value: item.id,
|
||||||
|
disabled: true,
|
||||||
|
children,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
item.type === type ||
|
||||||
|
(type === 'double' &&
|
||||||
|
['int', 'float', 'double', 'long'].includes(item.type))
|
||||||
|
) {
|
||||||
|
list.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return list;
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => source.value,
|
||||||
|
(newVal) => {
|
||||||
|
const v = newVal;
|
||||||
|
if (v === 'upper') {
|
||||||
|
const params =
|
||||||
|
props.name - 1 >= 0 ? { action: props.name - 1 } : undefined;
|
||||||
|
queryBuiltInParams(unref(data), params).then((resp) => {
|
||||||
|
if (resp.status === 200) {
|
||||||
|
const arr = treeDataFilter(
|
||||||
|
resp.result as any[],
|
||||||
|
props.item.expands?.businessType || props.item?.type,
|
||||||
|
);
|
||||||
|
builtInList.value = arr;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true },
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
|
@ -1,3 +1,77 @@
|
||||||
<template>
|
<template>
|
||||||
input-file
|
<a-input
|
||||||
|
allowClear
|
||||||
|
placeholder="请上传文件"
|
||||||
|
v-model:value="url"
|
||||||
|
@change="onChange"
|
||||||
|
>
|
||||||
|
<template #addonAfter>
|
||||||
|
<a-upload
|
||||||
|
name="file"
|
||||||
|
:showUploadList="false"
|
||||||
|
:accept="'image/jpeg,image/png'"
|
||||||
|
:disabled="loading"
|
||||||
|
:headers="{
|
||||||
|
[TOKEN_KEY]: LocalStore.get(TOKEN_KEY),
|
||||||
|
}"
|
||||||
|
:action="`${BASE_API_PATH}/file/static`"
|
||||||
|
@change="handleChange"
|
||||||
|
@beforeUpload="handleBeforeUpload"
|
||||||
|
>
|
||||||
|
<j-button type="link" style="height: 30px">
|
||||||
|
<AIcon type="LoadingOutlined" v-if="loading" />
|
||||||
|
<AIcon type="PlusOutlined" v-else />
|
||||||
|
上传附件
|
||||||
|
</j-button>
|
||||||
|
</a-upload>
|
||||||
</template>
|
</template>
|
||||||
|
</a-input>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable';
|
||||||
|
import { LocalStore, onlyMessage } from '@/utils/comm';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:value']);
|
||||||
|
const url = ref(props.value || undefined);
|
||||||
|
const loading = ref<boolean>(false);
|
||||||
|
|
||||||
|
const handleChange = (info: any) => {
|
||||||
|
if (info.file.status === 'uploading') {
|
||||||
|
loading.value = true;
|
||||||
|
}
|
||||||
|
if (info.file.status === 'done') {
|
||||||
|
info.file.url = info.file.response?.result;
|
||||||
|
loading.value = false;
|
||||||
|
const result = info.file.response?.result;
|
||||||
|
emit('update:value', result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBeforeUpload = (file: any) => {
|
||||||
|
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
|
||||||
|
if (!isJpgOrPng) {
|
||||||
|
onlyMessage('请上传正确格式图片', 'error');
|
||||||
|
}
|
||||||
|
const isSize = file.size / 1024 / 1024 < 4;
|
||||||
|
if (!isSize) {
|
||||||
|
onlyMessage(`图片大小必须小于4M`, 'error');
|
||||||
|
}
|
||||||
|
return isJpgOrPng && isSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChange = (e: any) => {
|
||||||
|
emit('update:value', e.target.value);
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -1,3 +1,75 @@
|
||||||
<template>
|
<template>
|
||||||
org
|
<j-tree-select
|
||||||
|
:listHeight="200"
|
||||||
|
v-model:value="keys"
|
||||||
|
placeholder="请选择组织"
|
||||||
|
:tree-data="departmentTree"
|
||||||
|
@change="onChange"
|
||||||
|
:fieldNames="{
|
||||||
|
label: 'name',
|
||||||
|
value: 'id',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import ConfigApi from '@/api/notice/config';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
notify: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:value']);
|
||||||
|
|
||||||
|
const departmentTree = ref<any[]>([]);
|
||||||
|
const keys = ref<any[]>([]);
|
||||||
|
|
||||||
|
const getDepartment = async (id: string) => {
|
||||||
|
if (props.notify.notifyType === 'dingTalk') {
|
||||||
|
const resp = await ConfigApi.dingTalkDept(id);
|
||||||
|
if (resp.status === 200) {
|
||||||
|
departmentTree.value = resp.result;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const resp = await ConfigApi.weChatDept(id);
|
||||||
|
if (resp.status === 200) {
|
||||||
|
departmentTree.value = resp.result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
() => {
|
||||||
|
keys.value = props?.value || [];
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.notify.notifierId,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
getDepartment(newVal);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
const onChange = (key: string[], label: string[]) => {
|
||||||
|
emit('update:value', {
|
||||||
|
source: 'fixed',
|
||||||
|
value: key,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
|
@ -1,3 +1,65 @@
|
||||||
<template>
|
<template>
|
||||||
tag
|
<j-select
|
||||||
|
style="width: 100%"
|
||||||
|
v-model:value="keys"
|
||||||
|
placeholder="请选择标签"
|
||||||
|
:options="tagsList"
|
||||||
|
@change="onChange"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import TemplateApi from '@/api/notice/template';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
notify: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:value']);
|
||||||
|
|
||||||
|
const tagsList = ref<any[]>([]);
|
||||||
|
const keys = ref<string>('');
|
||||||
|
|
||||||
|
const getDepartment = async (id: string) => {
|
||||||
|
const resp = await TemplateApi.getTags(id);
|
||||||
|
if (resp.status === 200) {
|
||||||
|
tagsList.value = resp.result.map((item: any) => ({value: item.id, label: item.name}))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(newVal) => {
|
||||||
|
keys.value = newVal || ''
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.notify.notifierId,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
getDepartment(newVal);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
const onChange = (key: string, label: string[]) => {
|
||||||
|
// TODO 回显label的问题
|
||||||
|
emit('update:value', {
|
||||||
|
source: 'fixed',
|
||||||
|
value: key,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
|
@ -1,3 +1,274 @@
|
||||||
<template>
|
<template>
|
||||||
user
|
<a-input-group compact>
|
||||||
|
<a-select
|
||||||
|
style="width: 120px"
|
||||||
|
v-model:value="mySource"
|
||||||
|
@change="sourceChange"
|
||||||
|
>
|
||||||
|
<a-select-option key="5" value="relation">
|
||||||
|
平台用户
|
||||||
|
</a-select-option>
|
||||||
|
<a-select-option
|
||||||
|
v-if="notifyType === 'dingTalk'"
|
||||||
|
key="1"
|
||||||
|
value="fixed"
|
||||||
|
>
|
||||||
|
钉钉用户
|
||||||
|
</a-select-option>
|
||||||
|
<a-select-option
|
||||||
|
v-else-if="notifyType === 'weixin'"
|
||||||
|
key="2"
|
||||||
|
value="fixed"
|
||||||
|
>
|
||||||
|
微信用户
|
||||||
|
</a-select-option>
|
||||||
|
<a-select-option
|
||||||
|
v-else-if="notifyType === 'email'"
|
||||||
|
key="3"
|
||||||
|
value="fixed"
|
||||||
|
>
|
||||||
|
固定邮箱
|
||||||
|
</a-select-option>
|
||||||
|
<a-select-option v-else key="4" value="fixed">
|
||||||
|
固定号码
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-tree-select
|
||||||
|
v-if="source === 'relation'"
|
||||||
|
style="width: calc(100% - 120px)"
|
||||||
|
placeholder="请选择收信人"
|
||||||
|
@select="treeSelect"
|
||||||
|
:tree-data="treeData"
|
||||||
|
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||||
|
:value="relationData"
|
||||||
|
/>
|
||||||
|
<a-select
|
||||||
|
style="width: calc(100% - 120px)"
|
||||||
|
v-else-if="['dingTalk', 'weixin'].includes(notifyType)"
|
||||||
|
placeholder="请选择收信人"
|
||||||
|
:value="value?.value"
|
||||||
|
@change="(val) => onChange(val)"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in relationList"
|
||||||
|
:key="item.id"
|
||||||
|
:value="item.id"
|
||||||
|
>{{ item.name }}</a-select-option
|
||||||
|
>
|
||||||
|
</a-select>
|
||||||
|
<a-input
|
||||||
|
style="width: calc(100% - 120px)"
|
||||||
|
v-else-if="['email'].includes(notifyType)"
|
||||||
|
placeholder="请输入固定邮箱"
|
||||||
|
:value="value?.value"
|
||||||
|
:multiple="true"
|
||||||
|
@change="(e) => onChange(e.target.value)"
|
||||||
|
></a-input>
|
||||||
|
<a-input
|
||||||
|
style="width: calc(100% - 120px)"
|
||||||
|
v-else-if="['sms', 'voice'].includes(notifyType)"
|
||||||
|
placeholder="请输入固定号码"
|
||||||
|
:value="value?.value"
|
||||||
|
@change="(e) => onChange(e.target.value)"
|
||||||
|
></a-input>
|
||||||
|
</a-input-group>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useSceneStore } from '@/store/scene';
|
||||||
|
import NoticeApi from '@/api/notice/config';
|
||||||
|
|
||||||
|
const sceneStore = useSceneStore();
|
||||||
|
const { data } = storeToRefs(sceneStore);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
notify: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: [Object],
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:value']);
|
||||||
|
|
||||||
|
const notifyType = computed(() => {
|
||||||
|
return props.notify?.notifyType;
|
||||||
|
});
|
||||||
|
|
||||||
|
const notifierId = computed(() => {
|
||||||
|
return props.notify?.notifierId;
|
||||||
|
});
|
||||||
|
|
||||||
|
const source = computed(() => {
|
||||||
|
if (props.value) {
|
||||||
|
return props.value?.source || 'relation';
|
||||||
|
} else {
|
||||||
|
return 'relation';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const triggerType = computed(() => {
|
||||||
|
return data?.trigger || data?.trigger?.type;
|
||||||
|
});
|
||||||
|
|
||||||
|
const relationData = computed(() => {
|
||||||
|
const item = props.value;
|
||||||
|
if (item?.source === 'relation') {
|
||||||
|
const relation = item?.relation;
|
||||||
|
if (relation) {
|
||||||
|
if (relation.objectId) {
|
||||||
|
// 平台用户
|
||||||
|
return relation.objectId;
|
||||||
|
} else {
|
||||||
|
// 关系用户
|
||||||
|
return relation.related?.relation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const relationList = ref<any[]>([]);
|
||||||
|
const treeData = ref<any[]>([
|
||||||
|
{
|
||||||
|
title: '平台用户',
|
||||||
|
value: 'p1',
|
||||||
|
key: 'p1',
|
||||||
|
selectable: false,
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const mySource = ref<string>('relation');
|
||||||
|
|
||||||
|
const getRelationUsers = async (notifyType: string, notifierId: string) => {
|
||||||
|
let resp = undefined;
|
||||||
|
if (notifyType === 'dingTalk') {
|
||||||
|
resp = await NoticeApi.queryDingTalkUsers(notifierId);
|
||||||
|
} else {
|
||||||
|
resp = await NoticeApi.queryWechatUsers(notifierId);
|
||||||
|
}
|
||||||
|
if (resp && resp.status === 200) {
|
||||||
|
relationList.value = resp.result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getUser = async (_source: string, triggerType: string) => {
|
||||||
|
const newTree = [
|
||||||
|
{
|
||||||
|
title: '平台用户',
|
||||||
|
value: 'p1',
|
||||||
|
key: 'p1',
|
||||||
|
selectable: false,
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let relationResp = undefined;
|
||||||
|
const platformResp = await NoticeApi.getPlatformUsers({
|
||||||
|
paging: false,
|
||||||
|
sorts: [{ name: 'name', order: 'asc' }],
|
||||||
|
});
|
||||||
|
if (triggerType && triggerType === 'device' && _source === 'relation') {
|
||||||
|
relationResp = await NoticeApi.getRelationUsers({
|
||||||
|
paging: false,
|
||||||
|
sorts: [{ name: 'name', order: 'asc' }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (platformResp.status === 200) {
|
||||||
|
newTree[0].children = platformResp.result.map((item: any) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
value: item.id,
|
||||||
|
key: item.id,
|
||||||
|
title: item.name,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (relationResp && relationResp.success) {
|
||||||
|
newTree.push({
|
||||||
|
title: '关系用户',
|
||||||
|
value: 'p2',
|
||||||
|
key: 'p2',
|
||||||
|
selectable: false,
|
||||||
|
children: relationResp.result.map((item: any) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
value: item.id,
|
||||||
|
key: item.id,
|
||||||
|
title: item.name,
|
||||||
|
isRelation: true,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
treeData.value = newTree;
|
||||||
|
};
|
||||||
|
|
||||||
|
const treeSelect = (val: string, _data: any) => {
|
||||||
|
const obj = {
|
||||||
|
source: source.value,
|
||||||
|
relation: {}
|
||||||
|
};
|
||||||
|
if (_data?.isRelation) {
|
||||||
|
obj.relation = {
|
||||||
|
objectType: 'device',
|
||||||
|
objectSource: {
|
||||||
|
source: 'upper',
|
||||||
|
upperKey: 'scene.deviceId',
|
||||||
|
},
|
||||||
|
related: {
|
||||||
|
objectType: 'user',
|
||||||
|
relation: val,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
obj.relation = {
|
||||||
|
objectType: 'user',
|
||||||
|
objectId: val,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
emit('update:value', obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
const sourceChange = (v: any) => {
|
||||||
|
emit('update:value', {
|
||||||
|
source: v,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChange = (val: any) => {
|
||||||
|
emit('update:value', {
|
||||||
|
source: source.value,
|
||||||
|
value: val,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => triggerType.value,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal && source.value === 'relation') {
|
||||||
|
getUser(source.value, newVal);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => source.value,
|
||||||
|
(newVal) => {
|
||||||
|
const v = newVal;
|
||||||
|
mySource.value = v as string;
|
||||||
|
if (
|
||||||
|
v === 'fixed' &&
|
||||||
|
['dingTalk', 'weixin'].includes(notifyType.value)
|
||||||
|
) {
|
||||||
|
getRelationUsers(notifyType.value, notifierId.value);
|
||||||
|
} else {
|
||||||
|
getUser(v, triggerType.value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true },
|
||||||
|
);
|
||||||
|
</script>
|
|
@ -42,6 +42,8 @@
|
||||||
:branchesName="props.name"
|
:branchesName="props.name"
|
||||||
:parallel="true"
|
:parallel="true"
|
||||||
:actions="parallelArray.length ? parallelArray[0].actions : []"
|
:actions="parallelArray.length ? parallelArray[0].actions : []"
|
||||||
|
@add="onAdd"
|
||||||
|
@delete="onDelete"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
|
@ -53,8 +55,6 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import ShakeLimit from '../components/ShakeLimit/index.vue';
|
import ShakeLimit from '../components/ShakeLimit/index.vue';
|
||||||
import { List } from './ListItem';
|
import { List } from './ListItem';
|
||||||
import { storeToRefs } from 'pinia';
|
|
||||||
import { useSceneStore } from '@/store/scene';
|
|
||||||
import { BranchesThen } from '../../typings';
|
import { BranchesThen } from '../../typings';
|
||||||
import { PropType } from 'vue';
|
import { PropType } from 'vue';
|
||||||
|
|
||||||
|
@ -73,7 +73,9 @@ const props = defineProps({
|
||||||
openShakeLimit: Boolean,
|
openShakeLimit: Boolean,
|
||||||
});
|
});
|
||||||
|
|
||||||
const shakeLimit = ref({});
|
const shakeLimit = ref({
|
||||||
|
enabled: false
|
||||||
|
});
|
||||||
const activeKeys = ref<string[]>(['1']);
|
const activeKeys = ref<string[]>(['1']);
|
||||||
const parallelArray = ref<BranchesThen[]>([]);
|
const parallelArray = ref<BranchesThen[]>([]);
|
||||||
const serialArray = ref<BranchesThen[]>([]);
|
const serialArray = ref<BranchesThen[]>([]);
|
||||||
|
@ -105,6 +107,13 @@ watch(
|
||||||
immediate: true,
|
immediate: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onDelete = (_key: string) => {
|
||||||
|
console.log(_key)
|
||||||
|
}
|
||||||
|
const onAdd = (data: any) => {
|
||||||
|
console.log(data)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
Loading…
Reference in New Issue