wangxy hai 2 meses
pai
achega
fc84e7a7ce

+ 50 - 0
api/kaoshi.js

@@ -137,3 +137,53 @@ export function getClientKsSave(data = {}) {
     timeout: 20000
   })
 }
+
+
+export function getClientKsChengjiView(data = {}) {
+  return request({
+    url: '/app/chengji/view',
+    headers: {
+      isToken: false
+    },
+    method: 'post',
+    data,
+    timeout: 20000
+  })
+}
+
+export function getClientKsChengjiList(data = {}) {
+  return request({
+    url: '/app/chengji/list',
+    headers: {
+      isToken: false
+    },
+    method: 'post',
+    data,
+    timeout: 20000
+  })
+}
+
+
+export function getAdminKsChengjiList(data = {}) {
+  return request({
+    url: '/app/chengji/guanliyuan/list',
+    headers: {
+      isToken: false
+    },
+    method: 'post',
+    data,
+    timeout: 20000
+  })
+}
+
+export function getAdminKsChengjiView(data = {}) {
+  return request({
+    url: '/app/chengji/guanliyuan/view',
+    headers: {
+      isToken: false
+    },
+    method: 'post',
+    data,
+    timeout: 20000
+  })
+}

+ 51 - 2
api/lianxi.js

@@ -26,7 +26,7 @@ export function getLianxiInfo(data = {}) {
 
 export function getClientLianxiList(data = {}) {
   return request({
-    url: '/app/lianxi/list',
+    url: '/app/lianxi/kaozheng/list',
     headers: {
       isToken: false
     },
@@ -38,7 +38,56 @@ export function getClientLianxiList(data = {}) {
 
 export function getClientLianxiInfo(data = {}) {
   return request({
-    url: '/app/lianxi/info',
+    url: '/app/lianxi/kaozheng/info',
+    headers: {
+      isToken: false
+    },
+    method: 'post',
+    data,
+    timeout: 20000
+  })
+}
+
+export function getClientLianxiStart(data = {}) {
+  return request({
+    url: '/app/lianxi/kaozheng/start',
+    headers: {
+      isToken: false
+    },
+    method: 'post',
+    data,
+    timeout: 20000
+  })
+}
+
+export function getClientLianxiSubmit(data = {}) {
+  return request({
+    url: '/app/lianxi/kaozheng/submit',
+    headers: {
+      isToken: false
+    },
+    method: 'post',
+    data,
+    timeout: 20000
+  })
+}
+
+export function getClientLianxiBiaoji(data = {}) {
+  return request({
+    url: '/app/lianxi/kaozheng/biaoji',
+    headers: {
+      isToken: false
+    },
+    method: 'post',
+    data,
+    timeout: 20000
+  })
+}
+
+
+export function getClientLianxiChengjiView(data = {}) {
+  return request({
+    url: '/app/lianxi/kaozheng/view',
     headers: {
       isToken: false
     },

+ 39 - 0
components/score/topCard.vue

@@ -0,0 +1,39 @@
+<template>
+	<view>
+		<view><text>{{name}}</text> <text>{{zyLevelName}}</text></view>
+		<view>
+			<text>{{userScore}}/{{Score}}</text>
+			<text @click="handleOpenCard"><i></i> {{count}}/{{total}}</text>
+		</view>
+	</view>
+</template>
+
+<script setup>
+	defineProps({
+		name: {
+			type: String
+		},
+		zyLevelName: {
+			type: String
+		},
+		userScore: {
+			type:  [String,Number]
+		},
+		Score: {
+			type: [String,Number]
+		},
+		count: {
+			type:  [String,Number]
+		},
+		total: {
+			type:  [String,Number]
+		},
+	})
+	const emits = defineEmits(['openCard'])
+	function handleOpenCard (){
+		emits('openCard')
+	}
+</script>
+
+<style>
+</style>

+ 8 - 1
components/zhuapaiConfirm/submitScore.vue

@@ -4,7 +4,7 @@
 		<view class="score-content">
 			<view class="icon-title-navBar-box">
 				<view @click="handleClose" class="nav-bar-icon"></view>
-				<text class="nav-bar-title">考试得分</text>
+				<text class="nav-bar-title">{{title}}</text>
 			</view>
 			
 			<view class="popup-height">
@@ -34,6 +34,13 @@
 		userScore: '',
 	})
 	
+	defineProps({
+		title: {
+			type: String,
+			default: '考试得分'
+		}
+	})
+	
 	const emits = defineEmits(['confirm', 'close'])
 	
 	function handleClose() {

+ 34 - 0
pages.json

@@ -100,6 +100,40 @@
 			"style": {
 				"navigationStyle": "custom"
 			}
+		},
+		{
+			"path": "pages/client/Lianxi/exam",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path" : "pages/client/Chengji/lxScoreShijuan",
+			"style" : 
+			{
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path" : "pages/client/Chengji/ksScoreShijuan",
+			"style" : 
+			{
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path" : "pages/client/Chengji/list",
+			"style" : 
+			{
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path" : "pages/admin/Chengji/list",
+			"style" : 
+			{
+				"navigationStyle": "custom"
+			}
 		}
 	],
 	"tabBar": {

+ 414 - 0
pages/admin/Chengji/ksScoreShijuan.vue

@@ -0,0 +1,414 @@
+<template>
+	<view class="socre-shijuan">
+		<!-- 导航区域 -->
+		<view class="icon-title-navBar-box">
+			<view @click="handleBack" class="nav-bar-icon"></view>
+			<text class="nav-bar-title">{{data.ksName}}</text>
+		</view>
+		<!-- 上方区域 -->
+		<topCard @openCard="handleOpenCard" :name="data.ksName" :zyLevelName="data.zyLevelName" :userScore="data.userScore" :Score="data.Score" :count="activeSt && activeSt.onlyNum||0" :total="data.StListForSearch.length"></topCard>
+		
+		<view>
+			<!-- 段落 -->
+			<view class="kaoshi-shiti-content">
+				<!-- 试题区域 -->
+				<view v-if="activeSt">
+					<template v-if="activeSt.stTypeId == 1">
+						<!-- 单选 -->
+						<danxuan :question="activeSt" :key="activeSt.stId"></danxuan>
+					</template>
+					<template v-if="activeSt.stTypeId == 2">
+						<!-- 多选 -->
+						<duoxuan :question="activeSt" :key="activeSt.stId"></duoxuan>
+					</template>
+					<template v-if="activeSt.stTypeId == 3">
+						<!-- 判断 -->
+						<panduan :question="activeSt" :key="activeSt.stId"></panduan>
+					</template>
+					<template v-if="activeSt.stTypeId == 4">
+						<!-- 填空 -->
+						<tiankong :question="activeSt" :key="activeSt.stId"></tiankong>
+					</template>
+				</view>
+			</view>
+			<!-- 解析 -->
+			<view v-if="activeSt">
+				<view class="phone-question-answer-box" v-if="activeSt.stTypeId != 4">
+					<view class="phone-line-title">答案解析</view>
+					<view class="btdf-row">本题得分:<text>{{answerRes.score}}</text>分</view>
+					<view class="zqda-row">正确答案:<text>{{answerRes.result}}</text></view>
+					<view class="ndda-row">您的答案:<text>{{answerRes.reply}}</text></view>
+					<view class="dajx-row">答案解析: 
+						<rich-text :nodes="answerRes.answer"></rich-text>
+					</view>
+				</view>
+				<view class="phone-question-answer-box" v-else>
+					<view class="phone-line-title">答案解析</view>
+					<view class="btdf-row">本题得分:<text>{{answerRes.score}}</text>分</view>
+					<view class="zqda-row">正确答案:
+						<view v-for="(item,index) in answerRes.result">{{`填空${index+1}`}} : {{item}}</view>
+					</view>
+					<view class="ndda-row">您的答案:
+					<view v-for="(item,index) in answerRes.reply"> {{`填空${index+1}`}}: {{item}}</view>
+					</view>
+					<view class="dajx-row">答案解析: 
+						<rich-text :nodes="answerRes.answer"></rich-text>
+					</view>
+				</view>
+			</view>	
+			<!-- 上下按钮 -->
+			<template v-if="activeSt">
+				<button type="default" size="mini" hover-class="none" class="phone-green-btn ks-btn-prev" @click="handlePrev" v-if="!isFistStId">上一题</button>
+				<button type="default" size="mini" hover-class="none"class="phone-green-btn ks-btn-next" @click="handleNext" v-if="!isLastStId">下一题</button>
+			</template>
+			
+			<!-- 答题卡 -->
+			<uni-popup ref="popupRef" background-color="#fff" :is-mask-click="false" :mask-click="false">
+				<view class="answer-card-popup">
+					<view class="icon-title-bjcolor-navBar-box">
+						<view @click="handlePopupBack" class="nav-bar-icon"> </view>
+						<text class="nav-bar-title">答题卡</text>
+					</view>
+					<view class="answer-card-content" v-for="(paragraph,paragraphIndex) in questionData" :key="paragraphIndex">
+						<view class="paragraph-title">
+							{{paragraph.name}}
+						</view>
+						<view class="paragraph-qa" v-for="(qa,qaIndex) in paragraph.qas" :key="qaIndex" 
+						:class="getQaClass(qa)" @click="answerCardItemClick(qa)">{{qa.onlyNum}}
+						</view>
+					</view>
+				</view>
+			</uni-popup>
+			
+		</view>
+	</view>
+</template>
+
+<script setup>
+	import topCard from "@/components/score/topCard.vue"
+	import danxuan from "@/components/questions/danxuan.vue";
+	import duoxuan from "@/components/questions/duoxuan.vue";
+	import tiankong from "@/components/questions/tiankong.vue";
+	import panduan from "@/components/questions/panduan.vue";
+	import {useQuestionTools} from "@/components/questions/useQuestionTools.js";
+	
+	import { onLoad } from "@dcloudio/uni-app";
+	import {ref,reactive,computed} from "vue"
+	import * as ksApi from "@/api/kaoshi.js"
+	const {
+		checkDanxuanReply,
+		checkDuoxuanReply,
+		checkPanduanReply,
+		checkTiankongReply,
+		getLetterByIndex
+	} = useQuestionTools();
+	
+	
+	const hisId = ref(null)
+	const popupRef = ref(null)
+	
+	const data = reactive({
+		ksId: null,
+		ksName: '',
+		stTotal: 0,
+		zyLevelName: '',
+		userScore: '',
+		ksScore: 0,
+		StListForSearch: [],
+		duanluo: []
+	})
+	
+	const questionData = ref([]);
+	const progress = reactive({
+		dlIndex: 0,
+		dtIndex: 0
+	})
+	
+	const dlName = computed(() => {
+		if (data.StListForSearch && activeSt.value) {
+			return data.StListForSearch[activeSt.value.onlyNum].paragraphName
+		} else {
+			return ''
+		}
+	})
+	
+	const activeSt = computed(() => {
+		if (questionData.value.length) {
+			return questionData.value.length && questionData.value[progress.dlIndex].qas[progress.dtIndex];
+		} else {
+			return null
+		}
+	})
+	
+	const answerRes = computed(() => {
+		const qa = activeSt.value ;
+		let score = qa.score;
+		let reply = '';
+		let result = '';
+		let answer = qa.answer;
+		if (qa.stTypeId == 1) {
+			// 单选题
+			if (qa.reply && qa.reply.trim() !== '') {
+				reply = getLetterByIndex(qa.reply)
+			} else {
+				reply = '未答'
+			}
+			
+			if (qa.result) {
+				result = getLetterByIndex(qa.result)
+			} else {
+				result = '无答案'
+			}
+		}
+		if (qa.stTypeId == 2) {
+			// 多选题
+			
+			if (qa.reply && qa.reply.length) {
+				reply = qa.reply.map(item => {
+					if (item.trim()) {
+						return getLetterByIndex(item.trim())
+					}
+				}).join(',')
+			} else {
+				reply = '未答'
+			}
+			if (qa.result) {
+				result = qa.result.map(item => {
+					if (item.trim()) {
+						return getLetterByIndex(item.trim())
+					}
+				}).join(',')
+			} else {
+				result = '无答案'
+			}
+		}
+		if (qa.stTypeId == 3) {
+			// 判断题
+			if (qa.reply == 0) {
+				reply = '错误'
+			}else if (qa.reply == 1) {
+				reply = '正确'
+			}
+			if (qa.result == 0) {
+				result = '错误'
+			}else if (qa.result == 1) {
+				result = '正确'
+			}
+		}
+		if (qa.stTypeId == 4) {
+			let reply = qa.reply || [];
+			let result =qa.result || [];
+			// 填空题
+			return {score,reply,result,answer}
+		} else {
+			return  {
+				score,reply,result,answer
+			}
+		}
+	})
+	
+	const isFistStId = computed(() => {
+		if (data.StListForSearch.length) {
+			return data.StListForSearch[0].stId == activeSt.value.stId
+		} else {
+			return false
+		}
+	});
+	const isLastStId = computed(() => {
+		if (data.StListForSearch.length) {
+			return data.StListForSearch[data.StListForSearch.length - 1].stId == activeSt.value.stId
+		} else {
+			return false
+		}
+	});
+	
+	
+	onLoad((options) => {
+		hisId.value = options.hisId;
+		initPage()
+	})
+	
+	
+	function getQaClass(qa) {
+		if (qa.marked && qa.marked === true) {
+			return 'paragraph-qa-block-mark';
+		} else {
+			if (qa.stTypeId == 1) {
+				if (checkDanxuanReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			} else if (qa.stTypeId == 2) {
+				if (checkDuoxuanReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			} else if (qa.stTypeId == 3) {
+				if (checkPanduanReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			} else if (qa.stTypeId == 4) {
+				if (checkTiankongReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			}
+		}
+	}
+	
+	
+	function handleBack() {
+		uni.redirectTo({
+			url: "/pages/admin/Lianxi/list"
+		})
+	}
+	
+	
+	function formatDuanluoList() {
+		let uIndex = 0; // 试题num
+		let iDuanluo = 0; // 段落num
+		let result = [];
+		for (const duanluo of data.duanluo) {
+			let paragraph = {
+				qas: [],
+			};
+			paragraph.name = duanluo.name;
+	
+			let iQa = 0; // 当前试题序号
+			let order = 0; // 当前题型中第几题
+			for (const iDanxuan of duanluo.danxuan) {
+				iDanxuan.type = 'danxuan';
+				iDanxuan.marked = false;
+				iDanxuan.onlyNum = uIndex + 1;
+				iDanxuan.order = order;
+				iDanxuan.iQa = iQa;
+				paragraph.qas.push(iDanxuan);
+				uIndex++;
+				order++;
+				iQa++;
+	
+				data.StListForSearch.push({
+					stId: iDanxuan.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iDanxuan.iQa,
+					num: iDanxuan.onlyNum
+				})
+			}
+			order = 0;
+			for (const iDuoxuan of duanluo.duoxuan) {
+				iDuoxuan.type = 'duoxuan';
+				iDuoxuan.marked = false;
+				iDuoxuan.onlyNum = uIndex + 1;
+				iDuoxuan.order = order;
+				paragraph.qas.push(iDuoxuan);
+				iDuoxuan.iQa = iQa;
+				uIndex++;
+				order++;
+				iQa++;
+	
+				data.StListForSearch.push({
+					stId: iDuoxuan.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iDuoxuan.iQa,
+					num: iDuoxuan.onlyNum
+				})
+			}
+			order = 0;
+			for (const iPanduan of duanluo.panduan) {
+				iPanduan.type = 'panduan';
+				iPanduan.marked = false;
+				iPanduan.onlyNum = uIndex + 1;
+				iPanduan.order = order;
+				paragraph.qas.push(iPanduan);
+				iPanduan.iQa = iQa;
+				uIndex++;
+				order++;
+				iQa++;
+	
+				data.StListForSearch.push({
+					stId: iPanduan.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iPanduan.iQa,
+					num: iPanduan.onlyNum
+				})
+			}
+			order = 0;
+			for (const iTiankong of duanluo.tiankong) {
+				iTiankong.type = 'tiankong';
+				iTiankong.marked = false;
+				iTiankong.onlyNum = uIndex + 1;
+				iTiankong.order = order;
+				paragraph.qas.push(iTiankong);
+				iTiankong.iQa = iQa;
+				uIndex++;
+				order++;
+				iQa++;
+	
+				data.StListForSearch.push({
+					stId: iTiankong.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iTiankong.iQa,
+					num: iTiankong.onlyNum
+				})
+			}
+			iDuanluo++;
+			questionData.value.push(paragraph)
+	
+		}
+	}
+	
+	function handlePrev() {
+		const qa = data.StListForSearch.find(item => item.stId == activeSt.value.stId);
+		const index = qa.num - 1;
+		if (index > 0) {
+			const result = data.StListForSearch[index - 1];
+			progress.dlIndex = result.dlIndex;
+			progress.dtIndex = result.dtIndex
+		}
+	
+	}
+	
+	function handleNext() {
+		const qa = data.StListForSearch.find(item => item.stId == activeSt.value.stId);
+		const index = qa.num - 1;
+		if (index < data.StListForSearch.length) {
+			const result = data.StListForSearch[index + 1];
+			progress.dlIndex = result.dlIndex;
+			progress.dtIndex = result.dtIndex
+		}
+	}
+	
+	
+	
+	function initPage() {
+		ksApi.getAdminKsChengjiView({hisId: hisId.value}).then(res => {
+			const { duanluoList,ksName, zyLevelName,userScore,ksScore } = res.data;
+			data.ksName = ksName;
+			data.zyLevelName = zyLevelName;
+			data.userScore = userScore;
+			data.ksScore = ksScore;
+			data.duanluo = duanluoList;
+			
+			formatDuanluoList();
+		})
+	}
+	function handlePopupBack() {
+			popupRef.value.close()
+	}
+	function handleOpenCard() {
+		popupRef.value.open('bottom')
+	}
+</script>
+
+<style>
+
+</style>

+ 198 - 0
pages/admin/Chengji/list.vue

@@ -0,0 +1,198 @@
+<template>
+	<view class="admin-kaoshi-page">
+		<view class="icon-title-navBar-box">
+			<view @click="goUpPage" class="nav-bar-icon"></view>
+			<text class="nav-bar-title">成绩</text>
+		</view>
+		<!-- 查询职业 -->
+		<view class="phone-search-box">
+			<input class="search-input" placeholder="请输入职业名称" v-model="data.zyName" />
+			<view class="search-icon" @click="handleSearch">
+				<uni-icons type="search" size="24" color="#fff"></uni-icons>
+			</view>
+		</view>
+		<!-- 课程列表 -->
+		<view class="kaoshi-content-box">
+			<scroll-view scroll-y="true" refresher-enabled="true" :refresher-triggered="data.loading"
+				:refresher-threshold="50" refresher-background="transparent" @refresherrefresh="onRefresh"
+				class="phone-scroll-view kaoshi-scroll-view">
+				<uni-list class="admin-list-box">
+					<uni-list-item v-for="item in data.list" class="admin-list-item-box">
+						<template v-slot:body>
+							<view class="item-kaoshi-row">
+								<!-- 数量 -->
+								<view class="ks-item-top">
+									<view>{{item.name}}</view>
+									<view class="ks-zyLevelName">{{item.zyLevelName}}</view>
+								</view>
+								<view class="ks-totalTm">
+									<icon class="phone-time-icon" /> 姓名:{{item.realName}} 
+									<icon class="phone-time-icon" /> 手机号:{{item.userName}} 
+								</view>
+								<view class="ks-totalTm">
+									<icon class="phone-time-icon" /> {{item.answerStartTime}} - {{item.answerEndTime}}
+								</view>
+								<view class="ks-totalTm">
+									<icon class="phone-time-icon" /> {{item.okScore}} / {{item.ksScore}}
+								</view>
+								<button @click="checkKecheng(item)" type="primary" size="mini"
+									class="kaoshi-btn">查看内容</button>
+							</view>
+						</template>
+					</uni-list-item>
+					<uni-load-more :status="data.state" @click="getMore(0)"
+						:contentText="data.contentText"></uni-load-more>
+				</uni-list>
+			</scroll-view>
+		</view>
+
+		<!-- 页面底端 -->
+		<customTabbarAdminVue></customTabbarAdminVue>
+	</view>
+</template>
+
+<script setup>
+	import customTabbarAdminVue from "@/components/custom-tabbar/custom-tabbar-admin.vue";
+	import {
+		ref,
+		reactive
+	} from "vue";
+	import {
+		onLoad
+	} from "@dcloudio/uni-app";
+	import * as kaoshiApi from "@/api/kaoshi.js"
+	import {
+		formatDuration
+	} from "@/utils/common.js"
+	
+
+	const data = reactive({
+		zyName: '', // 职业名称
+		list: [], // 考试列表
+		loading: false,
+		page: 0,
+		size: 10,
+		state: 'more',
+		contentText: {
+			contentdown: '查看更多',
+			contentrefresh: '加载中',
+			contentnomore: '没有更多'
+		}
+	})
+
+	function goUpPage() {
+		uni.redirectTo({
+			url: '/pages/client/ShouYe/shouye'
+		})
+	}
+
+	function handleSearch() {
+		data.page = 0;
+		refreshData();
+	}
+
+	function checkKecheng(item) {
+		uni.navigateTo({
+			url: `/pages/client/Chengji/ksScoreShijuan?hisId=${item.hisId}`
+		})
+	}
+
+	function onRefresh() {
+		data.page = 0;
+		data.list = [];
+		data.loading = true;
+		refreshData();
+	}
+
+	function refreshData() {
+		const opt = {
+			page: 1,
+			size: 10, // 固定查询10条
+			zyName: data.zyName
+		}
+		data.list = [];
+		// 数学
+		data.state = 'loading';
+		data.page++;
+		opt.page = data.page;
+
+		kaoshiApi.getAdminKsChengjiList(opt).then(res => {
+			data.list = data.list.concat(res.data.data);
+			data.loading = false;
+
+			if (res.data.total > data.list.length) {
+				data.state = 'more';
+				data.loading = false;
+			} else {
+				data.state = 'no-more';
+				data.loading = false;
+			}
+		}).catch(err => {
+			data.state = 'more';
+			data.loading = false;
+		})
+	}
+
+	function getMore() {
+		const opt = {
+			page: 1,
+			size: 10, // 固定查询10条
+			zyName: data.zyName
+		}
+		if (data.state == 'no-more') return;
+		data.state = 'loading';
+		data.page++;
+		opt.page = data.page;
+		kaoshiApi.getAdminKsChengjiList(opt).then(res => {
+			data.list = data.list.concat(res.data.data);
+			data.loading = false;
+
+			if (res.data.total > data.list.length) {
+				data.state = 'more';
+				data.loading = false;
+			} else {
+				data.state = 'no-more';
+				data.loading = false;
+			}
+		}).catch(err => {
+			data.state = 'more';
+			data.loading = false;
+		})
+	}
+
+	onLoad(() => {
+		getMore()
+	})
+</script>
+
+<style lang="scss" scoped>
+	.phone-kecheng-page {
+		background-color: #ccc;
+		box-sizing: border-box;
+	}
+
+	.phone-search-content {
+		position: relative;
+		background-color: #fff;
+		height: 42px;
+
+		.search-input {
+			height: 42px;
+			line-height: 40px;
+			border-radius: 20px;
+			border: 1px solid #ccc;
+			padding: 0 70px 0 20px;
+		}
+
+		.search-icon {
+			position: absolute;
+			right: 5px;
+			top: 4px;
+			padding: 6px;
+			background-color: #ccc;
+			border-radius: 20px;
+			width: 50px;
+			text-align: center;
+		}
+	}
+</style>

+ 1 - 1
pages/admin/Kaoshi/exam.vue

@@ -37,7 +37,7 @@
 		</view>
 
 		<view class="kaoshi-bottom-box">
-			<button class="phone-green-btn bj-btn" hover-class="none" type="default" size="mini" @click="handleBiaoji">标记</button>
+			<button class="phone-green-btn bj-btn" hover-class="none" type="default" size="mini" @click="handleBiaoji">{{activeSt && activeSt.marked ? '取标':'标记'}}</button>
 			<view @click="showAnswerCard" class="shiti-num-box">
 				<icon class="shiti-num-icon"></icon>
 				<text class="active-num">{{activeSt ? activeSt.onlyNum: 0}}</text>/<text>{{data.StListForSearch.length}}</text>

+ 1 - 2
pages/admin/Lianxi/lianxi.vue

@@ -37,7 +37,7 @@
 		</view>
 
 		<view class="kaoshi-bottom-box">
-			<button class="phone-green-btn bj-btn" hover-class="none" type="default" size="mini" @click="handleBiaoji">标记</button>
+			<button class="phone-green-btn bj-btn" hover-class="none" type="default" size="mini" @click="handleBiaoji">{{activeSt && activeSt.marked ? '取标':'标记'}}</button>
 			<view @click="showAnswerCard" class="shiti-num-box">
 				<icon class="shiti-num-icon"></icon>
 				<text class="active-num">{{activeSt ? activeSt.onlyNum: 0}}</text>/<text>{{data.StListForSearch.length}}</text>
@@ -120,7 +120,6 @@
 	const popupRef = ref(null)
 	const scoreAnswerRef = ref(null)
 	const scoreAnswerTkRef = ref(null)
-
 	const startCountDown = ref(false);
 
 	const data = reactive({

+ 414 - 0
pages/client/Chengji/ksScoreShijuan.vue

@@ -0,0 +1,414 @@
+<template>
+	<view class="socre-shijuan">
+		<!-- 导航区域 -->
+		<view class="icon-title-navBar-box">
+			<view @click="handleBack" class="nav-bar-icon"></view>
+			<text class="nav-bar-title">{{data.ksName}}</text>
+		</view>
+		<!-- 上方区域 -->
+		<topCard @openCard="handleOpenCard" :name="data.ksName" :zyLevelName="data.zyLevelName" :userScore="data.userScore" :Score="data.Score" :count="activeSt && activeSt.onlyNum||0" :total="data.StListForSearch.length"></topCard>
+		
+		<view>
+			<!-- 段落 -->
+			<view class="kaoshi-shiti-content">
+				<!-- 试题区域 -->
+				<view v-if="activeSt">
+					<template v-if="activeSt.stTypeId == 1">
+						<!-- 单选 -->
+						<danxuan :question="activeSt" :key="activeSt.stId"></danxuan>
+					</template>
+					<template v-if="activeSt.stTypeId == 2">
+						<!-- 多选 -->
+						<duoxuan :question="activeSt" :key="activeSt.stId"></duoxuan>
+					</template>
+					<template v-if="activeSt.stTypeId == 3">
+						<!-- 判断 -->
+						<panduan :question="activeSt" :key="activeSt.stId"></panduan>
+					</template>
+					<template v-if="activeSt.stTypeId == 4">
+						<!-- 填空 -->
+						<tiankong :question="activeSt" :key="activeSt.stId"></tiankong>
+					</template>
+				</view>
+			</view>
+			<!-- 解析 -->
+			<view v-if="activeSt">
+				<view class="phone-question-answer-box" v-if="activeSt.stTypeId != 4">
+					<view class="phone-line-title">答案解析</view>
+					<view class="btdf-row">本题得分:<text>{{answerRes.score}}</text>分</view>
+					<view class="zqda-row">正确答案:<text>{{answerRes.result}}</text></view>
+					<view class="ndda-row">您的答案:<text>{{answerRes.reply}}</text></view>
+					<view class="dajx-row">答案解析: 
+						<rich-text :nodes="answerRes.answer"></rich-text>
+					</view>
+				</view>
+				<view class="phone-question-answer-box" v-else>
+					<view class="phone-line-title">答案解析</view>
+					<view class="btdf-row">本题得分:<text>{{answerRes.score}}</text>分</view>
+					<view class="zqda-row">正确答案:
+						<view v-for="(item,index) in answerRes.result">{{`填空${index+1}`}} : {{item}}</view>
+					</view>
+					<view class="ndda-row">您的答案:
+					<view v-for="(item,index) in answerRes.reply"> {{`填空${index+1}`}}: {{item}}</view>
+					</view>
+					<view class="dajx-row">答案解析: 
+						<rich-text :nodes="answerRes.answer"></rich-text>
+					</view>
+				</view>
+			</view>	
+			<!-- 上下按钮 -->
+			<template v-if="activeSt">
+				<button type="default" size="mini" hover-class="none" class="phone-green-btn ks-btn-prev" @click="handlePrev" v-if="!isFistStId">上一题</button>
+				<button type="default" size="mini" hover-class="none"class="phone-green-btn ks-btn-next" @click="handleNext" v-if="!isLastStId">下一题</button>
+			</template>
+			
+			<!-- 答题卡 -->
+			<uni-popup ref="popupRef" background-color="#fff" :is-mask-click="false" :mask-click="false">
+				<view class="answer-card-popup">
+					<view class="icon-title-bjcolor-navBar-box">
+						<view @click="handlePopupBack" class="nav-bar-icon"> </view>
+						<text class="nav-bar-title">答题卡</text>
+					</view>
+					<view class="answer-card-content" v-for="(paragraph,paragraphIndex) in questionData" :key="paragraphIndex">
+						<view class="paragraph-title">
+							{{paragraph.name}}
+						</view>
+						<view class="paragraph-qa" v-for="(qa,qaIndex) in paragraph.qas" :key="qaIndex" 
+						:class="getQaClass(qa)" @click="answerCardItemClick(qa)">{{qa.onlyNum}}
+						</view>
+					</view>
+				</view>
+			</uni-popup>
+			
+		</view>
+	</view>
+</template>
+
+<script setup>
+	import topCard from "@/components/score/topCard.vue"
+	import danxuan from "@/components/questions/danxuan.vue";
+	import duoxuan from "@/components/questions/duoxuan.vue";
+	import tiankong from "@/components/questions/tiankong.vue";
+	import panduan from "@/components/questions/panduan.vue";
+	import {useQuestionTools} from "@/components/questions/useQuestionTools.js";
+	
+	import { onLoad } from "@dcloudio/uni-app";
+	import {ref,reactive,computed} from "vue"
+	import * as lxApi from "@/api/lianxi.js"
+	const {
+		checkDanxuanReply,
+		checkDuoxuanReply,
+		checkPanduanReply,
+		checkTiankongReply,
+		getLetterByIndex
+	} = useQuestionTools();
+	
+	
+	const hisId = ref(null)
+	const popupRef = ref(null)
+	
+	const data = reactive({
+		ksId: null,
+		ksName: '',
+		stTotal: 0,
+		zyLevelName: '',
+		userScore: '',
+		ksScore: 0,
+		StListForSearch: [],
+		duanluo: []
+	})
+	
+	const questionData = ref([]);
+	const progress = reactive({
+		dlIndex: 0,
+		dtIndex: 0
+	})
+	
+	const dlName = computed(() => {
+		if (data.StListForSearch && activeSt.value) {
+			return data.StListForSearch[activeSt.value.onlyNum].paragraphName
+		} else {
+			return ''
+		}
+	})
+	
+	const activeSt = computed(() => {
+		if (questionData.value.length) {
+			return questionData.value.length && questionData.value[progress.dlIndex].qas[progress.dtIndex];
+		} else {
+			return null
+		}
+	})
+	
+	const answerRes = computed(() => {
+		const qa = activeSt.value ;
+		let score = qa.score;
+		let reply = '';
+		let result = '';
+		let answer = qa.answer;
+		if (qa.stTypeId == 1) {
+			// 单选题
+			if (qa.reply && qa.reply.trim() !== '') {
+				reply = getLetterByIndex(qa.reply)
+			} else {
+				reply = '未答'
+			}
+			
+			if (qa.result) {
+				result = getLetterByIndex(qa.result)
+			} else {
+				result = '无答案'
+			}
+		}
+		if (qa.stTypeId == 2) {
+			// 多选题
+			
+			if (qa.reply && qa.reply.length) {
+				reply = qa.reply.map(item => {
+					if (item.trim()) {
+						return getLetterByIndex(item.trim())
+					}
+				}).join(',')
+			} else {
+				reply = '未答'
+			}
+			if (qa.result) {
+				result = qa.result.map(item => {
+					if (item.trim()) {
+						return getLetterByIndex(item.trim())
+					}
+				}).join(',')
+			} else {
+				result = '无答案'
+			}
+		}
+		if (qa.stTypeId == 3) {
+			// 判断题
+			if (qa.reply == 0) {
+				reply = '错误'
+			}else if (qa.reply == 1) {
+				reply = '正确'
+			}
+			if (qa.result == 0) {
+				result = '错误'
+			}else if (qa.result == 1) {
+				result = '正确'
+			}
+		}
+		if (qa.stTypeId == 4) {
+			let reply = qa.reply || [];
+			let result =qa.result || [];
+			// 填空题
+			return {score,reply,result,answer}
+		} else {
+			return  {
+				score,reply,result,answer
+			}
+		}
+	})
+	
+	const isFistStId = computed(() => {
+		if (data.StListForSearch.length) {
+			return data.StListForSearch[0].stId == activeSt.value.stId
+		} else {
+			return false
+		}
+	});
+	const isLastStId = computed(() => {
+		if (data.StListForSearch.length) {
+			return data.StListForSearch[data.StListForSearch.length - 1].stId == activeSt.value.stId
+		} else {
+			return false
+		}
+	});
+	
+	
+	onLoad((options) => {
+		hisId.value = options.hisId;
+		initPage()
+	})
+	
+	
+	function getQaClass(qa) {
+		if (qa.marked && qa.marked === true) {
+			return 'paragraph-qa-block-mark';
+		} else {
+			if (qa.stTypeId == 1) {
+				if (checkDanxuanReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			} else if (qa.stTypeId == 2) {
+				if (checkDuoxuanReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			} else if (qa.stTypeId == 3) {
+				if (checkPanduanReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			} else if (qa.stTypeId == 4) {
+				if (checkTiankongReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			}
+		}
+	}
+	
+	
+	function handleBack() {
+		uni.redirectTo({
+			url: "/pages/admin/Lianxi/list"
+		})
+	}
+	
+	
+	function formatDuanluoList() {
+		let uIndex = 0; // 试题num
+		let iDuanluo = 0; // 段落num
+		let result = [];
+		for (const duanluo of data.duanluo) {
+			let paragraph = {
+				qas: [],
+			};
+			paragraph.name = duanluo.name;
+	
+			let iQa = 0; // 当前试题序号
+			let order = 0; // 当前题型中第几题
+			for (const iDanxuan of duanluo.danxuan) {
+				iDanxuan.type = 'danxuan';
+				iDanxuan.marked = false;
+				iDanxuan.onlyNum = uIndex + 1;
+				iDanxuan.order = order;
+				iDanxuan.iQa = iQa;
+				paragraph.qas.push(iDanxuan);
+				uIndex++;
+				order++;
+				iQa++;
+	
+				data.StListForSearch.push({
+					stId: iDanxuan.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iDanxuan.iQa,
+					num: iDanxuan.onlyNum
+				})
+			}
+			order = 0;
+			for (const iDuoxuan of duanluo.duoxuan) {
+				iDuoxuan.type = 'duoxuan';
+				iDuoxuan.marked = false;
+				iDuoxuan.onlyNum = uIndex + 1;
+				iDuoxuan.order = order;
+				paragraph.qas.push(iDuoxuan);
+				iDuoxuan.iQa = iQa;
+				uIndex++;
+				order++;
+				iQa++;
+	
+				data.StListForSearch.push({
+					stId: iDuoxuan.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iDuoxuan.iQa,
+					num: iDuoxuan.onlyNum
+				})
+			}
+			order = 0;
+			for (const iPanduan of duanluo.panduan) {
+				iPanduan.type = 'panduan';
+				iPanduan.marked = false;
+				iPanduan.onlyNum = uIndex + 1;
+				iPanduan.order = order;
+				paragraph.qas.push(iPanduan);
+				iPanduan.iQa = iQa;
+				uIndex++;
+				order++;
+				iQa++;
+	
+				data.StListForSearch.push({
+					stId: iPanduan.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iPanduan.iQa,
+					num: iPanduan.onlyNum
+				})
+			}
+			order = 0;
+			for (const iTiankong of duanluo.tiankong) {
+				iTiankong.type = 'tiankong';
+				iTiankong.marked = false;
+				iTiankong.onlyNum = uIndex + 1;
+				iTiankong.order = order;
+				paragraph.qas.push(iTiankong);
+				iTiankong.iQa = iQa;
+				uIndex++;
+				order++;
+				iQa++;
+	
+				data.StListForSearch.push({
+					stId: iTiankong.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iTiankong.iQa,
+					num: iTiankong.onlyNum
+				})
+			}
+			iDuanluo++;
+			questionData.value.push(paragraph)
+	
+		}
+	}
+	
+	function handlePrev() {
+		const qa = data.StListForSearch.find(item => item.stId == activeSt.value.stId);
+		const index = qa.num - 1;
+		if (index > 0) {
+			const result = data.StListForSearch[index - 1];
+			progress.dlIndex = result.dlIndex;
+			progress.dtIndex = result.dtIndex
+		}
+	
+	}
+	
+	function handleNext() {
+		const qa = data.StListForSearch.find(item => item.stId == activeSt.value.stId);
+		const index = qa.num - 1;
+		if (index < data.StListForSearch.length) {
+			const result = data.StListForSearch[index + 1];
+			progress.dlIndex = result.dlIndex;
+			progress.dtIndex = result.dtIndex
+		}
+	}
+	
+	
+	
+	function initPage() {
+		lxApi.getClientKsChengjiView({hisId: hisId.value}).then(res => {
+			const { duanluoList,ksName, zyLevelName,userScore,ksScore } = res.data;
+			data.ksName = ksName;
+			data.zyLevelName = zyLevelName;
+			data.userScore = userScore;
+			data.ksScore = ksScore;
+			data.duanluo = duanluoList;
+			
+			formatDuanluoList();
+		})
+	}
+	function handlePopupBack() {
+			popupRef.value.close()
+	}
+	function handleOpenCard() {
+		popupRef.value.open('bottom')
+	}
+</script>
+
+<style>
+
+</style>

+ 194 - 0
pages/client/Chengji/list.vue

@@ -0,0 +1,194 @@
+<template>
+	<view class="admin-kaoshi-page">
+		<view class="icon-title-navBar-box">
+			<view @click="goUpPage" class="nav-bar-icon"></view>
+			<text class="nav-bar-title">成绩</text>
+		</view>
+		<!-- 查询职业 -->
+		<view class="phone-search-box">
+			<input class="search-input" placeholder="请输入职业名称" v-model="data.zyName" />
+			<view class="search-icon" @click="handleSearch">
+				<uni-icons type="search" size="24" color="#fff"></uni-icons>
+			</view>
+		</view>
+		<!-- 课程列表 -->
+		<view class="kaoshi-content-box">
+			<scroll-view scroll-y="true" refresher-enabled="true" :refresher-triggered="data.loading"
+				:refresher-threshold="50" refresher-background="transparent" @refresherrefresh="onRefresh"
+				class="phone-scroll-view kaoshi-scroll-view">
+				<uni-list class="admin-list-box">
+					<uni-list-item v-for="item in data.list" class="admin-list-item-box">
+						<template v-slot:body>
+							<view class="item-kaoshi-row">
+								<!-- 数量 -->
+								<view class="ks-item-top">
+									<view>{{item.name}}</view>
+									<view class="ks-zyLevelName">{{item.zyLevelName}}</view>
+								</view>
+								<view class="ks-totalTm">
+									<icon class="phone-time-icon" /> {{item.answerStartTime}} - {{item.answerEndTime}}
+								</view>
+								<view class="ks-totalTm">
+									<icon class="phone-time-icon" /> {{item.okScore}} / {{item.ksScore}}
+								</view>
+								<button @click="checkKecheng(item)" type="primary" size="mini"
+									class="kaoshi-btn">查看内容</button>
+							</view>
+						</template>
+					</uni-list-item>
+					<uni-load-more :status="data.state" @click="getMore(0)"
+						:contentText="data.contentText"></uni-load-more>
+				</uni-list>
+			</scroll-view>
+		</view>
+
+		<!-- 页面底端 -->
+		<customTabbarAdminVue></customTabbarAdminVue>
+	</view>
+</template>
+
+<script setup>
+	import customTabbarAdminVue from "@/components/custom-tabbar/custom-tabbar-admin.vue";
+	import {
+		ref,
+		reactive
+	} from "vue";
+	import {
+		onLoad
+	} from "@dcloudio/uni-app";
+	import * as kaoshiApi from "@/api/kaoshi.js"
+	import {
+		formatDuration
+	} from "@/utils/common.js"
+	
+
+	const data = reactive({
+		zyName: '', // 职业名称
+		list: [], // 考试列表
+		loading: false,
+		page: 0,
+		size: 10,
+		state: 'more',
+		contentText: {
+			contentdown: '查看更多',
+			contentrefresh: '加载中',
+			contentnomore: '没有更多'
+		}
+	})
+
+	function goUpPage() {
+		uni.redirectTo({
+			url: '/pages/client/ShouYe/shouye'
+		})
+	}
+
+	function handleSearch() {
+		data.page = 0;
+		refreshData();
+	}
+
+	function checkKecheng(item) {
+		uni.navigateTo({
+			url: `/pages/client/Chengji/ksScoreShijuan?hisId=${item.hisId}`
+		})
+	}
+
+	function onRefresh() {
+		data.page = 0;
+		data.list = [];
+		data.loading = true;
+		refreshData();
+	}
+
+	function refreshData() {
+		const opt = {
+			page: 1,
+			size: 10, // 固定查询10条
+			zyName: data.zyName
+		}
+		data.list = [];
+		// 数学
+		data.state = 'loading';
+		data.page++;
+		opt.page = data.page;
+
+		kaoshiApi.getClientKsChengjiList(opt).then(res => {
+			data.list = data.list.concat(res.data.data);
+			data.loading = false;
+
+			if (res.data.total > data.list.length) {
+				data.state = 'more';
+				data.loading = false;
+			} else {
+				data.state = 'no-more';
+				data.loading = false;
+			}
+		}).catch(err => {
+			data.state = 'more';
+			data.loading = false;
+		})
+	}
+
+	function getMore() {
+		const opt = {
+			page: 1,
+			size: 10, // 固定查询10条
+			zyName: data.zyName
+		}
+		if (data.state == 'no-more') return;
+		data.state = 'loading';
+		data.page++;
+		opt.page = data.page;
+		kaoshiApi.getClientKsChengjiList(opt).then(res => {
+			data.list = data.list.concat(res.data.data);
+			data.loading = false;
+
+			if (res.data.total > data.list.length) {
+				data.state = 'more';
+				data.loading = false;
+			} else {
+				data.state = 'no-more';
+				data.loading = false;
+			}
+		}).catch(err => {
+			data.state = 'more';
+			data.loading = false;
+		})
+	}
+
+	onLoad(() => {
+		getMore()
+	})
+</script>
+
+<style lang="scss" scoped>
+	.phone-kecheng-page {
+		background-color: #ccc;
+		box-sizing: border-box;
+	}
+
+	.phone-search-content {
+		position: relative;
+		background-color: #fff;
+		height: 42px;
+
+		.search-input {
+			height: 42px;
+			line-height: 40px;
+			border-radius: 20px;
+			border: 1px solid #ccc;
+			padding: 0 70px 0 20px;
+		}
+
+		.search-icon {
+			position: absolute;
+			right: 5px;
+			top: 4px;
+			padding: 6px;
+			background-color: #ccc;
+			border-radius: 20px;
+			width: 50px;
+			text-align: center;
+		}
+	}
+</style>

+ 414 - 0
pages/client/Chengji/lxScoreShijuan.vue

@@ -0,0 +1,414 @@
+<template>
+	<view class="socre-shijuan">
+		<!-- 导航区域 -->
+		<view class="icon-title-navBar-box">
+			<view @click="handleBack" class="nav-bar-icon"></view>
+			<text class="nav-bar-title">{{data.lxName}}</text>
+		</view>
+		<!-- 上方区域 -->
+		<topCard @openCard="handleOpenCard" :name="data.lxName" :zyLevelName="data.zyLevelName" :userScore="data.userScore" :Score="data.Score" :count="activeSt && activeSt.onlyNum||0" :total="data.StListForSearch.length"></topCard>
+		
+		<view>
+			<!-- 段落 -->
+			<view class="kaoshi-shiti-content">
+				<!-- 试题区域 -->
+				<view v-if="activeSt">
+					<template v-if="activeSt.stTypeId == 1">
+						<!-- 单选 -->
+						<danxuan :question="activeSt" :key="activeSt.stId"></danxuan>
+					</template>
+					<template v-if="activeSt.stTypeId == 2">
+						<!-- 多选 -->
+						<duoxuan :question="activeSt" :key="activeSt.stId"></duoxuan>
+					</template>
+					<template v-if="activeSt.stTypeId == 3">
+						<!-- 判断 -->
+						<panduan :question="activeSt" :key="activeSt.stId"></panduan>
+					</template>
+					<template v-if="activeSt.stTypeId == 4">
+						<!-- 填空 -->
+						<tiankong :question="activeSt" :key="activeSt.stId"></tiankong>
+					</template>
+				</view>
+			</view>
+			<!-- 解析 -->
+			<view v-if="activeSt">
+				<view class="phone-question-answer-box" v-if="activeSt.stTypeId != 4">
+					<view class="phone-line-title">答案解析</view>
+					<view class="btdf-row">本题得分:<text>{{answerRes.score}}</text>分</view>
+					<view class="zqda-row">正确答案:<text>{{answerRes.result}}</text></view>
+					<view class="ndda-row">您的答案:<text>{{answerRes.reply}}</text></view>
+					<view class="dajx-row">答案解析: 
+						<rich-text :nodes="answerRes.answer"></rich-text>
+					</view>
+				</view>
+				<view class="phone-question-answer-box" v-else>
+					<view class="phone-line-title">答案解析</view>
+					<view class="btdf-row">本题得分:<text>{{answerRes.score}}</text>分</view>
+					<view class="zqda-row">正确答案:
+						<view v-for="(item,index) in answerRes.result">{{`填空${index+1}`}} : {{item}}</view>
+					</view>
+					<view class="ndda-row">您的答案:
+					<view v-for="(item,index) in answerRes.reply"> {{`填空${index+1}`}}: {{item}}</view>
+					</view>
+					<view class="dajx-row">答案解析: 
+						<rich-text :nodes="answerRes.answer"></rich-text>
+					</view>
+				</view>
+			</view>	
+			<!-- 上下按钮 -->
+			<template v-if="activeSt">
+				<button type="default" size="mini" hover-class="none" class="phone-green-btn ks-btn-prev" @click="handlePrev" v-if="!isFistStId">上一题</button>
+				<button type="default" size="mini" hover-class="none"class="phone-green-btn ks-btn-next" @click="handleNext" v-if="!isLastStId">下一题</button>
+			</template>
+			
+			<!-- 答题卡 -->
+			<uni-popup ref="popupRef" background-color="#fff" :is-mask-click="false" :mask-click="false">
+				<view class="answer-card-popup">
+					<view class="icon-title-bjcolor-navBar-box">
+						<view @click="handlePopupBack" class="nav-bar-icon"> </view>
+						<text class="nav-bar-title">答题卡</text>
+					</view>
+					<view class="answer-card-content" v-for="(paragraph,paragraphIndex) in questionData" :key="paragraphIndex">
+						<view class="paragraph-title">
+							{{paragraph.name}}
+						</view>
+						<view class="paragraph-qa" v-for="(qa,qaIndex) in paragraph.qas" :key="qaIndex" 
+						:class="getQaClass(qa)" @click="answerCardItemClick(qa)">{{qa.onlyNum}}
+						</view>
+					</view>
+				</view>
+			</uni-popup>
+			
+		</view>
+	</view>
+</template>
+
+<script setup>
+	import topCard from "@/components/score/topCard.vue"
+	import danxuan from "@/components/questions/danxuan.vue";
+	import duoxuan from "@/components/questions/duoxuan.vue";
+	import tiankong from "@/components/questions/tiankong.vue";
+	import panduan from "@/components/questions/panduan.vue";
+	import {useQuestionTools} from "@/components/questions/useQuestionTools.js";
+	
+	import { onLoad } from "@dcloudio/uni-app";
+	import {ref,reactive,computed} from "vue"
+	import * as lxApi from "@/api/lianxi.js"
+	const {
+		checkDanxuanReply,
+		checkDuoxuanReply,
+		checkPanduanReply,
+		checkTiankongReply,
+		getLetterByIndex
+	} = useQuestionTools();
+	
+	
+	const hisId = ref(null)
+	const popupRef = ref(null)
+	
+	const data = reactive({
+		lxId: null,
+		lxName: '',
+		stTotal: 0,
+		zyLevelName: '',
+		userScore: '',
+		ksScore: 0,
+		StListForSearch: [],
+		duanluo: []
+	})
+	
+	const questionData = ref([]);
+	const progress = reactive({
+		dlIndex: 0,
+		dtIndex: 0
+	})
+	
+	const dlName = computed(() => {
+		if (data.StListForSearch && activeSt.value) {
+			return data.StListForSearch[activeSt.value.onlyNum].paragraphName
+		} else {
+			return ''
+		}
+	})
+	
+	const activeSt = computed(() => {
+		if (questionData.value.length) {
+			return questionData.value.length && questionData.value[progress.dlIndex].qas[progress.dtIndex];
+		} else {
+			return null
+		}
+	})
+	
+	const answerRes = computed(() => {
+		const qa = activeSt.value ;
+		let score = qa.score;
+		let reply = '';
+		let result = '';
+		let answer = qa.answer;
+		if (qa.stTypeId == 1) {
+			// 单选题
+			if (qa.reply && qa.reply.trim() !== '') {
+				reply = getLetterByIndex(qa.reply)
+			} else {
+				reply = '未答'
+			}
+			
+			if (qa.result) {
+				result = getLetterByIndex(qa.result)
+			} else {
+				result = '无答案'
+			}
+		}
+		if (qa.stTypeId == 2) {
+			// 多选题
+			
+			if (qa.reply && qa.reply.length) {
+				reply = qa.reply.map(item => {
+					if (item.trim()) {
+						return getLetterByIndex(item.trim())
+					}
+				}).join(',')
+			} else {
+				reply = '未答'
+			}
+			if (qa.result) {
+				result = qa.result.map(item => {
+					if (item.trim()) {
+						return getLetterByIndex(item.trim())
+					}
+				}).join(',')
+			} else {
+				result = '无答案'
+			}
+		}
+		if (qa.stTypeId == 3) {
+			// 判断题
+			if (qa.reply == 0) {
+				reply = '错误'
+			}else if (qa.reply == 1) {
+				reply = '正确'
+			}
+			if (qa.result == 0) {
+				result = '错误'
+			}else if (qa.result == 1) {
+				result = '正确'
+			}
+		}
+		if (qa.stTypeId == 4) {
+			let reply = qa.reply || [];
+			let result =qa.result || [];
+			// 填空题
+			return {score,reply,result,answer}
+		} else {
+			return  {
+				score,reply,result,answer
+			}
+		}
+	})
+	
+	const isFistStId = computed(() => {
+		if (data.StListForSearch.length) {
+			return data.StListForSearch[0].stId == activeSt.value.stId
+		} else {
+			return false
+		}
+	});
+	const isLastStId = computed(() => {
+		if (data.StListForSearch.length) {
+			return data.StListForSearch[data.StListForSearch.length - 1].stId == activeSt.value.stId
+		} else {
+			return false
+		}
+	});
+	
+	
+	onLoad((options) => {
+		hisId.value = options.hisId;
+		initPage()
+	})
+	
+	
+	function getQaClass(qa) {
+		if (qa.marked && qa.marked === true) {
+			return 'paragraph-qa-block-mark';
+		} else {
+			if (qa.stTypeId == 1) {
+				if (checkDanxuanReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			} else if (qa.stTypeId == 2) {
+				if (checkDuoxuanReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			} else if (qa.stTypeId == 3) {
+				if (checkPanduanReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			} else if (qa.stTypeId == 4) {
+				if (checkTiankongReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			}
+		}
+	}
+	
+	
+	function handleBack() {
+		uni.redirectTo({
+			url: "/pages/admin/Lianxi/list"
+		})
+	}
+	
+	
+	function formatDuanluoList() {
+		let uIndex = 0; // 试题num
+		let iDuanluo = 0; // 段落num
+		let result = [];
+		for (const duanluo of data.duanluo) {
+			let paragraph = {
+				qas: [],
+			};
+			paragraph.name = duanluo.name;
+	
+			let iQa = 0; // 当前试题序号
+			let order = 0; // 当前题型中第几题
+			for (const iDanxuan of duanluo.danxuan) {
+				iDanxuan.type = 'danxuan';
+				iDanxuan.marked = false;
+				iDanxuan.onlyNum = uIndex + 1;
+				iDanxuan.order = order;
+				iDanxuan.iQa = iQa;
+				paragraph.qas.push(iDanxuan);
+				uIndex++;
+				order++;
+				iQa++;
+	
+				data.StListForSearch.push({
+					stId: iDanxuan.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iDanxuan.iQa,
+					num: iDanxuan.onlyNum
+				})
+			}
+			order = 0;
+			for (const iDuoxuan of duanluo.duoxuan) {
+				iDuoxuan.type = 'duoxuan';
+				iDuoxuan.marked = false;
+				iDuoxuan.onlyNum = uIndex + 1;
+				iDuoxuan.order = order;
+				paragraph.qas.push(iDuoxuan);
+				iDuoxuan.iQa = iQa;
+				uIndex++;
+				order++;
+				iQa++;
+	
+				data.StListForSearch.push({
+					stId: iDuoxuan.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iDuoxuan.iQa,
+					num: iDuoxuan.onlyNum
+				})
+			}
+			order = 0;
+			for (const iPanduan of duanluo.panduan) {
+				iPanduan.type = 'panduan';
+				iPanduan.marked = false;
+				iPanduan.onlyNum = uIndex + 1;
+				iPanduan.order = order;
+				paragraph.qas.push(iPanduan);
+				iPanduan.iQa = iQa;
+				uIndex++;
+				order++;
+				iQa++;
+	
+				data.StListForSearch.push({
+					stId: iPanduan.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iPanduan.iQa,
+					num: iPanduan.onlyNum
+				})
+			}
+			order = 0;
+			for (const iTiankong of duanluo.tiankong) {
+				iTiankong.type = 'tiankong';
+				iTiankong.marked = false;
+				iTiankong.onlyNum = uIndex + 1;
+				iTiankong.order = order;
+				paragraph.qas.push(iTiankong);
+				iTiankong.iQa = iQa;
+				uIndex++;
+				order++;
+				iQa++;
+	
+				data.StListForSearch.push({
+					stId: iTiankong.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iTiankong.iQa,
+					num: iTiankong.onlyNum
+				})
+			}
+			iDuanluo++;
+			questionData.value.push(paragraph)
+	
+		}
+	}
+	
+	function handlePrev() {
+		const qa = data.StListForSearch.find(item => item.stId == activeSt.value.stId);
+		const index = qa.num - 1;
+		if (index > 0) {
+			const result = data.StListForSearch[index - 1];
+			progress.dlIndex = result.dlIndex;
+			progress.dtIndex = result.dtIndex
+		}
+	
+	}
+	
+	function handleNext() {
+		const qa = data.StListForSearch.find(item => item.stId == activeSt.value.stId);
+		const index = qa.num - 1;
+		if (index < data.StListForSearch.length) {
+			const result = data.StListForSearch[index + 1];
+			progress.dlIndex = result.dlIndex;
+			progress.dtIndex = result.dtIndex
+		}
+	}
+	
+	
+	
+	function initPage() {
+		lxApi.getClientLianxiChengjiView({hisId: hisId.value}).then(res => {
+			const { duanluoList,lxName, zyLevelName,userScore,ksScore } = res.data;
+			data.lxName = lxName;
+			data.zyLevelName = zyLevelName;
+			data.userScore = userScore;
+			data.ksScore = ksScore;
+			data.duanluo = duanluoList;
+			
+			formatDuanluoList();
+		})
+	}
+	function handlePopupBack() {
+			popupRef.value.close()
+	}
+	function handleOpenCard() {
+		popupRef.value.open('bottom')
+	}
+</script>
+
+<style>
+
+</style>

+ 22 - 12
pages/client/Kaoshi/exam.vue

@@ -14,7 +14,6 @@
 					:start="startCountDown"></uni-countdown>
 			</view>
 			<view v-if="activeSt" class="title-types">{{dlName}}</view>
-			<view>100分钟</view>
 		</view>
 
 
@@ -44,7 +43,7 @@
 
 		<view class="kaoshi-bottom-box">
 			<button class="phone-green-btn bj-btn" hover-class="none" type="default" size="mini"
-				@click="handleBiaoji">标记</button>
+				@click="handleBiaoji">{{activeSt && activeSt.marked ? '取标':'标记'}}</button>
 			<view @click="showAnswerCard" class="shiti-num-box">
 				<icon class="shiti-num-icon"></icon>
 				<text
@@ -167,16 +166,17 @@
 		ksName: '',
 		stTotal: 0,
 		stScore: 0,
-		biaoji: null,
+		biaoji: {},
 		endSecond: 0,
 		pageSize: 0,
 		toggleScreenFlag: 0,
 		toggleScreenSecond: 0,
 		zhuapai: 0,
 		duanluo: [],
-		markDB: [],
 		StListForSearch: [],
 	})
+	
+	const markDB = ref([]);
 
 	const questionData = ref([]);
 
@@ -354,15 +354,16 @@
 		})
 	
 		ksApi.getClientKsSubmit(result).then(res => {
-			console.log('result', result)
 			if (res.code == 0) {
-				subScoreRef.value.showDialog(res.data)
+				subScoreRef.value.showDialog(res.data);
+				// 清空缓存
+				removeCacheKs(data.operId);
 			}
 		})
 	}
 	
 	function onTimeUp() {
-		handleSubmit(true);
+		handleSubmit();
 	}
 	//  交卷相关功能 end
 
@@ -515,7 +516,7 @@
 			let order = 0; // 当前题型中第几题
 			for (const iDanxuan of duanluo.danxuan) {
 				iDanxuan.type = 'danxuan';
-				iDanxuan.marked = false;
+				iDanxuan.marked = data.biaoji[iDanxuan.stId] ? true: false;
 				iDanxuan.onlyNum = uIndex + 1;
 				iDanxuan.order = order;
 				iDanxuan.iQa = iQa;
@@ -535,7 +536,7 @@
 			order = 0;
 			for (const iDuoxuan of duanluo.duoxuan) {
 				iDuoxuan.type = 'duoxuan';
-				iDuoxuan.marked = false;
+				iDuoxuan.marked = data.biaoji[iDuoxuan.stId] ? true: false;
 				iDuoxuan.onlyNum = uIndex + 1;
 				iDuoxuan.order = order;
 				paragraph.qas.push(iDuoxuan);
@@ -556,7 +557,7 @@
 			order = 0;
 			for (const iPanduan of duanluo.panduan) {
 				iPanduan.type = 'panduan';
-				iPanduan.marked = false;
+				iPanduan.marked = data.biaoji[iPanduan.stId] ? true: false;
 				iPanduan.onlyNum = uIndex + 1;
 				iPanduan.order = order;
 				paragraph.qas.push(iPanduan);
@@ -576,7 +577,7 @@
 			order = 0;
 			for (const iTiankong of duanluo.tiankong) {
 				iTiankong.type = 'tiankong';
-				iTiankong.marked = false;
+				iTiankong.marked = data.biaoji[iTiankong.stId] ? true: false;
 				iTiankong.onlyNum = uIndex + 1;
 				iTiankong.order = order;
 				paragraph.qas.push(iTiankong);
@@ -603,6 +604,15 @@
 
 	function handleBiaoji() {
 		activeSt.value.marked = !activeSt.value.marked;
+		data.biaoji.value[activeSt.value.stId] = activeSt.value.marked
+		ksApi.getClientKaoshiBiaoji({
+			operId: data.operId,
+			biaoji: JSON.stringify(data.biaoji)
+		}).catch(err => {
+			uni.redirectTo({
+				url: '/pages/client/Kaoshi/list'
+			})
+		})
 	}
 
 	function formatKaoshiData() {
@@ -655,7 +665,7 @@
 			data.ksName = ksName;
 			data.stTotal = stTotal;
 			data.stScore = stScore;
-			data.biaoji = biaoji;
+			data.biaoji = biaoji ? JSON.parse(biaoji): {};
 			data.endSecond = endSecond;
 			data.pageSize = pageSize;
 			data.toggleScreenFlag = toggleScreenFlag;

+ 528 - 0
pages/client/Lianxi/exam.vue

@@ -0,0 +1,528 @@
+<template>
+	<view class="phone-kaoshi-page">
+		<!-- 导航区域 -->
+		<view class="icon-title-navBar-box">
+			<view @click="handleBack" class="nav-bar-icon"></view>
+			<text class="nav-bar-title">{{data.lxName}}</text>
+		</view>
+		<!-- 第一行 -->
+		<view class="kaoshi-page-title">
+			<!--  倒计时 -->
+			<view v-if="!!data.endSecond">
+				<text>考试倒计时:</text>
+				<uni-countdown :show-day="true" :second="1000" @timeup="onTimeUp"
+					:start="startCountDown"></uni-countdown>
+			</view>
+			<view v-if="activeSt" class="title-types">{{dlName}}</view>
+		</view>
+
+
+		<view class="kaoshi-shiti-content">
+			<!-- 内容区域 -->
+			<!-- 试题区域 -->
+			<view v-if="activeSt">
+				<template v-if="activeSt.stTypeId == 1">
+					<!-- 单选 -->
+					<danxuan :question="activeSt" :key="activeSt.stId"></danxuan>
+				</template>
+				<template v-if="activeSt.stTypeId == 2">
+					<!-- 多选 -->
+					<duoxuan :question="activeSt" :key="activeSt.stId"></duoxuan>
+				</template>
+				<template v-if="activeSt.stTypeId == 3">
+					<!-- 判断 -->
+					<panduan :question="activeSt" :key="activeSt.stId"></panduan>
+				</template>
+				<template v-if="activeSt.stTypeId == 4">
+					<!-- 填空 -->
+					<tiankong :question="activeSt" :key="activeSt.stId"></tiankong>
+				</template>
+			</view>
+
+		</view>
+
+		<view class="kaoshi-bottom-box">
+			<button class="phone-green-btn bj-btn" hover-class="none" type="default" size="mini"
+				@click="handleBiaoji">{{activeSt && activeSt.marked ? '取标':'标记'}}</button>
+			<view @click="showAnswerCard" class="shiti-num-box">
+				<icon class="shiti-num-icon"></icon>
+				<text
+					class="active-num">{{activeSt ? activeSt.onlyNum: 0}}</text>/<text>{{data.StListForSearch.length}}</text>
+			</view>
+		</view>
+		<template v-if="activeSt">
+			<button type="default" size="mini" hover-class="none" class="phone-green-btn ks-btn-prev"
+				@click="handlePrev" v-if="!isFistStId">上一题</button>
+			<button type="default" size="mini" hover-class="none" class="phone-green-btn ks-btn-next"
+				@click="handleNext" v-if="!isLastStId">下一题</button>
+			<button type="default" size="mini" hover-class="none" class="phone-green-btn ks-btn-next"
+				@click="handleJiaojuan" v-if="isLastStId">交卷</button>
+		</template>
+
+		<!-- 答题卡 -->
+		<uni-popup ref="popupRef" background-color="#fff" :is-mask-click="false" :mask-click="false">
+			<view class="answer-card-popup">
+				<view class="icon-title-bjcolor-navBar-box">
+					<view @click="handlePopupBack" class="nav-bar-icon"> </view>
+					<text class="nav-bar-title">答题卡</text>
+				</view>
+				<view class="answer-card-content" v-for="(paragraph,paragraphIndex) in questionData"
+					:key="paragraphIndex">
+					<view class="paragraph-title">
+						{{paragraph.name}}
+					</view>
+					<view class="paragraph-qa" v-for="(qa,qaIndex) in paragraph.qas" :key="qaIndex"
+						:class="getQaClass(qa)" @click="answerCardItemClick(qa)">{{qa.onlyNum}}
+					</view>
+				</view>
+			</view>
+		</uni-popup>
+		<!-- 交卷确认 -->
+		<answerQueren ref="answerQrRef" @confirm="handleQuerenConfirm"></answerQueren>
+		<!-- 考试得分 -->
+		<submitScoreVue title="练习得分" ref="subScoreRef" @confirm="handleScoreConfirm" @close="handleScoreClose"></submitScoreVue>
+	</view>
+</template>
+
+<script setup>
+	import {
+		ref,
+		reactive,
+		computed,
+		watch,
+		nextTick
+	} from "vue";
+	import answerQueren from "@/components/zhuapaiConfirm/answerQueren.vue";
+	import submitScoreVue from "@/components/zhuapaiConfirm/submitScore.vue";
+	import {
+		onLoad
+	} from "@dcloudio/uni-app";
+	import * as lxApi from "@/api/lianxi.js"
+	import danxuan from "@/components/questions/danxuan.vue";
+	import duoxuan from "@/components/questions/duoxuan.vue";
+	import tiankong from "@/components/questions/tiankong.vue";
+	import panduan from "@/components/questions/panduan.vue";
+	import {
+		useQuestionTools
+	} from "@/components/questions/useQuestionTools.js";
+
+
+	const {
+		checkDanxuanReply,
+		checkDuoxuanReply,
+		checkPanduanReply,
+		checkTiankongReply,
+		getLetterByIndex
+	} = useQuestionTools();
+
+	onLoad((option) => {
+		data.lxId = option.lxId;
+		data.zhuapai = option.zhuapai
+		initKaoshi();
+	})
+
+
+	const popupRef = ref(null)
+	const zhuapaiConfirmRef = ref(null)
+	const answerQrRef = ref(null);
+	const startCountDown = ref(false);
+	const subScoreRef = ref(null)
+	
+	const timer1 = ref(null);
+
+	const data = reactive({
+		lxId: null,
+		operId: null,
+		lxName: '',
+		stTotal: 0,
+		stScore: 0,
+		biaoji: {},
+		endSecond: 0,
+		pageSize: 0,
+		toggleScreenFlag: 0,
+		toggleScreenSecond: 0,
+		zhuapai: 0,
+		duanluo: [],
+		StListForSearch: [],
+	})
+	
+	const markDB = ref([]);
+
+	const questionData = ref([]);
+
+	const progress = reactive({
+		dlIndex: 0,
+		dtIndex: 0
+	})
+
+	const dlName = computed(() => {
+		if (data.StListForSearch && activeSt.value) {
+			return data.StListForSearch[activeSt.value.onlyNum - 1].paragraphName
+		} else {
+			return ''
+		}
+	})
+
+	watch(() => data.duanluo, (newVal) => {
+		// 计算已答试题数量
+	}, {
+		deep: true
+	})
+
+	const activeSt = computed(() => {
+		if (questionData.value.length) {
+			return questionData.value.length && questionData.value[progress.dlIndex].qas[progress.dtIndex];
+		} else {
+			return null
+		}
+	})
+
+	const isFistStId = computed(() => {
+		if (data.StListForSearch.length) {
+			return data.StListForSearch[0].stId == activeSt.value.stId
+		} else {
+			return false
+		}
+	});
+	const isLastStId = computed(() => {
+		if (data.StListForSearch.length) {
+			return data.StListForSearch[data.StListForSearch.length - 1].stId == activeSt.value.stId
+		} else {
+			return false
+		}
+	});
+	
+	
+	function handleScoreClose() {
+		uni.redirectTo({
+			url: '/pages/client/Lianxi/list'
+		})
+	}
+	
+	// 考试得分相关 start
+	function handleScoreConfirm() {
+		uni.redirectTo({
+			url: '/pages/client/Chengji/lxScoreShijuan'
+		})
+	}
+	
+	// 考试得分相关 end
+	
+	//  交卷相关功能 start
+	function checkJiaojuan() {
+		const result = []
+		let count = 0;
+		let total = 0;
+		questionData.value.forEach(dl => {
+			dl.qas.forEach(st => {
+				const opt = {
+					stId: st.stId,
+					reply: st.reply,
+					stTypeId: st.stTypeId
+				}
+				result.push(opt)
+			})
+		})
+
+		result.forEach(item => {
+			total++;
+			if (item.stTypeId == 1 && !checkDanxuanReply(item)) {
+				count++;
+			}
+			if (item.stTypeId == 2 && !checkDuoxuanReply(item)) {
+				count++;
+			}
+			if (item.stTypeId == 3 && !checkPanduanReply(item)) {
+				count++;
+			}
+			if (item.stTypeId == 4 && !checkTiankongReply(item)) {
+				count++;
+			}
+		})
+		return {
+			total,
+			count,
+		}
+	}
+
+	function handleJiaojuan() {
+		const result = checkJiaojuan()
+		console.log(result)
+		if (result.count) {
+			// 提示
+			answerQrRef.value.showDialog({
+				answercartsCount: result.count,
+				answercartsTotal: result.total,
+			})
+		} else {
+			handleSubmit()
+		}
+	}
+
+	function handleQuerenConfirm() {
+		handleSubmit()
+	}
+	
+	function handleSubmit(force = false) {
+		const result = {
+			force,
+			operId: data.operId,
+			replyList: []
+		};
+		questionData.value.forEach(dl => {
+			dl.qas.forEach(st => {
+				const opt = {
+					stId: st.stId,
+					reply: st.reply
+				}
+				result.replyList.push(opt)
+			})
+		})
+	
+		lxApi.getClientLianxiSubmit(result).then(res => {
+			if (res.code == 0) {
+				subScoreRef.value.showDialog(res.data);
+			}
+		})
+	}
+	
+	function onTimeUp() {
+		handleSubmit(true);
+	}
+	//  交卷相关功能 end
+
+	function forceSubmit() {
+		// 强制交卷
+		console.log('强制交卷')
+		handleSubmit(true)
+	}
+
+	function getQaClass(qa) {
+		if (qa.marked && qa.marked === true) {
+			return 'paragraph-qa-block-mark';
+		} else {
+			if (qa.stTypeId == 1) {
+				if (checkDanxuanReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			} else if (qa.stTypeId == 2) {
+				if (checkDuoxuanReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			} else if (qa.stTypeId == 3) {
+				if (checkPanduanReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			} else if (qa.stTypeId == 4) {
+				if (checkTiankongReply(qa)) {
+					return 'paragraph-qa-block-done';
+				} else {
+					return 'paragraph-qa-block-init';
+				}
+			}
+		}
+	}
+
+	function skipQuestion(dlIndex, dtIndex) {
+		progress.dlIndex = dlIndex;
+		progress.dtIndex = dtIndex;
+		handlePopupBack()
+	}
+
+	function answerCardItemClick(qa) {
+		const actQa = data.StListForSearch.find(item => item.stId == qa.stId);
+		skipQuestion(actQa.dlIndex, actQa.dtIndex)
+
+	}
+
+	function handleBack() {
+		uni.redirectTo({
+			url: "/pages/client/Lianxi/list"
+		})
+	}
+
+	function showAnswerCard() {
+		popupRef.value.open('bottom')
+	}
+
+	function handlePopupBack() {
+		popupRef.value.close()
+	}
+
+	function handlePrev() {
+		const qa = data.StListForSearch.find(item => item.stId == activeSt.value.stId);
+		const index = qa.onlyNum - 1;
+		if (index > 0) {
+			const result = data.StListForSearch[index - 1];
+			progress.dlIndex = result.dlIndex;
+			progress.dtIndex = result.dtIndex
+		}
+
+	}
+
+	function handleNext() {
+		const qa = data.StListForSearch.find(item => item.stId == activeSt.value.stId);
+		const index = qa.onlyNum - 1;
+		if (index < data.StListForSearch.length) {
+			const result = data.StListForSearch[index + 1];
+			progress.dlIndex = result.dlIndex;
+			progress.dtIndex = result.dtIndex
+		}
+	}
+
+	function formatDuanluoList(dlData) {
+		let uIndex = 0; // 试题onlyNum
+		let iDuanluo = 0; // 段落onlyNum
+		let result = [];
+		for (const duanluo of data.duanluo) {
+			let paragraph = {
+				qas: [],
+			};
+			paragraph.name = duanluo.name;
+
+			let iQa = 0; // 当前试题序号
+			let order = 0; // 当前题型中第几题
+			for (const iDanxuan of duanluo.danxuan) {
+				iDanxuan.type = 'danxuan';
+				iDanxuan.marked = data.biaoji[iDanxuan.stId] ? true: false;
+				iDanxuan.onlyNum = uIndex + 1;
+				iDanxuan.order = order;
+				iDanxuan.iQa = iQa;
+				paragraph.qas.push(iDanxuan);
+				uIndex++;
+				order++;
+				iQa++;
+
+				data.StListForSearch.push({
+					stId: iDanxuan.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iDanxuan.iQa,
+					onlyNum: iDanxuan.onlyNum
+				})
+			}
+			order = 0;
+			for (const iDuoxuan of duanluo.duoxuan) {
+				iDuoxuan.type = 'duoxuan';
+				iDuoxuan.marked = data.biaoji[iDuoxuan.stId] ? true: false;
+				iDuoxuan.onlyNum = uIndex + 1;
+				iDuoxuan.order = order;
+				paragraph.qas.push(iDuoxuan);
+				iDuoxuan.iQa = iQa;
+				iDuoxuan.reply = [];
+				uIndex++;
+				order++;
+				iQa++;
+
+				data.StListForSearch.push({
+					stId: iDuoxuan.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iDuoxuan.iQa,
+					onlyNum: iDuoxuan.onlyNum
+				})
+			}
+			order = 0;
+			for (const iPanduan of duanluo.panduan) {
+				iPanduan.type = 'panduan';
+				iPanduan.marked = data.biaoji[iPanduan.stId] ? true: false;
+				iPanduan.onlyNum = uIndex + 1;
+				iPanduan.order = order;
+				paragraph.qas.push(iPanduan);
+				iPanduan.iQa = iQa;
+				uIndex++;
+				order++;
+				iQa++;
+
+				data.StListForSearch.push({
+					stId: iPanduan.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iPanduan.iQa,
+					onlyNum: iPanduan.onlyNum
+				})
+			}
+			order = 0;
+			for (const iTiankong of duanluo.tiankong) {
+				iTiankong.type = 'tiankong';
+				iTiankong.marked = data.biaoji[iTiankong.stId] ? true: false;
+				iTiankong.onlyNum = uIndex + 1;
+				iTiankong.order = order;
+				paragraph.qas.push(iTiankong);
+				iTiankong.iQa = iQa;
+				iTiankong.reply = new Array(iTiankong.count).fill('');;
+				uIndex++;
+				order++;
+				iQa++;
+
+				data.StListForSearch.push({
+					stId: iTiankong.stId,
+					paragraphName: paragraph.name,
+					dlIndex: iDuanluo,
+					dtIndex: iTiankong.iQa,
+					onlyNum: iTiankong.onlyNum
+				})
+			}
+			iDuanluo++;
+			questionData.value.push(paragraph)
+			console.log('1', questionData.value)
+			console.log('2', data.StListForSearch)
+		}
+	}
+
+	function handleBiaoji() {
+		activeSt.value.marked = !activeSt.value.marked;
+		data.biaoji.value[activeSt.value.stId] = activeSt.value.marked
+		lxApi.getClientLianxiBiaoji({
+			operId: data.operId,
+			biaoji: JSON.stringify(data.biaoji)
+		}).catch(err => {
+			uni.redirectTo({
+				url: '/pages/client/Lianxi/list'
+			})
+		})
+	}
+
+
+	function initKaoshi() {
+		lxApi.getClientLianxiStart({
+			lxId: data.lxId
+		}).then(res => {
+			const {
+				lxId,
+				operId,
+				lxName,
+				stTotal,
+				stScore,
+				biaoji,
+				endSecond,
+				pageSize,
+				toggleScreenFlag,
+				toggleScreenSecond,
+				zhuapai,
+				duanluoList
+			} = res.data;
+
+			data.lxId = lxId;
+			data.operId = operId;
+			data.lxName = lxName;
+			data.stTotal = stTotal;
+			data.stScore = stScore;
+			data.biaoji = biaoji ? JSON.parse(biaoji): {};
+			data.endSecond = endSecond;
+			data.pageSize = pageSize;
+			data.duanluo = duanluoList;
+			formatDuanluoList(data.duanluo);
+			uni.setNavigationBarTitle({
+				title: data.lxName
+			});
+			startCountDown.value = true;
+		})
+	}
+</script>

+ 1 - 1
pages/client/Lianxi/list.vue

@@ -98,7 +98,7 @@
 	
 	function checkKaoshi(item) {
 		uni.redirectTo({
-			url: `/pages/client/Lianxi/lianxi?lxId=${item.lxId}`
+			url: `/pages/client/Lianxi/exam?lxId=${item.lxId}`
 		})
 	}