| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- <template>
- <div class="step_exam_item">
- <div class="left_line"></div>
- <div
- class="step_item"
- v-for="(item, index) in menuList"
- :key="index"
- :class="{ active: index === activeIndex, success: item.status === 1 }"
-
- >
- <div class="step_title" @click="MenuChange(index, item)">
- <div class="num_box">
- <!-- 假设 el-icon-success 是全局注册的组件或 CSS 类 -->
- <span v-if="item.status === 1" class="el-icon-success"></span>
- <span v-else class="step_num">{{ index + 1 }}</span>
- </div>
- <span>{{ item.name }}</span>
- </div>
- <div class="step_desc" v-if="item.name=='成绩查询'">
- <div class="menu_item" :class="childMenuPath==menu.path?'menu_item_active':''" v-for="menu in item.menu" @click="MenuSelect(menu)">
- {{menu.name}}
- </div>
- </div>
- <div v-else class="step_desc" @click="MenuChange(index, item)">
- {{ item.desc }}
- </div>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { ref, computed, onMounted, watch } from 'vue'
- import { useRoute, useRouter } from 'vue-router'
- import { useExamStore } from '@/store/exam'
- const examStore = useExamStore()
- // --- 响应式数据 ---
- const route = useRoute()//读取当前路由对象
- const router = useRouter()//访问全局路由方法
- const stepOnIndex = ref<number>(0)//步骤索引
- const childMenuPath = ref<string>('')//子级菜单路径
- const menuListRaw = ref<any[]>([]) // 用于存储计算后的菜单列表,以便 watch 能检测到变化(如果需要)
- // --- 计算属性 ---
- // 1. 考试科目 ID
- const examSubjectId = computed(() => {
- // 替换为: return makeTemplateStore.examTempDetail?.id
- return examStore.currentExam?.id
- })
- // 2. 考试状态字符串
- const examStateStr = computed(() => {
- // 替换为: return makeTemplateStore.examStateStr
- return examStore.currentExam?.examStateStr
- })
- // 3. 考试类型 1 选择题 2 填空题 3 Ai作文
- const examType=computed(() => {
- return examStore.currentExam?.examType // 默认为选择题
- })
- // 5. 动态菜单列表
- const menuList = computed(() => {
- console.log('打印菜单examType', examSubjectId.value, examType.value)
- let list: any[] = []
- if(examType.value==1)
- {
- //选择题判分
- list = [
- { name: '试题结构', number: '1', path: 'question', desc: '建立考试试题结构、设置标答、分组等信息', status: 0 },
- { name: '扫描学生', number: '2', path: 'scanList', desc: '扫描学生,处理扫描异常学生等', status: 0 },
- { name: '成绩查询', number: '3', path: 'analysis', desc: '设置每个主观题下的划分区信息及位置', status: 0 ,
- menu:[
- { name: '成绩单', path: 'score' },
- { name: '错题分析', path: 'errorAnalysis' },
- { name: '选项明细', path: 'optionDetail' },
- { name: '水平分布', path: 'levelDistribution' },
- { name: '班级对比', path: 'classComparison' },
- { name: '小题分析', path: 'questionAnalysis' },
- { name: '分组分析', path: 'groupAnalysis' },
- { name: '选项分析', path: 'optionAnalysis' },
- { name: '命题分析', path: 'propositionAnalysis' },
- ]
- },
- ];
-
- }
- else if(examType.value==2)
- {
- //填空题判分
- }
- else
- {
- //Ai作文
- }
-
-
-
- // // 更新状态
- // const stateStr = String(examStateStr.value || '')
- // list.forEach((item) => {
- // if (stateStr.includes(item.number)) {
- // item.status = 1
- // } else {
- // item.status = 0
- // }
- // })
- return list
- })
- // 6. 激活的菜单索引
- const activeIndex = computed(() => {
- const currentPath = route.path
-
- // 特殊处理 scanStudentHome 页面
- if (currentPath.includes('scanStudentHome')) {
- const stepActiveIndex = menuList.value.findIndex(item => item.name === '扫描学生')
- return stepActiveIndex !== -1 ? stepActiveIndex : stepOnIndex.value
- }
-
- // 根据路由路径找到匹配的菜单项索引
- const pathMatchIndex = menuList.value.findIndex(item => currentPath.includes(item.path))
- return pathMatchIndex !== -1 ? pathMatchIndex : stepOnIndex.value
- })
- // --- 方法 ---
- // 获取模板数据
- const GetThirdCardData = () => {
- if (!examSubjectId.value) return
- const param = {
- examSubjectId: examSubjectId.value
- }
-
- // 假设 $api 已全局挂载或在 utils 中引入
- // import { examApi } from '@/api/exam'
- ;(window as any).$api?.exam.getExamThirdCardData(param).then((res: any) => {
- console.log('获取模板相关数据 包含第三方卡和系统卡', res)
- if (res.code === 200) {
- localStorage.setItem('templateData', JSON.stringify(res.data.examCardPageVOS))
- localStorage.setItem('usedCardType', res.data.usedCardType)
-
- // 替换为 Store Commit/Action
- // makeTemplateStore.setMarkType(res.data.markType)
- // makeTemplateStore.setUsedCardType(res.data.usedCardType)
- console.warn('请在此处调用 Store 的 action 更新 markType 和 usedCardType')
- }
- })
- }
- // // 获取考试流程状态
- // const GetExamState = () => {
- // const param = {
- // examSubjectId: route.query.id
- // }
-
- // ;(window as any).$api?.reviewBlock.getExamFlowStatus(param).then((res: any) => {
- // console.log('打印考试流程状态返回', res)
- // if (res.code === 200) {
- // const newStateStr = res.data.finished.join(',')
- // // 替换为 Store Commit/Action
- // // makeTemplateStore.setExamStateStr(newStateStr)
- // console.warn('请在此处调用 Store 的 action 更新 examStateStr')
- // }
- // })
- // }
- // 菜单点击事件
- const MenuChange = (index: number, item: any) => {
- console.log('点击菜单', index, item)
- stepOnIndex.value = index
- childMenuPath.value = ''
- // 触发父组件事件
- // 在 <script setup> 中,需要使用 defineEmits
- router.push('/exam/'+item.path)
- }
- //子级菜单选择事件
- const MenuSelect = (menu: any) => {
- console.log('选择的子菜单', menu)
- stepOnIndex.value = 2;
- childMenuPath.value = menu.path;
- // 执行路由跳转
- router.push(`/exam/analysis/${menu.path}`)
- }
- // --- 生命周期 & 监听 ---
- // 定义 emits
- const emit = defineEmits(['menuChange'])
- watch(examStateStr, (newVal) => {
- // 由于 menuList 是 computed 且依赖 examStateStr,它会自动重新计算
- // 如果这里有其他副作用,请保留
- console.log('考试状态发生变化', newVal)
- })
- onMounted(() => {
- // 初始化 stepOnIndex
- if (route.path.includes('scanStudentHome')) {
-
-
-
- stepOnIndex.value = 0
-
- }
-
- })
- </script>
- <style lang="scss" scoped>
- .step_exam_item {
- position: relative;
- height: 100%;
- .left_line {
- position: absolute;
- top: 0;
- left: 15.55px;
- z-index: 6;
- height: 100%;
- width: 0;
- border-left: 1px dashed #C0C4CC;
- }
- .step_item {
- width: 100%;
- position: relative;
- z-index: 7;
- border-top-left-radius: 10px;
- border-bottom-left-radius: 10px;
- cursor: pointer;
- .step_title {
- display: flex;
- align-items: center;
- justify-content: flex-start;
- width: 100%;
- height: 34px;
- font-size: 16px;
- color: #333333;
- line-height: 34px;
- font-weight: 600;
- border-top-left-radius: 10px;
- }
- .num_box {
- width: 30px;
- height: 100%;
- display: flex;
- justify-content: center;
- align-items: center;
- .el-icon-success::before {
- font-size: 19px;
- }
- }
- .step_num {
- display: block;
- width: 17px;
- height: 17px;
- font-size: 12px;
- text-align: center;
- font-weight: 500;
- line-height: 17px;
- border-radius: 50%;
- background-color: #B0B2B7;
- color: #fff;
- }
- .step_desc {
- padding: 0px 5px 6px 20px;
- font-size: 12px;
- line-height: 16px;
- color: #999999;
- .menu_item
- {
- font-weight: 400;
- font-size: 14px;
- color: #666666;
- line-height: 35px;
- text-indent: 10px;
- }
- .menu_item_active
- {
- color: #2e64fa;
- }
- }
- &.success {
- border-color: #fff;
- .num_box > span {
- color: #15bc83;
- }
- }
- &.active {
- border-color: #2e64fa;
- background-color: rgba(46, 100, 250, 0.1);
- box-shadow: inset 1px -1px 0px 1.5px #2e64fa;
- .step_title {
- background-color: #2e64fa;
- color: #fff;
- }
- .step_num {
- background-color: #ffff;
- color: #2e64fa;
- }
- .step_desc {
- background-color: rgba(46, 100, 250, 0.1);
- }
- }
- }
- /* 小屏幕笔记本的样式 常见分辨率:1366x768 */
- @media (max-height: 768px) {
- .step_item {
- margin-bottom: 0px;
- .step_title {
- font-size: 14px;
- line-height: 30px;
- font-weight: 700;
- }
- .step_desc {
- padding: 0px 5px 6px 20px;
- font-size: 10px;
- line-height: 15px;
- }
- }
- }
- /* 中等屏幕笔记本的样式(14-15英寸) 常见分辨率:1600x900, 1920x1080*/
- @media (min-height: 769px) and (max-height: 1080px) {
- .step_item {
- margin-bottom: 15px;
- .step_title {
- font-size: 16px;
- line-height: 30px;
- }
- .step_desc {
- padding: 0px 5px 6px 20px;
- font-size: 12px;
- line-height: 15px;
- }
- }
- }
- /* 大屏幕笔记本的样式(17-20英寸) 常见分辨率:2560x1440*/
- @media screen and (min-height: 1081px) {
- .step_item {
- margin-bottom: 25px;
- .step_title {
- font-size: 17px;
- line-height: 30px;
- }
- .step_desc {
- padding: 10px 5px 10px 20px;
- font-size: 14px;
- line-height: 15px;
- }
- }
- }
- }
- </style>
|