|
@@ -0,0 +1,520 @@
|
|
|
+<template>
|
|
|
+ <div class="props">
|
|
|
+ <div v-if="props.pen.triggers && props.pen.triggers.length">
|
|
|
+ <div
|
|
|
+ class="flex between tigger-item"
|
|
|
+ v-for="(trigger, i) in props.pen.triggers"
|
|
|
+ :value="i"
|
|
|
+ >
|
|
|
+ <t-input
|
|
|
+ style="width: 190px; margin-left: 20px"
|
|
|
+ v-model="trigger.name"
|
|
|
+ placeholder="状态场景名"
|
|
|
+ />
|
|
|
+ <div class="flex operation">
|
|
|
+ <div class="icon-box icon-item-box" @click="onEditTrigger(trigger)">
|
|
|
+ <Edit2Icon />
|
|
|
+ </div>
|
|
|
+ <t-popconfirm
|
|
|
+ :content="`确认删除这条状态场景吗?`"
|
|
|
+ placement="bottom"
|
|
|
+ @confirm="delTrigger(i)"
|
|
|
+ >
|
|
|
+ <div class="icon-box">
|
|
|
+ <DeleteIcon />
|
|
|
+ </div>
|
|
|
+ </t-popconfirm>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="flex column center blank" v-else>
|
|
|
+ <img src="/img/blank.png" />
|
|
|
+ <div class="gray center">还没有状态场景</div>
|
|
|
+ <!-- <div class="mt-8">
|
|
|
+ <t-button style="height: 30px" @click="onAddTrigger">
|
|
|
+ 添加状态
|
|
|
+ </t-button>
|
|
|
+ </div> -->
|
|
|
+ </div>
|
|
|
+ <div class="flex center mt-8">
|
|
|
+ <t-button
|
|
|
+ style="height: 30px; width: 90%; margin: 12px"
|
|
|
+ @click="onAddTrigger"
|
|
|
+ >
|
|
|
+ 添加状态场景
|
|
|
+ </t-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <t-drawer
|
|
|
+ v-model:visible="drawer.visible"
|
|
|
+ :footer="false"
|
|
|
+ :header="drawer.header"
|
|
|
+ :size="'800px'"
|
|
|
+ >
|
|
|
+ <div v-if="trigger">
|
|
|
+ <t-collapse
|
|
|
+ v-model="openedCollapses"
|
|
|
+ :borderless="true"
|
|
|
+ :expand-on-row-click="true"
|
|
|
+ >
|
|
|
+ <t-collapse-panel v-for="(state, i) in trigger.status" :value="i">
|
|
|
+ <template #header>
|
|
|
+ <t-input
|
|
|
+ v-model="state.name"
|
|
|
+ style="width:90%"
|
|
|
+ @click="panelInputClick($event)"
|
|
|
+ placeholder="状态名"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+ <template #headerRightContent>
|
|
|
+ <t-space size="small" @click.stop>
|
|
|
+ <t-popconfirm
|
|
|
+ content="确认删除该状态吗?"
|
|
|
+ placement="left"
|
|
|
+ @confirm="trigger.status.splice(i, 1)"
|
|
|
+ >
|
|
|
+ <delete-icon class="hover" />
|
|
|
+ </t-popconfirm>
|
|
|
+ </t-space>
|
|
|
+ </template>
|
|
|
+ <!-- <Conditions :key="temCKey" :data="state" /> -->
|
|
|
+ <div class="props">
|
|
|
+ <div
|
|
|
+ v-if="state.conditions && state.conditions.length > 0"
|
|
|
+ class="form-item banner"
|
|
|
+ >
|
|
|
+ <label>满足条件</label>
|
|
|
+ <div class="w-full flex middle between">
|
|
|
+ <div></div>
|
|
|
+ <t-radio-group class="ml-8" v-model="state.conditionType">
|
|
|
+ <t-radio value="and"> 所有 </t-radio>
|
|
|
+ <t-radio value="or"> 任意 </t-radio>
|
|
|
+ </t-radio-group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-for="(c, index) in state.conditions" class="mb-12">
|
|
|
+ <div class="flex middle between" style="margin-top:10px;">
|
|
|
+ <div class="flex middle">
|
|
|
+ <arrow-right-icon class="mr-4" />
|
|
|
+ 条件{{ index + 1 }}
|
|
|
+ </div>
|
|
|
+ <close-icon
|
|
|
+ class="hover"
|
|
|
+ @click="state.conditions.splice(index, 1)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="">
|
|
|
+ <div class="form-item mt-4 px-16">
|
|
|
+ <label>条件类型</label>
|
|
|
+ <t-radio-group class="ml-8" 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 px-16">
|
|
|
+ <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: 132px"
|
|
|
+ >
|
|
|
+ <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>
|
|
|
+ <t-select
|
|
|
+ style="width: 132px"
|
|
|
+ v-model="c.operator"
|
|
|
+ placeholder="关系运算"
|
|
|
+ :options="operatorOptions"
|
|
|
+ clearable
|
|
|
+ class="shrink-0"
|
|
|
+ />
|
|
|
+ <t-select
|
|
|
+ style="width: 132px"
|
|
|
+ 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>
|
|
|
+ <t-input
|
|
|
+ v-if="!c.valueType"
|
|
|
+ v-model="c.value"
|
|
|
+ @change="valueChange($event, c)"
|
|
|
+ class="shrink-0"
|
|
|
+ />
|
|
|
+ <template v-else>
|
|
|
+ <t-tree-select
|
|
|
+ style="width: 132px"
|
|
|
+ v-model="c.target"
|
|
|
+ :data="penTree"
|
|
|
+ filterable
|
|
|
+ placeholder="对象"
|
|
|
+ class="shrink-0"
|
|
|
+ @change="onChangeTriggerTarget(c)"
|
|
|
+ />
|
|
|
+ <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"
|
|
|
+ placeholder="属性"
|
|
|
+ >
|
|
|
+ <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>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <div class="px-16">
|
|
|
+ <div>function condition(pen) {</div>
|
|
|
+ <CodeEditor
|
|
|
+ class="mt-4"
|
|
|
+ @change="codeChange($event, c)"
|
|
|
+ v-model="c.fnJs"
|
|
|
+ />
|
|
|
+ <div class="mt-4">}</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="mt-8">
|
|
|
+ <a @click="addTriggerCondition(state)"> + 添加触发条件 </a>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="form-item banner mt-16">
|
|
|
+ <label>执行动作</label>
|
|
|
+ </div>
|
|
|
+ <Actions class="mt-8" :key="temAKey" :data="state" />
|
|
|
+ </t-collapse-panel>
|
|
|
+ </t-collapse>
|
|
|
+ <div class="flex center mt-8">
|
|
|
+ <t-button
|
|
|
+ style="height: 30px; width: 100%; margin: 12px"
|
|
|
+ @click="addTriggerStatus(trigger)"
|
|
|
+ variant="outline"
|
|
|
+ >
|
|
|
+ <template #icon><add-icon /></template>
|
|
|
+ 添加状态
|
|
|
+ </t-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </t-drawer>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+import { reactive, defineComponent, ref } from 'vue';
|
|
|
+import Actions from './Actions.vue';
|
|
|
+// import Conditions from './Conditions.vue';
|
|
|
+import { Edit2Icon, DeleteIcon, ArrowRightIcon, CloseIcon, AddIcon } from 'tdesign-icons-vue-next';
|
|
|
+import { getPenTree, typeOptions, changeType } from '@/services/common';
|
|
|
+import CodeEditor from '@/views/components/common/CodeEditor.vue';
|
|
|
+
|
|
|
+const props = defineProps<{
|
|
|
+ pen: any;
|
|
|
+}>();
|
|
|
+
|
|
|
+const trigger = ref();
|
|
|
+const drawer = reactive({
|
|
|
+ visible: false,
|
|
|
+ header: '编辑状态',
|
|
|
+});
|
|
|
+
|
|
|
+const openedCollapses = ref([0]);
|
|
|
+
|
|
|
+const onAddTrigger = () => {
|
|
|
+ if (!props.pen.triggers) {
|
|
|
+ props.pen.triggers = [];
|
|
|
+ }
|
|
|
+ const i = props.pen.triggers.length;
|
|
|
+ props.pen.triggers.push({
|
|
|
+ name: `状态场景${i + 1}`,
|
|
|
+ status: [
|
|
|
+ {
|
|
|
+ name: '状态1',
|
|
|
+ conditions: [],
|
|
|
+ actions: [],
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ // key: '', //属性key
|
|
|
+ });
|
|
|
+
|
|
|
+ openedCollapses.value.push(i);
|
|
|
+};
|
|
|
+
|
|
|
+const delTrigger = (i: number) => {
|
|
|
+ props.pen.triggers.splice(i, 1);
|
|
|
+};
|
|
|
+
|
|
|
+// const temCKey = ref(0);
|
|
|
+const temAKey = ref(0);
|
|
|
+
|
|
|
+const onEditTrigger = (data: any) => {
|
|
|
+ // 辅助更新代码块数据
|
|
|
+ // temCKey.value = Math.random();
|
|
|
+ temAKey.value = Math.random();
|
|
|
+ trigger.value = data;
|
|
|
+ drawer.header = data.name;
|
|
|
+ drawer.visible = true;
|
|
|
+ penTree.value = getPenTree();
|
|
|
+};
|
|
|
+
|
|
|
+const editLast = () => {
|
|
|
+ const i = props.pen.triggers.length;
|
|
|
+ onEditTrigger(props.pen.triggers[i - 1]);
|
|
|
+};
|
|
|
+
|
|
|
+const addTriggerStatus = (triger: any) => {
|
|
|
+ const i = props.pen.triggers.length;
|
|
|
+ triger.status.push({
|
|
|
+ name: `状态${i}`,
|
|
|
+ conditionType: 'and',
|
|
|
+ conditions: [],
|
|
|
+ actions: [],
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const panelInputClick = (e) => {
|
|
|
+ e.e.stopPropagation();
|
|
|
+};
|
|
|
+
|
|
|
+const penTree: any = ref([]);
|
|
|
+
|
|
|
+const onChangeTriggerTarget = (c: any) => {
|
|
|
+ const target: any = meta2d.findOne(c.target);
|
|
|
+ if (target && target.realTimes) {
|
|
|
+ for (const item of target.realTimes) {
|
|
|
+ const found = cprops.value.findIndex(
|
|
|
+ (elem: any) => elem.value === item.key
|
|
|
+ );
|
|
|
+ if (found < 0) {
|
|
|
+ cprops.value.push({
|
|
|
+ value: item.key,
|
|
|
+ label: item.label,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const addTriggerCondition = (data: any) => {
|
|
|
+ if (!data.conditionType) {
|
|
|
+ data.conditionType = 'and';
|
|
|
+ }
|
|
|
+ data.conditions.push({
|
|
|
+ type: '',
|
|
|
+ operator: '=',
|
|
|
+ valueType: '',
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const onKeyInput = (item: any) => {
|
|
|
+ item.keyLabel = item.key;
|
|
|
+};
|
|
|
+
|
|
|
+const onInput = (item: any) => {
|
|
|
+ item.label = item.value;
|
|
|
+};
|
|
|
+
|
|
|
+const cprops = ref<any>([
|
|
|
+ {
|
|
|
+ value: 'x',
|
|
|
+ label: 'X',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'y',
|
|
|
+ label: 'Y',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'width',
|
|
|
+ label: '宽',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'height',
|
|
|
+ label: '高',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'visible',
|
|
|
+ label: '显示',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'text',
|
|
|
+ label: '文字',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'color',
|
|
|
+ label: '颜色',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'background',
|
|
|
+ label: '背景颜色',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'progress',
|
|
|
+ label: '进度',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'progressColor',
|
|
|
+ label: '进度颜色',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'showChild',
|
|
|
+ label: '状态',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'rotate',
|
|
|
+ label: '旋转',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'disabled',
|
|
|
+ label: '禁用',
|
|
|
+ },
|
|
|
+]);
|
|
|
+
|
|
|
+const operatorOptions = [
|
|
|
+ { label: '=', value: '=' },
|
|
|
+ { label: '!=', value: '!=' },
|
|
|
+ { label: '>', value: '>' },
|
|
|
+ { label: '<', value: '<' },
|
|
|
+ { label: '>=', value: '>=' },
|
|
|
+ { label: '<=', value: '<=' },
|
|
|
+ { label: '包含', value: '[)' },
|
|
|
+ { label: '不包含', value: '![)' },
|
|
|
+];
|
|
|
+
|
|
|
+const valueChange = (e, c: any) => {
|
|
|
+ c.value = changeType(e);
|
|
|
+};
|
|
|
+
|
|
|
+const codeChange = (e: any, a: any) => {
|
|
|
+ a.fn = null;
|
|
|
+};
|
|
|
+
|
|
|
+defineExpose({
|
|
|
+ editLast,
|
|
|
+});
|
|
|
+</script>
|
|
|
+<style lang="postcss" scoped>
|
|
|
+.tigger-item {
|
|
|
+ /* height: 50px; */
|
|
|
+ /* line-height: 50px; */
|
|
|
+ margin: 12px 8px;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ :deep(.t-input) {
|
|
|
+ border-color: transparent;
|
|
|
+ &:hover {
|
|
|
+ border-color: var(--color-border-input);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .operation {
|
|
|
+ height: 40px;
|
|
|
+ /* line-height: 40px; */
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ .icon-box {
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ margin: 4px;
|
|
|
+ text-align: center;
|
|
|
+ line-height: 24px;
|
|
|
+ border-radius: 4px;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background: var(--td-brand-color-light);
|
|
|
+ }
|
|
|
+
|
|
|
+ .t-icon {
|
|
|
+ width: 14px;
|
|
|
+ height: 14px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &:hover {
|
|
|
+ background: var(--color-background-input);
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+}
|
|
|
+:deep(.t-collapse) {
|
|
|
+ .t-collapse-panel__header {
|
|
|
+ .t-input {
|
|
|
+ border-color: transparent;
|
|
|
+ &:hover {
|
|
|
+ border-color: var(--color-border-input);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .t-collapse-panel__icon:hover {
|
|
|
+ background: none;
|
|
|
+ svg {
|
|
|
+ color: var(--color-primary);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .banner {
|
|
|
+ background-color: var(--color-background-input);
|
|
|
+ padding: 0 12px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* .props {
|
|
|
+ :deep(.value-input) {
|
|
|
+ max-width: 95px;
|
|
|
+ }
|
|
|
+} */
|
|
|
+
|
|
|
+/* :deep(.value-label) {
|
|
|
+ width: 50px;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+} */
|
|
|
+</style>
|