JLBA202505130001_关于吉林银行新建AI智能培训系统的需求_合并两个分支冲突

This commit is contained in:
田岩
2026-01-16 08:48:47 +08:00
21 changed files with 294 additions and 161 deletions
+3 -1
View File
@@ -4,7 +4,7 @@ ENV = 'development'
#VITE_APP_BASE_API_Url = 'https://aits.jlbank.com.cn:7001'
#VITE_APP_BASE_API_Url = 'https://aits.jlbank.com.cn:7002'
VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002'
@@ -15,8 +15,10 @@ VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002'
# VITE_APP_BASE_API_Url = 'http://192.168.108.129'
# dev
#VITE_APP_BASE_API_Url = 'http://25.18.122.65:7001'
# sit
#VITE_APP_BASE_API_Url = 'http://25.18.122.91:9786'
+3 -2
View File
@@ -4,12 +4,13 @@ ENV = 'development.yh'
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.65:7001'
VITE_APP_BASE_H5_API_Url = 'http://25.18.122.91:9786'
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.78:9786'
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.91:9786'
VITE_APP_BASE_H5_API_Url = 'http://25.18.122.78:9786'
# VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002'
# VITE_APP_BASE_H5_API_Url_TRAEXAM = 'http://25.64.32.154:9604'
# VITE_APP_BASE_H5_API_Url_TRAPRACTICE = 'http://25.64.32.156:9603'
# VITE_APP_BASE_H5_API_Url_TRAAPP = 'http://25.64.32.154:9601'
# VITE_APP_BASE_H5_API_Url_TRAAPP = 'http://25.64.32.158:9601'
# VITE_APP_BASE_H5_API_Url_TRASTUDY = 'http://25.64.32.154:9602'
# VITE_APP_BASE_H5_API_Url_TRAASK = 'http://25.64.32.157:9605'
+41 -35
View File
@@ -7,15 +7,17 @@
<image :src="select_status_icon" class="img"></image>
</view>
</view>
<view class="dimension-line" v-for="item in evalSettingVos">
<text class="tr">{{ item.gradeDimens }}</text>
<text class="td">{{ item.anlyGrade }}</text>
<view class="dimension-max" v-for="(item,index) in evalSettingVos">
<view class="dimension-div">
<image class="icon-img" :src="index % 2 === 1 ?li2:li1" mode=""></image>
<text class="tr">{{ item.gradeDimens }}</text>
<text class="td">{{ item.anlyGrade }}</text>
</view>
<view class="your_answer" v-if="item.dimensCode === '01'">
<rich-text v-if="missingKeywords.length !== keywordsLength" :nodes="highlightedText" class="content" />
<rich-text v-if="missingKeywords.length !== keywordsLength" :nodes="highlightedText" class="content" />
<view class="mt-10" v-if="missingKeywords.length">
<text class="">未命中</text>
<text v-for="(keyword, index) in missingKeywords" :key="index" class="miss-keyword-item">
<!-- 关键词红色 -->
<text class="keyword-text">{{ keyword }}</text>
<text class="separator" v-if="index < missingKeywords.length - 1"></text>
</text>
@@ -28,7 +30,8 @@
<script setup>
import { ref, reactive, onMounted, nextTick, computed, watch } from 'vue';
import { optionErrorIcon, optionSuccessIcon } from '@/common/imgSvg';
import li1 from '@/static/images/examination/li-1.png'
import li2 from '@/static/images/examination/li-2.png'
const emit = defineEmits(['click_option']);
const props = defineProps({
value: {
@@ -56,7 +59,7 @@
return optionErrorIcon();
}
});
const keywords = computed(() => {
if (!props.value?.relKeyword) return [];
return props.value.relKeyword.split(/[,、/]/).map((key) => key.trim());
@@ -129,7 +132,7 @@
if (!props.anserResult) {
return [];
}
// 步骤1:按顿号拆分关键词组
const keywordGroups = relKeyword.split('、');
const missing = [];
@@ -138,7 +141,7 @@
// 拆分同关键词的不同说法(/ 分隔)
const keywordVariants = group.split('/');
let isFound = false;
// 检查答案中是否包含任意一种说法
for (const variant of keywordVariants) {
// 可选:增加 trim() 忽略首尾空格,提升匹配容错
@@ -147,13 +150,13 @@
break;
}
}
// 未找到则加入缺失列表
if (isFound) {
missing.push(group);
}
});
return missing;
});
const click_option = () => {
@@ -167,17 +170,17 @@
}
.analysis_div {
:deep(.highlight) {
color: #15b859;
color: #333333;
}
}
.success {
background-color: #e7f8ed;
background-color: #f5f5f5;
.td {
color: #15b859;
}
}
.error {
background-color: #fce8e9;
background-color: #f5f5f5;
.td {
color: #f5212d;
}
@@ -188,19 +191,19 @@
text-decoration: underline;
}
}
.hit-keyword-item{
.hit-keyword-item {
.keyword-text {
color: #15b859;
text-decoration: underline;
}
}
.miss-keyword-item{
.miss-keyword-item {
.keyword-text {
color: #d70c18;
text-decoration: underline;
color: #666666;
// text-decoration: underline;
}
}
.separator {
}
.analysis_div {
@@ -212,24 +215,26 @@
margin: 12rpx 0;
position: relative;
}
.dimension-line {
.dimension-max {
// margin: 12rpx 0;
// position: relative;
// padding-left: 1.5em;
// display: flex;
// align-items: center;
}
.dimension-div {
margin: 12rpx 0;
position: relative;
padding-left: 1.5em;
}
.dimension-line::before {
content: '';
position: absolute;
left: 0.5rem; /* 对齐padding-left的起始位置 */
top: 0.5rem;
// transform: translateY(-50%);
width: 16rpx; /* 圆点大小(默认是4px左右,调大到8px) */
height: 16rpx; /* 和宽度一致,保证圆形 */
border-radius: 50%; /* 圆形 */
background-color: #333; /* 圆点颜色,可自定义 */
// padding-left: 48rpx;
display: flex;
align-items: center;
}
.icon-img {
width: 28rpx;
height: 28rpx;
margin-right: 14rpx;
}
.tr {
font-weight: 600;
font-size: 30rpx;
@@ -240,9 +245,10 @@
font-size: 30rpx;
}
.your_answer {
padding-left: 42rpx;
font-weight: 500;
font-size: 30rpx;
color: #333333;
font-size: 26rpx;
color: #666666;
line-height: 46rpx;
text-align: left;
margin-top: 12rpx;
@@ -59,7 +59,7 @@
line-height: 48rpx;
text-align: left;
:deep(.highlight) {
color: #15b859;
color: #333333;
text-decoration: underline;
}
}
+22 -15
View File
@@ -1,10 +1,14 @@
<template>
<view class="item" :class="{'no-touch':qnsTyp === 'ES' && !isDisabled && ['examination', 'practice', 'mistake_in', 'pk_in'].includes(props.mode)}">
<view class="top">
<view class="type">{{ subject_type_text }}</view>
<!-- v-if="!['study'].includes(props.mode)" -->
<view class="type" v-if="!['study_answer'].includes(props.mode)">{{ subject_type_text }}</view>
<view class="score" v-if="['settlement', 'examination', 'pk_in'].includes(props.mode)">
{{ item.tgtGrade }}
</view>
<view class="score answerMethod" v-if="['study','examination', 'practice'].includes(props.mode)">
{{ answerMethod }}
</view>
<view class="fl1"></view>
<view class="right">
<!-- 反馈中心 -->
@@ -40,12 +44,12 @@
</template>
</view>
</view>
<view class="question_text" v-show="props.showStem">
<view class="question_text" v-if="!['study_answer'].includes(props.mode)">
{{ subject_data.qnsContent }}
</view>
<view :style="{ height: animationHeight }" :class="{ collapse_wrapper: props.mode === 'mistake' }" ref="wrapperRef">
<view class="collapse-content" ref="contentRef">
<view class="option_div" v-show="props.showStem">
<view class="option_div" v-if="!['study_answer'].includes(props.mode)">
<template v-if="qnsTyp === 'ES'">
<questionVue
@@ -71,7 +75,7 @@
class="option_div_button"
v-if="
qnsTyp === 'MU' &&
['practice', 'study', 'pk_in', 'mistake_in'].includes(props.mode) &&
['practice', 'study', 'study_answer', 'pk_in', 'mistake_in'].includes(props.mode) &&
!props.isPreview &&
clearResult
"
@@ -92,7 +96,7 @@
class="analysis_div"
v-if="
!clearResult &&
['study', 'mistake', 'settlement', 'practice', 'mistake_in', 'practice_record', 'pk_in'].includes(props.mode)
['study', 'study_answer', 'mistake', 'settlement', 'practice', 'mistake_in', 'practice_record', 'pk_in'].includes(props.mode)
"
>
<view class="analysis_title" v-if="qnsTyp !== 'ES'">
@@ -102,7 +106,7 @@
<text :class="right_or_wrong_class ? 'success' : 'error'">{{ myResultLabel.join('') }}</text>
</view>
</view>
<view class="reference_answer" v-if="qnsTyp === 'ES'">
<view class="reference_answer" v-if="qnsTyp === 'ES' && !['study', 'study_answer'].includes(props.mode)">
<view class="reference_answer_title">你的答案:</view>
{{ subject_data.anserResult ?? '' }}
</view>
@@ -136,7 +140,7 @@
import { markIcon, feedbackIcon } from '@/common/imgSvg';
import { SUBJECT_TYPE } from '@/enum.js';
import common from '@/common/common';
import {ANSWER_METHOD_MAP} from '@/enum'
// 多选的确定按钮的样式
const customStyle = {
borderRadius: '16rpx',
@@ -144,7 +148,8 @@
backgroundColor: '#0066FF',
border: '1rpx solid rgb(12, 123, 245)'
};
const answerMethod = computed(() => ANSWER_METHOD_MAP[props.item?.answerMethod || ''] || '');
const emit = defineEmits(['subject_click', 'update:modelValue']);
const props = defineProps({
modelValue: {
@@ -155,10 +160,6 @@
type: Object,
required: true
},
showStem: {
type: Boolean,
default: true
},
mode: {
type: String,
required: true,
@@ -170,7 +171,7 @@
// 学习: study
// 考试结算页 settlement
// 练习记录页 practice_record, 'practice_record'
return ['examination', 'practice', 'mistake', 'mistake_in', 'study', 'settlement', 'practice_record', 'pk_in'].includes(
return ['examination', 'practice', 'mistake', 'mistake_in', 'study', 'study_answer', 'settlement', 'practice_record', 'pk_in'].includes(
value
);
}
@@ -317,7 +318,7 @@
if (item_answer.value.includes(analysisVo.itemId)) {
item_answer.value = item_answer.value.filter((id) => id !== analysisVo.itemId);
modelValue.value = item_answer.value;
if (!['study'].includes(props.mode)) {
if (!['study','study_answer'].includes(props.mode)) {
muCheckbox('choose');
}
} else if (props.item.qnsTyp === 'SN') {
@@ -331,7 +332,7 @@
// 多选直接插入
item_answer.value.push(analysisVo.itemId);
modelValue.value = item_answer.value;
if (!['study'].includes(props.mode)) {
if (!['study','study_answer'].includes(props.mode)) {
muCheckbox('choose');
}
} else if (props.item.qnsTyp === 'JD') {
@@ -520,6 +521,12 @@
color: #333333;
text-align: left;
}
.answerMethod{
font-size: 22rpx;
font-family: ArialMT;
color: #999;
text-align: left;
}
.right {
display: flex;
+53 -33
View File
@@ -34,7 +34,16 @@
:src="holidayInfo.ossAddr"
></image-preview>
</view>
<view class="festival-text-div">{{ holidayInfo.holidayDesc }}</view>
<!-- holidayInfo.holidayDesc -->
<view class="festival-text-div">
<view class="text-1">
{{ text1 }}
</view>
<view class="text-2">
{{ text2 }}
</view>
</view>
<image
class="festival-main-img"
mode="widthFix"
@@ -44,12 +53,10 @@
<view class="festival-main-title">
{{ done.tipText }}
</view>
<view class="festival-main-number-div">
{{ score }}积分
</view>
<view class="festival-main-number-div">{{ score }}积分</view>
</view>
</view>
<view class="festival-button-div" @click="startLottery()">{{ done.buttonText }}</view>
</view>
<view class="close-div" @click="close(false)"></view>
@@ -60,13 +67,18 @@
</template>
<script setup lang="ts">
import type { HolidayInfo, CompleteCallback, StartLotteryCallback,pointsBadges } from './types/holiday';
import type { HolidayInfo, CompleteCallback, StartLotteryCallback, pointsBadges } from './types/holiday';
import { RewardType, AnimationStatus } from './types/holiday';
import { ref, computed, reactive } from 'vue';
import { optionErrorIcon, optionSuccessIcon } from '@/common/imgSvg';
import { obtainRewardRandom } from '@/api/pointsAndRank';
import common from '@/common/common';
const text = computed(() => holidayInfo.holidayDesc.slice(0, 16));
// 单行定义 text1:前半部分
const text1 = computed(() => text.value.length<=8?text.value:text.value.slice(0, Math.floor(text.value.length / 2)));
// 单行定义 text2:后半部分
const text2 = computed(() => text.value.length<=8?'':text.value.slice(Math.floor(text.value.length / 2)));
const countToRef = ref(null);
const popup = ref(null);
const animationLoading = ref<AnimationStatus>(AnimationStatus.UNSTARTED);
@@ -100,7 +112,7 @@
holidayCode: holidayInfo.holidayCode,
successCb: (body) => {
console.log('badgesList', body.badgesList);
holidayInfo.badgesList = body.badgesList
holidayInfo.badgesList = body.badgesList;
// const { body } = await obtainRewardRandom({ holidayCode: holidayInfo.holidayCode });
const finalScore = body.val;
// 记录已完成的循环圈数
@@ -172,7 +184,7 @@
// 背景图片的OSS访问地址(图片完整URL)
backgroundOssAddr: '',
// 获得的徽章
badgesList:[]
badgesList: []
});
let completeCallback: CompleteCallback | undefined; // 关闭弹窗的回调
let startLotteryCallback: StartLotteryCallback | undefined; // 抽奖的回调
@@ -181,15 +193,15 @@
const close = (status: boolean): void => {
// 如果是固定积分,就设置一下
console.log('如果是固定积分,就设置一下', holidayInfo.rewardType);
if(holidayInfo.rewardType === RewardType.FIXED_POINT) {
if (holidayInfo.rewardType === RewardType.FIXED_POINT) {
startLotteryCallback({
holidayCode: '',
failCb: undefined,
successCb: () => {
console.log('设置成功');
}
})
});
}
uni.showTabBar({
success() {
@@ -198,7 +210,7 @@
typeof completeCallback === 'function' &&
completeCallback({
status,
badgesList:holidayInfo.badgesList
badgesList: holidayInfo.badgesList
});
}
});
@@ -213,9 +225,9 @@
console.log('holidayBody', holidayBody);
Object.assign(holidayInfo, holidayBody);
if (!holidayInfo.rewardFlag || holidayInfo.obtainFlag) {
// if (!holidayInfo.rewardFlag) {
// if (!holidayInfo.rewardFlag) {
// 如果当前没有节日窗口,立刻返回回调函数
completeCallback({ status: false });
completeCallback({ status: false, badgesList: [] });
return;
}
// 设置初始得分
@@ -253,7 +265,7 @@
// height: 56rpx;
// }
// }
.festival-main-div {
// margin-top: 8rpx;
z-index: 20;
@@ -281,7 +293,7 @@
.festival-main-title {
font-weight: normal;
font-size: 30rpx;
color: #B24325;
color: #b24325;
line-height: 40rpx;
text-align: center;
}
@@ -291,29 +303,37 @@
margin-right: 8rpx;
font-weight: 600;
font-size: 30rpx;
color: #B24325;
color: #b24325;
line-height: 25rpx;
text-align: center;
}
}
.festival-text-div {
position: relative;
z-index: 60;
width: 100%;
height: 136rpx;
padding-top: 0;
margin: 0 auto;
font-weight: 600;
font-size: 42rpx;
color: #B24325;
line-height: 62rpx;
text-align: center;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
z-index: 60;
width: 100%;
height: 136rpx;
padding-top: 0;
margin: 0 auto;
font-weight: 600;
font-size: 42rpx;
color: #b24325;
line-height: 62rpx;
text-align: center;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
.text-1{
text-align: center;
}
.text-2{
text-align: center;
}
}
}
.festival-button-div {
position: relative;
+6 -1
View File
@@ -157,10 +157,15 @@ export default function useCheckIn() {
checkInDays: localStatus.checkInDays,
popUpStatus: localStatus.popupDay === today
}
const holidayBody = {
let holidayBody = {
rewardFlag: localStatus.rewardFlag,
obtainFlag: localStatus.obtainFlag
}
// 如果没有记录获取节日徽章,那么需要重新获取节日徽章信息
if(holidayBody.rewardFlag && !holidayBody.obtainFlag) {
const {body:holidayData} = await queryHolidayReward()
holidayBody = holidayData
}
complete(checkInInfo, holidayBody)
return true;
}
+8
View File
@@ -32,6 +32,14 @@ export const SUBJECT_TYPE = [{
label: "问答题",
}
]
// 回答方式
export const ANSWER_METHOD_MAP = {
'01': '不限制回答方式',
'02': '仅文字回答',
'03': '仅语音回答'
};
export const defaultAvatar = '/static/images/me/default_user_avatar.png'
export const defaultAnonymousAvatar = '/static/images/competition/competition_default_avatar.png'
export const styleButton = {
+37 -9
View File
@@ -33,11 +33,17 @@
<!-- 加载状态 -->
<CommonLoading color="#06f" v-show="dataInfo.isLoading" />
<!-- 参考答案 -->
<view class="talking-text" v-if="type === 5 && !dataInfo.isLoading" style="overflow: hidden">
<view class="talking-text" v-if="
false
//type === 5
&& !dataInfo.isLoading" style="overflow: hidden">
参考答案:{{ dataInfo.itemAnswer }}
</view>
<!-- 维度信息预览 -->
<view v-if="type === 5 && !dataInfo.isLoading" style="padding-top: 16rpx">
<view v-if="
false
//type === 5
&& !dataInfo.isLoading" style="padding-top: 16rpx">
<ChartFour v-if="dataInfo.evalDimens.length === 4" :dataList="dataInfo.evalDimens"
:score="dataInfo.asrGrade" />
<ChartThree v-if="dataInfo.evalDimens.length === 3" :dataList="dataInfo.evalDimens"
@@ -46,16 +52,17 @@
:score="dataInfo.asrGrade" />
</view>
<!-- 题干/段落内容 -->
<text class="talking-text" v-if="[3, 5, 6, 9].indexOf(type) >= 0 && !dataInfo.isLoading">
<text class="talking-text" v-if="[3,
// 5,
6, 9].indexOf(type) >= 0 && !dataInfo.isLoading">
{{ type === 5 ? '试题解析:' : '' }}{{ showContent }}
</text>
<view class="type-tag" v-if="[4].indexOf(type) >= 0 && dataInfo.qnsTyp === 'ES'">问答题</view>
<!-- <view class="type-tag" v-if="[4].indexOf(type) >= 0 && dataInfo.qnsTyp === 'ES'">问答题</view>
<text class="talking-text" v-if="[4].indexOf(type) >= 0 && dataInfo.qnsTyp === 'ES'">
<!-- 请您思考并作答:<br> -->
{{ showContent }}
</text>
</text> -->
<!-- 试题问题 -->
<Subject v-if="[4, 8].indexOf(type) >= 0 && dataInfo.qnsTyp !== 'ES'" :isPreview="!isLast" :item="subjectInfo" :showStem="type===4"
<Subject v-if="[4, 5, 8].indexOf(type) >= 0 && !dataInfo.isLoading" :isPreview="!isLast" :item="subjectInfo"
:mode="mode" :clearResult="type === 4" @subject_click="subject_click" />
<!-- 试题问题反馈 -->
<!-- <RadioSubjectRequest v-if="[8].indexOf(type) >= 0 && dataInfo.qnsTyp !== 'ES'" :item="dataInfo" :mode="mode" @subject_click="subject_click" /> -->
@@ -275,6 +282,10 @@
default: '',
type: String
},
answerMethod: {
default: '01',
type: String
},
isLast: {
default: false,
type: Boolean
@@ -324,10 +335,27 @@
return {
...dataInfo.value,
...(dataInfo.value?.traQnsInfoVo || {}),
my_answer: dataInfo.value?.traQnsInfoVo?.anserResult || ''
my_answer: dataInfo.value?.traQnsInfoVo?.anserResult || '',
answerMethod: props.answerMethod,
...(props.type === 5?{
"qnsTyp": "ES",
my_answer: dataInfo.value,
itemVos: [{
...dataInfo.value,
"qnsTyp": "ES",
"qnsId": dataInfo.value.qnsId,
"itemAnswer": dataInfo.value.itemAnswer,
"relKeyword": dataInfo.value.relKeyword,
anserResult:dataInfo.value?.traQnsInfoVo?.anserResult || '',
"evalSettingVos": dataInfo.value?.essayEvalVo,
}]
}:{})
};
});
const mode = ref('study'); // 考试 examination 练习practice 学习study
const mode = computed(()=>{
return props.type == 5 ? 'study_answer' : 'study'
}); // 考试 examination 练习practice 学习study 学习结果study_answer
const imgAddrs = computed(()=>{
return (dataInfo.value.imageAddrs || [])
+8 -7
View File
@@ -10,7 +10,7 @@
placeholder="请输入文字"></uv-input>
</view>
<!-- @click="showTalkingModel = true" -->
<view class="talk-btn-box" v-show="!onlyVoice">
<view class="talk-btn-box" v-show="!onlyVoice && props.answerMethod !== '03'">
<image class="talk-btn-icon" v-show="!keyboardIsShow" src="/src/static/images/course/jianpan.png" mode=""
@click="changeBtn"></image>
<image class="talk-btn-icon" v-show="keyboardIsShow && !answerValue" src="/src/static/images/course/record.png"
@@ -36,7 +36,7 @@
</view>
<view class="btns-box" v-if="transVoiceIng">
<view class="cancel-btn transVoiceIng" @click="closeModel()"></view>
<view class="trans-btn transVoiceIng" @click="sendVoice()"></view>
<view class="trans-btn transVoiceIng" @click="sendVoice()" v-show="props.answerMethod !== '02'"></view>
<view class="send-btn" @click="sendText()">发送</view>
</view>
<view class="btns-box" v-else>
@@ -51,10 +51,10 @@
<image class="btn-box" v-else src="/src/static/images/course/translate-active.png" mode="heightFix"></image>
</view>
</view>
<view :class="['talk-dialog', isOut ? 'is-out' : '']" v-show="!isOutRight">
<view :class="['talk-dialog', isOut ? 'is-out' : '']" v-show="!isOutRight && !transVoiceIng">
<image src="@/static/images/course/voice-white.gif" mode="" class="gif-box"></image>
</view>
<view :class="['talk-dialog talk-textarea' ]" v-show="isOutRight" @click.stop>
<view :class="['talk-dialog talk-textarea' ]" v-show="isOutRight || transVoiceIng" @click.stop>
<view class="trans-loading-box" v-show="transLoading">
<CommonLoading color="#fff" class="loading-box" />
</view>
@@ -231,7 +231,8 @@
}
audioPath.value = res.tempFilePath;
console.log(isOut.value, isOutLeft.value, isOutRight.value)
if (!isOut.value) {
if (!isOut.value && (props.answerMethod !== '02')) {
console.log(11111111111)
if (startFlag.value !== 2) {
closeModel(() => {
nextTick(() => {
@@ -249,7 +250,7 @@
} else if (isOutLeft.value) {
console.log('取消')
closeModel();
} else if (isOutRight.value) {
} else if (isOutRight.value || (props.answerMethod === '02')) {
console.log('转文本')
transLoading.value = true
commonUploadVoiceFile(audioPath.value, '/traapp/voice/voiceChart', {}).then(res => {
@@ -551,7 +552,7 @@
isMoving.value = false;
if (!showTalkingModel.value) return;
//#ifdef APP-PLUS
transVoiceIng.value = isOutRight.value
transVoiceIng.value = isOutRight.value || (props.answerMethod === '02')
stopRecord();
// #endif
+57 -15
View File
@@ -47,13 +47,13 @@
课程学习
</view>
<view class="study-num">
<view class="color-blue">{{ showOrder }}</view>
<view class="color-black ml-40">学习中<text class="color-gray"><text class="color-black">{{ showOrder }}</text>/{{ pgrphNum }}</text></view>
<view class="bg-block">
<view class="bg-gray">
<view class="bg-blue" :style="`width: ${showOrder/pgrphNum * 100}%;`"></view>
</view>
</view>
<text>{{ pgrphNum }}</text>
</view>
<scroll-view class="talking-list" :scroll-y="true" :scroll-top="scrollTop" :show-scrollbar="false" :scroll-with-animation="true">
@@ -69,6 +69,7 @@
:voiceRate="chooseRate"
:lastQuestionInfo="lastTalkingInfo"
:teacherInfo="choiceTeacherInfo"
:answerMethod="answerMethod"
@changePlay="changePlayItemId"
@nextQuestion="nextQuestionSuccess"
@withdraw="withdrawNow"
@@ -80,6 +81,20 @@
<!-- </view> -->
</scroll-view>
<TouchBtn
v-if="answerMethod !== '03'"
class="talk-btns"
@uploadVoice="uploadRecordNow"
@submitAnswer="submitAnswerNow"
@startRecord="changePlayItemId('')"
:isLoading="isUploadingVoice"
:onlyVoice="answerOnlyVoice"
:canAnswer="testAnswer"
:adjustPosition="true"
:canAnswerText="canAnswerText"
:answerMethod="answerMethod"
:isDisabled="(lastTalkingInfo.type || 0) !== 4 || ['SN', 'MU', 'JD'].includes(lastTalkingInfo.qnsTyp)" />
<TouchBtnOnlyVoice
v-else
class="talk-btns"
@uploadVoice="uploadRecordNow"
@submitAnswer="submitAnswerNow"
@@ -152,6 +167,7 @@ import TalkingItem from '@/pages/course/components/talkingItem.vue'
import ImagePreview from '@/components/image-preview/image-preview.vue'
import PreviewDetail from '@/components/image-preview/preview-detail.vue'
import TouchBtn from '@/pages/course/components/touchBtn.vue'
import TouchBtnOnlyVoice from '@/pages/course/components/touchBtnOnlyVoice.vue'
import badge from '@/components/points-and-badge/badge';
import points from '@/components/points-and-badge/points';
import usePointsAndBadge from '@/components/points-and-badge/usePointsAndBadge';
@@ -406,7 +422,7 @@ const backRouter = () => {
}
const answerOnlyVoice = computed(() => {
return lastTalkingInfo.value.answerWay === 'V'
return lastTalkingInfo.value.answerWay === 'V' || (answerMethod.value === '03')
})
const canAnswerText = computed(() => {
@@ -1315,38 +1331,64 @@ const chooseRateNow = item => {
}
.study-num {
height: 56rpx;
height: 110rpx;
line-height: 46rpx;
font-size: 36rpx;
text-align: center;
padding-top: 10rpx;
text-align: left;
padding-left: 30rpx;
padding-right: 30rpx;
padding-top: 20rpx;
box-sizing: border-box;
background: url(@/static/images/course/study-bg.png) no-repeat;
border-radius: 30rpx 30rpx 0 0;
display: flex;
flex-direction: row;
justify-content: center;
font-size: 29rpx;
.color-blue {
color: #06f;
display: inline;
}
.color-black{
color: #333;
position: relative;
height: 44rpx;
line-height: 44rpx;
&.ml-40{
padding-left: 24rpx;
&::before{
content: '';
display: block;
width: 12rpx;
height: 12rpx;
overflow: hidden;
position: absolute;
border-radius: 50%;
background-color: #06f;
top: 50%;
left: 0;
transform: translateY(-50%);
}
}
}
.color-gray{
color: #999;
}
.bg-block{
display: inline-block;
width: 200rpx;
height: 100%;
display: block;
width: 100%;
height: 56rpx;
// padding: 4rpx 0 12rpx;
position: relative;
margin: 0 30rpx;
// margin: 0 30rpx;
}
.bg-gray{
width: 100%;
background-color: #e6eafd;
background-color: #ededed;
overflow: hidden;
border-radius: 15rpx;
position: absolute;
top: 13rpx;
left:0;
height: 20rpx;
height: 16rpx;
.bg-blue{
height: 100%;
float: left;
@@ -14,6 +14,7 @@
<view class="fz-30 fw-600 mb-8">更新时间</view>
<view class="fz-30 fw-400 color-666">{{ (modelValue.mtTime || '').substr(0, 16) }}</view>
</view>
<view class="info-bottom">
<view class="bottom-left">
<view class="mb-64">
@@ -37,10 +38,14 @@
<image src="/src/static/images/courseDetail/ditu.png" class="right-img" mode="widthFix"></image>
</view>
</view>
<view class="info-middle font_pf">
<view class="fz-30 fw-600 mb-8">回答方式</view>
<view class="fz-30 fw-400 color-666">{{answerMethod}}</view>
</view>
<view class="mb-64">
<view class="fz-30 font_pf fw-600 mb-4">课程核心</view>
<view class="examination_core color-666">
{{ modelValue.crsCore }}
{{ modelValue.crsCore || '无' }}
</view>
</view>
<view class="mb-64 file-items" v-if="(modelValue.fileList || []).length>0">
@@ -53,12 +58,16 @@
</template>
<script setup>
import {computed} from 'vue'
import {
previewFileFnc
} from '@/common/common'
const props = defineProps({
modelValue: Object
});
import {ANSWER_METHOD_MAP} from '@/enum.js'
const answerMethod = computed(() => ANSWER_METHOD_MAP[props.item?.answerMethod || ''] || ANSWER_METHOD_MAP['01']);
const previewFile = info => {
previewFileFnc({
fileId: info.fileId,
+29 -20
View File
@@ -26,21 +26,14 @@
src="/src/static/images/courseDetail/zhishidian.png"
mode="widthFix"
></image>
<view class="">知识点</view>
<view class="text-1">当前进度</view>
</view>
<view class="line-progress-div">
<view class="text-1">{{ form.styParaGraphNum || 0 }}</view>
<uv-line-progress
:percentage="progress"
:showText="false"
activeColor="#0066FF"
inactiveColor="#D9DEE8"
:height="8"
></uv-line-progress>
<view class="text-2">{{ form.pgrphNum || 0 }}</view>
<text class="text-2">(<text class="text-1">{{ form.styParaGraphNum || 0 }}</text>/{{ form.pgrphNum || 0 }})</text>
<view class="progress-div">
<view class="progress-line"></view>
</view>
</view>
<view
class="num-item examination"
@click="common.navigateTo(`/pages/examRanking/index?crsId=${crsId}`)"
@@ -143,9 +136,9 @@
const progress = computed(() => {
// 计算进度百分比(保留两位小数)
const total = form.value.pgrphNum;
if (total === 0) return 0;
if (total === 0) return '0%';
const completed = form.value.styParaGraphNum;
return Math.min(Math.round((completed / total) * 10000) / 100, 100);
return Math.min(Math.round((completed / total) * 10000) / 100, 100)+'%';
});
const tabSwitch = (item) => {
tabAct.value = item.index;
@@ -450,7 +443,7 @@
.examination {
color: #0066ff;
margin: 0 14rpx;
.back-icon {
position: relative;
width: 40rpx;
@@ -538,9 +531,8 @@
display: flex;
align-items: center;
font-size: 30rpx;
margin-right: 16rpx;
color: #666666;
height: 30rpx;
}
.line-progress-div {
display: flex;
@@ -548,14 +540,31 @@
flex: 1;
margin-right: 20rpx;
.text-1 {
color: #0066ff;
color: #333333;
font-size: 30rpx;
margin: 0 16rpx;
}
.text-2 {
color: #999999;
font-size: 30rpx;
margin: 0 16rpx;
margin: 0 8rpx;
}
.progress-div{
position: relative;
background-color: #D9DEE8;
width: 100%;
height: 16rpx;
border-radius: 10rpx;
overflow: hidden;
.progress-line{
position: absolute;
top: 0;
left: 0;
background-color: #0066FF;
// width: 100%;
width: v-bind(progress);
height: 100%;
border-radius: 10rpx;
}
}
}
.learn {
@@ -31,10 +31,10 @@
{{ showContent }}
</text>
<!-- 试题问题 -->
<Subject v-if="[4, 8].indexOf(type) >= 0 && dataInfo.qnsTyp !== 'ES'" :isPreview="!isLast" :item="subjectInfo"
<Subject v-if="[4, 8].indexOf(type) >= 0" :isPreview="!isLast" :item="subjectInfo"
:mode="mode" :clearResult="type === 4" @subject_click="subject_click" />
<esQuestion v-if="[4, 8].indexOf(type) >= 0 && dataInfo.qnsTyp === 'ES'" @changePlay="changePlay"
:activeVoiceId="activeVoiceId" :dataInfo="esSubjectInfo" />
<!-- <esQuestion v-if="[4, 8].indexOf(type) >= 0 && dataInfo.qnsTyp === 'ES'" @changePlay="changePlay"
:activeVoiceId="activeVoiceId" :dataInfo="esSubjectInfo" /> -->
<!-- 试题问题反馈 -->
<!-- <RadioSubjectRequest v-if="[8].indexOf(type) >= 0 && dataInfo.qnsTyp !== 'ES'" :item="dataInfo" :mode="mode" @subject_click="subject_click" /> -->
<!-- 段落图片视频预览 -->
@@ -55,14 +55,14 @@
></VideoPreview>
</view>
<!-- 维度信息预览 -->
<view v-if="[4, 8].indexOf(type) >= 0 && dataInfo.qnsTyp === 'ES'" style="padding-top: 16rpx;">
<!-- <view v-if="[4, 8].indexOf(type) >= 0 && dataInfo.qnsTyp === 'ES'" style="padding-top: 16rpx;">
<ChartFour v-if="esSubjectInfo?.evalSettingVos?.length === 4" :dataList="esSubjectInfo.evalSettingVos"
:score="intrctGrade" />
<ChartThree v-if="esSubjectInfo?.evalSettingVos?.length === 3" :dataList="esSubjectInfo.evalSettingVos"
:score="intrctGrade" />
<ChartFive v-if="esSubjectInfo?.evalSettingVos?.length === 5" :dataList="esSubjectInfo.evalSettingVos"
:score="intrctGrade" />
</view>
</view> -->
<!-- 参考答案 -->
<view class="talking-text" v-if="type === 5 && !dataInfo.isLoading" style="overflow: hidden;">
参考答案{{ dataInfo.itemAnswer }}
+4 -7
View File
@@ -407,6 +407,7 @@
}
topicList.push(
...examination.qnsInfoVos.map((res) => {
const es_status = (() => {
try {
@@ -471,7 +472,8 @@
...res,
mark: false,
es_status: es_status,
my_answer: my_answer
my_answer: my_answer,
answerMethod:answerMethod.value
};
})
);
@@ -955,11 +957,8 @@
.nav-div {
position: relative;
.title {
// padding-top:var(--status-bar-height);
// padding: 0 30rpx;
margin: 0 calc($bg-margin-left + 70rpx);
margin: 0 calc($bg-margin-left + 90rpx);
height: 70rpx;
font-family: PingFangSC;
font-weight: 500;
@@ -974,9 +973,7 @@
position: absolute;
right: $bg-margin-left;
top: 0;
// width: 70rpx;
height: 70rpx;
// background-color: red;
display: flex;
align-items: center;
justify-content: flex-end;
+3 -6
View File
@@ -370,13 +370,13 @@
isPreview: false,
clearResult: true,
es_status: '', // 预设一下问答题的状态,'' 空为没有 00 转圈 01 播放,其他暂定
my_answer: []
my_answer: [],
answerMethod:answerMethod.value
}));
answerMethod.value = practice.answerMethod ?? '01'
console.log('answerMethod', answerMethod.value);
addProblem();
// 记录练习起始时间
practiceStartTime = new Date().getTime();
setupKeyboardHeightListener((height) => {
popup_input_bottom.value = `${height}px`;
@@ -739,11 +739,8 @@
.nav-div {
position: relative;
.title {
// padding-top:var(--status-bar-height);
// padding: 0 30rpx;
margin: 0 calc($bg-margin-left + 70rpx);
margin: 0 calc($bg-margin-left + 90rpx);
height: 70rpx;
font-family: PingFangSC;
font-weight: 500;
+3 -2
View File
@@ -28,10 +28,11 @@ export class ProtocolConst {
export enum MessageType {
PING = 0b0001, // 心跳消息(支持空包体)
AUDIO_DATA = 0b0010, // 纯音频数据
TEXT_MESSAGE = 0b0011, // 文本消息
TEXT_MESSAGE = 0b0011, // 大模型回复的文本消息
CONTROL_CMD = 0b0100, // 控制指令
IDENTITY = 0b0101, // 身份校验包json格式
ERROR = 0b0110 // 错误信息json格式
ERROR = 0b0110, // 错误信息json格式
TIP_MESSAGE = 0b0111 // 大模型生成的回答提示
// 预留12种类型用于扩展(0b0100 ~ 0b1111
}
+1 -1
View File
@@ -124,7 +124,7 @@ export default function useWebSocket(aaas = null, options = {}) {
}
break;
case MessageType.TEXT_MESSAGE:
console.log('TEXT_MESSAGE', body);
break;
Binary file not shown.

After

Width:  |  Height:  |  Size: 855 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB