提交 670709d1 authored 作者: 王鹏飞's avatar 王鹏飞

feat: 用户旅行-营销动作 新增AB分配

上级 0adba430
......@@ -4,56 +4,35 @@ const props = defineProps<{ node: NodeProps }>()
const component = computed(() => {
const allComponent: any = {
TCRealTimeTrigger: markRaw(
defineAsyncComponent(() => import('./components/triggeringConditions/realTimeTrigger/Index.vue'))
),
TCRealTimeTrigger: markRaw(defineAsyncComponent(() => import('./components/triggeringConditions/realTimeTrigger/Index.vue'))),
TCJoinGroup: markRaw(defineAsyncComponent(() => import('./components/triggeringConditions/joinGroup/Index.vue'))),
TCChangeProps: markRaw(
defineAsyncComponent(() => import('./components/triggeringConditions/changeProps/Index.vue'))
),
TCOffiaccount: markRaw(
defineAsyncComponent(() => import('./components/triggeringConditions/offiaccount/Index.vue'))
),
TCChangeProps: markRaw(defineAsyncComponent(() => import('./components/triggeringConditions/changeProps/Index.vue'))),
TCOffiaccount: markRaw(defineAsyncComponent(() => import('./components/triggeringConditions/offiaccount/Index.vue'))),
TCDouyin: markRaw(defineAsyncComponent(() => import('./components/triggeringConditions/douyin/Index.vue'))),
TCXiaohongshu: markRaw(
defineAsyncComponent(() => import('./components/triggeringConditions/xiaohongshu/Index.vue'))
),
TCXiaohongshu: markRaw(defineAsyncComponent(() => import('./components/triggeringConditions/xiaohongshu/Index.vue'))),
TCWeibo: markRaw(defineAsyncComponent(() => import('./components/triggeringConditions/weibo/Index.vue'))),
TCCustom: markRaw(defineAsyncComponent(() => import('./components/triggeringConditions/custom/Index.vue'))),
TCXiaoetong: markRaw(defineAsyncComponent(() => import('./components/triggeringConditions/xiaoetong/Index.vue'))),
TCWenjuanxing: markRaw(
defineAsyncComponent(() => import('./components/triggeringConditions/wenjuanxing/Index.vue'))
),
TCWenjuanxing: markRaw(defineAsyncComponent(() => import('./components/triggeringConditions/wenjuanxing/Index.vue'))),
MAEndTrip: markRaw(defineAsyncComponent(() => import('./components/marketingAction/endTrip/Index.vue'))),
MAJoinGroup: markRaw(defineAsyncComponent(() => import('./components/marketingAction/joinGroup/Index.vue'))),
MALeaveGroup: markRaw(defineAsyncComponent(() => import('./components/marketingAction/leaveGroup/Index.vue'))),
MAChangeProps: markRaw(defineAsyncComponent(() => import('./components/marketingAction/changeProps/Index.vue'))),
MADelayProcess: markRaw(defineAsyncComponent(() => import('./components/marketingAction/delayProcess/Index.vue'))),
MAInternalNotice: markRaw(
defineAsyncComponent(() => import('./components/marketingAction/internalNotice/Index.vue'))
),
MAInternalNotice: markRaw(defineAsyncComponent(() => import('./components/marketingAction/internalNotice/Index.vue'))),
MAOffiaccount: markRaw(defineAsyncComponent(() => import('./components/marketingAction/offiaccount/Index.vue'))),
MAEmail: markRaw(defineAsyncComponent(() => import('./components/marketingAction/email/Index.vue'))),
MASMS: markRaw(defineAsyncComponent(() => import('./components/marketingAction/sms/Index.vue'))),
MADouyin: markRaw(defineAsyncComponent(() => import('./components/marketingAction/douyin/Index.vue'))),
MAWeibo: markRaw(defineAsyncComponent(() => import('./components/marketingAction/weibo/Index.vue'))),
MADingTalk: markRaw(defineAsyncComponent(() => import('./components/marketingAction/dingtalk/Index.vue'))),
CBAttributeJudgment: markRaw(
defineAsyncComponent(() => import('./components/conditionalBranch/attributeJudgment/Index.vue'))
),
CBGroupJudgment: markRaw(
defineAsyncComponent(() => import('./components/conditionalBranch/groupJudgment/Index.vue'))
),
CBEventJudgment: markRaw(
defineAsyncComponent(() => import('./components/conditionalBranch/eventJudgment/Index.vue'))
),
CBTimeJudgment: markRaw(
defineAsyncComponent(() => import('./components/conditionalBranch/timeJudgment/Index.vue'))
),
MAAB: markRaw(defineAsyncComponent(() => import('./components/marketingAction/ab/Index.vue'))),
CBAttributeJudgment: markRaw(defineAsyncComponent(() => import('./components/conditionalBranch/attributeJudgment/Index.vue'))),
CBGroupJudgment: markRaw(defineAsyncComponent(() => import('./components/conditionalBranch/groupJudgment/Index.vue'))),
CBEventJudgment: markRaw(defineAsyncComponent(() => import('./components/conditionalBranch/eventJudgment/Index.vue'))),
CBTimeJudgment: markRaw(defineAsyncComponent(() => import('./components/conditionalBranch/timeJudgment/Index.vue'))),
CBOffiaccount: markRaw(defineAsyncComponent(() => import('./components/conditionalBranch/offiaccount/Index.vue'))),
CBLabelJudgment: markRaw(
defineAsyncComponent(() => import('./components/conditionalBranch/labelJudgment/Index.vue'))
)
CBLabelJudgment: markRaw(defineAsyncComponent(() => import('./components/conditionalBranch/labelJudgment/Index.vue')))
}
return allComponent[props.node?.data.component_name || props.node?.data.componentName]
})
......
......@@ -51,7 +51,9 @@ onConnect(params => {
'handle-yes': { label: '是', style: { stroke: '#81b337' } },
'handle-no': { label: '否', style: { stroke: '#a16222' } },
'handle-success': { label: '成功', style: { stroke: '#81b337' } },
'handle-failure': { label: '失败', style: { stroke: '#a16222' } }
'handle-failure': { label: '失败', style: { stroke: '#a16222' } },
'handle-a': { label: 'A', style: { stroke: '#81b337' } },
'handle-b': { label: 'B', style: { stroke: '#a16222' } }
}
let customParams = {}
if (params.sourceHandle) {
......
......@@ -216,6 +216,14 @@ const list = ref([
component_type: 9,
component_name: 'MADingTalk',
connection_type: 2
},
{
name: 'A/B分配',
type: 2,
type_name: '营销动作',
icon: '101',
component_type: 12,
component_name: 'MAAB'
}
]
},
......@@ -280,9 +288,7 @@ const currentList = computed(() => {
return list.value.map(item => {
return {
...item,
children: item.children.filter(item =>
item.connection_type ? connections.value.find(connection => connection.type === item.connection_type) : true
)
children: item.children.filter(item => (item.connection_type ? connections.value.find(connection => connection.type === item.connection_type) : true))
}
})
})
......@@ -301,18 +307,9 @@ const onDragStart = (event: DragEvent, data: any) => {
<dt :style="`background: ${parent.background?.color}`">{{ parent.name }}</dt>
<dd>
<ul>
<li
v-for="(item, index) in parent.children"
:key="index"
:draggable="true"
@dragstart="event => onDragStart(event, item)">
<li v-for="(item, index) in parent.children" :key="index" :draggable="true" @dragstart="event => onDragStart(event, item)">
<div class="icon-box">
<Icon
class="circle"
:color="item.color || parent.background?.color"
:name="parent.background?.icon || ''"
w="60"
h="60"></Icon>
<Icon class="circle" :color="item.color || parent.background?.color" :name="parent.background?.icon || ''" w="60" h="60"></Icon>
<Icon class="icon" color="#fff" :name="item.icon" w="24" h="24"></Icon>
</div>
<p>{{ item.name }}</p>
......
......@@ -3,10 +3,10 @@ import type { NodeProps } from '@vue-flow/core'
import { useVueFlow, Handle, Position } from '@vue-flow/core'
import { Setting, Delete } from '@element-plus/icons-vue'
const props = withDefaults(
defineProps<{ node: NodeProps; connectionType?: number; canSetting?: boolean; canConnect?: boolean }>(),
{ canSetting: true, canConnect: true }
)
const props = withDefaults(defineProps<{ node: NodeProps; connectionType?: number; canSetting?: boolean; canConnect?: boolean }>(), {
canSetting: true,
canConnect: true
})
const emit = defineEmits<{ (e: 'setting'): void }>()
......@@ -42,6 +42,10 @@ function onRemove() {
<Handle id="handle-failure" class="handle-link is-no" :position="Position.Left">失败</Handle>
<Handle id="handle-any" class="handle-link is-any" :position="Position.Left">继续</Handle>
</template>
<template v-else-if="connectionType === 3">
<Handle id="handle-a" class="handle-link is-yes" :position="Position.Left">A</Handle>
<Handle id="handle-b" class="handle-link is-no" :position="Position.Left">B</Handle>
</template>
<template v-else>
<Handle id="handle-any" class="handle-default" :position="Position.Left">
<svg
......
<script setup lang="ts">
import ConfigTemplate from '../../ConfigTemplate.vue'
const props = defineProps<{ node: any }>()
const role = inject('role') as string
const form = reactive({
a: 60,
b: 40
})
watchEffect(() => {
Object.assign(form, props.node.data[role])
})
watchEffect(() => {
form.b = 100 - (form.a || 0)
})
</script>
<template>
<ConfigTemplate :model="form" :node="node">
<el-form-item label="A路径">
<el-input-number v-model="form.a" :max="100" :min="0" :controls="false" style="width: 100%" />
</el-form-item>
<el-form-item label="B路径">
<el-input-number v-model="form.b" :controls="false" disabled style="width: 100%" />
</el-form-item>
</ConfigTemplate>
</template>
<script setup lang="ts">
import ConfigViewTemplate from '../../ConfigViewTemplate.vue'
const role = inject('role') as string
defineProps<{ node: any }>()
</script>
<template>
<ConfigViewTemplate :node="node">
<el-form-item :label="role === 'student' ? '我的答案' : '学生答案'"> A路径:{{ node.data.student?.a }} B路径:{{ node.data.student?.b }} </el-form-item>
<el-form-item label="正确答案"> A路径:{{ node.data.teacher?.a }} B路径:{{ node.data.teacher?.b }} </el-form-item>
</ConfigViewTemplate>
</template>
<!-- 变更属性 -->
<script setup lang="ts">
import NodeTemplate from '../../NodeTemplate.vue'
import Icon from '@/components/ConnectionIcon.vue'
const Config = defineAsyncComponent(() => import('./Config.vue'))
const ConfigView = defineAsyncComponent(() => import('./ConfigView.vue'))
const Rule = defineAsyncComponent(() => import('./Rule.vue'))
const props = defineProps<{ node: any }>()
const action = inject('action') as string
const role = inject('role') as string
const templateType = inject('templateType') as string
// 是否置灰
const isGray = computed(() => {
return templateType === '2' && role === 'student' && action === 'edit' && !props.node.data[role]
})
// 设置
const settingVisible = ref(false)
</script>
<template>
<NodeTemplate :node="node" :connectionType="3" @setting="settingVisible = true">
<div class="node-item">
<Icon class="circle" name="square" :color="isGray ? '#9a9a9a' : '#19AAA5'" w="60" h="60"></Icon>
<Icon class="icon" name="101" color="#fff" w="24" h="24"></Icon>
</div>
</NodeTemplate>
<!-- 配置 -->
<Config v-model="settingVisible" :node="node" v-if="settingVisible && action === 'edit'" />
<!-- 查看配置 -->
<ConfigView v-model="settingVisible" :node="node" v-if="settingVisible && action === 'view'" />
<!-- 数据生成规则 -->
<Rule v-model="settingVisible" :node="node" v-if="settingVisible && action === 'rule'" />
</template>
<script setup lang="ts">
import RuleTemplate from '../../RuleTemplate.vue'
import { useUserAttr } from '../../../composables/useAllData'
const props = defineProps<{ node: any }>()
const { getUserAttr } = useUserAttr()
const config = computed(() => {
return props.node.data.teacher || {}
})
function paramsParse(data: any) {
return data.rules
}
</script>
<template>
<RuleTemplate :node="node" step :paramsParse="paramsParse">
<template #header-answer>
<p v-for="(item, index) in config.rules" :key="index">
<span>{{ getUserAttr(item.attr_id)?.name }}</span>
<span class="is-operate">&nbsp;&nbsp;{{ item.operate }}&nbsp;&nbsp;</span>
<span class="is-answer">{{ item.value }}</span>
&nbsp;&nbsp;&nbsp;&nbsp;
</p>
</template>
</RuleTemplate>
</template>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论