diff --git a/src/store/scene.ts b/src/store/scene.ts
index 973f334e..a1f1d94a 100644
--- a/src/store/scene.ts
+++ b/src/store/scene.ts
@@ -94,8 +94,8 @@ export const useSceneStore = defineStore('scene', () => {
const branchesLength = branches.length;
if (
triggerType === 'device' &&
- ((branchesLength === 1 && !!branches[0]?.when?.length) || // 有一组数据并且when有值
- (branchesLength > 1 && !branches[branchesLength - 1]?.when?.length)) // 有多组否则数据,并且最后一组when有值
+ ((branchesLength === 1 && branches[0]?.when?.length) || // 有一组数据并且when有值
+ (branchesLength > 1 && branches[branchesLength - 1]?.when?.length)) // 有多组否则数据,并且最后一组when有值
) {
branches.push(null);
}
diff --git a/src/views/media/Device/Channel/Save.vue b/src/views/media/Device/Channel/Save.vue
index 2dc4fe43..f5196dfd 100644
--- a/src/views/media/Device/Channel/Save.vue
+++ b/src/views/media/Device/Channel/Save.vue
@@ -76,6 +76,9 @@
:rules="[
{ required: true, message: '请输入视频地址' },
{ max: 128, message: '最多可输入128个字符' },
+ {
+ validator: validateUrl,
+ },
]"
>
@@ -237,7 +240,7 @@ watch(
* @param _rule
* @param value
*/
-let validateChannelId = async (_rule: Rule, value: string) => {
+const validateChannelId = async (_rule: Rule, value: string) => {
// ID非必填, 没有输入ID时, 不校验ID是否存在
if (!value) return;
const { result } = await ChannelApi.validateField({
@@ -252,6 +255,21 @@ let validateChannelId = async (_rule: Rule, value: string) => {
}
};
+/**
+ * 校验视频地址
+ * @param _rule
+ * @param value
+ */
+const validateUrl = async (_rule: Rule, value: string) => {
+ console.log('value: ', value);
+ const reg = /(http|https|rtsp|rtmp):\/\/([\w.]+\/?)\S*/;
+ return new Promise((resolve, reject) => {
+ reg.test(value) || !value
+ ? resolve('')
+ : reject('请输入正确的视频地址');
+ });
+};
+
/**
* 提交
*/
diff --git a/src/views/media/Device/Save/SaveProduct.vue b/src/views/media/Device/Save/SaveProduct.vue
index dc63279b..3b5c2ffc 100644
--- a/src/views/media/Device/Save/SaveProduct.vue
+++ b/src/views/media/Device/Save/SaveProduct.vue
@@ -13,7 +13,13 @@
{
res.result.id,
);
if (deployResp.success) {
- emit('save', {...res.result})
+ emit('save', { ...res.result });
message.success('操作成功');
handleCancel();
}
diff --git a/src/views/media/Device/Save/index.vue b/src/views/media/Device/Save/index.vue
index 4ef4eeaa..b1d63fb7 100644
--- a/src/views/media/Device/Save/index.vue
+++ b/src/views/media/Device/Save/index.vue
@@ -4,10 +4,14 @@
-
+
@@ -28,7 +32,24 @@
@@ -79,7 +114,17 @@
import { getImage } from '@/utils/comm';
-import { Form } from 'ant-design-vue';
import { message } from 'ant-design-vue';
-
import DeviceApi from '@/api/media/device';
-
import { PROVIDER_OPTIONS } from '@/views/media/Device/const';
import type { ProductType } from '@/views/media/Device/typings';
import SaveProduct from './SaveProduct.vue';
const router = useRouter();
const route = useRoute();
-const useForm = Form.useForm;
// 表单数据
const formData = ref({
@@ -266,10 +311,10 @@ const formData = ref({
channel: 'gb28181-2016',
photoUrl: getImage('/device-media.png'),
productId: undefined,
+ description: '',
others: {
access_pwd: '',
},
- description: '',
// 编辑字段
streamMode: 'UDP',
manufacturer: '',
@@ -277,50 +322,9 @@ const formData = ref({
firmware: '',
});
-// 验证规则
-const formRules = ref({
- id: [
- {
- required: true,
- message: '请输入ID',
- },
- { max: 64, message: '最多输入64个字符' },
- {
- pattern: /^[j-zA-Z0-9_\-]+$/,
- message: '请输入英文或者数字或者-或者_',
- },
- ],
- name: [
- { required: true, message: '请输入名称' },
- { max: 64, message: '最多可输入64个字符' },
- ],
- productId: [{ required: true, message: '请选择所属产品' }],
- channel: [{ required: true, message: '请选择接入方式' }],
- 'others.access_pwd': [{ required: true, message: '请输入接入密码' }],
- description: [{ max: 200, message: '最多可输入200个字符' }],
- streamMode: [{ required: true, message: '请选择流传输模式' }],
-});
-
-watch(
- () => formData.value.channel,
- (val) => {
- formRules.value['id'][0].required = val === 'gb28181-2016';
- formRules.value['others.access_pwd'][0].required =
- val === 'gb28181-2016';
- validate();
- getProductList();
- },
-);
-
-const { resetFields, validate, validateInfos, clearValidate } = useForm(
- formData.value,
- formRules.value,
-);
-
-const clearValid = () => {
- setTimeout(() => {
- clearValidate();
- }, 200);
+const handleChannelChange = () => {
+ formData.value.productId = undefined;
+ getProductList();
};
/**
@@ -328,7 +332,6 @@ const clearValid = () => {
*/
const productList = ref([]);
const getProductList = async () => {
- // console.log('formData.productId: ', formData.value.productId);
const params = {
paging: false,
sorts: [{ name: 'createTime', order: 'desc' }],
@@ -352,12 +355,8 @@ const saveProductVis = ref(false);
*/
const getDetail = async () => {
const res = await DeviceApi.detail(route.query.id as string);
- // console.log('res: ', res);
- // formData.value = res.result;
Object.assign(formData.value, res.result);
formData.value.channel = res.result.provider;
-
- console.log('formData.value: ', formData.value);
};
onMounted(() => {
@@ -368,23 +367,51 @@ onMounted(() => {
* 表单提交
*/
const btnLoading = ref(false);
+const formRef = ref();
const handleSubmit = () => {
- // console.log('formData.value: ', formData.value);
- validate()
+ const {
+ others,
+ id,
+ streamMode,
+ manufacturer,
+ model,
+ firmware,
+ ...extraParams
+ } = formData.value;
+ let params: any;
+ if (formData.value.channel === 'fixed-media') {
+ // 固定地址
+ params = !id
+ ? extraParams
+ : { id, streamMode, manufacturer, model, firmware, ...extraParams };
+ } else {
+ // 国标
+ params = !id
+ ? { others, id, ...extraParams }
+ : {
+ others,
+ id,
+ streamMode,
+ manufacturer,
+ model,
+ firmware,
+ ...extraParams,
+ };
+ }
+
+ formRef.value
+ ?.validate()
.then(async () => {
btnLoading.value = true;
- let res;
- if (!route.query.id) {
- res = await DeviceApi.save(formData.value);
- } else {
- res = await DeviceApi.update(formData.value);
- }
+ const res = !route.query.id
+ ? await DeviceApi.save(params)
+ : await DeviceApi.update(params);
if (res?.success) {
message.success('保存成功');
router.back();
}
})
- .catch((err) => {
+ .catch((err: any) => {
console.log('err: ', err);
})
.finally(() => {
diff --git a/src/views/media/Device/index.vue b/src/views/media/Device/index.vue
index e5888f35..ac0c47dd 100644
--- a/src/views/media/Device/index.vue
+++ b/src/views/media/Device/index.vue
@@ -328,7 +328,7 @@ const getActions = (
? '设备已离线'
: data.state.value === 'notActive'
? '设备已禁用'
- : '',
+ : '更新通道',
},
disabled:
data.state.value === 'offline' ||
diff --git a/src/views/rule-engine/Scene/Save/action/ListItem/FilterCondition.vue b/src/views/rule-engine/Scene/Save/action/ListItem/FilterCondition.vue
index 13b973fd..4de9e365 100644
--- a/src/views/rule-engine/Scene/Save/action/ListItem/FilterCondition.vue
+++ b/src/views/rule-engine/Scene/Save/action/ListItem/FilterCondition.vue
@@ -82,6 +82,7 @@ import ParamsDropdown, { DoubleParamsDropdown } from '../../components/ParamsDro
import { inject } from 'vue'
import { useSceneStore } from 'store/scene'
import { storeToRefs } from 'pinia';
+import { flattenDeep, set } from 'lodash-es'
const sceneStore = useSceneStore()
const { data: formModel } = storeToRefs(sceneStore)
@@ -207,12 +208,32 @@ const mouseout = () => {
}
}
-const columnSelect = () => {
+const handleOptionsColumnsValue = (termsColumns: any[], _options: any) => {
+ formModel.value.branches![props.branchName].then[props.thenName].actions[props.name].options!.termsColumns = termsColumns
+ const flatten = new Set(flattenDeep(termsColumns))
+ let newColumns = [...flatten.values()]
+ if (_options?.otherColumns) {
+ newColumns = [..._options?.otherColumns, ...newColumns]
+ }
+ formModel.value.branches![props.branchName].then[props.thenName].actions[props.name].options!.columns = newColumns
+}
+
+const columnSelect = (e: any) => {
paramsValue.termType = 'eq'
paramsValue.value = {
source: tabsOptions.value[0].key,
value: undefined
}
+
+ const columns = e.metadata === true ? [e.column] : []
+ const _options = formModel.value.branches![props.branchName].then[props.thenName].actions[props.actionName].options
+ const termsColumns = _options?.termsColumns || []
+ set(
+ termsColumns,
+ [props.termsName, props.name],
+ columns
+ )
+ handleOptionsColumnsValue(termsColumns, _options)
emit('update:value', { ...paramsValue })
}
@@ -245,6 +266,14 @@ const termAdd = () => {
const onDelete = () => {
formModel.value.branches?.[props.branchName]?.then?.[props.thenName]?.actions?.[props.actionName].terms?.[props.termsName].terms?.splice(props.name, 1)
+ const _options = formModel.value.branches![props.branchName].then[props.thenName].actions[props.name].options
+ const termsColumns = _options?.termsColumns || []
+ set(
+ termsColumns,
+ [props.termsName, props.name],
+ []
+ )
+ handleOptionsColumnsValue(termsColumns, _options)
}
nextTick(() => {
diff --git a/src/views/rule-engine/Scene/Save/action/ListItem/FilterGroup.vue b/src/views/rule-engine/Scene/Save/action/ListItem/FilterGroup.vue
index f7c1c7ec..77bd060d 100644
--- a/src/views/rule-engine/Scene/Save/action/ListItem/FilterGroup.vue
+++ b/src/views/rule-engine/Scene/Save/action/ListItem/FilterGroup.vue
@@ -58,7 +58,7 @@ import { storeToRefs } from 'pinia'
import { useSceneStore } from 'store/scene'
import DropdownButton from '../../components/DropdownButton'
import FilterItem from './FilterCondition.vue'
-import { isArray } from 'lodash-es'
+import { flattenDeep, isArray, set } from 'lodash-es'
import { provide } from 'vue'
import { randomString } from '@/utils/utils'
import { useParams } from '@/views/rule-engine/Scene/Save/util'
@@ -66,8 +66,6 @@ import { useParams } from '@/views/rule-engine/Scene/Save/util'
const sceneStore = useSceneStore()
const { data: formModel } = storeToRefs(sceneStore)
-
-
const props = defineProps({
isFirst: {
type: Boolean,
@@ -103,9 +101,7 @@ const { columnOptions } = useParams({
branch: props.branchName,
branchGroup: props.thenName,
action: props.actionName
-}, [
- formModel.value.branches![props.branchName].then[props.thenName].actions[props.actionName]
-])
+})
provide('filter-params', columnOptions)
@@ -123,6 +119,16 @@ const mouseout = () => {
showDelete.value = false
}
+const handleOptionsColumnsValue = (termsColumns: any[], _options: any) => {
+ formModel.value.branches![props.branchName].then[props.thenName].actions[props.name].options!.termsColumns = termsColumns
+ const flatten = new Set(flattenDeep(termsColumns))
+ let newColumns = [...flatten.values()]
+ if (_options?.otherColumns) {
+ newColumns = [..._options?.otherColumns, ...newColumns]
+ }
+ formModel.value.branches![props.branchName].then[props.thenName].actions[props.name].options!.columns = newColumns
+}
+
const addTerms = () => {
const item: any = {
type: 'and',
@@ -154,6 +160,13 @@ const onDelete = () => {
.then[props.thenName]
.actions[props.actionName]
.terms?.splice(props.name, 1)
+
+ const _options = formModel.value.branches![props.branchName].then[props.thenName].actions[props.actionName].options
+ const termsColumns = _options?.termsColumns || []
+ if (_options?.termsColumns) {
+ termsColumns.splice(props.name, 1)
+ handleOptionsColumnsValue(termsColumns, _options)
+ }
}
const rules = [
diff --git a/src/views/rule-engine/Scene/Save/action/ListItem/Item.vue b/src/views/rule-engine/Scene/Save/action/ListItem/Item.vue
index f93c8e96..0a34f6d5 100644
--- a/src/views/rule-engine/Scene/Save/action/ListItem/Item.vue
+++ b/src/views/rule-engine/Scene/Save/action/ListItem/Item.vue
@@ -446,6 +446,11 @@ const termsOptions = computed(() => {
});
const onDelete = () => {
+ if (props.name !== 0 && !props.parallel) { // 清空上一个串行执行动作中的options.termsColumns和terms
+ _data.value.branches![props.branchesName].then[props.thenName].actions[props.name - 1].options!.termsColumns = []
+ _data.value.branches![props.branchesName].then[props.thenName].actions[props.name - 1].options!.terms = []
+ _data.value.branches![props.branchesName].then[props.thenName].actions[props.name - 1].terms = []
+ }
emit('delete');
};
@@ -453,11 +458,16 @@ const onClose = () => {
visible.value = false;
};
-const onSave = (data: ActionsType, options?: any) => {
- emit('update', data, options);
- // setTimeout(() => {
- // getParams();
- // }, 10);
+const onSave = (data: ActionsType, options: any) => {
+ const { key, terms } = _data.value.branches![props.branchesName].then?.[props.thenName].actions?.[props.name]
+ const actionItem: ActionsType = {
+ ...data,
+ options,
+ key,
+ terms
+ }
+ _data.value.branches![props.branchesName].then[props.thenName].actions.splice(props.name, 1, actionItem)
+
visible.value = false;
};
diff --git a/src/views/rule-engine/Scene/Save/action/ListItem/List.vue b/src/views/rule-engine/Scene/Save/action/ListItem/List.vue
index ec79be4f..1d15c422 100644
--- a/src/views/rule-engine/Scene/Save/action/ListItem/List.vue
+++ b/src/views/rule-engine/Scene/Save/action/ListItem/List.vue
@@ -11,7 +11,6 @@
:isLast="index === actions.length - 1"
:options="item.options"
@delete="_delete(item.key || '')"
- @update="(data, options) => _update(data, options, item)"
/>
@@ -37,7 +36,6 @@ import { PropType } from 'vue';
import { ActionsType, ParallelType } from '../../../typings';
import Modal from '../Modal/index.vue';
import Item from './Item.vue';
-import { pick } from 'lodash';
import { useSceneStore } from '@/store/scene';
import { storeToRefs } from 'pinia';
@@ -98,9 +96,7 @@ 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})
+const _update = () => {
visible.value = false
}
diff --git a/src/views/rule-engine/Scene/Save/action/Modal/index.vue b/src/views/rule-engine/Scene/Save/action/Modal/index.vue
index 9af550d7..73cee953 100644
--- a/src/views/rule-engine/Scene/Save/action/Modal/index.vue
+++ b/src/views/rule-engine/Scene/Save/action/Modal/index.vue
@@ -131,7 +131,8 @@ const onOk = () => {
emit(
'save',
{
- ...props.data,
+ // ...props.data,
+ key: props.data.key,
executor: 'alarm',
alarm: { mode: values.type },
},
diff --git a/src/views/rule-engine/Scene/Save/action/index.vue b/src/views/rule-engine/Scene/Save/action/index.vue
index 18dbf802..7a8269e8 100644
--- a/src/views/rule-engine/Scene/Save/action/index.vue
+++ b/src/views/rule-engine/Scene/Save/action/index.vue
@@ -1,63 +1,63 @@
-
-
- 执行
-
-
-
-
-
-
-
- 串行
-
- 按顺序依次执行动作,适用于基于动作输出参数,判断是否执行后续动作的场景
-
-
-
-
- onAdd(_item, false)"
- @delete="(_key) => onDelete(_key, false)"
- />
-
-
-
-
-
- 并行
-
- 同时执行所有动作,适用于不需要关注执行动作先后顺序和结果的场景
-
-
-
-
- onAdd(_item, true)"
- @delete="(_key) => onDelete(_key, true)"
- />
-
-
-
-
+
+
+ 执行
+
+
+
+
+
+
+ 串行
+
+ 按顺序依次执行动作,适用于基于动作输出参数,判断是否执行后续动作的场景
+
+
+
+
+ onAdd(_item, false)"
+ @delete="(_key) => onDelete(_key, false)"
+ />
+
+
+
+
+
+ 并行
+
+ 同时执行所有动作,适用于不需要关注执行动作先后顺序和结果的场景
+
+
+
+
+ onAdd(_item, true)"
+ @delete="(_key) => onDelete(_key, true)"
+ />
+
+
+
+
+