update: 优化场景联动-触发规则回显
This commit is contained in:
parent
56d81a0bf8
commit
db82ec462a
|
@ -19,7 +19,12 @@
|
|||
</a-steps>
|
||||
<a-divider style='margin-bottom: 0px' />
|
||||
<div class='steps-content'>
|
||||
<Product v-if='addModel.stepNumber === 0' v-model:rowKey='addModel.productId' v-model:detail='addModel.productDetail' />
|
||||
<Product
|
||||
v-if='addModel.stepNumber === 0'
|
||||
v-model:rowKey='addModel.productId'
|
||||
v-model:detail='addModel.productDetail'
|
||||
@change='productChange'
|
||||
/>
|
||||
<DeviceSelect
|
||||
v-else-if='addModel.stepNumber === 1'
|
||||
:productId='addModel.productId'
|
||||
|
@ -32,6 +37,7 @@
|
|||
ref='typeRef'
|
||||
v-else-if='addModel.stepNumber === 2'
|
||||
:metadata='addModel.metadata'
|
||||
:operator='addModel.operator'
|
||||
/>
|
||||
</div>
|
||||
<template #footer>
|
||||
|
@ -53,11 +59,11 @@ import { detail as deviceDetail } from '@/api/device/instance'
|
|||
import Product from './Product.vue'
|
||||
import DeviceSelect from './DeviceSelect.vue'
|
||||
import Type from './Type.vue'
|
||||
import { continuousValue, timeUnitEnum } from '@/views/rule-engine/Scene/Save/components/Timer/util'
|
||||
|
||||
type Emit = {
|
||||
(e: 'cancel'): void
|
||||
(e: 'update:value', data: TriggerDevice): void
|
||||
(e: 'update:options', data: any): void
|
||||
(e: 'save', data: TriggerDevice, options: Record<string, any>): void
|
||||
}
|
||||
|
||||
interface AddModelType extends Omit<TriggerDevice, 'selectorValues'> {
|
||||
|
@ -65,8 +71,9 @@ interface AddModelType extends Omit<TriggerDevice, 'selectorValues'> {
|
|||
deviceKeys: Array<{ label: string, value: string }>
|
||||
orgId: Array<{ label: string, value: string }>
|
||||
productDetail: any
|
||||
selectorValues: Array<{ label: string, value: string }>
|
||||
metadata: metadataType
|
||||
selectorValues: Array<Record<string, any>>
|
||||
metadata: metadataType,
|
||||
operator: TriggerDeviceOptions
|
||||
}
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
|
@ -82,7 +89,7 @@ const props = defineProps({
|
|||
})
|
||||
},
|
||||
options: {
|
||||
type: Object as PropType<any>,
|
||||
type: Object as PropType<Record<string, any>>,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
|
@ -95,13 +102,106 @@ const addModel = reactive<AddModelType>({
|
|||
deviceKeys: [],
|
||||
orgId: [],
|
||||
productDetail: {},
|
||||
metadata: {}
|
||||
metadata: {},
|
||||
operator: {
|
||||
operator: 'online'
|
||||
}
|
||||
})
|
||||
|
||||
const optionsCache = ref(props.options)
|
||||
|
||||
Object.assign(addModel, props.value)
|
||||
|
||||
const handleOptions = (data: TriggerDeviceOptions) => {
|
||||
const typeIconMap = {
|
||||
writeProperty: 'icon-bianji1',
|
||||
invokeFunction: 'icon-widgets',
|
||||
reportEvent: 'icon-shijian',
|
||||
readProperty: 'icon-Group',
|
||||
};
|
||||
|
||||
const _options: any = {
|
||||
name: '', // 名称
|
||||
extraName: '', // 拓展参数
|
||||
onlyName: false,
|
||||
type: '', // 触发类型
|
||||
typeIcon: typeIconMap[data.operator],
|
||||
productName: '',
|
||||
selectorIcon: '',
|
||||
time: undefined,
|
||||
when: undefined,
|
||||
extraTime: undefined,
|
||||
action: optionsCache.value?.action,
|
||||
};
|
||||
|
||||
if (addModel.selector === 'fixed') {
|
||||
let isLimit = false;
|
||||
let indexOf = 0;
|
||||
const nameStr = addModel.selectorValues!.reduce((_prev, next, index) => {
|
||||
if (_prev.length <= 30) {
|
||||
indexOf = index;
|
||||
return index === 0 ? next.name : _prev + '、' + next.name;
|
||||
} else {
|
||||
isLimit = true;
|
||||
}
|
||||
return _prev;
|
||||
}, '');
|
||||
// _options.name = TriggerDeviceModel.selectorValues?.map((item) => item.name).join('、');
|
||||
_options.name = nameStr;
|
||||
if (isLimit && addModel.selectorValues!.length > indexOf) {
|
||||
_options.extraName = `等${addModel.selectorValues!.length}台设备`;
|
||||
}
|
||||
_options.selectorIcon = 'icon-shebei1';
|
||||
} else if (addModel.selector === 'org') {
|
||||
_options.name = addModel.selectorValues?.[0].name + '的';
|
||||
_options.productName = addModel.productDetail.name; // 产品名称
|
||||
_options.selectorIcon = 'icon-zuzhi';
|
||||
} else {
|
||||
_options.name = '所有的' + addModel.productDetail.name;
|
||||
}
|
||||
|
||||
if (data.timer) {
|
||||
const _timer = data.timer;
|
||||
if (_timer.trigger === 'cron') {
|
||||
_options.time = _timer.cron;
|
||||
} else {
|
||||
// console.log('continuousValue', continuousValue(_timer.when! || [], _timer!.trigger))
|
||||
let whenStr = '每天';
|
||||
if (_timer.when!.length) {
|
||||
whenStr = _timer!.trigger === 'week' ? '每周' : '每月';
|
||||
const whenStrArr = continuousValue(_timer.when! || [], _timer!.trigger);
|
||||
const whenStrArr3 = whenStrArr.splice(0, 3);
|
||||
whenStr += whenStrArr3.join('、');
|
||||
whenStr += `等${_timer.when!.length}天`;
|
||||
}
|
||||
_options.when = whenStr;
|
||||
if (_timer.once) {
|
||||
_options.time = _timer.once.time + ' 执行1次';
|
||||
} else if (_timer.period) {
|
||||
_options.time = _timer.period.from + '-' + _timer.period.to;
|
||||
_options.extraTime = `每${_timer.period.every}${timeUnitEnum[_timer.period.unit]}执行1次`;
|
||||
}
|
||||
}
|
||||
|
||||
if (data.operator === 'online') {
|
||||
_options.type = '上线';
|
||||
_options.action = '';
|
||||
_options.typeIcon = 'icon-a-Group4713';
|
||||
}
|
||||
|
||||
if (data.operator === 'offline') {
|
||||
_options.type = '离线';
|
||||
_options.action = '';
|
||||
_options.typeIcon = 'icon-a-Group4892';
|
||||
}
|
||||
|
||||
if (data.operator === 'reportProperty') {
|
||||
_options.type = '属性上报';
|
||||
_options.action = '';
|
||||
_options.typeIcon = 'icon-file-upload-outline';
|
||||
}
|
||||
return _options;
|
||||
}
|
||||
}
|
||||
|
||||
const prev = () => {
|
||||
|
@ -120,6 +220,16 @@ const handleMetadata = (metadata?: string) => {
|
|||
}
|
||||
}
|
||||
|
||||
const productChange = () => {
|
||||
addModel.deviceKeys = []
|
||||
addModel.orgId = []
|
||||
addModel.selector = 'fixed'
|
||||
addModel.operator = {
|
||||
operator: 'online'
|
||||
}
|
||||
addModel.selectorValues = []
|
||||
}
|
||||
|
||||
const save = async (step?: number) => {
|
||||
let _step = step !== undefined ? step : addModel.stepNumber
|
||||
if (_step === 0) {
|
||||
|
@ -139,9 +249,16 @@ const save = async (step?: number) => {
|
|||
addModel.stepNumber = 2
|
||||
} else {
|
||||
const typeData = await typeRef.value.vail()
|
||||
console.log(typeData)
|
||||
if (typeData) {
|
||||
const _options = handleOptions(typeData);
|
||||
optionsCache.value.action = typeData.action
|
||||
const _options = handleOptions(typeData.data);
|
||||
const data = {
|
||||
operator: typeData.data,
|
||||
selector: addModel.selector,
|
||||
selectorValues: addModel.selectorValues,
|
||||
productId: addModel.productId
|
||||
}
|
||||
emit('save', data, _options)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ import { getImage } from '@/utils/comm'
|
|||
type Emit = {
|
||||
(e: 'update:rowKey', data: string): void
|
||||
(e: 'update:detail', data: string): void
|
||||
(e: 'change', data: string): void
|
||||
}
|
||||
|
||||
const actionRef = ref()
|
||||
|
@ -246,6 +247,7 @@ const productQuery = (p: any) => {
|
|||
const handleClick = (detail: any) => {
|
||||
emit('update:rowKey', detail.id)
|
||||
emit('update:detail', detail)
|
||||
emit('change', detail)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
import { filterSelectNode } from '@/utils/comm'
|
||||
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 { metadataType, TriggerDeviceOptions } from '@/views/rule-engine/Scene/typings'
|
||||
import type { PropType } from 'vue'
|
||||
import { TypeEnum } from '@/views/rule-engine/Scene/Save/Device/util'
|
||||
import ReadProperties from './ReadProperties.vue'
|
||||
|
@ -70,6 +70,10 @@ const props = defineProps({
|
|||
metadata: {
|
||||
type: Object as PropType<metadataType>,
|
||||
default: () => ({})
|
||||
},
|
||||
operator: {
|
||||
type: Object as PropType<TriggerDeviceOptions>,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -83,6 +87,8 @@ const formModel = reactive({
|
|||
functionParameters: []
|
||||
})
|
||||
|
||||
Object.assign(formModel, props.operator)
|
||||
|
||||
const optionCache = reactive({
|
||||
action: ''
|
||||
})
|
||||
|
@ -222,7 +228,7 @@ defineExpose({
|
|||
filterKey.push('writeProperties')
|
||||
}
|
||||
|
||||
resolve(omit(cloneModel, filterKey))
|
||||
resolve({ data: omit(cloneModel, filterKey), action: optionCache.action })
|
||||
})
|
||||
}
|
||||
})
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<Title :options='data.options.trigger' />
|
||||
</AddButton>
|
||||
</a-form-item>
|
||||
<AddModel v-if='visible' @cancel='visible = false' v-model='data.device' v-model:options='data.options.trigger' />
|
||||
<AddModel v-if='visible' @cancel='visible = false' @save='save' :value='data.trigger.device' :options='data.options.trigger' />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -24,9 +24,10 @@ import { useSceneStore } from '@/store/scene'
|
|||
import AddModel from './AddModal.vue'
|
||||
import AddButton from '../components/AddButton.vue'
|
||||
import Title from '../components/Title.vue'
|
||||
import type { TriggerDevice } from '@/views/rule-engine/Scene/typings'
|
||||
|
||||
const sceneStore = useSceneStore()
|
||||
const { data } = storeToRefs<any>(sceneStore)
|
||||
const { data } = storeToRefs(sceneStore)
|
||||
|
||||
const visible = ref(false)
|
||||
|
||||
|
@ -39,6 +40,11 @@ const rules = [{
|
|||
},
|
||||
}]
|
||||
|
||||
const save = (device: TriggerDevice, options: Record<string, any>) => {
|
||||
data.value.trigger!.device = device
|
||||
data.value.options!.trigger = options
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { isArray } from 'lodash-es'
|
||||
export const numberToString = {
|
||||
1: '星期一',
|
||||
2: '星期二',
|
||||
|
@ -7,3 +8,45 @@ export const numberToString = {
|
|||
6: '星期六',
|
||||
7: '星期日',
|
||||
};
|
||||
|
||||
export const timeUnitEnum = {
|
||||
seconds: '秒',
|
||||
minutes: '分',
|
||||
hours: '小时',
|
||||
};
|
||||
|
||||
type continuousValueFn = (data: (string | number)[], type: string) => (number | string)[];
|
||||
|
||||
export const continuousValue: continuousValueFn = (data, type) => {
|
||||
let start = 0;
|
||||
const newArray: (number | string)[] = [];
|
||||
const isWeek = type === 'week';
|
||||
if (isArray(data)) {
|
||||
data.forEach((item, index) => {
|
||||
const _item = Number(item);
|
||||
const nextValue = data[index + 1];
|
||||
const previousValue = data[index - 1];
|
||||
const nextItemValue = _item + 1;
|
||||
const previousItemValue = _item - 1;
|
||||
if (nextItemValue === nextValue && previousItemValue !== previousValue) {
|
||||
start = _item;
|
||||
} else if (previousItemValue === previousValue && nextItemValue !== nextValue) {
|
||||
// 表示前start和item连续,并且item与nextValue不连续
|
||||
if (_item - start >= 2) {
|
||||
// 至少三位连续
|
||||
newArray.push(
|
||||
isWeek
|
||||
? `${numberToString[start]} - ${numberToString[_item]}`
|
||||
: `${start} - ${_item}号`,
|
||||
);
|
||||
} else {
|
||||
newArray.push(isWeek ? numberToString[start] : `${start}号`);
|
||||
newArray.push(isWeek ? numberToString[_item] : `${_item}号`);
|
||||
}
|
||||
} else if (previousItemValue !== previousValue && nextItemValue !== nextValue) {
|
||||
newArray.push(isWeek ? numberToString[_item] : `${_item}号`);
|
||||
}
|
||||
});
|
||||
}
|
||||
return newArray;
|
||||
};
|
|
@ -5,13 +5,13 @@
|
|||
<div class='center-item'>
|
||||
<AIcon v-if='options.selectorIcon' :type='options.selectorIcon' class='icon-padding-right' />
|
||||
<span class='trigger-options-name'>
|
||||
<Ellipsis style='width: 310px'>
|
||||
<Ellipsis style='max-width: 310px'>
|
||||
{{ options.name }}
|
||||
</Ellipsis>
|
||||
</span>
|
||||
</span>
|
||||
<span v-if='options.extraName'>{{ options.extraName }}</span>
|
||||
</div>
|
||||
<template v-if='options.onlyName'>
|
||||
<template v-if='!options.onlyName'>
|
||||
<div v-if='options.productName' class='center-item'>
|
||||
<AIcon type='icon-chanpin1' class='icon-padding-right' />
|
||||
<span className='trigger-options-type'>{{ options.productName }}</span>
|
||||
|
@ -28,7 +28,7 @@
|
|||
</div>
|
||||
<div v-if='options.action' class='center-item'>
|
||||
<AIcon :type='options.typeIcon' class='icon-padding-right' />
|
||||
<span className='trigger-options-action'>{{ options.productName }}</span>
|
||||
<span className='trigger-options-action'>{{ options.action }}</span>
|
||||
</div>
|
||||
<div v-if='options.type' class='center-item'>
|
||||
<AIcon :type='options.typeIcon' class='icon-padding-right' />
|
||||
|
@ -57,6 +57,8 @@ const isAdd = computed(() => {
|
|||
|
||||
<style scoped lang='less'>
|
||||
.trigger-options-content {
|
||||
display: inline-flex;
|
||||
gap: 16px;
|
||||
|
||||
.center-item {
|
||||
display: flex;
|
||||
|
|
|
@ -3896,10 +3896,10 @@ jetlinks-store@^0.0.3:
|
|||
resolved "https://registry.npmjs.org/jetlinks-store/-/jetlinks-store-0.0.3.tgz"
|
||||
integrity sha512-AZf/soh1hmmwjBZ00fr1emuMEydeReaI6IBTGByQYhTmK1Zd5pQAxC7WLek2snRAn/HHDgJfVz2hjditKThl6Q==
|
||||
|
||||
jetlinks-ui-components@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.0.tgz#dca7bb82e53f464990b0851635e8f82be6c69db6"
|
||||
integrity sha512-pgJ0Uiw4Dxc0AU2GqaOaVhNYun1VEmv78OtJcir2sq9rVSIuXCtTl1eHYMPiiPb6z1fG677KKs1gqvrpUwhguQ==
|
||||
jetlinks-ui-components@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.1.tgz#12fe9a193af14b859e1baf02fbd706a2be5b31cf"
|
||||
integrity sha512-4hdEJUaKNMSIcmbn4qKcG8oK7h6VSYP3X3fCNndBm6WhHh+9ONf8f+3OSrUy1PvxdenmqO0VN2QdWV0KupByKQ==
|
||||
dependencies:
|
||||
"@vueuse/core" "^9.12.0"
|
||||
ant-design-vue "^3.2.15"
|
||||
|
|
Loading…
Reference in New Issue