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

chore: update

上级 2214818c
......@@ -115,6 +115,7 @@
"useArrayFilter": true,
"useArrayFind": true,
"useArrayFindIndex": true,
"useArrayFindLast": true,
"useArrayJoin": true,
"useArrayMap": true,
"useArrayReduce": true,
......
......@@ -7,8 +7,7 @@ const routes: RouteRecordRaw[] = [
component: Layout,
children: [
{ path: '', component: () => import('./views/Index.vue') },
{ path: 'score', component: () => import('./views/Score.vue') },
{ path: 'review', component: () => import('./views/Review.vue') }
{ path: 'score', component: () => import('./views/Score.vue') }
]
}
]
......
<!-- 批改用户旅程 -->
<script setup lang="ts">
import TripFlow from '@/components/flow/Index.vue'
const elements = ref([
{
id: '1',
type: 'custom',
label: '实时触发',
position: { x: 0, y: 0 },
data: { name: '实时触发', type: '触发条件', score: 10, componentName: 'TriggeringConditions6' }
}
])
watchEffect(() => {
console.log(elements)
})
// 保存
function handleSubmit() {}
</script>
<template>
<AppCard>
<TripFlow v-model="elements" action="view" role="teacher" style="height: 80vh">
<template #footer>
<el-row justify="center">
<el-button type="primary" auto-insert-space @click="handleSubmit">保存</el-button>
</el-row>
</template>
</TripFlow>
</AppCard>
</template>
<!-- 学生查看用户旅程成绩 -->
<script setup lang="ts">
import type { Trip } from '../types'
import TripFlow from '@/components/flow/Index.vue'
import { getStudentTrip } from '../api'
const elements = ref([
{
id: '1',
type: 'custom',
label: '实时触发',
position: { x: 0, y: 0 },
data: { name: '实时触发', type: '触发条件', score: 10, componentName: 'TriggeringConditions6' }
}
])
const detail = ref<Trip>()
const elements = ref([])
watchEffect(() => {
console.log(elements)
// 获取旅程信息
async function fetchInfo() {
const res = await getStudentTrip()
detail.value = res.data
try {
elements.value = res.data.graph ? JSON.parse(res.data.graph) : []
} catch (error) {
console.log(error)
}
}
onMounted(() => {
fetchInfo()
})
// 保存
function handleSubmit() {}
const commentVisible = ref(false)
</script>
<template>
<AppCard>
<TripFlow v-model="elements" action="view" role="student" style="height: 80vh">
<template #footer>
<el-row justify="center">
<el-button type="primary" auto-insert-space @click="handleSubmit">保存</el-button>
</el-row>
</template>
</TripFlow>
<AppCard :title="detail?.experiment_itinerary_type_name">
<el-card shadow="never" style="margin-bottom: 20px" v-if="detail">
<el-descriptions class="info">
<el-descriptions-item label="课程名称:">{{ detail.course_name }}</el-descriptions-item>
<el-descriptions-item label="实验名称:">{{ detail.experiment_name }}</el-descriptions-item>
<el-descriptions-item label="旅程类型:">{{ detail.experiment_itinerary_type_name }}</el-descriptions-item>
<el-descriptions-item label="客户旅程总分:">{{ detail.score }}</el-descriptions-item>
<el-descriptions-item label="客户旅程得分:">{{ detail.score }}</el-descriptions-item>
<el-descriptions-item>
<el-button type="primary" @click="commentVisible = true">教师评语</el-button>
</el-descriptions-item>
</el-descriptions>
</el-card>
<TripFlow v-model="elements" action="view" role="student"></TripFlow>
</AppCard>
<el-dialog title="评语" width="500px" append-to-body v-model="commentVisible">
{{ detail?.comment }}
<template #footer>
<el-row justify="center">
<el-button auto-insert-space plain @click="commentVisible = false">关闭</el-button>
</el-row>
</template>
</el-dialog>
</template>
import httpRequest from '@/utils/axios'
// 获取学员提交的旅程配置记录
export function getStudentTripRecord() {
return httpRequest.get('/api/lab/v1/teacher/experiment/itinerary-record')
}
// 教师评阅学员提交的旅程配置
export function checkStudentTripRecord(data: { itinerary_id: string; score: number; graph: string; comment: string }) {
return httpRequest.post('/api/lab/v1/teacher/experiment/check-itinerary-record', data)
}
// 保存实验旅程的评论
export function submitStudentTripRecordComment(data: { itinerary_id: string; comment: string }) {
return httpRequest.post('/api/lab/v1/teacher/experiment/save-itinerary-comment', data)
}
import type { RouteRecordRaw } from 'vue-router'
import Layout from '@/components/layout/Index.vue'
const routes: RouteRecordRaw[] = [
{
path: '/trip/review',
component: Layout,
children: [{ path: '', component: () => import('../template/views/Index.vue') }]
}
]
export { routes }
<!-- 批改用户旅程 -->
<script setup lang="ts">
import { ElMessage } from 'element-plus'
import TripFlow from '@/components/flow/Index.vue'
import { getStudentTripRecord, submitStudentTripRecordComment, checkStudentTripRecord } from '../api'
import { getNameByValue, tripTemplateTypeList } from '@/utils/dictionary'
const detail = ref()
const elements = ref([])
// 是否批阅
const isReviewed = computed(() => {
return detail.value?.record.comment_status === '1'
})
function fetchRecord() {
getStudentTripRecord().then(res => {
detail.value = res.data.detail
// 评语
form.comment = res.data.detail.record.comment
try {
elements.value = res.data.detail.record.graph ? JSON.parse(res.data.detail.record.graph) : []
} catch (error) {
console.log(error)
}
})
}
onMounted(() => fetchRecord())
const commentVisible = ref(false)
const form = reactive({ comment: '' })
// 保存评语
function handleSubmitComment() {
const params = { ...form, itinerary_id: detail.value?.itinerary.id }
submitStudentTripRecordComment(params).then(() => {
ElMessage({ message: '保存成功', type: 'success' })
commentVisible.value = false
})
}
// 保存
function handleSubmit() {
const score = elements.value.reduce((total: number, item: any) => {
return total + (item?.data?.score ? parseFloat(item.data.score) : 0)
}, 0)
const params = {
...form,
itinerary_id: detail.value?.itinerary.id,
graph: JSON.stringify(elements.value),
score
}
checkStudentTripRecord(params).then(() => {
ElMessage({ message: '保存成功', type: 'success' })
})
}
</script>
<template>
<AppCard>
<el-descriptions :column="4" v-if="detail">
<el-descriptions-item label="课程名称:">{{ detail.course.name }}</el-descriptions-item>
<el-descriptions-item label="实验名称:">{{ detail.experiment.name }}</el-descriptions-item>
<el-descriptions-item label="用户旅程名称:">{{ detail.itinerary.name }}</el-descriptions-item>
<el-descriptions-item label="旅程类型:">
{{ getNameByValue(detail.itinerary.type, tripTemplateTypeList) }}
</el-descriptions-item>
<el-descriptions-item label="客户旅程总分:">{{ detail.itinerary.score }}</el-descriptions-item>
<el-descriptions-item label="客户旅程得分:">{{ detail.record.score }}</el-descriptions-item>
<el-descriptions-item>
<el-button type="primary" @click="commentVisible = true">填写评语</el-button>
</el-descriptions-item>
</el-descriptions>
<TripFlow v-model="elements" action="view" role="teacher">
<template #footer>
<el-row justify="center">
<el-button type="primary" auto-insert-space @click="handleSubmit" :disabled="isReviewed">保存</el-button>
</el-row>
</template>
</TripFlow>
</AppCard>
<el-dialog title="评语" width="500px" append-to-body v-model="commentVisible">
<el-form :model="form">
<el-form-item prop="comment">
<el-input type="textarea" :autosize="{ minRows: 4 }" placeholder="请填写实验整体评语" v-model="form.comment" />
</el-form-item>
</el-form>
<template #footer>
<el-row justify="center">
<el-button auto-insert-space plain @click="commentVisible = false">取消</el-button>
<el-button auto-insert-space plain type="primary" @click="handleSubmitComment">保存</el-button>
</el-row>
</template>
</el-dialog>
</template>
......@@ -21,7 +21,14 @@ router.beforeEach(async (to, from, next) => {
}
}
if (!to.query.experiment_id) {
next({ path: to.path, query: { ...to.query, experiment_id: from.query.experiment_id || '7025368348925886464' } })
next({
path: to.path,
query: {
...to.query,
experiment_id: from.query.experiment_id || '7025368348925886464',
student_id: from.query.student_id
}
})
} else {
next()
}
......
import { defineStore } from 'pinia'
export const useStore = defineStore('main', {
state: () => {
return {
layers: {
messageToEdit: '',
elements: {},
messages: [
{ id: 'simple-textc9xkhtp5yypo7qsnp9e1gh', type: 'simple-text', subtitle: 'bbb', color: '#000000' },
{ id: 'simple-textfuxp9gjvnc78ru0n1tkhul', type: 'simple-text', subtitle: 'aaa', color: '#000000' }
],
default_values: {
image:
'https://images.unsplash.com/photo-1545703399-4313b14625d9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8NHx8fGVufDB8fHx8&w=1000&q=80',
video: 'https://drive.google.com/uc?export=view&confirm=yTib&id=1g8uCFA1CDKMvVsPwb8V8ayk-3Mop3_Hu'
}
}
}
},
getters: {
getMessages: state => {
return () => state.layers.messages
},
getMessageById: state => {
return messageId => state.layers.messages.find(element => element.id == messageId)
},
getItemById: state => {
return (messageId, itemId) => state.getMessageById(messageId).items.find(element => element.id == itemId)
},
getDefaultValues: state => {
return () => state.layers.default_values
}
},
actions: {
setMessageItems(messageId, items) {
let result = this.layers.messages.find(element => element.id === messageId)
result.items = items
}
}
})
......@@ -16,10 +16,16 @@ httpRequest.interceptors.request.use(
const params = new URLSearchParams(window.location.search)
if (config.method === 'get')
config.params = Object.assign({}, config.params, { experiment_id: params.get('experiment_id') })
config.params = Object.assign({}, config.params, {
experiment_id: params.get('experiment_id'),
student_id: params.get('student_id')
})
if (config.method === 'post')
config.data = Object.assign({}, config.data, { experiment_id: params.get('experiment_id') })
config.data = Object.assign({}, config.data, {
experiment_id: params.get('experiment_id'),
student_id: params.get('student_id')
})
return config
},
......
import getId from './radomId'
const createVueNode = (event, addNodes, project, store) => {
let id = getId()
const type = event.dataTransfer?.getData('application/vueflow')
const position = project({ x: event.clientX - 450, y: event.clientY - 20 })
let newNode = {
id: type + id,
type,
position,
label: `${type} node`
}
//////////////////////////////////////////.
switch (type) {
case 'facebook-message':
store.$patch(state => {
state.layers.messages.push({
id: newNode.id,
type: 'facebook-message',
label: 'Label',
color: '#ffffff',
items: [
{
id: getId(),
type: 'messengerTextVue',
text: 'Enter Message Text',
buttons: []
}
]
})
})
break
case 'starting-step':
store.$patch(state => {
state.layers.messages.push({
id: newNode.id,
type: 'starting-step',
label: 'Label',
content: 'Type',
color: '#ffffff',
items: []
})
})
break
case 'container':
store.$patch(state => {
state.layers.messages.push({
id: newNode.id,
type: 'container',
label: 'Label',
width: '20rem',
height: '10rem',
color: '#3A8CC7'
})
})
break
case 'redirector':
store.$patch(state => {
state.layers.messages.push({
id: newNode.id,
type: 'redirector',
label: 'Label',
color: '#000000'
})
})
break
case 'node-image':
store.$patch(state => {
state.layers.messages.push({
id: newNode.id,
type: 'node-image',
label: 'Label',
src: '',
width: '340px',
height: '240px',
color: '#000000'
})
})
break
case 'free-mind':
store.$patch(state => {
state.layers.messages.push({
id: newNode.id,
type: 'free-mind',
label: 'Label',
src: '',
width: '340px',
height: '240px',
color: '#40CE03'
})
})
break
case 'box-with-title':
store.$patch(state => {
state.layers.messages.push({
id: newNode.id,
type: 'box-with-title',
label: 'Label',
title: 'Title',
subtitle: 'Subtitle',
color: '#000000'
})
})
break
case 'simple-text':
store.$patch(state => {
state.layers.messages.push({
id: newNode.id,
type: 'simple-text',
subtitle: 'Subtitle',
color: '#000000'
})
})
break
case 'quick-reply':
store.$patch(state => {
state.layers.messages.push({
id: newNode.id,
type: 'quick-reply',
text: 'Quick Reply',
color: '#ffffff'
})
})
break
simpleText
default:
break
}
//////////////////////////////////////////.
// Implementation of a basic container catching
if (event.target.parentNode.id.substring(-1, 9) === 'container') {
newNode.parentNode = event.target.parentNode.id
}
////////////////////////////////////////////.
addNodes([newNode])
}
const copyVueNode = (addNodes, eid, getNode, store) => {
let id = getId() // Create a New UUid
const nodeById = getNode.value(eid) // Get The node to copy by its Id (eid)
const type = nodeById.type // Get the node's type
// When we copy, we need to create it above the old one (translate +50 x y)
const position = {
...nodeById.position,
x: nodeById.position.x + 50,
y: nodeById.position.y - 50
}
// Create a new message in the store
store.$patch(state => {
const currentMessage = state.layers.messages.filter(item => item.id === eid) // Get all the old message info
state.layers.messages = [
...state.layers.messages,
{
...JSON.parse(JSON.stringify(currentMessage))[0], // The element is copied by reference do we need to dereference it
id: type + id
}
]
})
addNodes([
{
id: type + id,
type,
position,
label: `${type} node`
}
])
}
export { createVueNode, copyVueNode }
export default function () {
let date = new Date();
return [
date.getDate(),
date.getMonth() + 1,
date.getFullYear(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
].join("-");
}
\ No newline at end of file
export default function() {
return (
Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15)
)
}
......@@ -26,6 +26,16 @@ export default defineConfig(({ mode }) => ({
cert: fs.readFileSync(path.join(__dirname, './https/ezijing.com.pem'))
},
proxy: {
'/api/lab': {
target: 'http://com-resource-api-test.ezijing.com',
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-dml.ezijing.com'
}
},
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论