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

feat: 数字营销实验室

上级 e31d7992
VITE_LOGIN_URL=https://login.ezijing.com/auth/login/index
VITE_LAB_URL=https://bi.ezijing.com/bi/?proc=0&action=index
VITE_SASS_DML=https://saas-dml.ezijing.com
\ No newline at end of file
VITE_DML_URL=https://saas-dml.ezijing.com
\ No newline at end of file
......@@ -101,7 +101,9 @@ export function getTripConfig(params: { experiment_id: string }) {
// 更新旅程配置
export function updateTripConfig(data: { experiment_id: string }) {
return httpRequest.post('/api/lab/v1/experiment/itinerary-config/save', data)
return httpRequest.post('/api/lab/v1/experiment/itinerary-config/save', data, {
headers: { 'Content-Type': 'application/json' }
})
}
// 获取实验下的所有用户属性
......
......@@ -4,6 +4,7 @@ import type { ExperimentItem } from '../types'
import { ElMessage } from 'element-plus'
import { getTripConfig, updateTripConfig } from '../api'
import { useConnection, useUserAttr, useMetaEvent, useTag, useGroup, useMaterial } from '../composables/useAllData'
import { useDocumentVisibility } from '@vueuse/core'
const props = defineProps<{
data: ExperimentItem
......@@ -21,6 +22,10 @@ const { tagList } = useTag(props.data.id)
const { groupList } = useGroup(props.data.id)
const { materialList } = useMaterial(props.data.id)
const dmlURL = computed(() => {
return `${import.meta.env.VITE_DML_URL}/trip/template?experiment_id=${props.data.id}`
})
const formRef = $ref<FormInstance>()
const form = reactive({
experiment_id: props.data.id,
......@@ -29,6 +34,7 @@ const form = reactive({
user_attr_config: { is_all: true, items: [] },
event_config: { is_all: true, items: [] },
is_use_common: 0,
ids: [],
tag_ids: [],
group_ids: [],
material_ids: []
......@@ -40,8 +46,13 @@ let templateList = $ref<{ id: string; name: string }[]>([])
function fetchInfo() {
getTripConfig({ experiment_id: props.data.id }).then(res => {
const data = res.data
if (!data.itinerary?.id) return
templateList = [data.itinerary]
const connect_ids = data.connections.map((item: any) => item.id)
if (!data.is_config_created) {
Object.assign(form, { itinerary_id: data.itinerary.id, connect_ids })
return
}
const user_attr_config = {
is_all: data.user_attr_config.is_all,
items: data.user_attr_config.items.map((item: any) => item.id)
......@@ -67,6 +78,11 @@ function fetchInfo() {
}
watchEffect(() => fetchInfo())
const visibility = useDocumentVisibility()
watch(visibility, (current, previous) => {
if (current === 'visible' && previous === 'hidden') fetchInfo()
})
const step = ref(0)
// 上一步
function handlePrev() {
......@@ -113,13 +129,25 @@ function handleSubmit() {
<el-tabs v-model="step">
<el-tab-pane label="模板与连接" :name="0">
<el-form-item label="旅程模板" label-width="82" prop="itinerary_id">
<el-select v-model="form.itinerary_id" style="width: 100%">
<el-option v-for="item in templateList" :label="item.name" :value="item.id" :key="item.id"></el-option>
</el-select>
<template v-if="templateList.length">
<el-select v-model="form.itinerary_id" style="width: 100%">
<el-option v-for="item in templateList" :label="item.name" :value="item.id" :key="item.id"></el-option>
</el-select>
</template>
<template v-else>
<a :href="dmlURL" target="_blank">
<el-button type="primary">新建旅程模板</el-button>
</a>
</template>
</el-form-item>
<el-form-item label="连接" label-width="82" prop="connect_ids">
<el-select v-model="form.connect_ids" multiple style="width: 100%">
<el-option v-for="item in connectionList" :label="item.name" :value="item.id" :key="item.id"></el-option>
<el-option
v-for="item in connectionList"
:label="item.name"
:value="item.id"
:key="item.id"
disabled></el-option>
</el-select>
</el-form-item>
</el-tab-pane>
......@@ -161,7 +189,9 @@ function handleSubmit() {
<template v-if="form.is_use_common === 0">
<el-divider />
<el-form-item label="用户/事件数据" label-width="118">
<el-select style="width: 100%"></el-select>
<el-select v-model="form.ids" multiple style="width: 100%">
<el-option value="教师维护的用户和事件数据"></el-option>
</el-select>
</el-form-item>
<el-form-item label="标签数据" label-width="118" prop="tag_ids">
<el-select v-model="form.tag_ids" multiple style="width: 100%">
......
......@@ -93,9 +93,15 @@ function handleSubmit() {
// 当前评分方法
function currentRuleNames(value: number) {
const typeList = form.rule_list.map((item: any) => item.type)
return gradeRuleList.filter(item => {
const tempList = gradeRuleList.filter(item => {
return item.value === value || item.value === 5 || !typeList.includes(item.value)
})
if (props.data.type === '4') {
// 数字营销实验
return tempList.filter(item => [1, 5, 6, 7, 8, 9].includes(item.value as number))
} else {
return tempList.filter(item => item.value <= 5)
}
}
function handleTypeChange(row: any) {
......
......@@ -113,7 +113,7 @@ export function useConnection(experiment_id: string) {
function fetchConnectionList() {
getConnectionList({ experiment_id }).then((res: any) => {
connectionList.value = res.data.items.map((item: any) => {
const attrs = JSON.parse(item.config_attributes)
const attrs = item.config_attributes
const name = Array.isArray(attrs) ? attrs.find((item: any) => item.prop === 'name')?.value : attrs.name
return { ...item, config_attributes: attrs, name }
})
......
......@@ -80,7 +80,7 @@ function handleRemoveClass(row: ClassItem) {
const gradeRulesVisible = $ref(false)
const reportRulesVisible = $ref(false)
const dmlURL = computed(() => {
return `${import.meta.env.VITE_SASS_DML}?experiment_id=${props.id}`
return `${import.meta.env.VITE_DML_URL}?experiment_id=${props.id}`
})
</script>
......
......@@ -130,6 +130,33 @@ function scoreValue(value: any) {
const pictureVisible = $ref(false)
const prepareVisible = $ref(false)
const resultVisible = $ref(false)
function getOperationUrl(type: number) {
if (type === 1) {
// 批改实验报告
return `/admin/lab/score/report?experiment_id=${props.data.experiment_id}&student_id=${props.data.student_id}`
} else if (type === 6) {
// 用户标签
return `${import.meta.env.VITE_DML_URL}/label?experiment_id=${props.data.experiment_id}&student_id=${
props.data.student_id
}`
} else if (type === 7) {
// 用户群组
return `${import.meta.env.VITE_DML_URL}/group?experiment_id=${props.data.experiment_id}&student_id=${
props.data.student_id
}`
} else if (type === 8) {
// 用户旅程
return `${import.meta.env.VITE_DML_URL}/trip?experiment_id=${props.data.experiment_id}&student_id=${
props.data.student_id
}`
} else if (type === 9) {
// 营销资料
return `${import.meta.env.VITE_DML_URL}/material?experiment_id=${props.data.experiment_id}&student_id=${
props.data.student_id
}`
}
}
</script>
<template>
......@@ -186,7 +213,21 @@ const resultVisible = $ref(false)
<template #default="{ row }"> {{ row.percent }}% </template>
</el-table-column>
<el-table-column label="满分" prop="score" align="center"></el-table-column>
<el-table-column label="得分" prop="commit_score" align="center"></el-table-column>
<el-table-column label="得分" prop="commit_score" align="center">
<template #default="{ row }">
<el-input-number
v-model="row.commit_score"
:min="0"
:max="row.score"
:controls="false"
:step="0.01"
step-strictly
placeholder="请输入成绩"
style="width: 100px"
v-if="!(row.type === 1 && experiment.report_upload_way === 2)"></el-input-number>
<span v-else>{{ row.commit_score }}</span>
</template>
</el-table-column>
<el-table-column label="操作" prop="commit_score" align="center">
<template #default="{ row }">
<template v-if="row.type === 1">
......@@ -195,38 +236,19 @@ const resultVisible = $ref(false)
type="primary"
@click="$emit('update:modelValue')"
v-if="experiment.report_upload_way === 2">
<router-link
:to="`/admin/lab/score/report?experiment_id=${data.experiment_id}&student_id=${data.student_id}`"
target="_blank"
>批改</router-link
>
<a :href="getOperationUrl(row.type)" target="_blank">批改</a>
</el-button>
<template v-if="experiment.report_upload_way === 1">
<el-input-number
v-model="row.commit_score"
:min="0"
:max="row.score"
:controls="false"
:step="0.01"
step-strictly
placeholder="请输入成绩"
style="width: 100px"></el-input-number>
<el-button text type="primary" v-if="file?.url">
<a :href="file.url" target="_blank">查阅报告</a>
</el-button>
<p style="color: red" v-else>未上传</p>
</template>
</template>
<template v-else>
<el-input-number
v-model="row.commit_score"
:min="0"
:max="row.score"
:controls="false"
:step="0.01"
step-strictly
placeholder="请输入成绩"
style="width: 100px"></el-input-number>
<template v-else-if="[6, 7, 8, 9].includes(row.type)">
<el-button text type="primary">
<a :href="getOperationUrl(row.type)" target="_blank">查看结果</a>
</el-button>
</template>
</template>
</el-table-column>
......
......@@ -33,6 +33,16 @@ function fetchInfo() {
onMounted(() => {
fetchInfo()
})
function getOperationUrl(type: number) {
if (type === 1) {
// 实验报告
return `/student/lab/report/view/${experiment.id}`
} else if (type === 8) {
// 用户旅程
return `${import.meta.env.VITE_DML_URL}/trip?experiment_id=${experiment.id}&student_id=${experiment.student.id}`
}
}
</script>
<template>
......@@ -85,9 +95,10 @@ onMounted(() => {
<el-table-column label="得分" width="100" align="center">
<template #default="{ row }">
{{ row.commit_score }}
<template v-if="row.type === 1 && experiment.report_upload_way === 2">
<!-- 实验报告 | 用户旅程 -->
<template v-if="(row.type === 1 && experiment.report_upload_way === 2) || row.type === 8">
<el-button text type="primary">
<a :href="`/student/lab/report/view/${experiment.id}`" target="_blank">查看明细</a>
<a :href="getOperationUrl(row.type)" target="_blank">查看明细</a>
</el-button>
</template>
</template>
......
......@@ -90,7 +90,11 @@ watchEffect(() => {
})
// 右侧
const LAB_URL = import.meta.env.VITE_LAB_URL
const LAB_URL = computed(() => {
return experimentInfo?.type === 4
? `${import.meta.env.VITE_DML_URL}/trip?experiment_id=${form.experiment_id}`
: import.meta.env.VITE_LAB_URL
})
let iframeKey = $ref(Date.now())
// 返回首页
function handleBackHome() {
......
......@@ -26,7 +26,11 @@ export const gradeRule: Record<number, any> = {
2: '实验准备',
3: '实验结果',
4: '课堂活跃度',
5: '自定义'
5: '自定义',
6: '用户标签',
7: '用户群组',
8: '用户旅程',
9: '营销资料'
}
// 参赛模式列表
export const gradeRuleList = json2Array(gradeRule)
......
......@@ -31,6 +31,11 @@ export default defineConfig(({ mode }) => ({
changeOrigin: true,
rewrite: path => path.replace(/^\/api\/lab/, '')
},
'/api/resource': {
target: 'http://com-resource-admin-test.ezijing.com',
changeOrigin: true,
rewrite: path => path.replace(/^\/api\/resource/, '')
},
'/api': 'https://saas-lab.ezijing.com'
}
},
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论