提交 22d768cd authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 8ec30db3
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
"typescript": "~4.9.5", "typescript": "~4.9.5",
"unplugin-auto-import": "^0.15.2", "unplugin-auto-import": "^0.15.2",
"vite": "^4.3.1", "vite": "^4.3.1",
"vue-tsc": "^1.4.0" "vue-tsc": "^1.2.0"
} }
}, },
"node_modules/@ampproject/remapping": { "node_modules/@ampproject/remapping": {
...@@ -1552,48 +1552,45 @@ ...@@ -1552,48 +1552,45 @@
} }
}, },
"node_modules/@volar/language-core": { "node_modules/@volar/language-core": {
"version": "1.4.0", "version": "1.3.0-alpha.0",
"resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-1.4.0.tgz", "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-1.3.0-alpha.0.tgz",
"integrity": "sha512-zZg771L/v4MCPwM1KJxvnQ3q3QgbGJtEytivqf+PsxPr0kQ7XtwB1J30dd+YSGN869pXXZ0V6vWdHkDpWC8F3A==", "integrity": "sha512-W3uMzecHPcbwddPu4SJpUcPakRBK/y/BP+U0U6NiPpUX1tONLC4yCawt+QBJqtgJ+sfD6ztf5PyvPL3hQRqfOA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@volar/source-map": "1.4.0" "@volar/source-map": "1.3.0-alpha.0"
} }
}, },
"node_modules/@volar/source-map": { "node_modules/@volar/source-map": {
"version": "1.4.0", "version": "1.3.0-alpha.0",
"resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-1.4.0.tgz", "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-1.3.0-alpha.0.tgz",
"integrity": "sha512-gkV8ol9qtP7aMdgijc8a5Yoxxoo90TT55YCi9bsMbKxEUDsOAnlciFNlijR9Ebe42d67GV3w15/RzjveTRNGBw==", "integrity": "sha512-jSdizxWFvDTvkPYZnO6ew3sBZUnS0abKCbuopkc0JrIlFbznWC/fPH3iPFIMS8/IIkRxq1Jh9VVG60SmtsdaMQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"muggle-string": "^0.2.2" "muggle-string": "^0.2.2"
} }
}, },
"node_modules/@volar/typescript": { "node_modules/@volar/typescript": {
"version": "1.4.0", "version": "1.3.0-alpha.0",
"resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-1.4.0.tgz", "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-1.3.0-alpha.0.tgz",
"integrity": "sha512-r6OMHj/LeS86iQy3LEjjS+qpmHr9I7BiH8gAwp9WEJP76FHlMPi/EPDQxhf3VcMQ/w6Pi5aBczqI+I3akr9t4g==", "integrity": "sha512-5UItyW2cdH2mBLu4RrECRNJRgtvvzKrSCn2y3v/D61QwIDkGx4aeil6x8RFuUL5TFtV6QvVHXnsOHxNgd+sCow==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@volar/language-core": "1.4.0" "@volar/language-core": "1.3.0-alpha.0"
},
"peerDependencies": {
"typescript": "*"
} }
}, },
"node_modules/@volar/vue-language-core": { "node_modules/@volar/vue-language-core": {
"version": "1.4.0", "version": "1.2.0",
"resolved": "https://registry.npmmirror.com/@volar/vue-language-core/-/vue-language-core-1.4.0.tgz", "resolved": "https://registry.npmmirror.com/@volar/vue-language-core/-/vue-language-core-1.2.0.tgz",
"integrity": "sha512-AIl9iW/6qac1FIJNi6cL27HNNWQWN1gzYkAA3qgcyvpx83a7YEbm9uPC9oelQhiODwFtdt3f3U5ta0l/5kKqjw==", "integrity": "sha512-w7yEiaITh2WzKe6u8ZdeLKCUz43wdmY/OqAmsB/PGDvvhTcVhCJ6f0W/RprZL1IhqH8wALoWiwEh/Wer7ZviMQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@volar/language-core": "1.4.0", "@volar/language-core": "1.3.0-alpha.0",
"@volar/source-map": "1.4.0", "@volar/source-map": "1.3.0-alpha.0",
"@vue/compiler-dom": "^3.2.0", "@vue/compiler-dom": "^3.2.47",
"@vue/compiler-sfc": "^3.2.0", "@vue/compiler-sfc": "^3.2.47",
"@vue/reactivity": "^3.2.0", "@vue/reactivity": "^3.2.47",
"@vue/shared": "^3.2.0", "@vue/shared": "^3.2.47",
"minimatch": "^9.0.0", "minimatch": "^6.1.6",
"muggle-string": "^0.2.2", "muggle-string": "^0.2.2",
"vue-template-compiler": "^2.7.14" "vue-template-compiler": "^2.7.14"
} }
...@@ -1608,25 +1605,25 @@ ...@@ -1608,25 +1605,25 @@
} }
}, },
"node_modules/@volar/vue-language-core/node_modules/minimatch": { "node_modules/@volar/vue-language-core/node_modules/minimatch": {
"version": "9.0.0", "version": "6.2.0",
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.0.tgz", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-6.2.0.tgz",
"integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", "integrity": "sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
}, },
"engines": { "engines": {
"node": ">=16 || 14 >=14.17" "node": ">=10"
} }
}, },
"node_modules/@volar/vue-typescript": { "node_modules/@volar/vue-typescript": {
"version": "1.4.0", "version": "1.2.0",
"resolved": "https://registry.npmmirror.com/@volar/vue-typescript/-/vue-typescript-1.4.0.tgz", "resolved": "https://registry.npmmirror.com/@volar/vue-typescript/-/vue-typescript-1.2.0.tgz",
"integrity": "sha512-DOwKNuK4ScK+NXOU+kxMqVbOK9vCIj9TSOX7iBA34CHzIdnjDWK3ne1Iw74ltat2VX1PEyVQKzC74ZxoInV9bw==", "integrity": "sha512-zjmRi9y3J1EkG+pfuHp8IbHmibihrKK485cfzsHjiuvJMGrpkWvlO5WVEk8oslMxxeGC5XwBFE9AOlvh378EPA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@volar/typescript": "1.4.0", "@volar/typescript": "1.3.0-alpha.0",
"@volar/vue-language-core": "1.4.0" "@volar/vue-language-core": "1.2.0"
} }
}, },
"node_modules/@vue-flow/controls": { "node_modules/@vue-flow/controls": {
...@@ -5764,14 +5761,13 @@ ...@@ -5764,14 +5761,13 @@
} }
}, },
"node_modules/vue-tsc": { "node_modules/vue-tsc": {
"version": "1.4.0", "version": "1.2.0",
"resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-1.4.0.tgz", "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-1.2.0.tgz",
"integrity": "sha512-zASWNqFTIHaY6K8ua0ifFpiX7lA4pz8zKkevLAVYyzBQu6Jc63xWdY3eH0qCUJm7L4K4h9nzbwysta89sfq7ZQ==", "integrity": "sha512-rIlzqdrhyPYyLG9zxsVRa+JEseeS9s8F2BbVVVWRRsTZvJO2BbhLEb2HW3MY+DFma0378tnIqs+vfTzbcQtRFw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@volar/vue-language-core": "1.4.0", "@volar/vue-language-core": "1.2.0",
"@volar/vue-typescript": "1.4.0", "@volar/vue-typescript": "1.2.0"
"semver": "^7.3.8"
}, },
"bin": { "bin": {
"vue-tsc": "bin/vue-tsc.js" "vue-tsc": "bin/vue-tsc.js"
......
...@@ -44,6 +44,6 @@ ...@@ -44,6 +44,6 @@
"typescript": "~4.9.5", "typescript": "~4.9.5",
"unplugin-auto-import": "^0.15.2", "unplugin-auto-import": "^0.15.2",
"vite": "^4.3.1", "vite": "^4.3.1",
"vue-tsc": "^1.4.0" "vue-tsc": "^1.2.0"
} }
} }
...@@ -47,14 +47,14 @@ const correctUserTotalText = computed(() => { ...@@ -47,14 +47,14 @@ const correctUserTotalText = computed(() => {
// 操作错误用户数 // 操作错误用户数
const errorUserTotalText = computed(() => { const errorUserTotalText = computed(() => {
return form.error_operation_type === 3 ? '0' : '实际判断结果计算' return form.error_operation_type === 3 ? 0 : '实际判断结果计算'
}) })
watchEffect(() => { watchEffect(() => {
Object.assign(form, props.model, props.node.data.rule?.form) Object.assign(form, props.model, props.node.data.rule)
}) })
const { total, expectedTotal, query } = useQueryUser(props.node) const { total, expectedTotal, prevNodeRule, prevNodeExpectedTotal, query } = useQueryUser(props.node)
watchEffect(() => { watchEffect(() => {
form.user_total = total.value form.user_total = total.value
...@@ -85,7 +85,14 @@ async function handleSubmit() { ...@@ -85,7 +85,14 @@ async function handleSubmit() {
function updateNode() { function updateNode() {
if (!props.node) return if (!props.node) return
const params = props.paramsParse ? props.paramsParse(props.node.data.teacher, form) : {} const params = props.paramsParse ? props.paramsParse(props.node.data.teacher, form) : {}
Object.assign(props.node.data, { rule: { form, params } }) Object.assign(props.node.data, {
rule: {
...form,
correct_operation_user_total: correctUserTotalText.value,
error_operation_user_total: errorUserTotalText.value
},
rule_params: params
})
} }
// 计算中 // 计算中
...@@ -105,7 +112,7 @@ async function handleCalculate() { ...@@ -105,7 +112,7 @@ async function handleCalculate() {
</script> </script>
<template> <template>
<el-dialog :title="title" append-to-body width="700px" class="rule-template"> <el-dialog :title="title" append-to-body width="800px" class="rule-template">
<slot :model="form"> <slot :model="form">
<slot name="header"> <slot name="header">
<el-form ref="formRef" :model="form" :rules="rules" label-suffix=":"> <el-form ref="formRef" :model="form" :rules="rules" label-suffix=":">
...@@ -126,21 +133,30 @@ async function handleCalculate() { ...@@ -126,21 +133,30 @@ async function handleCalculate() {
<el-form-item label="用户总数"> <el-form-item label="用户总数">
<span class="rule-num">{{ form.user_total }}</span> <span class="rule-num">{{ form.user_total }}</span>
</el-form-item> </el-form-item>
<el-form-item label="满足答案的用户总数"> <el-form-item label="满足答案的用户总数" v-if="node.data.type === 1">
<span class="rule-num">{{ expectedUserTotalText }}</span> <span class="rule-num">{{ expectedUserTotalText }}</span>
<el-button type="primary" :loading="isCalculating" @click="handleCalculate">计算</el-button> <el-button type="primary" :loading="isCalculating" @click="handleCalculate">计算</el-button>
</el-form-item> </el-form-item>
<el-form-item label="上一节点用户总数" v-else>
<div>
<p class="rule-num">正确:{{ prevNodeRule.correct_operation_user_total || prevNodeRule.expected_user_total }}</p>
<p class="rule-num">错误:{{ prevNodeRule.correct_operation_user_total || 0 }}</p>
</div>
<!-- <el-button type="primary" :loading="isCalculating" @click="handleCalculate">计算</el-button> -->
</el-form-item>
</el-form> </el-form>
</el-row> </el-row>
</slot> </slot>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="STEP 2:配置生成规则" :name="1"> <el-tab-pane label="STEP 2:配置生成规则" :name="1">
<slot name="step2"> <slot name="step2">
<div class="rule-result-header"> <!-- 触发条件 -->
<template v-if="node.data.type === 1">
<header class="rule-result-header">
<p>用户总数:{{ form.user_total }}</p> <p>用户总数:{{ form.user_total }}</p>
<p>满足答案的用户总数:{{ expectedUserTotalText }}</p> <p>满足答案的用户总数:{{ expectedUserTotalText }}</p>
</div> </header>
<div class="rule-result-body"> <section class="rule-result-body">
<div class="rule-result-col"> <div class="rule-result-col">
<p class="rule-result-tips"> <p class="rule-result-tips">
<el-icon class="is-success"><SuccessFilled /></el-icon>操作正确,选取数据数量: <el-icon class="is-success"><SuccessFilled /></el-icon>操作正确,选取数据数量:
...@@ -213,16 +229,75 @@ async function handleCalculate() { ...@@ -213,16 +229,75 @@ async function handleCalculate() {
</el-form-item> </el-form-item>
</template> </template>
</div> </div>
</section>
</template>
<!-- 营销动作 -->
<template v-if="node.data.type === 2">
<header class="rule-result-header">
<p>用户总数:{{ form.user_total }}</p>
<p v-if="node.data.type === 1">满足答案的用户总数:{{ expectedUserTotalText }}</p>
<p v-else>上一节点用户总数:{{ prevNodeExpectedTotal }}</p>
</header>
<section class="rule-result-body">
<div class="rule-result-col">
<p class="rule-result-tips">
<el-icon class="is-success"><SuccessFilled /></el-icon>操作正确,选取数据数量:
</p>
</div>
<el-divider direction="vertical" style="height: auto" />
<div class="rule-result-col">
<p class="rule-result-tips">
<el-icon class="is-error"><CircleCloseFilled /></el-icon>操作错误,选取数据数量:
</p>
</div>
</section>
</template>
<!-- 条件判断 -->
<template v-if="node.data.type === 3">
<header class="rule-result-header">
<p>用户总数:{{ form.user_total }}</p>
<p v-if="node.data.type === 1">满足答案的用户总数:{{ expectedUserTotalText }}</p>
<p v-else>上一节点用户总数:{{ prevNodeExpectedTotal }}</p>
</header>
<section class="rule-result-body">
<div class="rule-result-col">
<p class="rule-result-tips">
<el-icon class="is-success"><SuccessFilled /></el-icon>操作正确,选取数据数量:
</p>
<el-form-item label="满足判断条件数据">
<el-radio :model-value="1" :label="1">根据实际判断结果计算</el-radio>
</el-form-item>
<el-form-item label="不满足判断条件数据">
<el-radio :model-value="1" :label="1">根据实际判断结果计算</el-radio>
</el-form-item>
</div> </div>
<el-divider direction="vertical" style="height: auto" />
<div class="rule-result-col">
<p class="rule-result-tips">
<el-icon class="is-error"><CircleCloseFilled /></el-icon>操作错误,选取数据数量:
</p>
<el-form-item label="满足判断条件数据">
<el-radio :model-value="1" :label="1">根据实际判断结果计算</el-radio>
</el-form-item>
<el-form-item label="不满足判断条件数据">
<el-radio :model-value="1" :label="1">根据实际判断结果计算</el-radio>
</el-form-item>
</div>
</section>
</template>
</slot> </slot>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="STEP 3:预期数据量计算" :name="2"> <el-tab-pane label="STEP 3:预期数据量计算" :name="2">
<slot name="step3"> <slot name="step3">
<div class="rule-result-header"> <!-- 触发条件 -->
<template v-if="node.data.type === 1">
<header class="rule-result-header">
<p>用户总数:{{ form.user_total }}</p> <p>用户总数:{{ form.user_total }}</p>
<p>满足答案的用户总数:{{ expectedUserTotalText }}</p> <p>满足答案的用户总数:{{ expectedUserTotalText }}</p>
</div> </header>
<div class="rule-result-body"> <section class="rule-result-body">
<div class="rule-result-col"> <div class="rule-result-col">
<p class="rule-result-tips"> <p class="rule-result-tips">
<el-icon class="is-success"><SuccessFilled /></el-icon>操作正确,选取数据数量: <el-icon class="is-success"><SuccessFilled /></el-icon>操作正确,选取数据数量:
...@@ -236,7 +311,45 @@ async function handleCalculate() { ...@@ -236,7 +311,45 @@ async function handleCalculate() {
</p> </p>
<p class="rule-num">{{ errorUserTotalText }}</p> <p class="rule-num">{{ errorUserTotalText }}</p>
</div> </div>
</section>
</template>
<!-- 营销动作 -->
<template v-if="node.data.type === 2"> </template>
<!-- 条件判断 -->
<template v-if="node.data.type === 3">
<header class="rule-result-header">
<p>用户总数:{{ form.user_total }}</p>
<p>上一节点用户总数:{{ prevNodeExpectedTotal }}</p>
</header>
<section class="rule-result-body">
<div class="rule-result-col">
<p class="rule-result-tips">
<el-icon class="is-success"><SuccessFilled /></el-icon>操作正确,选取数据数量:
</p>
<el-form-item label="满足判断条件数据">{{ form.expected_user_total }}</el-form-item>
<el-form-item label="不满足判断条件数据">
{{ prevNodeExpectedTotal - (form.expected_user_total || 0) }}
</el-form-item>
</div> </div>
<el-divider direction="vertical" style="height: auto" />
<div class="rule-result-col">
<p class="rule-result-tips">
<el-icon class="is-error"><CircleCloseFilled /></el-icon>操作错误,选取数据数量:
</p>
<el-form-item label="满足判断条件数据">
<el-radio :model-value="1" :label="1">根据实际判断结果计算</el-radio>
</el-form-item>
<el-form-item label="不满足判断条件数据">
<el-radio :model-value="1" :label="1">根据实际判断结果计算</el-radio>
</el-form-item>
</div>
</section>
<el-row justify="center" style="margin-top: 20px">
<el-button type="primary" :loading="isCalculating" @click="handleCalculate">计算</el-button>
</el-row>
</template>
</slot> </slot>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
......
<script setup lang="ts"> <script setup lang="ts">
import RuleTemplate from '../../RuleTemplate.vue' import RuleTemplate from '../../RuleTemplate.vue'
import { useUserAttr } from '../../../composables/useAllData'
defineProps<{ node: any }>() const props = defineProps<{ node: any }>()
const { getUserAttr } = useUserAttr()
const config = computed(() => {
return props.node.data.teacher || {}
})
function paramsParse(data: any) {
return data.rules
}
</script> </script>
<template> <template>
<RuleTemplate :node="node" step> <RuleTemplate :node="node" step :paramsParse="paramsParse">
<template #header-answer>答案</template> <template #header-answer>
<span class="is-answer" v-for="(item, index) in config.rules" :key="index">
{{ getUserAttr(item.attr_id)?.name }} {{ item.operate }} {{ item.value }}
</span>
</template>
</RuleTemplate> </RuleTemplate>
</template> </template>
...@@ -5,7 +5,7 @@ const props = defineProps<{ node: any }>() ...@@ -5,7 +5,7 @@ const props = defineProps<{ node: any }>()
function onSubmit(form: any) { function onSubmit(form: any) {
form.expected_user_total = form.user_total form.expected_user_total = form.user_total
Object.assign(props.node.data, { rule: { form, params: {} } }) Object.assign(props.node.data, { rule: form, rule_params: {} })
} }
</script> </script>
......
...@@ -44,7 +44,7 @@ export function useQueryUser(node: any) { ...@@ -44,7 +44,7 @@ export function useQueryUser(node: any) {
const filters = prevNodes.map(node => ({ const filters = prevNodes.map(node => ({
type: node.data.type, type: node.data.type,
component_type: node.data.component_type, component_type: node.data.component_type,
params: node.data.rule?.params || {} params: node.data.rule_params || {}
})) }))
const { data } = await ruleQuery({ const { data } = await ruleQuery({
experiment_id: route.query.experiment_id as string, experiment_id: route.query.experiment_id as string,
...@@ -53,5 +53,21 @@ export function useQueryUser(node: any) { ...@@ -53,5 +53,21 @@ export function useQueryUser(node: any) {
expectedTotal.value = data.count expectedTotal.value = data.count
} }
return { total, expectedTotal, query } // 上一节点
const prevNode = computed(() => {
const prevEdges = sortEdges(node.id, edges.value)
const prevNodes = sortNodes(node.id, prevEdges, nodes.value)
return prevNodes[prevNodes.length - 2]
})
const prevNodeRule = computed(() => {
return prevNode.value?.data?.rule ?? {}
})
// 上一节点预期用户数量
const prevNodeExpectedTotal = computed(() => {
return prevNodeRule.value?.expected_user_total ?? 0
})
return { total, expectedTotal, prevNode, prevNodeRule, prevNodeExpectedTotal, query }
} }
...@@ -63,7 +63,9 @@ function fetchInfo() { ...@@ -63,7 +63,9 @@ function fetchInfo() {
const { detail } = res.data const { detail } = res.data
const [user_attr_rule = { current_logic_operate: 'and', items: [] }] = detail.user_attr_rule const [user_attr_rule = { current_logic_operate: 'and', items: [] }] = detail.user_attr_rule
const [event_attr_rule = { current_logic_operate: 'and', items: [] }] = detail.event_attr_rule const [event_attr_rule = { current_logic_operate: 'and', items: [] }] = detail.event_attr_rule
const [tag_rule = { current_logic_operate: 'and', items: [] }] = detail.tag_rule const [tag_rule = { current_logic_operate: 'and', items: [] }] = detail.tag_rule.map((item: any) => {
return { ...item, items: item.items.map((item: any) => item.id) }
})
Object.assign(form, { user_attr_rule, event_attr_rule, tag_rule }) Object.assign(form, { user_attr_rule, event_attr_rule, tag_rule })
}) })
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论