This commit is contained in:
likun 2025-06-16 18:14:25 +08:00
parent 4ed261d9b4
commit 5f165f82ae
10 changed files with 977 additions and 113 deletions

View File

@ -0,0 +1,5 @@
.editorTopRightToolBarBtn {
margin: 0;
padding: 0 8px 0 8px;
border: 0
}

View File

@ -24,7 +24,6 @@ body {
-moz-osx-font-smoothing: grayscale;
}
*/
body {
height: 100%;
margin: 0;

View File

@ -0,0 +1,277 @@
<script setup>
import {defineAsyncComponent} from 'vue';
const propertyFilterShow = defineAsyncComponent(() => import("./propertyConditionType.vue"))
const propertyFilterSelectShow = defineAsyncComponent(() => import("./propertyConditionFilter.vue"))
/*
{
nodeType: "", // "" "and" "or"andor
propertyInfo: {
name: "user_id",
cond: "eq", // "eq", "ne", "st", "se", "gt", "ge", "valued", "valueless","range"
// "eq","ne", "contain", "exclusive", "regmatch", "regnotmatch"
value1: "",
value2: ""
}
}
{
nodeType: "and", // "" "and" "or"andor
children: [
{...}
]
}
{
nodeType: "or", // "" "and" "or"andor
children: [
{...}
]
}
*/
const rawSelectedTree = reactive({
nodeType: "and",
children: [
{
nodeType: "",
propertyInfo: {
name: "user_id",
alias: "账户id",
cond: "eq",
value1: "account_xxx1"
}
},
{
nodeType: "and",
children: [
{
nodeType: "or",
children: [
{
nodeType: "",
propertyInfo: {
name: "role_id",
alias: "角色id",
cond: "contain",
value1: "role123"
}
},
{
nodeType: "",
propertyInfo: {
name: "user_id",
alias: "账户id",
cond: "eq",
value1: "account_xxx1"
}
},
{
nodeType: "and",
children: [
{
nodeType: "",
propertyInfo: {
name: "role_id",
alias: "角色id",
cond: "contain",
value1: "role123"
}
},
{
nodeType: "",
propertyInfo: {
name: "user_id",
alias: "账户id",
cond: "eq",
value1: "account_xxx1"
}
},
]
}
]
},
{
nodeType: "",
propertyInfo: {
name: "user_id",
alias: "账户id",
cond: "eq",
value1: "account_xxx1"
}
},
]
},
{ //
nodeType: "or",
desc: "invalid node",
children: []
},
{ //
nodeType: "and",
desc: "wait tidy node",
children: [
{
nodeType: "or",
children: [
{
nodeType: "",
propertyInfo: {
name: "user_id",
alias: "账户id",
cond: "eq",
value1: "account_xxx1"
}
},
]
}
]
}
],
})
//
const tidySelectedTreeInvalidChild = (node) => {
if (node.nodeType !== "") {
if (node.children.length === 0) {
return null
}
let i = 0
while (true) {
if (i >= node.children.length) {
break
}
let child = node.children[i]
let newChild = tidySelectedTreeInvalidChild(child)
if (newChild !== null) {
node.children[i] = newChild
i++
} else {
node.children.splice(i, 1)
}
}
if (node.children.length === 1) {
node = node.children[0]
}
} else {
}
return node
}
const treeMaxNodeId = ref(0)
const getTreeMaxNodeId = () => {
treeMaxNodeId.value += 1
return treeMaxNodeId.value
}
const numberTreeId = (node) => {
node.id = getTreeMaxNodeId()
if (node.nodeType !== "") {
node.children.forEach((child, index) => {
node.children[index] = numberTreeId(child)
})
}
return node
}
tidySelectedTreeInvalidChild(rawSelectedTree)
numberTreeId(rawSelectedTree)
const newTree = rawSelectedTree
const findNodeAndApply = (curNodeChildIndex, curNode, parent, findNodeId, applyFunc) => {
if (curNode.id === findNodeId) {
applyFunc(curNodeChildIndex, curNode, parent)
return true
}
if (curNode.nodeType === "") {
return false
}
for (let i = 0; i < curNode.children.length; i++) {
const child = curNode.children[i]
const find = findNodeAndApply(i, child, curNode, findNodeId, applyFunc)
if (find) {
return true
}
}
return false
}
const onNodeSplit = (nodeId) => {
//
// and|or
findNodeAndApply(0, newTree, {
nodeType: 'and',
children: [newTree]
}, nodeId, (findNodeChildIndex, findNode, findParent) => {
findParent.children[findNodeChildIndex] = {
nodeType: 'and',
id: getTreeMaxNodeId(),
children: [findNode, {
nodeType: '',
id: getTreeMaxNodeId(),
propertyInfo: {
name: "",
alias: "",
cond: "",
value1: "",
value2: "",
},
children: []
}]
}
})
tidySelectedTreeInvalidChild(newTree)
numberTreeId(newTree)
}
const onAddBrother = (nodeId) => {
findNodeAndApply(0, newTree, {
nodeType: 'and',
children: [newTree]
}, nodeId, (findNodeChildIndex, findNode, findParent) => {
findParent.children.push({
nodeType: '',
id: getTreeMaxNodeId(),
propertyInfo: {
name: "",
alias: "",
cond: "",
value1: "",
value2: "",
},
children: []
})
})
tidySelectedTreeInvalidChild(newTree)
numberTreeId(newTree)
}
const onDeleteNode = (nodeId) => {
findNodeAndApply(0, newTree, {
nodeType: 'and',
children: [newTree]
}, nodeId, (findNodeChildIndex, findNode, findParent) => {
findParent.children.splice(findNodeChildIndex, 1)
})
tidySelectedTreeInvalidChild(newTree)
numberTreeId(newTree)
}
const propertyShowHandlerInfo = {
showComp: propertyFilterSelectShow,
onSplitNode: onNodeSplit,
onAddBrother: onAddBrother,
onDeleteNode: onDeleteNode,
}
</script>
<template>
<propertyFilterShow :node="newTree" :propertyShowHandlerInfo="propertyShowHandlerInfo"/>
</template>
<style scoped>
</style>

View File

@ -0,0 +1,106 @@
<script setup>
import {ForkOutlined} from '@ant-design/icons-vue';
const props = defineProps({
propertyHandlerInfo: {
propertyInfo: {},
onSplitNode: null,
onAddBrother: null,
onDeleteNode: null,
},
})
// console.log("", props.propertyInfo)
const allProperties = ref([
{
label: "用户属性",
options: [
{
value: "account_id",
label: "游戏账号"
},
{
value: "role_id",
label: "角色id"
},
{
value: "role_name",
label: "角色名"
}
]
},
{
label: "事件属性",
options: [
{
value: "item_id",
label: "道具id"
},
{
value: "item_name",
label: "道具名"
},
{
value: "cur_num",
label: "cur_num"
}
]
}
])
const canDelete = ref(false)
const filterOption = (input, option) => {
return option.value.filter((item) => {
if (item.options && item.options.length > 0) {
return item.options.filter(opt => {
return opt.includes(input)
})
}
return item.label.includes(input)
})
};
const selectedPropertyValue = ref('')
</script>
<template>
<div>
<a-space :size="2">
<a-select showArrow show-search v-model:value="selectedPropertyValue"
:options="allProperties" :filter-option="filterOption" @change=""
style="width: 100px;margin: 0 5px 0 0"/>
<el-button class="filterToolBtn" @click="propertyHandlerInfo.onSplitNode(propertyHandlerInfo.propertyInfo.id)">
<ForkOutlined style="transform: rotate(90deg)"/>
</el-button>
<el-button class="filterToolBtn" @click="propertyHandlerInfo.onAddBrother(propertyHandlerInfo.propertyInfo.id)">
<el-icon :size="16">
<CirclePlus/>
</el-icon>
</el-button>
<el-button class="filterToolBtn" @click="propertyHandlerInfo.onDeleteNode(propertyHandlerInfo.propertyInfo.id)">
<el-icon :size="16">
<Delete/>
</el-icon>
</el-button>
</a-space>
<!-- {{ propertyInfo.propertyInfo.alias }}-->
</div>
</template>
<style scoped lang="scss">
.filterToolBtn {
margin: 0;
padding: 0;
border: 0;
width: 20px;
height: 20px;
}
</style>

View File

@ -0,0 +1,64 @@
<script setup>
const name = "PropertyConditionType";
const props = defineProps({
node: {},
propertyShowHandlerInfo: {},
})
</script>
<template>
<!-- <el-row>-->
<!-- <div class="conditionShowAnd">-->
<!-- <p style="color: white">and</p>-->
<!-- </div>-->
<!-- <div style="display: inline-flex;flex-direction: column">-->
<!-- <component :is="propertyComp" :propertyInfo="{propertyInfo: {alias: '角色名'}}"></component>-->
<!-- <component :is="propertyComp" :propertyInfo="{propertyInfo: {alias: '账号id'}}"></component>-->
<!-- </div>-->
<!-- </el-row>-->
<el-row v-if="node.nodeType !== ''">
<div :class="{
'conditionShowAnd': node.nodeType === 'and',
'conditionShowOr': node.nodeType === 'or'
}">
<p style="color: black">{{ node.nodeType }}</p>
</div>
<div style="display: inline-flex;flex-direction: column">
<template v-for="child in node.children">
<PropertyConditionType :node="child" :propertyShowHandlerInfo="propertyShowHandlerInfo"/>
</template>
</div>
</el-row>
<el-row v-else>
<component :is="propertyShowHandlerInfo.showComp" :propertyHandlerInfo="{
propertyInfo: node,
onSplitNode: props.propertyShowHandlerInfo.onSplitNode,
onAddBrother: props.propertyShowHandlerInfo.onAddBrother,
onDeleteNode: props.propertyShowHandlerInfo.onDeleteNode,
}"></component>
</el-row>
</template>
<style scoped lang="scss">
.conditionShowAnd {
display: flex;
justify-content: center;
align-items: center;
border-right: 2px solid #202241;
//background-color: #202241;
}
.conditionShowOr {
display: flex;
justify-content: center;
align-items: center;
border-right: 2px solid #42b983;
//background-color: #42b983;
}
</style>

View File

@ -2,8 +2,8 @@
import {ref} from 'vue';
import {defineAsyncComponent} from 'vue';
const editLayout = defineAsyncComponent(() => import("./analyseMetricEditorLayout.vue"))
const editor = defineAsyncComponent(() => import("./editor/event.vue"))
const editLayout = defineAsyncComponent(() => import("./editor/layout/analyseMetricEditorLayout.vue"))
const editor = defineAsyncComponent(() => import("./editor/event/index.vue"))
const editorAreaInfo = {
editorPane: editor,

View File

@ -1,7 +1,11 @@
<script setup>
import {FunctionOutlined} from '@ant-design/icons-vue';
import {ref, computed} from "vue";
import {computed, ref} from "vue";
const props = defineProps({
index: 0,
onDeleteMetricSelect: null,
})
const eventAllData = {
userProperties: [
@ -92,6 +96,8 @@ const eventAllData = {
const selectEventValue = ref('')
const selectEventOptions = ref([])
const selectedEventInfo = ref({})
eventAllData.eventDescList.forEach((eventInfo) => {
let addOptionInfo = {
value: eventInfo.name,
@ -104,7 +110,6 @@ eventAllData.eventDescList.forEach((eventInfo) => {
})
selectEventValue.value = selectEventOptions.value[0].label
const selectedEventInfo = ref({})
const defaultSelectEventRelationMetrics = {
label: "预置指标",
@ -147,7 +152,7 @@ for (let i = 0; i < defaultMetricTypeNumberOpList1.length; i++) {
})
}
console.log("oplist:", defaultMetricTypeNumberOpList)
// console.log("oplist:", defaultMetricTypeNumberOpList)
const selectedEventRelationMetricValue = ref('')
const disableMetricSelectOp = ref(true)
@ -156,7 +161,7 @@ const selectEventRelationMetrics = computed(() => {
if (!eventInfo) {
return [defaultSelectEventRelationMetrics]
}
console.log("选择事件:", eventInfo)
// console.log("", eventInfo)
selectedEventInfo.value = eventInfo
let userMetrics = {
@ -198,8 +203,8 @@ const selectEventRelationMetrics = computed(() => {
const selectedMetricRelationOpValue = ref('')
const selectMetricRelationOpList = computed(() => {
console.log("selectEventRelationMetrics:", selectedEventRelationMetricValue.value)
console.log("selectEventRelationMetrics:", selectEventRelationMetrics.value)
// console.log("selectEventRelationMetrics:", selectedEventRelationMetricValue.value)
// console.log("selectEventRelationMetrics:", selectEventRelationMetrics.value)
let opList = []
selectEventRelationMetrics.value.find((v, idx) => {
const selectedMetric = v.options.find((v1, idx1) => {
@ -211,7 +216,7 @@ const selectMetricRelationOpList = computed(() => {
}
return false
})
console.log("oplist", opList)
// console.log("oplist", opList)
selectedMetricRelationOpValue.value = ''
disableMetricSelectOp.value = opList.length === 0;
return opList
@ -221,119 +226,77 @@ const onSelectEvent = (value) => {
}
const filterOption = (input, option) => {
return option.value.filter((item) => {
if (item.options && item.options.length > 0) {
return item.options.filter(opt => {
return opt.includes(input)
})
}
return item.label.includes(input)
})
};
onSelectEvent(selectEventValue.value)
</script>
<template>
<div class="editorAreaOuter">
<div class="editorAreaInner">
<el-row style="height: 40px" align="middle">
<el-col :span="6">
<span style="font-weight: bold;">
分析指标
</span>
</el-col>
<el-col :span="10" :offset="8">
<el-row justify="end">
<el-button class="editorTopRightToolBarBtn">
<el-icon :size="20">
<Plus/>
</el-icon>
</el-button>
<el-button class="editorTopRightToolBarBtn">
<FunctionOutlined style="font-size: 20px"/>
</el-button>
</el-row>
</el-col>
</el-row>
<div class="editorOperationArea">
<!-- <div-->
<!-- style="background-color: #202241;margin-right: 5px;border-radius: 5px;;width: 3px;height: 70px;display: inline-flex;justify-content: center;align-items: center;">-->
<!-- &lt;!&ndash; <p style="font-weight: bold;color: white;margin: 0">1</p>&ndash;&gt;-->
<!-- </div>-->
<el-row justify="end">
<a-space>
<el-button class="editorTopRightToolBarBtn" @click="onDeleteMetricSelect(index)">
<el-icon :size="20">
<Delete/>
</el-icon>
</el-button>
</a-space>
</el-row>
<el-row style="width: 100%;height: 50px;">
<a-space :size="5">
<div
style="background-color: #202241;border-radius: 5px;;width: 3px;height: 35px;display: inline-flex;justify-content: center;align-items: center;">
<!-- <p style="font-weight: bold;color: white;margin: 0">1</p>-->
</div>
<a-select ref="select" v-model:value="selectEventValue" :options="selectEventOptions" @change="onSelectEvent"
style="width: 100px;margin: 0"/>
<div
style="background-color: #202241;border-radius: 5px;width: 25px;height: 25px;display: flex;justify-content: center;align-items: center;">
<p style="color: white;margin: 0"></p>
</div>
<a-select ref="metricSelect" v-model:value="selectedEventRelationMetricValue"
:options="selectEventRelationMetrics" @change=""
style="width: 100px;margin: 0"/>
<!-- <div-->
<!-- style="background-color: #202241;border-radius: 5px;;width: 25px;height: 25px;display: flex;justify-content: center;align-items: center;">-->
<!-- <p style="color: white;margin: 0">.</p>-->
<!-- </div>-->
<div
style="height: 100%;display: inline-flex;flex-direction: column;justify-content: end">
<p style="color: black;font-weight: bold;font-size: 20px;margin: 0">·</p>
</div>
<a-select ref="metricSelect" :disabled="disableMetricSelectOp" v-model:value="selectedMetricRelationOpValue"
:options="selectMetricRelationOpList" @change=""
style="width: 100px;margin: 0"/>
</a-space>
</el-row>
<el-row style="height: 30px"></el-row>
<el-row style="height: 40px" align="middle">
<el-col :span="6">
<span style="font-weight: bold;">
全局筛选
</span>
</el-col>
<el-col :span="10" :offset="8">
<el-row justify="end">
<el-button class="editorTopRightToolBarBtn">
<el-icon :size="20">
<Plus/>
</el-icon>
</el-button>
</el-row>
</el-col>
</el-row>
<el-row style="height: 30px"></el-row>
<el-row style="height: 40px" align="middle">
<el-col :span="6">
<span style="font-weight: bold;">
分组项
</span>
</el-col>
<el-col :span="10" :offset="8">
<el-row justify="end">
<el-button class="editorTopRightToolBarBtn">
<el-icon :size="20">
<Plus/>
</el-icon>
</el-button>
</el-row>
</el-col>
</el-row>
</div>
<el-row justify="end">
<a-space :size="5">
<div
style="background-color: #202241;border-radius: 5px;width: 25px;height: 25px;display: flex;justify-content: center;align-items: center;">
<p style="color: white;margin: 0"></p>
</div>
<a-select showArrow show-search v-model:value="selectedEventRelationMetricValue"
:options="selectEventRelationMetrics" :filter-option="filterOption" @change=""
style="width: 100px;margin: 0"/>
<!-- <div-->
<!-- style="background-color: #202241;border-radius: 5px;;width: 25px;height: 25px;display: flex;justify-content: center;align-items: center;">-->
<!-- <p style="color: white;margin: 0">.</p>-->
<!-- </div>-->
<div
style="height: 100%;display: inline-flex;flex-direction: column;justify-content: end">
<p style="color: black;font-weight: bold;font-size: 20px;margin: 0">·</p>
</div>
<a-select showArrow :disabled="disableMetricSelectOp"
v-model:value="selectedMetricRelationOpValue"
:filter-option="filterOption"
:options="selectMetricRelationOpList" @change=""
style="width: 100px;margin: 0"/>
</a-space>
</el-row>
</div>
</template>
<style scoped>
<style scoped lang="scss">
.editorAreaOuter {
width: 100%;
@use '@/assets/styles/editorToolbarBtn.scss';
.editorOperationArea {
height: 100%;
position: relative;
display: inline-flex;
flex-direction: column;
justify-content: start;
margin-bottom: 5px;
border-left: 3px solid #202241;
padding-left: 5px;
}
.editorAreaInner {
width: calc(100% - 30px);
height: calc(100% - 10px);
position: absolute;
top: 10px;
left: 15px;
}
.editorTopRightToolBarBtn {
margin: 0;
padding: 0 8px 0 8px;
border: 0
}
</style>

View File

@ -0,0 +1,224 @@
<script setup>
import {FunctionOutlined} from '@ant-design/icons-vue';
import {ref, computed, defineAsyncComponent} from "vue";
const metricSelect = defineAsyncComponent(() => import("./metricSelect.vue"))
const globalFilterSelect = defineAsyncComponent(() => import("./globalFilterSelect.vue"))
const filterPropertiesSelect = defineAsyncComponent(() => import("@/components/bi/propertyCondition/propertiesConditionFilter.vue"))
const eventAllData = {
userProperties: [
{
name: "account_id",
alias: "账户id",
propertyType: 2,
},
{
name: "account_name",
alias: "账户名",
propertyType: 2,
},
{
name: "role_id",
alias: "角色id",
propertyType: 2,
},
{
name: "server_id",
alias: "服务器id",
propertyType: 2,
},
{
name: "currency_coin",
alias: "金币数",
propertyType: 1,
},
],
eventDescList: [
{
name: "role_login",
alias: "角色登录",
fields: [
{
name: "sign_day",
alias: "签到天数",
propertyType: 1,
}
]
},
{
name: "item_change",
alias: "item_change",
fields: [
{
name: "item_id",
alias: "item_id",
propertyType: 1,
},
{
name: "item_name",
alias: "item_name",
propertyType: 2,
},
{
name: "num_before",
alias: "num_before",
propertyType: 1,
},
{
name: "num_after",
alias: "num_after",
propertyType: 1,
},
{
name: "delta",
alias: "delta",
propertyType: 1,
}
]
},
{
name: "role_logout",
alias: "角色登出",
fields: [
{
name: "online_duration",
alias: "在线时长",
propertyType: 1,
}
]
}
]
}
const metricSelectMaxNo = ref(0)
const metricSelectList = ref([])
const onAddMetricSelect = () => {
const curNo = metricSelectMaxNo.value + 1
metricSelectMaxNo.value += curNo
metricSelectList.value.push(curNo)
}
const onDeleteMetricSelect = (no) => {
metricSelectList.value.splice(metricSelectList.value.indexOf(no), 1)
}
const globalFilterSelectMaxNo = ref(0)
const globalFilterSelectList = ref([])
const onAddGlobalFilterSelect = () => {
const curNo = globalFilterSelectMaxNo.value + 1
globalFilterSelectMaxNo.value += curNo
globalFilterSelectList.value.push(curNo)
}
const onDeleteGlobalFilterSelect = (no) => {
globalFilterSelectList.value.splice(globalFilterSelectList.value.indexOf(no), 1)
}
onMounted(() => {
onAddMetricSelect()
})
</script>
<template>
<div class="editorAreaOuter">
<div class="editorAreaInner">
<el-row style="height: 40px" align="middle">
<el-col :span="6">
<span style="font-weight: bold;">
分析指标
</span>
</el-col>
<el-col :span="10" :offset="8">
<el-row justify="end">
<el-button class="editorTopRightToolBarBtn" @click="onAddMetricSelect">
<el-icon :size="20">
<Plus/>
</el-icon>
</el-button>
<el-button class="editorTopRightToolBarBtn">
<FunctionOutlined style="font-size: 20px"/>
</el-button>
</el-row>
</el-col>
</el-row>
<el-row style="width: 100%;min-height: 70px;">
<template v-for="(no,index) in metricSelectList" :key="no">
<metricSelect :index="no" :canDelete="(metricSelectList.length > 1)"
:onDeleteMetricSelect="onDeleteMetricSelect" :eventAllData="eventAllData"/>
</template>
</el-row>
<el-row style="height: 30px"></el-row>
<el-row style="height: 40px" align="middle">
<el-col :span="6">
<span style="font-weight: bold;">
全局筛选
</span>
</el-col>
<el-col :span="10" :offset="8">
<el-row justify="end">
<el-button class="editorTopRightToolBarBtn" @click="onAddGlobalFilterSelect">
<el-icon :size="20">
<Plus/>
</el-icon>
</el-button>
</el-row>
</el-col>
</el-row>
<el-row style="width: 100%;min-height: 0px;">
<filterPropertiesSelect/>
<template v-for="(no,index) in globalFilterSelectList" :key="no">
<globalFilterSelect :index="no" :onDeleteMetricSelect="onDeleteGlobalFilterSelect"/>
</template>
</el-row>
<el-row style="height: 1px"></el-row>
<el-row style="height: 40px" align="middle">
<el-col :span="6">
<span style="font-weight: bold;">
分组项
</span>
</el-col>
<el-col :span="10" :offset="8">
<el-row justify="end">
<el-button class="editorTopRightToolBarBtn">
<el-icon :size="20">
<Plus/>
</el-icon>
</el-button>
</el-row>
</el-col>
</el-row>
</div>
</div>
</template>
<style scoped lang="scss">
@use '@/assets/styles/editorToolbarBtn.scss';
.editorAreaOuter {
width: 100%;
height: 100%;
position: relative;
}
.editorAreaInner {
width: calc(100% - 30px);
height: calc(100% - 10px);
position: absolute;
top: 10px;
left: 15px;
}
</style>

View File

@ -0,0 +1,224 @@
<script setup>
import {computed, ref} from "vue";
const props = defineProps({
index: 0,
canDelete: true,
onDeleteMetricSelect: null,
eventAllData: {},
})
const eventAllData = props.eventAllData
const selectEventValue = ref('')
const selectEventOptions = ref([])
eventAllData.eventDescList.forEach((eventInfo) => {
let addOptionInfo = {
value: eventInfo.name,
label: eventInfo.name,
}
if (eventInfo.alias !== undefined && eventInfo.alias !== "") {
addOptionInfo.label = eventInfo.alias
}
selectEventOptions.value.push(addOptionInfo)
})
selectEventValue.value = selectEventOptions.value[0].label
const selectedEventInfo = ref({})
const defaultSelectEventRelationMetrics = {
label: "预置指标",
options: [
{
value: "totalCount",
label: "总次数",
opList: []
},
{
value: "triggerUserCount",
label: "触发用户数",
opList: []
},
{
value: "userAvgCount",
label: "人均次数",
opList: []
}
]
}
const defaultMetricTypeNumberOpList1 = [
"总和", "均值", "人均值", "中位数", "最大值", "最小值", "去重数", "方差", "标准差",
"99分位数", "95分位数", "90分位数", "85分位数", "80分位数", "75分位数", "70分位数",
"60分位数", "50分位数", "40分位数", "30分位数", "20分位数", "10分位数", "5分位数"
]
const defaultMetricTypeNumberOpList2 = [
"totalCount", "avg", "avgPerUser", "median", "max", "min", "distinct", "variance", "standardDeviation",
"99qualtile", "95qualtile", "90qualtile", "85qualtile", "80qualtile", "75qualtile", "70qualtile",
"60qualtile", "50qualtile", "40qualtile", "30qualtile", "20qualtile", "10qualtile", "5qualtile"
]
const defaultMetricTypeNumberOpList = []
const defaultMetricTypeStringOpList = [{value: "distinct", label: "去重数"}]
for (let i = 0; i < defaultMetricTypeNumberOpList1.length; i++) {
defaultMetricTypeNumberOpList.push({
value: defaultMetricTypeNumberOpList2[i],
label: defaultMetricTypeNumberOpList1[i]
})
}
// console.log("oplist:", defaultMetricTypeNumberOpList)
const selectedEventRelationMetricValue = ref('')
const disableMetricSelectOp = ref(true)
const selectEventRelationMetrics = computed(() => {
const eventInfo = eventAllData.eventDescList.find((v, i) => v.alias === selectEventValue.value)
if (!eventInfo) {
return [defaultSelectEventRelationMetrics]
}
// console.log("", eventInfo)
selectedEventInfo.value = eventInfo
let userMetrics = {
label: "用户属性",
options: []
}
let eventMetrics = {
label: "事件属性",
options: []
}
eventInfo.fields.forEach(field => {
let opList = []
if (field.propertyType === 1) {
opList = defaultMetricTypeNumberOpList
} else if (field.propertyType === 2) {
opList = defaultMetricTypeStringOpList
}
eventMetrics.options.push({
value: field.name,
label: field.alias,
opList: opList
})
})
eventAllData.userProperties.forEach(field => {
let opList = []
if (field.propertyType === 1) {
opList = defaultMetricTypeNumberOpList
} else if (field.propertyType === 2) {
opList = defaultMetricTypeStringOpList
}
userMetrics.options.push({
value: field.name,
label: field.alias,
opList: opList
})
})
return [defaultSelectEventRelationMetrics, eventMetrics, userMetrics,]
})
const selectedMetricRelationOpValue = ref('')
const selectMetricRelationOpList = computed(() => {
// console.log("selectEventRelationMetrics:", selectedEventRelationMetricValue.value)
// console.log("selectEventRelationMetrics:", selectEventRelationMetrics.value)
let opList = []
selectEventRelationMetrics.value.find((v, idx) => {
const selectedMetric = v.options.find((v1, idx1) => {
return v1.value === selectedEventRelationMetricValue.value
})
if (selectedMetric) {
opList = selectedMetric.opList
return true
}
return false
})
// console.log("oplist", opList)
selectedMetricRelationOpValue.value = ''
disableMetricSelectOp.value = opList.length === 0;
return opList
})
const onSelectEvent = (value) => {
}
const filterOption = (input, option) => {
return option.value.filter((item) => {
if (item.options && item.options.length > 0) {
return item.options.filter(opt => {
return opt.includes(input)
})
}
return item.label.includes(input)
})
};
onSelectEvent(selectEventValue.value)
</script>
<template>
<div class="editorOperationArea">
<!-- <div-->
<!-- style="background-color: #202241;margin-right: 5px;border-radius: 5px;;width: 3px;height: 70px;display: inline-flex;justify-content: center;align-items: center;">-->
<!-- &lt;!&ndash; <p style="font-weight: bold;color: white;margin: 0">1</p>&ndash;&gt;-->
<!-- </div>-->
<el-row>
<el-row>
<el-row justify="end" style="width: 100%">
<a-space align="end" style="float: right">
<el-button class="editorTopRightToolBarBtn" :disabled="(!canDelete)" @click="onDeleteMetricSelect(index)">
<el-icon :size="20">
<Delete/>
</el-icon>
</el-button>
</a-space>
</el-row>
<a-space :size="5">
<a-select showArrow :show-search="true" v-model:value="selectEventValue" :options="selectEventOptions"
@change="onSelectEvent" :filter-option="filterOption"
style="width: 100px;margin: 0"/>
<div
style="background-color: #202241;border-radius: 5px;width: 25px;height: 25px;display: flex;justify-content: center;align-items: center;">
<p style="color: white;margin: 0"></p>
</div>
<a-select showArrow show-search v-model:value="selectedEventRelationMetricValue"
:options="selectEventRelationMetrics" :filter-option="filterOption" @change=""
style="width: 100px;margin: 0"/>
<!-- <div-->
<!-- style="background-color: #202241;border-radius: 5px;;width: 25px;height: 25px;display: flex;justify-content: center;align-items: center;">-->
<!-- <p style="color: white;margin: 0">.</p>-->
<!-- </div>-->
<div
style="height: 100%;display: inline-flex;flex-direction: column;justify-content: end">
<p style="color: black;font-weight: bold;font-size: 20px;margin: 0">·</p>
</div>
<a-select showArrow :disabled="disableMetricSelectOp"
v-model:value="selectedMetricRelationOpValue"
:filter-option="filterOption"
:options="selectMetricRelationOpList" @change=""
style="width: 100px;margin: 0"/>
</a-space>
</el-row>
</el-row>
</div>
</template>
<style scoped lang="scss">
@use '@/assets/styles/editorToolbarBtn.scss';
.editorOperationArea {
height: 100%;
display: inline-flex;
flex-direction: row;
align-items: center;
margin-bottom: 5px;
border-left: 3px solid #202241;
padding-left: 5px;
}
</style>

View File

@ -11,7 +11,9 @@ defineProps({
<template>
<div class="editorContainer .clearfix">
<div class="editorOperationArea">
<component :is="editorAreaInfo.editorPane"/>
<el-scrollbar>
<component :is="editorAreaInfo.editorPane"/>
</el-scrollbar>
</div>
<div class="editorFinishArea">
<div class="editorFinishBtns">