Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
S
saas-dml
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
saas-dml
Commits
37cd14b1
提交
37cd14b1
authored
2月 20, 2025
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
chore: update
上级
850d249d
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
91 行增加
和
32 行删除
+91
-32
RFMRuleItem.vue
src/components/rule/RFMRuleItem.vue
+76
-23
LabelRuleDialog.vue
src/modules/label/components/LabelRuleDialog.vue
+15
-9
没有找到文件。
src/components/rule/RFMRuleItem.vue
浏览文件 @
37cd14b1
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
import
{
QuestionFilled
}
from
'@element-plus/icons-vue'
import
{
QuestionFilled
}
from
'@element-plus/icons-vue'
import
{
useUserAttr
,
useMetaEvent
,
useUserAttrRange
}
from
'@/composables/useRFMData'
import
{
useUserAttr
,
useMetaEvent
,
useUserAttrRange
}
from
'@/composables/useRFMData'
import
{
searchMetaMemberAttrs
}
from
'@/api/base'
import
{
searchMetaMemberAttrs
}
from
'@/api/base'
import
{
cloneDeep
}
from
'lodash-es'
defineProps
<
{
label
:
string
}
>
()
defineProps
<
{
label
:
string
}
>
()
const
form
=
defineModel
<
any
>
()
const
form
=
defineModel
<
any
>
()
...
@@ -9,12 +10,12 @@ const form = defineModel<any>()
...
@@ -9,12 +10,12 @@ const form = defineModel<any>()
const
ruleList
=
[
const
ruleList
=
[
{
label
:
'属性值平均法'
,
value
:
'101'
,
basis
:
[
'1'
]
},
{
label
:
'属性值平均法'
,
value
:
'101'
,
basis
:
[
'1'
]
},
{
label
:
'属性值分类法'
,
value
:
'102'
,
basis
:
[
'1'
]
},
{
label
:
'属性值分类法'
,
value
:
'102'
,
basis
:
[
'1'
]
},
{
label
:
'事件发生次数平均法'
,
value
:
'201'
,
basis
:
[
'2'
]
}
{
label
:
'事件发生次数平均法'
,
value
:
'201'
,
basis
:
[
'2'
]
}
,
]
]
const
defaultLevel
=
[
const
defaultLevel
=
[
{
level
:
'高'
,
value
:
''
},
{
level
:
'高'
,
value
:
''
},
{
level
:
'低'
,
value
:
''
}
{
level
:
'低'
,
value
:
''
}
,
]
]
const
defaultScore
=
[
const
defaultScore
=
[
...
@@ -22,7 +23,7 @@ const defaultScore = [
...
@@ -22,7 +23,7 @@ const defaultScore = [
{
score
:
2
,
min_value
:
''
,
max_value
:
''
},
{
score
:
2
,
min_value
:
''
,
max_value
:
''
},
{
score
:
3
,
min_value
:
''
,
max_value
:
''
},
{
score
:
3
,
min_value
:
''
,
max_value
:
''
},
{
score
:
4
,
min_value
:
''
,
max_value
:
''
},
{
score
:
4
,
min_value
:
''
,
max_value
:
''
},
{
score
:
5
,
min_value
:
''
,
max_value
:
''
}
{
score
:
5
,
min_value
:
''
,
max_value
:
''
}
,
]
]
onMounted
(()
=>
{
onMounted
(()
=>
{
...
@@ -33,8 +34,8 @@ onMounted(() => {
...
@@ -33,8 +34,8 @@ onMounted(() => {
event_id
:
'-1'
,
event_id
:
'-1'
,
attr_id
:
''
,
attr_id
:
''
,
attr_type
:
''
,
attr_type
:
''
,
config
:
[...
defaultScore
]
,
config
:
cloneDeep
(
defaultScore
)
,
extend_config
:
{
default_score_config
:
{
switch
:
false
,
score
:
undefined
}
}
extend_config
:
{
default_score_config
:
{
switch
:
false
,
score
:
undefined
}
}
,
},
},
form
.
value
form
.
value
)
)
...
@@ -45,7 +46,7 @@ const { metaEventList, fetchMetaEventList } = useMetaEvent()
...
@@ -45,7 +46,7 @@ const { metaEventList, fetchMetaEventList } = useMetaEvent()
const
{
userAttrRange
,
fetchUserAttrRange
}
=
useUserAttrRange
()
const
{
userAttrRange
,
fetchUserAttrRange
}
=
useUserAttrRange
()
const
currentRuleList
=
computed
(()
=>
{
const
currentRuleList
=
computed
(()
=>
{
return
ruleList
.
filter
(
item
=>
item
.
basis
.
includes
(
form
.
value
.
basis
))
return
ruleList
.
filter
(
(
item
)
=>
item
.
basis
.
includes
(
form
.
value
.
basis
))
})
})
const
currentMetaEventList
=
computed
(()
=>
{
const
currentMetaEventList
=
computed
(()
=>
{
...
@@ -58,21 +59,31 @@ function handleBasisChange(value: any) {
...
@@ -58,21 +59,31 @@ function handleBasisChange(value: any) {
}
else
{
}
else
{
form
.
value
.
rule
=
'201'
form
.
value
.
rule
=
'201'
}
}
form
.
value
.
attr_id
=
''
// 清空数据
Object
.
assign
(
form
.
value
,
cloneDeep
({
event_id
:
'-1'
,
attr_id
:
''
,
attr_type
:
''
,
config
:
defaultScore
,
extend_config
:
{
default_score_config
:
{
switch
:
false
,
score
:
undefined
}
},
})
)
handleRuleChange
(
form
.
value
.
rule
)
handleRuleChange
(
form
.
value
.
rule
)
}
}
function
handleRuleChange
(
value
:
any
)
{
function
handleRuleChange
(
value
:
any
)
{
if
(
value
===
'102'
)
{
if
(
value
===
'102'
)
{
form
.
value
.
config
=
[...
defaultLevel
]
form
.
value
.
config
=
cloneDeep
(
defaultLevel
)
}
else
{
}
else
{
form
.
value
.
config
=
[...
defaultScore
]
form
.
value
.
config
=
cloneDeep
(
defaultScore
)
}
}
form
.
value
.
attr_id
=
''
form
.
value
.
attr_id
=
''
}
}
function
handleAttrChange
(
value
:
any
)
{
function
handleAttrChange
(
value
:
any
)
{
form
.
value
.
attr_type
=
userAttrList
.
value
.
find
(
item
=>
item
.
id
===
value
)?.
type
form
.
value
.
attr_type
=
userAttrList
.
value
.
find
(
(
item
)
=>
item
.
id
===
value
)?.
type
}
}
const
options
=
ref
<
{
label
:
string
;
value
:
string
}[]
>
([])
const
options
=
ref
<
{
label
:
string
;
value
:
string
}[]
>
([])
...
@@ -81,7 +92,7 @@ async function remoteMethod(search: string = '') {
...
@@ -81,7 +92,7 @@ async function remoteMethod(search: string = '') {
options
.
value
=
[]
options
.
value
=
[]
if
(
form
.
value
.
attr_id
)
{
if
(
form
.
value
.
attr_id
)
{
loading
.
value
=
true
loading
.
value
=
true
await
searchMetaMemberAttrs
({
search
,
member_meta_id
:
form
.
value
.
attr_id
,
per_page
:
100
}).
then
(
res
=>
{
await
searchMetaMemberAttrs
({
search
,
member_meta_id
:
form
.
value
.
attr_id
,
per_page
:
100
}).
then
(
(
res
)
=>
{
options
.
value
=
res
.
data
.
list
.
map
((
item
:
any
)
=>
{
options
.
value
=
res
.
data
.
list
.
map
((
item
:
any
)
=>
{
return
{
label
:
item
.
attr_value
,
value
:
item
.
attr_value
}
return
{
label
:
item
.
attr_value
,
value
:
item
.
attr_value
}
})
})
...
@@ -96,7 +107,7 @@ function querySearch(queryString: string, cb: any) {
...
@@ -96,7 +107,7 @@ function querySearch(queryString: string, cb: any) {
watch
(
watch
(
()
=>
form
.
value
.
attr_id
,
()
=>
form
.
value
.
attr_id
,
attrId
=>
{
(
attrId
)
=>
{
if
(
form
.
value
.
rule
===
'102'
)
{
if
(
form
.
value
.
rule
===
'102'
)
{
remoteMethod
()
remoteMethod
()
}
else
{
}
else
{
...
@@ -120,7 +131,7 @@ const a = [
...
@@ -120,7 +131,7 @@ const a = [
{
id
:
'002'
,
label
:
'1500'
},
{
id
:
'002'
,
label
:
'1500'
},
{
id
:
'003'
,
label
:
'3000'
},
{
id
:
'003'
,
label
:
'3000'
},
{
id
:
'004'
,
label
:
'2200'
},
{
id
:
'004'
,
label
:
'2200'
},
{
id
:
'005'
,
label
:
'1800'
}
{
id
:
'005'
,
label
:
'1800'
}
,
]
]
const
defaultOptions
=
Array
.
from
({
length
:
5
}).
map
((
_
,
index
)
=>
({
value
:
index
+
1
,
label
:
index
+
1
}))
const
defaultOptions
=
Array
.
from
({
length
:
5
}).
map
((
_
,
index
)
=>
({
value
:
index
+
1
,
label
:
index
+
1
}))
...
@@ -147,11 +158,23 @@ const defaultOptions = Array.from({ length: 5 }).map((_, index) => ({ value: ind
...
@@ -147,11 +158,23 @@ const defaultOptions = Array.from({ length: 5 }).map((_, index) => ({ value: ind
</el-radio-group>
</el-radio-group>
<p
style=
"margin-left: 10px"
>
计算规则:
</p>
<p
style=
"margin-left: 10px"
>
计算规则:
</p>
<el-select
v-model=
"form.rule"
style=
"width: 170px"
@
change=
"handleRuleChange"
>
<el-select
v-model=
"form.rule"
style=
"width: 170px"
@
change=
"handleRuleChange"
>
<el-option
v-for=
"item in currentRuleList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
></el-option>
<el-option
v-for=
"item in currentRuleList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
></el-option>
</el-select>
</el-select>
<div
class=
"rfm-tips"
>
<div
class=
"rfm-tips"
>
<el-popover
popper-class=
"rfm-popover"
placement=
"right"
title=
"属性值平均法"
:width=
"400"
trigger=
"hover"
v-if=
"form.rule == '101'"
>
<el-popover
<p>
用于计算选中属性的平均值,通过对选定的字段中的所有记录进行数值相加,然后除以记录的数量来计算的。主要针对“数字”和“整数”两种字段类型。
</p>
popper-class=
"rfm-popover"
placement=
"right"
title=
"属性值平均法"
:width=
"400"
trigger=
"hover"
v-if=
"form.rule == '101'"
>
<p>
用于计算选中属性的平均值,通过对选定的字段中的所有记录进行数值相加,然后除以记录的数量来计算的。主要针对“数字”和“整数”两种字段类型。
</p>
<p>
举例:
</p>
<p>
举例:
</p>
<el-table
:data=
"a"
border
>
<el-table
:data=
"a"
border
>
<el-table-column
prop=
"id"
label=
"用户ID"
/>
<el-table-column
prop=
"id"
label=
"用户ID"
/>
...
@@ -162,13 +185,25 @@ const defaultOptions = Array.from({ length: 5 }).map((_, index) => ({ value: ind
...
@@ -162,13 +185,25 @@ const defaultOptions = Array.from({ length: 5 }).map((_, index) => ({ value: ind
<el-icon><QuestionFilled
/></el-icon>
<el-icon><QuestionFilled
/></el-icon>
</
template
>
</
template
>
</el-popover>
</el-popover>
<el-popover
popper-class=
"rfm-popover"
placement=
"right"
title=
"属性值分类法"
:width=
"400"
trigger=
"hover"
v-if=
"form.rule == '102'"
>
<el-popover
popper-class=
"rfm-popover"
placement=
"right"
title=
"属性值分类法"
:width=
"400"
trigger=
"hover"
v-if=
"form.rule == '102'"
>
<p>
将数据的属性值按照一定的规则或特性进行分类,本系统中分了“高”和“低”两类。主要针对“字符串”的字段类型。
</p>
<p>
将数据的属性值按照一定的规则或特性进行分类,本系统中分了“高”和“低”两类。主要针对“字符串”的字段类型。
</p>
<
template
#
reference
>
<
template
#
reference
>
<el-icon><QuestionFilled
/></el-icon>
<el-icon><QuestionFilled
/></el-icon>
</
template
>
</
template
>
</el-popover>
</el-popover>
<el-popover
popper-class=
"rfm-popover"
placement=
"right"
title=
"事件发生次数平均法"
:width=
"400"
trigger=
"hover"
v-if=
"form.rule == '201'"
>
<el-popover
popper-class=
"rfm-popover"
placement=
"right"
title=
"事件发生次数平均法"
:width=
"400"
trigger=
"hover"
v-if=
"form.rule == '201'"
>
<p>
分析事件发生频率的方法,即通过计算用户事件发生的平均次数。
</p>
<p>
分析事件发生频率的方法,即通过计算用户事件发生的平均次数。
</p>
<
template
#
reference
>
<
template
#
reference
>
<el-icon><QuestionFilled
/></el-icon>
<el-icon><QuestionFilled
/></el-icon>
...
@@ -177,19 +212,37 @@ const defaultOptions = Array.from({ length: 5 }).map((_, index) => ({ value: ind
...
@@ -177,19 +212,37 @@ const defaultOptions = Array.from({ length: 5 }).map((_, index) => ({ value: ind
</div>
</div>
<el-select
v-model=
"form.event_id"
placeholder=
"选择事件"
style=
"width: 160px"
v-if=
"form.basis === '2'"
>
<el-select
v-model=
"form.event_id"
placeholder=
"选择事件"
style=
"width: 160px"
v-if=
"form.basis === '2'"
>
<el-option
v-for=
"item in currentMetaEventList"
:key=
"item.event_id"
:label=
"item.event_name"
:value=
"item.event_id"
></el-option>
<el-option
v-for=
"item in currentMetaEventList"
:key=
"item.event_id"
:label=
"item.event_name"
:value=
"item.event_id"
></el-option>
</el-select>
</el-select>
<el-select
v-model=
"form.attr_id"
placeholder=
"选择属性"
style=
"width: 160px"
@
change=
"handleAttrChange"
v-else
>
<el-select
v-model=
"form.attr_id"
placeholder=
"选择属性"
style=
"width: 160px"
@
change=
"handleAttrChange"
v-else
>
<el-option
v-for=
"item in userAttrList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
<el-option
v-for=
"item in userAttrList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
</el-select>
</el-select>
<div
style=
"flex: 1; display: flex; justify-content: space-between"
v-if=
"form.basis == 1 && form.rule != '102' && form.attr_id"
>
<div
<p>
最小值:{{ userAttrRange.min }}
<br
/>
最大值:{{ userAttrRange.max }}
<br
/>
"0"值数量:{{ userAttrRange.zero_count }}
</p>
style=
"flex: 1; display: flex; justify-content: space-between"
<p>
平均值:{{ userAttrRange.avg }}
<br
/>
中位数:{{ userAttrRange.median }}
<br
/>
中位数(不含0):{{ userAttrRange.no_zero_median }}
</p>
v-if=
"form.basis == 1 && form.rule != '102' && form.attr_id"
>
<p>
最小值:{{ userAttrRange.min }}
<br
/>
最大值:{{ userAttrRange.max }}
<br
/>
"0"值数量:{{
userAttrRange.zero_count
}}
</p>
<p>
平均值:{{ userAttrRange.avg }}
<br
/>
中位数:{{ userAttrRange.median }}
<br
/>
中位数(不含0):{{
userAttrRange.no_zero_median
}}
</p>
</div>
</div>
</div>
</div>
<div
class=
"rfm-header-extra"
v-if=
"form.rule === '101' && form.extend_config"
>
<div
class=
"rfm-header-extra"
v-if=
"form.rule === '101' && form.extend_config"
>
<p>
未匹配数据默认赋值
</p>
<p>
未匹配数据默认赋值
</p>
<el-select-v2
v-model=
"form.extend_config.default_score_config.score"
:options=
"defaultOptions"
style=
"width: 100px; margin: 0 10px"
clearable
/>
<el-select-v2
v-model=
"form.extend_config.default_score_config.score"
:options=
"defaultOptions"
style=
"width: 100px; margin: 0 10px"
clearable
/>
<el-switch
v-model=
"form.extend_config.default_score_config.switch"
></el-switch>
<el-switch
v-model=
"form.extend_config.default_score_config.switch"
></el-switch>
</div>
</div>
<div
class=
"rfm-body"
>
<div
class=
"rfm-body"
>
...
...
src/modules/label/components/LabelRuleDialog.vue
浏览文件 @
37cd14b1
...
@@ -31,13 +31,13 @@ const statusList = useMapStore().getMapValuesByKey('system_status')
...
@@ -31,13 +31,13 @@ const statusList = useMapStore().getMapValuesByKey('system_status')
const
formRef
=
$ref
<
FormInstance
>
()
const
formRef
=
$ref
<
FormInstance
>
()
const
form
=
reactive
({
const
form
:
any
=
reactive
({
id
:
''
,
id
:
''
,
rules
:
undefined
rules
:
undefined
,
})
})
function
fetchInfo
()
{
function
fetchInfo
()
{
getLabelRule
({
id
:
props
.
data
.
id
}).
then
(
res
=>
{
getLabelRule
({
id
:
props
.
data
.
id
}).
then
(
(
res
)
=>
{
const
{
detail
}
=
res
.
data
const
{
detail
}
=
res
.
data
let
rules
=
detail
.
rules
let
rules
=
detail
.
rules
...
@@ -47,9 +47,9 @@ function fetchInfo() {
...
@@ -47,9 +47,9 @@ function fetchInfo() {
event_attr_rule
:
{
event_attr_rule
:
{
current_logic_operate
:
'and'
,
current_logic_operate
:
'and'
,
happen_info
:
{
is_happened
:
true
,
event_id
:
'-1'
,
event_name
:
'所有事件'
,
attr_list
:
[]
},
happen_info
:
{
is_happened
:
true
,
event_id
:
'-1'
,
event_name
:
'所有事件'
,
attr_list
:
[]
},
trigger_info
:
{
operate
:
''
,
operate_name
:
''
,
value
:
''
}
trigger_info
:
{
operate
:
''
,
operate_name
:
''
,
value
:
''
}
,
},
},
tag_rule
:
{
event_id
:
''
,
event_name
:
''
,
attr_id
:
''
,
attr_name
:
''
,
type
:
1
,
value
:
undefined
}
tag_rule
:
{
event_id
:
''
,
event_name
:
''
,
attr_id
:
''
,
attr_name
:
''
,
type
:
1
,
value
:
undefined
}
,
}
}
}
}
if
(
detail
.
label
==
'3'
)
{
if
(
detail
.
label
==
'3'
)
{
...
@@ -57,9 +57,9 @@ function fetchInfo() {
...
@@ -57,9 +57,9 @@ function fetchInfo() {
event_attr_rule
:
{
event_attr_rule
:
{
current_logic_operate
:
'and'
,
current_logic_operate
:
'and'
,
happen_info
:
{
is_happened
:
true
,
event_id
:
'-1'
,
event_name
:
'所有事件'
,
attr_list
:
[]
},
happen_info
:
{
is_happened
:
true
,
event_id
:
'-1'
,
event_name
:
'所有事件'
,
attr_list
:
[]
},
trigger_info
:
{
operate
:
''
,
operate_name
:
''
,
value
:
''
}
trigger_info
:
{
operate
:
''
,
operate_name
:
''
,
value
:
''
}
,
},
},
tag_rule
:
{
way
:
''
}
tag_rule
:
{
way
:
''
}
,
}
}
}
}
if
(
detail
.
label
===
'4'
)
{
if
(
detail
.
label
===
'4'
)
{
...
@@ -75,7 +75,7 @@ function fetchInfo() {
...
@@ -75,7 +75,7 @@ function fetchInfo() {
rules
=
{
rules
=
{
user_attr_rule
:
{
current_logic_operate
:
'and'
,
items
:
[]
},
user_attr_rule
:
{
current_logic_operate
:
'and'
,
items
:
[]
},
event_attr_rule
:
{
current_logic_operate
:
'and'
,
items
:
[]
},
event_attr_rule
:
{
current_logic_operate
:
'and'
,
items
:
[]
},
user_action_rule
:
{
current_logic_operate
:
'and'
,
items
:
[]
}
user_action_rule
:
{
current_logic_operate
:
'and'
,
items
:
[]
}
,
}
}
}
}
}
}
...
@@ -100,9 +100,15 @@ function handleUpdate() {
...
@@ -100,9 +100,15 @@ function handleUpdate() {
// item.value = Array.isArray(item.value) ? item.value.join(',') : item.value
// item.value = Array.isArray(item.value) ? item.value.join(',') : item.value
// return item
// return item
// })
// })
let
rules
=
form
.
rules
if
(
props
.
data
.
label
==
'1'
&&
rules
?.
length
>
0
)
{
rules
=
rules
.
map
((
item
:
any
,
index
:
number
)
=>
{
return
{
...
item
,
level
:
index
}
})
}
const
params
=
{
const
params
=
{
id
:
form
.
id
,
id
:
form
.
id
,
rules
:
JSON
.
stringify
(
form
.
rules
)
rules
:
JSON
.
stringify
(
rules
),
// user_attr_rule: JSON.stringify([{ ...form.user_attr_rule, items: attrRuleItems }]),
// user_attr_rule: JSON.stringify([{ ...form.user_attr_rule, items: attrRuleItems }]),
// event_attr_rule: JSON.stringify([{ ...form.event_attr_rule, items: eventRuleItems }])
// event_attr_rule: JSON.stringify([{ ...form.event_attr_rule, items: eventRuleItems }])
}
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论