|
@@ -0,0 +1,436 @@
|
|
|
+<template>
|
|
|
+ <div class="props">
|
|
|
+ <t-collapse
|
|
|
+ :borderless="true"
|
|
|
+ :expand-on-row-click="false"
|
|
|
+ v-model="openedCollapses"
|
|
|
+ >
|
|
|
+ <t-collapse-panel v-for="(trigger, i) in data.triggers" :value="i + 1">
|
|
|
+ <template #header>
|
|
|
+ <t-input v-model="trigger.name" class="mr-12" />
|
|
|
+ </template>
|
|
|
+ <template #headerRightContent>
|
|
|
+ <t-popconfirm
|
|
|
+ content="确认删除该行为吗?"
|
|
|
+ @confirm="data.triggers.splice(i, 1)"
|
|
|
+ >
|
|
|
+ <delete-icon class="hover" />
|
|
|
+ </t-popconfirm>
|
|
|
+ </template>
|
|
|
+ <section>
|
|
|
+ <div class="form-item">
|
|
|
+ <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">
|
|
|
+ <arrow-right-icon class="mr-4" />
|
|
|
+ 条件{{ index + 1 }}
|
|
|
+ </div>
|
|
|
+ <close-icon
|
|
|
+ class="hover"
|
|
|
+ @click="trigger.conditions.splice(index, 1)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="py-4">
|
|
|
+ <div class="form-item mt-8">
|
|
|
+ <label>对象</label>
|
|
|
+ <t-tree-select
|
|
|
+ v-model="c.source"
|
|
|
+ :data="penTree"
|
|
|
+ filterable
|
|
|
+ placeholder="对象"
|
|
|
+ class="shrink-0"
|
|
|
+ @change="onChangeTriggerTarget(c)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <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>
|
|
|
+ <t-select-input
|
|
|
+ v-model:inputValue="c.key"
|
|
|
+ :value="c.keyLabel"
|
|
|
+ v-model:popupVisible="c.keyPopupVisible"
|
|
|
+ allow-input
|
|
|
+ clearable
|
|
|
+ @clear="c.keyLabel = undefined"
|
|
|
+ @focus="c.keyPopupVisible = true"
|
|
|
+ @blur="c.keyPopupVisible = false"
|
|
|
+ @input-change="onKeyInput(c)"
|
|
|
+ class="shrink-0"
|
|
|
+ style="width: 152px"
|
|
|
+ >
|
|
|
+ <template #panel>
|
|
|
+ <ul style="padding: 8px 12px">
|
|
|
+ <li
|
|
|
+ v-for="item in cProps"
|
|
|
+ :key="item.value"
|
|
|
+ @click="
|
|
|
+ c.key = item.value;
|
|
|
+ c.keyLabel = item.label;
|
|
|
+ c.keyPopupVisible = false;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ {{ item.label }}
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </template>
|
|
|
+ </t-select-input>
|
|
|
+ </div>
|
|
|
+ <div class="form-item mt-8">
|
|
|
+ <label>关系运算</label>
|
|
|
+ <t-select
|
|
|
+ v-model="c.operator"
|
|
|
+ placeholder="关系运算"
|
|
|
+ :options="operatorOptions"
|
|
|
+ clearable
|
|
|
+ class="shrink-0"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="form-item mt-8">
|
|
|
+ <label>运算对象</label>
|
|
|
+ <t-select
|
|
|
+ v-model="c.valueType"
|
|
|
+ class="shrink-0"
|
|
|
+ placeholder="固定值"
|
|
|
+ >
|
|
|
+ <t-option key="" value="" label="固定值"> 固定值 </t-option>
|
|
|
+ <t-option key="prop" value="prop" label="对象属性值">
|
|
|
+ 对象属性值
|
|
|
+ </t-option>
|
|
|
+ </t-select>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ v-if="!c.valueType"
|
|
|
+ class="form-item mt-8 form-item-valueType"
|
|
|
+ >
|
|
|
+ <label>值</label>
|
|
|
+ <t-input
|
|
|
+ v-model="c.value"
|
|
|
+ @change="valueChange($event, c)"
|
|
|
+ class="shrink-0"
|
|
|
+ style="width: 320px"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <template v-else>
|
|
|
+ <div class="form-item mt-8">
|
|
|
+ <label>对象</label>
|
|
|
+ <t-tree-select
|
|
|
+ v-model="c.target"
|
|
|
+ :data="penTree"
|
|
|
+ filterable
|
|
|
+ placeholder="对象"
|
|
|
+ class="shrink-0"
|
|
|
+ @change="onChangeTriggerTarget(c)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="form-item mt-8">
|
|
|
+ <label>属性</label>
|
|
|
+ <t-select-input
|
|
|
+ v-model:inputValue="c.value"
|
|
|
+ :value="c.label"
|
|
|
+ v-model:popupVisible="c.popupVisible"
|
|
|
+ allow-input
|
|
|
+ clearable
|
|
|
+ @clear="c.label = undefined"
|
|
|
+ @focus="c.popupVisible = true"
|
|
|
+ @blur="c.popupVisible = false"
|
|
|
+ @input-change="onInput(c)"
|
|
|
+ class="shrink-0"
|
|
|
+ >
|
|
|
+ <template #panel>
|
|
|
+ <ul style="padding: 8px 12px">
|
|
|
+ <li
|
|
|
+ v-for="item in cProps"
|
|
|
+ :key="item.value"
|
|
|
+ @click="
|
|
|
+ c.value = item.value;
|
|
|
+ c.label = item.label;
|
|
|
+ c.popupVisible = false;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ {{ item.label }}
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </template>
|
|
|
+ </t-select-input>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <div>function condition(pen) {</div>
|
|
|
+ <CodeEditor
|
|
|
+ class="mt-4"
|
|
|
+ @change="codeChange($event, c)"
|
|
|
+ v-model="c.fnJs"
|
|
|
+ />
|
|
|
+ <div class="mt-4">}</div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="mt-8">
|
|
|
+ <a @click="addTriggerCondition(trigger)"> + 添加条件 </a>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="form-item banner mt-16">
|
|
|
+ <label>执行动作</label>
|
|
|
+ </div>
|
|
|
+ <Actions class="mt-8" :data="trigger" />
|
|
|
+ </section>
|
|
|
+ </t-collapse-panel>
|
|
|
+ </t-collapse>
|
|
|
+
|
|
|
+ <div class="mt-8 ml-16">
|
|
|
+ <a @click="onAddTrigger"> + 添加行为 </a>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+import {
|
|
|
+ getCurrentInstance,
|
|
|
+ onBeforeMount,
|
|
|
+ onMounted,
|
|
|
+ onBeforeUnmount,
|
|
|
+ onUnmounted,
|
|
|
+ reactive,
|
|
|
+ ref,
|
|
|
+ toRaw,
|
|
|
+} from 'vue';
|
|
|
+import { getPenTree, typeOptions, changeType } from '@/services/common';
|
|
|
+import { ArrowRightIcon, CloseIcon, DeleteIcon } from 'tdesign-icons-vue-next';
|
|
|
+import CodeEditor from '@/views/components/common/CodeEditor.vue';
|
|
|
+import Actions from './Actions.vue';
|
|
|
+
|
|
|
+const openedCollapses = ref([1]);
|
|
|
+onBeforeMount(() => {
|
|
|
+ penTree.value = getPenTree();
|
|
|
+});
|
|
|
+const data = reactive({
|
|
|
+ triggers: [],
|
|
|
+});
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ const d = meta2d.store.data as any;
|
|
|
+ if (!d.triggers) {
|
|
|
+ d.triggers = [];
|
|
|
+ }
|
|
|
+ data.triggers = d.triggers;
|
|
|
+ meta2d.on('opened', getTriggers);
|
|
|
+});
|
|
|
+
|
|
|
+onBeforeUnmount(() => {
|
|
|
+ meta2d.off('opened', getTriggers);
|
|
|
+});
|
|
|
+
|
|
|
+const getTriggers = () => {
|
|
|
+ const d = meta2d.store.data as any;
|
|
|
+ if (!d.triggers) {
|
|
|
+ d.triggers = [];
|
|
|
+ }
|
|
|
+ data.triggers = d.triggers;
|
|
|
+};
|
|
|
+const penTree: any = ref([]);
|
|
|
+
|
|
|
+const operatorOptions = ref<any>([
|
|
|
+ { label: '=', value: '=' },
|
|
|
+ { label: '!=', value: '!=' },
|
|
|
+ { label: '>', value: '>' },
|
|
|
+ { label: '<', value: '<' },
|
|
|
+ { label: '>=', value: '>=' },
|
|
|
+ { label: '<=', value: '<=' },
|
|
|
+ { label: '包含', value: '[)' },
|
|
|
+ { label: '不包含', value: '![)' },
|
|
|
+]);
|
|
|
+
|
|
|
+const cProps = [
|
|
|
+ {
|
|
|
+ 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 valueChange = (e, c: any) => {
|
|
|
+ c.value = changeType(e);
|
|
|
+};
|
|
|
+
|
|
|
+const onChangeTriggerTarget = (c: any) => {
|
|
|
+ /*
|
|
|
+ c.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 && target.realTimes) {
|
|
|
+ for (const item of target.realTimes) {
|
|
|
+ const found = cProps.findIndex((elem: any) => elem.value === item.key);
|
|
|
+ if (found < 0) {
|
|
|
+ cProps.push({
|
|
|
+ value: item.key,
|
|
|
+ label: item.label,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const onInput = (item: any) => {
|
|
|
+ item.label = item.value;
|
|
|
+};
|
|
|
+
|
|
|
+const onKeyInput = (item: any) => {
|
|
|
+ item.keyLabel = item.key;
|
|
|
+};
|
|
|
+
|
|
|
+const addTriggerCondition = (trigger: any) => {
|
|
|
+ trigger.conditions.push({
|
|
|
+ type: '',
|
|
|
+ operator: '=',
|
|
|
+ valueType: '',
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const codeChange = (e: any, a: any) => {
|
|
|
+ a.fn = null;
|
|
|
+};
|
|
|
+
|
|
|
+const onAddTrigger = () => {
|
|
|
+ const i = data.triggers.length;
|
|
|
+ data.triggers.push({
|
|
|
+ name: `行为${i + 1}`,
|
|
|
+ conditionType: 'and',
|
|
|
+ conditions: [],
|
|
|
+ actions: [],
|
|
|
+ });
|
|
|
+};
|
|
|
+</script>
|
|
|
+<style lang="postcss" scoped>
|
|
|
+:deep(.t-collapse.t--border-less) {
|
|
|
+ .t-collapse-panel__header {
|
|
|
+ border: none;
|
|
|
+ /* border-top: none; */
|
|
|
+ /* border-bottom: 1px solid var(--td-border-level-1-color); */
|
|
|
+ padding: 8px 12px;
|
|
|
+
|
|
|
+ .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>
|