提交 4e99f391 authored 作者: 王鹏飞's avatar 王鹏飞

chore: RFM优化

上级 68fd12c1
...@@ -19,3 +19,8 @@ export function getMemberAttrRange(params: { member_meta_id: string }) { ...@@ -19,3 +19,8 @@ export function getMemberAttrRange(params: { member_meta_id: string }) {
export function getRfmRes() { export function getRfmRes() {
return httpRequest.get('/api/lab/v1/experiment/group/bda-rfm-res') return httpRequest.get('/api/lab/v1/experiment/group/bda-rfm-res')
} }
// 获取最近一次Rfm标签的统计结果
export function getRfmStatistics(params: { tag_id: string }) {
return httpRequest.get('/api/lab/v1/experiment/tag/bda-rfm-statistics-result', { params })
}
<script setup lang="ts"> <script setup lang="ts">
import type { TagRule } from '@/types' import type { TagRule } from '@/types'
import { PriceTag, Plus, CloseBold } from '@element-plus/icons-vue' import { PriceTag, Plus, CloseBold, QuestionFilled } from '@element-plus/icons-vue'
import { useTag } from '@/composables/useAllData' import { useTag } from '@/composables/useAllData'
import { useRfmRes } from '@/composables/useRFMData' import { useRfmRes } from '@/composables/useRFMData'
...@@ -38,6 +38,23 @@ function handleRfmChange(rfmKey: string, item: any) { ...@@ -38,6 +38,23 @@ function handleRfmChange(rfmKey: string, item: any) {
const found = rfmResList.value.find(item => item.frm_key === rfmKey) const found = rfmResList.value.find(item => item.frm_key === rfmKey)
item.rfm_value = found?.frm_value item.rfm_value = found?.frm_value
} }
const a = [
{ label: '重要价值用户', r: '高', f: '高', m: '高', group: '最近一次消费时间近,消费频率高,消费金额大', guide: '重点维系和保持' },
{ label: '重要发展用户', r: '高', f: '低', m: '高', group: '最近一次消费时间较近,消费频率高,消费金额大', guide: '促进其持续消费' },
{ label: '重要保持用户', r: '低', f: '高', m: '高', group: '最近一次消费时间较远,消费频率低,消费金额大', guide: '尽快采取措施挽回' },
{ label: '重要挽留用户', r: '低', f: '低', m: '高', group: '最近一次消费时间远,消费频率高,消费金额低', guide: '引导其提升消费水平' },
{ label: '一般价值用户', r: '高', f: '高', m: '低', group: '最近一次消费时间近,消费频率低,消费金额大', guide: '尝试提高其消费频率' },
{
label: '一般发展用户',
r: '高',
f: '低',
m: '低',
group: '最近一次消费时间近,消费频率高,消费金额低',
guide: '可考虑通过提升产品或服务质量来提高其消费水平'
},
{ label: '一般保持用户', r: '低', f: '高', m: '低', group: '最近一次消费时间远,消费频率低,消费金额低', guide: '根据资源和战略考虑是否进行挽回' },
{ label: '一般挽留用户', r: '低', f: '低', m: '低', group: '最近一次消费时间近,消费频率低,消费金额低', guide: '根据其消费习惯和变化进行适当调整' }
]
</script> </script>
<template> <template>
...@@ -58,13 +75,24 @@ function handleRfmChange(rfmKey: string, item: any) { ...@@ -58,13 +75,24 @@ function handleRfmChange(rfmKey: string, item: any) {
<el-select v-model="item.tag_id" style="width: 400px"> <el-select v-model="item.tag_id" style="width: 400px">
<el-option v-for="option in tagList" :key="option.id" :label="option.name" :value="option.id"></el-option> <el-option v-for="option in tagList" :key="option.id" :label="option.name" :value="option.id"></el-option>
</el-select> </el-select>
<el-select <template v-if="showRfm(item.tag_id)">
v-model="item.rfm_key" <el-select v-model="item.rfm_key" @change="value => handleRfmChange(value, item)" style="width: 200px; margin-left: 10px">
@change="value => handleRfmChange(value, item)" <el-option v-for="item in rfmResList" :key="item.frm_key" :label="item.frm_value" :value="item.frm_key"></el-option>
v-if="showRfm(item.tag_id)" </el-select>
style="width: 200px; margin-left: 10px"> <el-popover popper-class="rfm-popover" placement="top" :width="800" trigger="hover">
<el-option v-for="item in rfmResList" :key="item.frm_key" :label="item.frm_value" :value="item.frm_key"></el-option> <el-table :data="a" border stripe>
</el-select> <el-table-column prop="label" label="标签值" width="110" />
<el-table-column prop="r" label="R" width="40" />
<el-table-column prop="f" label="F" width="40" />
<el-table-column prop="m" label="M" width="40" />
<el-table-column prop="group" label="运营群组" />
<el-table-column prop="guide" label="营销策略建议" />
</el-table>
<template #reference>
<el-icon><QuestionFilled /></el-icon>
</template>
</el-popover>
</template>
</el-form-item> </el-form-item>
</div> </div>
<el-button text :icon="CloseBold" @click="handleRemove(tagRule.items, index)"></el-button> <el-button text :icon="CloseBold" @click="handleRemove(tagRule.items, index)"></el-button>
......
<script setup lang="ts"> <script setup lang="ts">
import RFMRuleItem from './RFMRuleItem.vue' import RFMRuleItem from './RFMRuleItem.vue'
import { useRfmStatistics } from '@/composables/useRFMData'
const props = defineProps<{ tagId?: string }>()
const form = defineModel<any>({ const form = defineModel<any>({
default: { default: {
R: {}, R: {},
...@@ -8,10 +10,23 @@ const form = defineModel<any>({ ...@@ -8,10 +10,23 @@ const form = defineModel<any>({
M: {} M: {}
} }
}) })
const { rfmStatistics } = useRfmStatistics(props.tagId || '')
</script> </script>
<template> <template>
<RFMRuleItem label="R" v-model="form.R" /> <RFMRuleItem label="R" v-model="form.R">
<RFMRuleItem label="F" v-model="form.F" style="margin-top: 20px" /> <template #header-aside="{ data }">
<RFMRuleItem label="M" v-model="form.M" style="margin-top: 20px" /> <template v-if="data.rule === '101' && rfmStatistics.is_complete">R值计算结果为:{{ rfmStatistics.rfm_tag_res.r }} </template>
</template>
</RFMRuleItem>
<RFMRuleItem label="F" v-model="form.F" style="margin-top: 20px">
<template #header-aside="{ data }">
<template v-if="data.rule === '101' && rfmStatistics.is_complete">F值计算结果为:{{ rfmStatistics.rfm_tag_res.f }} </template>
</template>
</RFMRuleItem>
<RFMRuleItem label="M" v-model="form.M" style="margin-top: 20px">
<template #header-aside="{ data }">
<template v-if="data.rule === '101' && rfmStatistics.is_complete">M值计算结果为:{{ rfmStatistics.rfm_tag_res.m }} </template>
</template>
</RFMRuleItem>
</template> </template>
...@@ -116,8 +116,15 @@ const a = [ ...@@ -116,8 +116,15 @@ const a = [
<template> <template>
<el-card shadow="never"> <el-card shadow="never">
<template #header> <template #header>
<el-button circle type="primary" style="width: 32px; margin-right: 10px">{{ label }}</el-button> <div class="rfm-top">
{{ label }}值计算规则 <div>
<el-button circle type="primary" style="width: 32px; margin-right: 10px">{{ label }}</el-button>
{{ label }}值计算规则
</div>
<div>
<slot name="header-aside" :data="form"></slot>
</div>
</div>
</template> </template>
<div class="rfm-header"> <div class="rfm-header">
<p style="margin-right: 10px">{{ label }}值计算依据</p> <p style="margin-right: 10px">{{ label }}值计算依据</p>
...@@ -198,6 +205,11 @@ const a = [ ...@@ -198,6 +205,11 @@ const a = [
</template> </template>
<style lang="scss"> <style lang="scss">
.rfm-top {
display: flex;
align-items: center;
justify-content: space-between;
}
.rfm-header { .rfm-header {
display: flex; display: flex;
align-items: center; align-items: center;
......
import { getMemberAttrList, getEventAttrList, getMemberAttrRange, getRfmRes } from '@/api/rfm' import { getMemberAttrList, getEventAttrList, getMemberAttrRange, getRfmRes, getRfmStatistics } from '@/api/rfm'
// 用户属性类型 // 用户属性类型
export interface AttrType { export interface AttrType {
...@@ -67,3 +67,25 @@ export function useRfmRes() { ...@@ -67,3 +67,25 @@ export function useRfmRes() {
}) })
return { fetchRfmResList, rfmResList } return { fetchRfmResList, rfmResList }
} }
interface RfmStatistics {
is_complete: boolean
rfm_tag_res: {
r: number
f: number
m: number
}
}
const rfmStatistics = ref<RfmStatistics>({ is_complete: false, rfm_tag_res: { r: 0, f: 0, m: 0 } })
export function useRfmStatistics(tagId: string) {
async function fetchRfmStatistics() {
if (!tagId) return
await getRfmStatistics({ tag_id: tagId }).then((res: any) => {
rfmStatistics.value = res.data
})
}
onMounted(() => {
fetchRfmStatistics()
})
return { fetchRfmStatistics, rfmStatistics }
}
...@@ -146,7 +146,7 @@ function handleUpdate() { ...@@ -146,7 +146,7 @@ function handleUpdate() {
<!-- 事件指标 --> <!-- 事件指标 -->
<EventTargetRule v-model="form.rules" v-if="data.label == '3'"></EventTargetRule> <EventTargetRule v-model="form.rules" v-if="data.label == '3'"></EventTargetRule>
<!-- RFM模型 --> <!-- RFM模型 -->
<RFMRule v-model="form.rules" v-if="data.label == '4'"></RFMRule> <RFMRule v-model="form.rules" :tagId="form.id" v-if="data.label == '4'"></RFMRule>
<!-- 自定义 --> <!-- 自定义 -->
<CustomRule v-model="form.rules" v-if="data.label == '7'"></CustomRule> <CustomRule v-model="form.rules" v-if="data.label == '7'"></CustomRule>
<!-- 单属性 --> <!-- 单属性 -->
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论