|
@@ -172,7 +172,7 @@
|
|
:visible="true"
|
|
:visible="true"
|
|
class="data-link-dialog"
|
|
class="data-link-dialog"
|
|
header="动态数据绑定"
|
|
header="动态数据绑定"
|
|
- @cancel="
|
|
|
|
|
|
+ @close="
|
|
dataBindDialog.data.binds = dataBindDialog.bkBinds;
|
|
dataBindDialog.data.binds = dataBindDialog.bkBinds;
|
|
dataBindDialog.show = false;
|
|
dataBindDialog.show = false;
|
|
"
|
|
"
|
|
@@ -227,28 +227,181 @@
|
|
:visible="true"
|
|
:visible="true"
|
|
class="data-events-dialog"
|
|
class="data-events-dialog"
|
|
header="数据触发器"
|
|
header="数据触发器"
|
|
- @cancel="triggersDialog.show = false"
|
|
|
|
@confirm="triggersDialog.show = false"
|
|
@confirm="triggersDialog.show = false"
|
|
|
|
+ @close="triggersDialog.show = false"
|
|
:width="700"
|
|
:width="700"
|
|
>
|
|
>
|
|
<div class="body">
|
|
<div class="body">
|
|
- <div class="mb-12" v-for="(trigger, i) in triggersDialog.data.triggers">
|
|
|
|
- <div class="flex middle between">
|
|
|
|
- <div class="title">触发器{{ i + 1 }}</div>
|
|
|
|
|
|
+ <t-collapse
|
|
|
|
+ v-model="triggersDialog.openedCollapses"
|
|
|
|
+ :borderless="true"
|
|
|
|
+ :expand-on-row-click="false"
|
|
|
|
+ >
|
|
|
|
+ <t-collapse-panel
|
|
|
|
+ v-for="(trigger, i) in triggersDialog.data.triggers"
|
|
|
|
+ :value="i"
|
|
|
|
+ >
|
|
|
|
+ <template #header>
|
|
|
|
+ <t-input v-model="trigger.name" class="mr-12" />
|
|
|
|
+ </template>
|
|
|
|
+ <template #headerRightContent>
|
|
|
|
+ <t-popconfirm
|
|
|
|
+ content="确认删除该触发器吗?"
|
|
|
|
+ @confirm="triggersDialog.data.triggers.splice(i, 1)"
|
|
|
|
+ >
|
|
|
|
+ <t-icon name="delete" class="hover" />
|
|
|
|
+ </t-popconfirm>
|
|
|
|
+ </template>
|
|
|
|
+ <section>
|
|
|
|
+ <div class="form-item banner">
|
|
|
|
+ <label>触发条件</label>
|
|
|
|
+ <div class="w-full flex middle between">
|
|
|
|
+ <div></div>
|
|
|
|
+ <t-radio-group v-model="trigger.conditionType">
|
|
|
|
+ <t-radio value="and"> 满足全部条件 </t-radio>
|
|
|
|
+ <t-radio value="or"> 满足任意条件 </t-radio>
|
|
|
|
+ </t-radio-group>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div v-for="(c, index) in trigger.conditions" class="mb-12">
|
|
|
|
+ <div class="flex middle between head">
|
|
|
|
+ <div class="flex middle">
|
|
|
|
+ <t-icon name="arrow-right" class="mr-4" />
|
|
|
|
+ 条件{{ index + 1 }}
|
|
|
|
+ </div>
|
|
|
|
+ <t-icon
|
|
|
|
+ name="close"
|
|
|
|
+ class="hover"
|
|
|
|
+ @click="trigger.conditions.splice(index, 1)"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ <div class="px-16 py-4">
|
|
|
|
+ <div class="form-item mt-4">
|
|
|
|
+ <label>条件类型</label>
|
|
|
|
+ <t-radio-group v-model="c.type">
|
|
|
|
+ <t-radio value=""> 关系条件 </t-radio>
|
|
|
|
+ <t-radio value="fn"> 高阶条件 </t-radio>
|
|
|
|
+ </t-radio-group>
|
|
|
|
+ </div>
|
|
|
|
+ <template v-if="!c.type">
|
|
|
|
+ <div class="form-item mt-8">
|
|
|
|
+ <label>比较条件</label>
|
|
|
|
+ <div class="flex middle">
|
|
|
|
+ <label class="shrink-0 mr-8">数据</label>
|
|
|
|
+ <t-select
|
|
|
|
+ v-model="c.operator"
|
|
|
|
+ placeholder="关系运算"
|
|
|
|
+ :options="operatorOptions"
|
|
|
|
+ class="shrink-0 mr-8"
|
|
|
|
+ style="width: 80px"
|
|
|
|
+ />
|
|
|
|
+ <t-select
|
|
|
|
+ v-model="c.valueType"
|
|
|
|
+ class="shrink-0 mr-8"
|
|
|
|
+ style="width: 110px"
|
|
|
|
+ placeholder="固定值"
|
|
|
|
+ >
|
|
|
|
+ <t-option key="" value="" label="固定值">
|
|
|
|
+ 固定值
|
|
|
|
+ </t-option>
|
|
|
|
+ <t-option key="prop" value="prop" label="对象属性值">
|
|
|
|
+ 对象属性值
|
|
|
|
+ </t-option>
|
|
|
|
+ </t-select>
|
|
|
|
+ <template v-if="!c.valueType">
|
|
|
|
+ <t-input
|
|
|
|
+ v-model="c.value"
|
|
|
|
+ class="shrink-0"
|
|
|
|
+ style="width: 320px"
|
|
|
|
+ />
|
|
|
|
+ </template>
|
|
|
|
+ <template v-else>
|
|
|
|
+ <t-tree-select
|
|
|
|
+ v-model="c.target"
|
|
|
|
+ :data="penTree"
|
|
|
|
+ filterable
|
|
|
|
+ placeholder="对象"
|
|
|
|
+ class="shrink-0 mr-8"
|
|
|
|
+ style="width: 160px"
|
|
|
|
+ @change="onChangeTriggerTarget(c)"
|
|
|
|
+ />
|
|
|
|
+ <t-select-input
|
|
|
|
+ v-model:inputValue="c.value"
|
|
|
|
+ :value="c.value"
|
|
|
|
+ v-model:popupVisible="triggersDialog.popupVisible"
|
|
|
|
+ allow-input
|
|
|
|
+ @focus="triggersDialog.popupVisible = true"
|
|
|
|
+ @blur="triggersDialog.popupVisible = false"
|
|
|
|
+ class="shrink-0"
|
|
|
|
+ style="width: 152px"
|
|
|
|
+ >
|
|
|
|
+ <template #panel>
|
|
|
|
+ <ul style="padding: 8px 12px">
|
|
|
|
+ <li
|
|
|
|
+ v-for="item in triggersDialog.targetProps"
|
|
|
|
+ :key="item.value"
|
|
|
|
+ @click="c.value = item.value"
|
|
|
|
+ >
|
|
|
|
+ {{ item.label }}
|
|
|
|
+ </li>
|
|
|
|
+ </ul>
|
|
|
|
+ </template>
|
|
|
|
+ </t-select-input>
|
|
|
|
+ </template>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+ <template v-else>
|
|
|
|
+ <div>function condition(pen) {</div>
|
|
|
|
+ <CodeEditor class="mt-4" v-model="c.fnJs" />
|
|
|
|
+ <div class="mt-4">}</div>
|
|
|
|
+ </template>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="mt-8">
|
|
|
|
+ <a @click="addTriggerCondition(trigger)"> + 添加条件 </a>
|
|
|
|
+ </div>
|
|
|
|
|
|
- <t-popconfirm
|
|
|
|
- content="确认删除该触发器吗?"
|
|
|
|
- @confirm="triggersDialog.data.triggers.splice(i, 1)"
|
|
|
|
- >
|
|
|
|
- <t-icon name="close" class="hover" />
|
|
|
|
- </t-popconfirm>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- <div>
|
|
|
|
- <a @click="triggersDialog.data.triggers.push({})">
|
|
|
|
- <t-icon name="add" />
|
|
|
|
- 添加触发器
|
|
|
|
- </a>
|
|
|
|
|
|
+ <div class="form-item banner mt-16">
|
|
|
|
+ <label>执行动作</label>
|
|
|
|
+ </div>
|
|
|
|
+ <div v-for="(a, index) in trigger.actions" class="mb-12">
|
|
|
|
+ <div class="flex middle between head">
|
|
|
|
+ <div class="flex middle">
|
|
|
|
+ <t-icon name="arrow-right" class="mr-4" />
|
|
|
|
+ 动作{{ index + 1 }}
|
|
|
|
+ </div>
|
|
|
|
+ <t-icon
|
|
|
|
+ name="close"
|
|
|
|
+ class="hover"
|
|
|
|
+ @click="trigger.actions.splice(index, 1)"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ <div class="px-16 py-4">
|
|
|
|
+ <div class="form-item mt-4">
|
|
|
|
+ <label>动作类型</label>
|
|
|
|
+ <div>
|
|
|
|
+ <t-select v-model="a.action" placeholder="请选择">
|
|
|
|
+ <t-option
|
|
|
|
+ v-for="option in actionOptions"
|
|
|
|
+ :key="option.value"
|
|
|
|
+ :value="option.value"
|
|
|
|
+ :label="option.label"
|
|
|
|
+ />
|
|
|
|
+ </t-select>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="mt-8">
|
|
|
|
+ <a @click="trigger.actions.push({})"> + 添加动作 </a>
|
|
|
|
+ </div>
|
|
|
|
+ </section>
|
|
|
|
+ </t-collapse-panel>
|
|
|
|
+ </t-collapse>
|
|
|
|
+
|
|
|
|
+ <div class="mt-8">
|
|
|
|
+ <a @click="onAddTrigger"> + 添加触发器 </a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</t-dialog>
|
|
</t-dialog>
|
|
@@ -267,8 +420,10 @@ import { useRoute, useRouter } from 'vue-router';
|
|
import { MessagePlugin } from 'tdesign-vue-next';
|
|
import { MessagePlugin } from 'tdesign-vue-next';
|
|
import axios from 'axios';
|
|
import axios from 'axios';
|
|
import { debounce } from '@/services/debouce';
|
|
import { debounce } from '@/services/debouce';
|
|
|
|
+import { getPenTree } from '@/services/common';
|
|
|
|
+import { updatePen } from './pen';
|
|
|
|
|
|
-import { updatePen } from './pen.ts';
|
|
|
|
|
|
+import CodeEditor from '@/views/components/common/CodeEditor.vue';
|
|
|
|
|
|
const route = useRoute();
|
|
const route = useRoute();
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
@@ -365,6 +520,69 @@ const typeOptions = [
|
|
},
|
|
},
|
|
];
|
|
];
|
|
|
|
|
|
|
|
+const actionOptions = [
|
|
|
|
+ {
|
|
|
|
+ label: '打开链接',
|
|
|
|
+ value: 0,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: '打开视图',
|
|
|
|
+ value: 13,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: '播放动画',
|
|
|
|
+ value: 2,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: '暂停动画',
|
|
|
|
+ value: 3,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: '停止动画',
|
|
|
|
+ value: 4,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: '更改属性',
|
|
|
|
+ value: 1,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: '打开弹框',
|
|
|
|
+ value: 14,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: '发送消息',
|
|
|
|
+ value: 7,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: '发送MQTT',
|
|
|
|
+ value: 15,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: '发送Websocket',
|
|
|
|
+ value: 16,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: '发送HTTP(s)',
|
|
|
|
+ value: 17,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: '播放视频',
|
|
|
|
+ value: 8,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: '暂停视频',
|
|
|
|
+ value: 9,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: '停止视频',
|
|
|
|
+ value: 10,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ label: '自定义函数',
|
|
|
|
+ value: 18,
|
|
|
|
+ },
|
|
|
|
+];
|
|
|
|
+
|
|
const addDataDialog = reactive<any>({
|
|
const addDataDialog = reactive<any>({
|
|
show: false,
|
|
show: false,
|
|
data: undefined,
|
|
data: undefined,
|
|
@@ -400,6 +618,17 @@ const dataSetColumns = [
|
|
},
|
|
},
|
|
];
|
|
];
|
|
|
|
|
|
|
|
+const operatorOptions = ref<any>([
|
|
|
|
+ { label: '=', value: '=' },
|
|
|
|
+ { label: '!=', value: '!=' },
|
|
|
|
+ { label: '>', value: '>' },
|
|
|
|
+ { label: '<', value: '<' },
|
|
|
|
+ { label: '>=', value: '>=' },
|
|
|
|
+ { label: '<=', value: '<=' },
|
|
|
|
+ { label: '包含', value: '[)' },
|
|
|
|
+ { label: '不包含', value: '![)' },
|
|
|
|
+]);
|
|
|
|
+
|
|
const query = reactive<{
|
|
const query = reactive<{
|
|
current: number;
|
|
current: number;
|
|
pageSize: number;
|
|
pageSize: number;
|
|
@@ -417,6 +646,8 @@ const triggersDialog = reactive<any>({
|
|
data: undefined,
|
|
data: undefined,
|
|
});
|
|
});
|
|
|
|
|
|
|
|
+const penTree: any = ref([]);
|
|
|
|
+
|
|
let timer: any;
|
|
let timer: any;
|
|
|
|
|
|
onBeforeMount(() => {
|
|
onBeforeMount(() => {
|
|
@@ -613,8 +844,88 @@ const onTrigger = (item: any) => {
|
|
if (!item.triggers) {
|
|
if (!item.triggers) {
|
|
item.triggers = [];
|
|
item.triggers = [];
|
|
}
|
|
}
|
|
|
|
+ triggersDialog.openedCollapses = [0];
|
|
triggersDialog.data = item;
|
|
triggersDialog.data = item;
|
|
|
|
+ triggersDialog.targetProps = [];
|
|
triggersDialog.show = true;
|
|
triggersDialog.show = true;
|
|
|
|
+
|
|
|
|
+ penTree.value = getPenTree();
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+const onAddTrigger = () => {
|
|
|
|
+ const i = triggersDialog.data.triggers.length;
|
|
|
|
+ triggersDialog.data.triggers.push({
|
|
|
|
+ name: `触发器${i + 1}`,
|
|
|
|
+ conditionType: 'and',
|
|
|
|
+ conditions: [],
|
|
|
|
+ actions: [],
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ triggersDialog.openedCollapses.push(i);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+const addTriggerCondition = (trigger: any) => {
|
|
|
|
+ trigger.conditions.push({
|
|
|
|
+ type: '',
|
|
|
|
+ operator: '=',
|
|
|
|
+ valueType: '',
|
|
|
|
+ });
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+const onChangeTriggerTarget = (c: any) => {
|
|
|
|
+ triggersDialog.targetProps = [
|
|
|
|
+ {
|
|
|
|
+ value: 'x',
|
|
|
|
+ label: 'X',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ value: 'y',
|
|
|
|
+ label: 'Y',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ value: 'width',
|
|
|
|
+ label: '宽',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ value: 'height',
|
|
|
|
+ label: '高',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ value: 'visible',
|
|
|
|
+ label: '显示',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ value: 'text',
|
|
|
|
+ label: '文字',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ value: 'progress',
|
|
|
|
+ label: '进度',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ value: 'showChild',
|
|
|
|
+ label: '状态',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ value: 'rotate',
|
|
|
|
+ label: '旋转',
|
|
|
|
+ },
|
|
|
|
+ ];
|
|
|
|
+
|
|
|
|
+ const target: any = meta2d.findOne(c.target);
|
|
|
|
+ if (target) {
|
|
|
|
+ for (const item of target.realTimes) {
|
|
|
|
+ const found = triggersDialog.targetProps.findIndex(
|
|
|
|
+ (elem: any) => elem.value === item.key
|
|
|
|
+ );
|
|
|
|
+ if (found < 0) {
|
|
|
|
+ triggersDialog.targetProps.push({
|
|
|
|
+ value: item.key,
|
|
|
|
+ label: item.label,
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
};
|
|
};
|
|
|
|
|
|
onUnmounted(() => {
|
|
onUnmounted(() => {
|
|
@@ -633,6 +944,10 @@ onUnmounted(() => {
|
|
background: var(--color-background-input);
|
|
background: var(--color-background-input);
|
|
line-height: 36px;
|
|
line-height: 36px;
|
|
margin-bottom: 6px;
|
|
margin-bottom: 6px;
|
|
|
|
+
|
|
|
|
+ .title {
|
|
|
|
+ line-height: 36px;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -685,4 +1000,53 @@ onUnmounted(() => {
|
|
overflow: auto;
|
|
overflow: auto;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+.body {
|
|
|
|
+ :deep(.t-collapse.t--border-less) {
|
|
|
|
+ .t-collapse-panel__header {
|
|
|
|
+ border-top: none;
|
|
|
|
+ border-bottom: 1px solid var(--td-border-level-1-color);
|
|
|
|
+ padding: 8px 0;
|
|
|
|
+
|
|
|
|
+ .t-input {
|
|
|
|
+ border: none;
|
|
|
|
+ padding-left: 0;
|
|
|
|
+ font-size: 14px;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .t-collapse-panel__content {
|
|
|
|
+ padding: 8px 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .title {
|
|
|
|
+ position: relative;
|
|
|
|
+ margin: 8px 0;
|
|
|
|
+
|
|
|
|
+ :deep(.t-input) {
|
|
|
|
+ border-color: var(--color-background-input);
|
|
|
|
+ border-radius: 0;
|
|
|
|
+ border-left: none;
|
|
|
|
+ border-top: none;
|
|
|
|
+ border-right: none;
|
|
|
|
+ padding-left: 0;
|
|
|
|
+ padding-bottom: 8px;
|
|
|
|
+ font-size: 14px;
|
|
|
|
+
|
|
|
|
+ &:hover {
|
|
|
|
+ border-color: var(--color-border-input);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .head {
|
|
|
|
+ margin-top: 10px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .banner {
|
|
|
|
+ background-color: var(--color-background-input);
|
|
|
|
+ padding: 0 12px;
|
|
|
|
+ }
|
|
|
|
+}
|
|
</style>
|
|
</style>
|