feat: 新增场景联动-触发规则-属性修改
This commit is contained in:
parent
c24be85601
commit
e4a124a433
|
@ -0,0 +1,82 @@
|
|||
<template>
|
||||
<a-row :gutter='[24]'>
|
||||
<a-col :span='10'>
|
||||
<a-form-item
|
||||
name='readProperties'
|
||||
:rules="[{ required: true, message: '请选择属性' }]"
|
||||
>
|
||||
<a-select
|
||||
show-search
|
||||
mode='multiple'
|
||||
max-tag-count='responsive'
|
||||
placeholder='请选择属性'
|
||||
style='width: 100%'
|
||||
v-model:value='readProperties'
|
||||
:options='properties'
|
||||
:filter-option='filterSelectNode'
|
||||
@change='change'
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span='14'>
|
||||
<a-form-item>定时读取所选属性值</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name='ReadProperties'>
|
||||
import { filterSelectNode } from '@/utils/comm'
|
||||
import type { PropType } from 'vue'
|
||||
|
||||
type Emit = {
|
||||
(e: 'update:value', data: Array<string>): void
|
||||
(e: 'update:action', data: string): void
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Array as PropType<Array<string>>,
|
||||
default: () => []
|
||||
},
|
||||
action: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
properties: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
|
||||
const readProperties = ref<string[]>(props.value)
|
||||
|
||||
const change = (values: string[], optionItems: any[]) => {
|
||||
console.log(values, optionItems)
|
||||
const names = optionItems.map((item) => item.name);
|
||||
let extraStr = '';
|
||||
let isLimit = false;
|
||||
let indexOf = 0;
|
||||
extraStr = names.reduce((_prev, next, index) => {
|
||||
if (_prev.length <= 30) {
|
||||
indexOf = index;
|
||||
return index === 0 ? next : _prev + '、' + next;
|
||||
} else {
|
||||
isLimit = true;
|
||||
}
|
||||
return _prev;
|
||||
}, '');
|
||||
|
||||
if (isLimit && names.length - 1 > indexOf) {
|
||||
extraStr += `等${optionItems.length}个属性`;
|
||||
}
|
||||
emit('update:value', values)
|
||||
emit('update:action', `读取 ${extraStr}`)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,66 @@
|
|||
<template>
|
||||
<a-row :futter='[24]'>
|
||||
<a-col :span='10'>
|
||||
<a-select
|
||||
showSearch
|
||||
max-tag-count='responsive'
|
||||
style='width: 100%'
|
||||
placeholder='placeholder'
|
||||
v-model:value='reportKey'
|
||||
:options='properties'
|
||||
:filter-option='filterSelectNode'
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span='14'>定时调用所选属性</a-col>
|
||||
<a-col :span='24' v-if='showTable'>
|
||||
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name='ReportEvent'>
|
||||
import { filterSelectNode } from '@/utils/comm'
|
||||
import type { PropType } from 'vue'
|
||||
|
||||
type Emit = {
|
||||
(e: 'update:value', data: Array<string>): void
|
||||
(e: 'update:action', data: string): void
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Array as PropType<Array<string>>,
|
||||
default: () => []
|
||||
},
|
||||
action: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
properties: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
|
||||
const reportKey = ref<Array<string>>([])
|
||||
const callData = ref<Array<{}>>()
|
||||
|
||||
const showTable = computed(() => {
|
||||
return !!reportKey.value
|
||||
})
|
||||
|
||||
watch([props.value, props.properties], () => {
|
||||
if (props.value && props.properties?.length) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -7,23 +7,33 @@
|
|||
>
|
||||
<TopCard
|
||||
:label-bottom='true'
|
||||
:options='options'
|
||||
:options='topOptions'
|
||||
v-model:value='formModel.operator'
|
||||
/>
|
||||
</a-form-item>
|
||||
<Timer v-if='showTimer' />
|
||||
<Timer v-if='showTimer' v-model:value='formModel.timer' />
|
||||
<ReadProperties v-if='showReadProperty' v-model:value='formModel.readProperties' v-model:action='optionCache.action' :properties='readProperties' />
|
||||
<a-form-item
|
||||
v-if='showWriteProperty'
|
||||
name='writeProperties'
|
||||
:rules="[{ required: true, message: '请输入修改值' }]"
|
||||
>
|
||||
<WriteProperty v-model:value='formModel.writeProperties' v-model:action='optionCache.action' :properties='writeProperties' />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts'>
|
||||
|
||||
import TopCard from '@/views/rule-engine/Scene/Save/components/TopCard.vue'
|
||||
import { TopCard, Timer } from '@/views/rule-engine/Scene/Save/components'
|
||||
import { getImage } from '@/utils/comm'
|
||||
import { metadataType } from '@/views/rule-engine/Scene/typings'
|
||||
import type { PropType } from 'vue'
|
||||
import { TypeEnum } from '@/views/rule-engine/Scene/Save/Device/util'
|
||||
import Timer from '../components/Timer.vue'
|
||||
import ReadProperties from './ReadProperties.vue'
|
||||
import ReportEvent from './ReportEvent.vue'
|
||||
import WriteProperty from './WriteProperty.vue'
|
||||
|
||||
const props = defineProps({
|
||||
metadata: {
|
||||
|
@ -34,12 +44,19 @@ const props = defineProps({
|
|||
|
||||
const formModel = reactive({
|
||||
operator: 'online',
|
||||
timer: {},
|
||||
readProperties: [],
|
||||
writeProperties: {}
|
||||
})
|
||||
|
||||
const optionCache = reactive({
|
||||
action: ''
|
||||
})
|
||||
|
||||
const readProperties = ref<any[]>([])
|
||||
const writeProperties = ref<any[]>([])
|
||||
|
||||
const options = computed(() => {
|
||||
const topOptions = computed(() => {
|
||||
const baseOptions = [
|
||||
{
|
||||
label: '设备上线',
|
||||
|
@ -59,9 +76,9 @@ const options = computed(() => {
|
|||
|
||||
if (props.metadata.properties?.length) {
|
||||
const _properties = props.metadata.properties
|
||||
readProperties.value = _properties.filter((item: any) => item.expands.type?.includes('read'))
|
||||
writeProperties.value = _properties.filter((item: any) => item.expands.type?.includes('write'))
|
||||
const reportProperties = _properties.filter((item: any) => item.expands.type?.includes('report'))
|
||||
readProperties.value = _properties.filter((item: any) => item.expands.type?.includes('read')).map(item => ({...item, label: item.name, value: item.id }))
|
||||
writeProperties.value = _properties.filter((item: any) => item.expands.type?.includes('write')).map(item => ({...item, label: item.name, value: item.id }))
|
||||
const reportProperties = _properties.filter((item: any) => item.expands.type?.includes('report')).map(item => ({...item, label: item.name, value: item.id }))
|
||||
|
||||
if (readProperties.value.length) {
|
||||
baseOptions.push(TypeEnum.readProperty)
|
||||
|
@ -84,8 +101,28 @@ const options = computed(() => {
|
|||
return baseOptions
|
||||
})
|
||||
|
||||
const showReadProperty = computed(() => {
|
||||
return formModel.operator === TypeEnum.readProperty.value
|
||||
})
|
||||
|
||||
const showWriteProperty = computed(() => {
|
||||
return formModel.operator === TypeEnum.writeProperty.value
|
||||
})
|
||||
|
||||
const showReportEvent = computed(() => {
|
||||
return formModel.operator === TypeEnum.reportEvent.value
|
||||
})
|
||||
|
||||
const showInvokeFunction = computed(() => {
|
||||
return formModel.operator === TypeEnum.invokeFunction.value
|
||||
})
|
||||
|
||||
const showTimer = computed(() => {
|
||||
return ['readProperty', 'writeProperty', 'invokeFunction'].includes(formModel.operator)
|
||||
return [
|
||||
TypeEnum.readProperty.value,
|
||||
TypeEnum.writeProperty.value,
|
||||
TypeEnum.invokeFunction.value
|
||||
].includes(formModel.operator)
|
||||
})
|
||||
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
<template>
|
||||
<a-row :futter='[24, 24]'>
|
||||
<a-col :span='10'>
|
||||
<a-select
|
||||
showSearch
|
||||
style='width: 100%'
|
||||
placeholder='请选择属性'
|
||||
v-model:value='reportKey'
|
||||
:options='properties'
|
||||
:filter-option='filterSelectNode'
|
||||
@change='change'
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span='14'>
|
||||
<span style='line-height: 32px;padding-left: 24px'>
|
||||
定时调用所选属性
|
||||
</span>
|
||||
</a-col>
|
||||
<a-col :span='24' v-if='showTable'>
|
||||
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name='WriteProperties'>
|
||||
import { filterSelectNode } from '@/utils/comm'
|
||||
import type { PropType } from 'vue'
|
||||
|
||||
type Emit = {
|
||||
(e: 'update:value', data: Record<string, any>): void
|
||||
(e: 'update:action', data: string): void
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Object as PropType<Record<string, any>>,
|
||||
default: () => []
|
||||
},
|
||||
action: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
properties: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
|
||||
const reportKey = ref<string>()
|
||||
const callData = ref<Array<Record<string, any>>>()
|
||||
|
||||
const callDataOptions = computed(() => {
|
||||
const _valueKeys = Object.keys(props.value)
|
||||
if (_valueKeys.length) {
|
||||
return _valueKeys.map(key => {
|
||||
const item: any = props.properties.find((p: any) => p.id === key)
|
||||
if (item) {
|
||||
return {
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
type: item.valueType ? item.valueType.type : '-',
|
||||
format: item.valueType ? item.valueType.format : undefined,
|
||||
options: item.valueType ? item.valueType.element : undefined,
|
||||
value: props.value[key]
|
||||
}
|
||||
}
|
||||
return {
|
||||
id: key,
|
||||
name: key,
|
||||
type: '',
|
||||
format: undefined,
|
||||
options: undefined,
|
||||
value: props.value[key]
|
||||
}
|
||||
})
|
||||
}
|
||||
return []
|
||||
})
|
||||
|
||||
const showTable = computed(() => {
|
||||
return !!reportKey.value
|
||||
})
|
||||
|
||||
const change = (v: string, option: any) => {
|
||||
console.log(v, option)
|
||||
const _data = {
|
||||
[v]: undefined
|
||||
}
|
||||
callData.value = [_data]
|
||||
emit('update:value', _data)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,38 @@
|
|||
<template>
|
||||
<a-table
|
||||
:data-source='dataSource'
|
||||
:columns='columns'
|
||||
>
|
||||
<template #bodyCell="{ column, record, index }">
|
||||
<template v-if='column.key'>
|
||||
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name='FunctionCall'>
|
||||
|
||||
const dataSource = []
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '参数名称',
|
||||
dataIndex: 'name'
|
||||
},
|
||||
{
|
||||
title: '参数名称',
|
||||
dataIndex: 'name'
|
||||
},
|
||||
{
|
||||
title: '值',
|
||||
dataIndex: 'value',
|
||||
align: 'center',
|
||||
width: 260
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,98 @@
|
|||
<template>
|
||||
<div class='timer-when-warp'>
|
||||
<div :class='["when-item-option", allActive ? "active" : ""]' @click='() => change(0)'>每天</div>
|
||||
<div
|
||||
v-for='item in timeOptions'
|
||||
:class='["when-item-option", rowKeys.includes(item.value) ? "active" : ""]'
|
||||
@click='() => change(item.value)'
|
||||
>
|
||||
{{ item.label }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name='WhenOption'>
|
||||
import type { PropType } from 'vue'
|
||||
import { numberToString } from './util'
|
||||
|
||||
type Emit = {
|
||||
(e: 'update:value', data: Array<number>):void
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Array as PropType<Array<number>>,
|
||||
default: []
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
|
||||
const timeOptions = ref<Array<{ label: string, value: number}>>([])
|
||||
const rowKeys = ref<Array<number>>(props.value)
|
||||
|
||||
const change = (number: number) => {
|
||||
const _keys = new Set(rowKeys.value)
|
||||
if (number === 0) { // 全选
|
||||
_keys.clear()
|
||||
} else {
|
||||
if (_keys.has(number)) {
|
||||
_keys.delete(number)
|
||||
} else {
|
||||
_keys.add(number)
|
||||
}
|
||||
}
|
||||
rowKeys.value = [..._keys.values()]
|
||||
emit('update:value', rowKeys.value)
|
||||
}
|
||||
|
||||
const allActive = computed(() => {
|
||||
return !rowKeys.value.length
|
||||
})
|
||||
|
||||
watch(() => props.type, () => {
|
||||
const isMonth = props.type === 'month'
|
||||
const day = isMonth ? 31 : 7
|
||||
change(0)
|
||||
timeOptions.value = new Array(day)
|
||||
.fill(1)
|
||||
.map((_, index) => {
|
||||
const _value = index + 1
|
||||
return {
|
||||
label: isMonth ? `${_value}号` : numberToString[_value],
|
||||
value: _value
|
||||
}
|
||||
})
|
||||
}, { immediate: true })
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
.timer-when-warp {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px 16px;
|
||||
padding: 16px;
|
||||
background: #fafafa;
|
||||
|
||||
.when-item-option {
|
||||
width: 76px;
|
||||
padding: 6px 0;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
border: 1px solid #e6e6e6;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.active {
|
||||
color: #233dd7;
|
||||
border-color: #233dd7;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,3 @@
|
|||
import Timer from './index.vue'
|
||||
|
||||
export default Timer
|
|
@ -17,12 +17,26 @@
|
|||
button-style='solid'
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item v-if='showCron' name='cron'>
|
||||
<a-input placeholder='corn表达式' v-model='formModel.cron' />
|
||||
<a-form-item v-if='showCron' name='cron' :rules="[
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
{
|
||||
validator: async (_, v) => {
|
||||
if (v) {
|
||||
if (!isCron(v)) {
|
||||
return Promise.reject(new Error('请输入正确的cron表达式'));
|
||||
}
|
||||
} else {
|
||||
return Promise.reject(new Error('请输入cron表达式'));
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
]">
|
||||
<a-input placeholder='corn表达式' v-model:value='formModel.cron' />
|
||||
</a-form-item>
|
||||
<template v-else>
|
||||
<a-form-item name='when'>
|
||||
|
||||
<WhenOption v-model:value='formModel.when' :type='formModel.trigger' />
|
||||
</a-form-item>
|
||||
<a-form-item name='mod'>
|
||||
<a-radio-group
|
||||
|
@ -38,9 +52,10 @@
|
|||
</template>
|
||||
<a-space v-if='showOnce' style='display: flex;gap: 24px'>
|
||||
<a-form-item :name="['once', 'time']">
|
||||
<a-time-picker valueFormat='HH:mm:ss' v-model:value='formModel.once.time' style='width: 100%' format='HH:mm:ss' />
|
||||
<a-time-picker valueFormat='HH:mm:ss' v-model:value='formModel.once.time' style='width: 100%'
|
||||
format='HH:mm:ss' />
|
||||
</a-form-item>
|
||||
<a-form-item> 执行一次 </a-form-item>
|
||||
<a-form-item> 执行一次</a-form-item>
|
||||
</a-space>
|
||||
<a-space v-if='showPeriod' style='display: flex;gap: 24px'>
|
||||
<a-form-item>
|
||||
|
@ -89,9 +104,17 @@
|
|||
<script setup lang='ts' name='Timer'>
|
||||
import type { PropType } from 'vue'
|
||||
import moment from 'moment'
|
||||
import WhenOption from './WhenOption.vue'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import type { OperationTimer } from '../../../typings'
|
||||
import { isCron } from '@/utils/regular'
|
||||
|
||||
type NameType = string[] | string
|
||||
|
||||
type Emit = {
|
||||
(e: 'update:value', data: OperationTimer): void
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
name: {
|
||||
type: [String, Array] as PropType<NameType>,
|
||||
|
@ -103,13 +126,15 @@ const props = defineProps({
|
|||
}
|
||||
})
|
||||
|
||||
const formModel = reactive({
|
||||
const emit = defineEmits<Emit>()
|
||||
|
||||
const formModel = reactive<OperationTimer>({
|
||||
trigger: 'week',
|
||||
when: [],
|
||||
mod: 'period',
|
||||
cron: undefined,
|
||||
once: {
|
||||
time: ''
|
||||
time: moment(new Date()).format('HH:mm:ss')
|
||||
},
|
||||
period: {
|
||||
from: moment(new Date()).startOf('day').format('HH:mm:ss'),
|
||||
|
@ -119,6 +144,8 @@ const formModel = reactive({
|
|||
}
|
||||
})
|
||||
|
||||
Object.assign(formModel, props.value)
|
||||
|
||||
const showCron = computed(() => {
|
||||
return formModel.trigger === 'cron'
|
||||
})
|
||||
|
@ -131,6 +158,22 @@ const showPeriod = computed(() => {
|
|||
return formModel.trigger !== 'cron' && formModel.mod === 'period'
|
||||
})
|
||||
|
||||
watch(() => formModel, () => {
|
||||
const cloneValue = cloneDeep(formModel)
|
||||
if (cloneValue.trigger === 'cron') {
|
||||
delete cloneValue.when
|
||||
} else {
|
||||
delete cloneValue.cron
|
||||
}
|
||||
|
||||
if (cloneValue.mod === 'period') {
|
||||
delete cloneValue.once
|
||||
} else {
|
||||
delete cloneValue.period
|
||||
}
|
||||
emit('update:value', cloneValue)
|
||||
}, { deep: true })
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
|
@ -0,0 +1,9 @@
|
|||
export const numberToString = {
|
||||
1: '星期一',
|
||||
2: '星期二',
|
||||
3: '星期三',
|
||||
4: '星期四',
|
||||
5: '星期五',
|
||||
6: '星期六',
|
||||
7: '星期日',
|
||||
};
|
|
@ -0,0 +1,3 @@
|
|||
export { default as Timer } from './Timer'
|
||||
export { default as TopCard } from './TopCard.vue'
|
||||
export { default as TriggerWay } from './TriggerWay.vue'
|
|
@ -93,7 +93,7 @@ export enum ActionAlarmMode {
|
|||
export interface OperationTimerPeriod {
|
||||
from: string;
|
||||
to: string;
|
||||
every: string[];
|
||||
every: number;
|
||||
unit: keyof typeof TimeUnit;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue