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

feat: 新增匹配老师数据和清空用户数据

上级 37cd14b1
import httpRequest from '@/utils/axios'
// 获取实验试题列表
export function getExperimentQuestionList() {
return httpRequest.get('/api/lab/v1/student/experiment-question/list')
}
// 学生创建群组页面-获取老师维护的群组
export function getTeacherGroups(params?: { type?: string }) {
return httpRequest.get('/api/lab/v1/experiment/group/teacher-groups', { params })
}
// 学生创建标签页面-获取老师维护的标签
export function getTeacherTags() {
return httpRequest.get('/api/lab/v1/experiment/tag/teacher-tags')
}
// 学生创建营销物料页面-获取老师维护的营销物料
export function getTeacherMaterials(params?: { type?: string }) {
return httpRequest.get('/api/lab/v1/experiment/marketing-ai/teacher-materials', { params })
}
import type { Ref } from 'vue'
import { getExperimentQuestionList, getTeacherGroups, getTeacherTags, getTeacherMaterials } from '@/api/question'
import { useUserStore } from '@/stores/user'
type QuesitonItem = {
experiment_id: string
id: string
type: string
}
type OptionItem = {
id: string
name: string
}
type MaterialItem = {
id: string
name: string
type: string
content: ''
}
export function useQuestion(questionType: string | Ref<string>, type?: string) {
questionType = shallowRef(questionType)
const useStore = useUserStore()
// 试题列表
const questionList = ref<QuesitonItem[]>([])
const fetchQuestionList = async () => {
const res = await getExperimentQuestionList()
questionList.value = res.data.items
}
const hasQuestion = computed(() => {
return !!questionList.value.find((item) => item.type === questionType.value)
})
onMounted(async () => {
if (useStore.role?.id === 1) {
await fetchQuestionList()
}
if (hasQuestion.value) {
if (questionType.value == '202') await fetchTeacherTagList()
if (questionType.value == '301' || questionType.value == '302') await fetchTeacherGroupList()
if (['401', '402', '403', '404', '405', '406', '407', '408'].includes(questionType.value)) {
await fetchTeacherMaterialList()
}
}
})
const teacherGroupList = ref<OptionItem[]>([])
const fetchTeacherGroupList = async () => {
const res = await getTeacherGroups({ type })
teacherGroupList.value = res.data.items
}
const teacherTagList = ref<OptionItem[]>([])
const fetchTeacherTagList = async () => {
const res = await getTeacherTags()
teacherTagList.value = res.data.items
}
const teacherMaterialAllList = ref<MaterialItem[]>([])
const teacherMaterialList = computed(() => {
const questionTypes: any = {
'401': 1,
'402': 2,
'403': 3,
'404': 4,
'405': 5,
'406': 6,
'407': 7,
'408': 8,
}
return teacherMaterialAllList.value.filter((item) => item.type == questionTypes[questionType.value])
})
const fetchTeacherMaterialList = async () => {
const res = await getTeacherMaterials()
teacherMaterialAllList.value = res.data.items
}
return {
hasQuestion,
questionList,
fetchQuestionList,
teacherGroupList,
fetchTeacherGroupList,
teacherTagList,
fetchTeacherTagList,
teacherMaterialList,
fetchTeacherMaterialList,
}
}
......@@ -10,7 +10,7 @@ import {
updateDynamicGroup,
getGroupInfo,
createRFMGroup,
updateRFMGroup
updateRFMGroup,
} from '../api'
import UserRule from '@/components/rule/UserRule.vue'
import EventRule from '@/components/rule/EventRule.vue'
......@@ -18,6 +18,7 @@ import LabelRule from '@/components/rule/LabelRule.vue'
import UserActionRule from '@/components/rule/UserActionRule.vue'
import RFMRule from '@/components/rule/RFMRule.vue'
import { pick, merge } from 'lodash-es'
import { useQuestion } from '@/composables/useQuestion'
interface Props {
data: Partial<Group>
......@@ -47,7 +48,8 @@ const form: any = reactive({
event_attr_rule: { current_logic_operate: 'and', items: [] },
tag_rule: { current_logic_operate: 'and', items: [] },
user_action_rule: { current_logic_operate: 'and', items: [] },
rules: { R: {}, F: {}, M: {} }
rules: { R: {}, F: {}, M: {} },
teacher_id: '',
})
function genRuleData(data: any) {
......@@ -56,7 +58,7 @@ function genRuleData(data: any) {
}
function fetchInfo() {
if (!props.data.id) return
getGroupInfo({ id: props.data.id }).then(res => {
getGroupInfo({ id: props.data.id }).then((res) => {
const { detail } = res.data
const user_attr_rule = genRuleData(detail.user_attr_rule)
const event_attr_rule = genRuleData(detail.event_attr_rule)
......@@ -82,7 +84,7 @@ function fetchInfo() {
event_attr_rule: { ...event_attr_rule, items: eventRuleItems },
user_action_rule,
tag_rule: { ...tag_rule, items: tagRuleItems },
update_rule: { type: 1, info: 1 }
update_rule: { type: 1, info: 1 },
})
})
}
......@@ -90,9 +92,13 @@ function fetchInfo() {
watchEffect(() => fetchInfo())
const rules = ref<FormRules>({
name: [{ required: true, message: '请输入群组名称' }]
name: [{ required: true, message: '请输入群组名称' }],
})
const questionType = props.data.type === '1' ? '301' : '302'
const { hasQuestion, teacherGroupList } = useQuestion(questionType, props.data.type)
// 提交
function handleSubmit() {
formRef.value?.validate().then(() => (isUpdate.value ? handleUpdate() : handleCreate()))
......@@ -122,7 +128,7 @@ async function handleCreate() {
user_attr_rule: JSON.stringify([form.user_attr_rule]),
event_attr_rule: JSON.stringify([form.event_attr_rule]),
tag_rule: JSON.stringify([{ ...form.tag_rule, ...tagRule }]),
user_action_rule: JSON.stringify(form.user_action_rule)
user_action_rule: JSON.stringify(form.user_action_rule),
},
[
'name',
......@@ -132,7 +138,8 @@ async function handleCreate() {
'user_attr_rule',
'event_attr_rule',
'tag_rule',
'user_action_rule'
'user_action_rule',
'teacher_id',
]
)
await createDynamicGroup(params)
......@@ -142,9 +149,9 @@ async function handleCreate() {
{
...form,
update_rule: JSON.stringify(form.update_rule),
rules: JSON.stringify(form.rules)
rules: JSON.stringify(form.rules),
},
['name', 'status', 'update_status', 'update_rule', 'rules']
['name', 'status', 'update_status', 'update_rule', 'rules', 'teacher_id']
)
await createRFMGroup(params)
}
......@@ -156,7 +163,7 @@ async function handleCreate() {
async function handleUpdate() {
if (props.data.type === '1') {
// 静态群组
const params = pick(form, ['id', 'name', 'status'])
const params = pick(form, ['id', 'name', 'status', 'teacher_id'])
await updateStaticGroup(params)
} else if (props.data.type === '2') {
// 动态群组
......@@ -186,7 +193,7 @@ async function handleUpdate() {
user_attr_rule: JSON.stringify([{ ...form.user_attr_rule, items: attrRuleItems }]),
event_attr_rule: JSON.stringify([{ ...form.event_attr_rule, items: eventRuleItems }]),
tag_rule: JSON.stringify([{ ...form.tag_rule, ...tagRule }]),
user_action_rule: JSON.stringify(form.user_action_rule)
user_action_rule: JSON.stringify(form.user_action_rule),
},
[
'id',
......@@ -197,7 +204,8 @@ async function handleUpdate() {
'user_attr_rule',
'event_attr_rule',
'tag_rule',
'user_action_rule'
'user_action_rule',
'teacher_id',
]
)
await updateDynamicGroup(params)
......@@ -209,7 +217,8 @@ async function handleUpdate() {
'status',
'update_status',
'update_rule',
'rules'
'rules',
'teacher_id',
])
await updateRFMGroup(params)
}
......@@ -221,7 +230,7 @@ async function handleUpdate() {
<template>
<el-dialog :title="title" :close-on-click-modal="false" width="980px" @closed="$emit('update:modelValue', false)">
<el-form ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="100px">
<el-form ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="110px">
<el-form-item label="群组名称" prop="name">
<el-input v-model="form.name" placeholder="请输入" />
</el-form-item>
......@@ -269,6 +278,11 @@ async function handleUpdate() {
</div>
</el-form-item>
</template>
<el-form-item label="匹配老师标签" prop="teacher_id" v-if="hasQuestion">
<el-select v-model="form.teacher_id" style="width: 100%">
<el-option v-for="item in teacherGroupList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-switch v-model="form.status" active-text="生效" active-value="1" inactive-text="失效" inactive-value="0" />
</el-form-item>
......
......@@ -6,6 +6,7 @@ import { updateStatusRuleList, dateUnitList, weekList, labelList } from '@/utils
import { createLabel, updateLabel } from '../api'
import { useLabelType } from '../composables/useLabelType'
import { pick } from 'lodash-es'
import { useQuestion } from '@/composables/useQuestion'
const props = defineProps<{
data?: Label
......@@ -30,7 +31,8 @@ const form = reactive({
update_rule: { type: 1, info: 1 },
status: '1',
label: '',
weight: 0
weight: 0,
teacher_id: '',
})
watchEffect(() => {
if (props.data) {
......@@ -48,9 +50,11 @@ const rules = ref<FormRules>({
name: [{ required: true, message: '请输入标签名称' }],
label: [{ required: true, message: '请选择标签类型' }],
type_id: [{ required: true, message: '请选择标签目录' }],
update_status: [{ required: true, message: '请选择更新评率' }]
update_status: [{ required: true, message: '请选择更新评率' }],
})
const { hasQuestion, teacherTagList } = useQuestion('202')
// 提交
function handleSubmit() {
formRef?.validate().then(() => (isUpdate ? handleUpdate() : handleCreate()))
......@@ -64,7 +68,8 @@ function handleCreate() {
'update_rule',
'status',
'label',
'weight'
'weight',
'teacher_id',
])
createLabel(params).then(() => {
ElMessage({ message: '创建成功', type: 'success' })
......@@ -82,7 +87,8 @@ function handleUpdate() {
'update_rule',
'status',
'label',
'weight'
'weight',
'teacher_id',
])
updateLabel(params).then(() => {
ElMessage({ message: '修改成功', type: 'success' })
......@@ -94,7 +100,7 @@ function handleUpdate() {
<template>
<el-dialog :title="title" :close-on-click-modal="false" width="600px" @closed="$emit('update:modelValue', false)">
<el-form ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="100px">
<el-form ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="110px">
<el-form-item label="标签名称" prop="name">
<el-input v-model="form.name" placeholder="请输入" />
</el-form-item>
......@@ -103,6 +109,11 @@ function handleUpdate() {
<el-option v-for="item in labelList" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="匹配老师标签" prop="teacher_id" v-if="hasQuestion">
<el-select v-model="form.teacher_id" style="width: 100%">
<el-option v-for="item in teacherTagList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="标签目录" prop="type_id">
<el-select v-model="form.type_id" style="width: 100%">
<el-option v-for="item in typeList" :key="item.id" :label="item.name" :value="item.id"></el-option>
......
......@@ -29,6 +29,7 @@ export interface Label {
updated_operator: Operator
label: string
weight: string
teacher_id?: string
}
// 标签更新规则
export interface LabelUpdateRule {
......@@ -38,7 +39,10 @@ export interface LabelUpdateRule {
export type LabelListRequest = Pick<Label, 'id' | 'name'> & { experiment_id?: string }
export type LabelUpdateRequest = Pick<Label, 'id' | 'name' | 'type_id' | 'update_status' | 'update_rule' | 'status' | 'label'> & {
export type LabelUpdateRequest = Pick<
Label,
'id' | 'name' | 'type_id' | 'update_status' | 'update_rule' | 'status' | 'label' | 'teacher_id'
> & {
experiment_id?: string
}
......
<script setup>
import { useMapStore } from '@/stores/map'
import { materialMethodList } from '@/utils/dictionary'
import { useQuestion } from '@/composables/useQuestion'
const materialType = useMapStore().getMapValuesByKey('experiment_marketing_material_type')
......@@ -14,7 +15,7 @@ const formRef = ref()
const rules = ref({
type: [{ required: true, message: '请选择营销内容类型' }],
name: [{ required: true, message: '请输入内容名称' }]
name: [{ required: true, message: '请输入内容名称' }],
})
async function handleValidate() {
......@@ -35,25 +36,61 @@ function wayDisabled(item, type) {
}
return false
}
const questionType = computed(() => {
const questionTypes = {
1: '401',
2: '402',
3: '403',
4: '404',
5: '405',
6: '406',
7: '407',
8: '408',
}
return questionTypes[form.value.type]
})
const { hasQuestion, teacherMaterialList } = useQuestion(questionType, form.value.type)
</script>
<template>
<el-card shadow="never">
<template #header>基础信息</template>
<el-form label-suffix=":" label-width="130" :model="form" :rules="rules" ref="formRef" :disabled="action === 'view'">
<el-form
label-suffix=":"
label-width="130"
:model="form"
:rules="rules"
ref="formRef"
:disabled="action === 'view'">
<el-form-item label="营销内容类型" prop="type">
<el-radio-group v-model="form.type" :disabled="action === 'update'" @change="form.way = '2'">
<el-radio v-for="item in materialType" :key="item.id" :value="item.value" :disabled="$route.query.type ? item.value !== $route.query.type : false">{{ item.label }}</el-radio>
<el-radio
v-for="item in materialType"
:key="item.id"
:value="item.value"
:disabled="$route.query.type ? item.value !== $route.query.type : false"
>{{ item.label }}</el-radio
>
</el-radio-group>
</el-form-item>
<el-form-item label="内容名称" prop="name">
<el-input v-model="form.name" placeholder="请输入内容名称" />
</el-form-item>
<el-form-item label="匹配老师标签" prop="teacher_id" v-if="hasQuestion">
<el-select v-model="form.teacher_id" style="width: 100%">
<el-option v-for="item in teacherMaterialList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="创作方式" prop="way">
<el-radio-group v-model="form.way">
<el-radio v-for="item in materialMethodList" :key="item.value" :value="item.value" :disabled="wayDisabled(item, form.type)">{{
item.label
}}</el-radio>
<el-radio
v-for="item in materialMethodList"
:key="item.value"
:value="item.value"
:disabled="wayDisabled(item, form.type)"
>{{ item.label }}</el-radio
>
</el-radio-group>
</el-form-item>
</el-form>
......
......@@ -25,6 +25,7 @@ const form: any = reactive({
key_points: '',
content: '',
extend_info: {},
teacher_id: '',
})
const detail = ref()
......
......@@ -120,3 +120,8 @@ export function getConnectionList() {
export function syncMember() {
return httpRequest.get('/api/lab/v1/experiment/member/sync-member')
}
// 学生用户列表-清空数据(lab系统)
export function clearMember() {
return httpRequest.get('/api/lab/v1/experiment/member/clear')
}
<script setup lang="ts">
import { Plus, Download, Upload, Delete } from '@element-plus/icons-vue'
import AppList from '@/components/base/AppList.vue'
import { getMemberList, deleteMember, getMemberConnectionsList, syncMember } from '../api'
import { getMemberList, deleteMember, getMemberConnectionsList, syncMember, clearMember } from '../api'
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus'
import type { MemberProp, ConnectionsProp } from '../types'
import { useUserStore } from '@/stores/user'
......@@ -211,6 +211,17 @@ const handleSync = async () => {
ElMessage({ message: '同步成功', type: 'success' })
handleRefresh()
}
const handleClear = async () => {
await ElMessageBox.confirm('确定要清空用户数据吗?', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
await clearMember()
ElMessage({ message: '清空成功', type: 'success' })
handleRefresh()
}
</script>
<template>
......@@ -270,6 +281,7 @@ const handleSync = async () => {
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button type="danger" @click="handleClear" v-if="userStore.role?.id == 1">清空数据</el-button>
</el-space>
<el-space>
<router-link to="/analyze/user"><el-button type="primary">用户分析</el-button></router-link>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论