搜索页等

This commit is contained in:
田岩
2025-08-28 16:54:52 +08:00
parent caa4a8b1ec
commit bbfd232ae8
23 changed files with 550 additions and 617 deletions
+12 -1
View File
@@ -72,4 +72,15 @@ export const queryPaperExamRankingList = (data) => {
data
});
};
// 反馈问题
export const saveTraQnsFeedback = (data) => {
return request({
url: base_url + '/traCrsPapers/saveTraQnsFeedback',
method: 'post',
toastErrors: true,
data
});
};
+66 -32
View File
@@ -21,7 +21,6 @@ function show(title, msg, showCancel = true, cancelText = '取消', confirmText
confirmText,
success: (res) => {
// 统一处理成功回调,解析为布尔值
console.log('res.confirm', res.confirm);
resolve(!!res.confirm);
}
};
@@ -65,23 +64,23 @@ const hideLoading = () => uni.hideLoading()
// 防抖工具函数
function debounce(fn, wait = 300) {
let isLocked = false; // 锁定状态标记
return function(...args) {
// 如果处于锁定状态,直接返回不执行
if (isLocked) {
return;
}
// 执行函数
fn.apply(this, args);
// 锁定,防止再次执行
isLocked = true;
// 等待指定时间后解锁
setTimeout(() => {
isLocked = false;
}, wait);
};
let isLocked = false; // 锁定状态标记
return function(...args) {
// 如果处于锁定状态,直接返回不执行
if (isLocked) {
return;
}
// 执行函数
fn.apply(this, args);
// 锁定,防止再次执行
isLocked = true;
// 等待指定时间后解锁
setTimeout(() => {
isLocked = false;
}, wait);
};
}
// 保留当前页面,跳转到应用内的某个页面,使用uni.navigateBack可以返回到原页面。
@@ -174,23 +173,23 @@ export const getUserInfo = (key = '') => {
}
// 数字转换,把传入的秒转换为HH:mm:ss格式
export const formatSeconds = (seconds) => {
// 处理非数字或负数情况
if (typeof seconds !== 'number' || isNaN(seconds) || seconds < 0) {
return '00:00:00';
}
// 处理非数字或负数情况
if (typeof seconds !== 'number' || isNaN(seconds) || seconds < 0) {
return '00:00:00';
}
// 计算小时、分钟和剩余秒数
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const remainingSeconds = Math.floor(seconds % 60);
// 计算小时、分钟和剩余秒数
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const remainingSeconds = Math.floor(seconds % 60);
// 补零函数:将数字转为两位数字符串
const padZero = (num) => num.toString().padStart(2, '0');
// 补零函数:将数字转为两位数字符串
const padZero = (num) => num.toString().padStart(2, '0');
// 拼接成00:00:00格式
return `${padZero(hours)}:${padZero(minutes)}:${padZero(remainingSeconds)}`;
};
// 拼接成00:00:00格式
return `${padZero(hours)}:${padZero(minutes)}:${padZero(remainingSeconds)}`;
};
/**
* 判断当前运行平台是否匹配指定标识
* @param {string} flag - 平台标识:'IOS' 表示苹果iOS平台,'AND' 表示安卓平台
@@ -242,6 +241,41 @@ function isLogin() {
return !!getToken();
}
// 封装键盘高度变化处理
export function setupKeyboardHeightListener(updateCallback) {
// #ifndef APP-PLUS
return () => {};
// #endif
// #ifdef APP-PLUS
// 获取系统信息
const systemInfo = uni.getSystemInfoSync();
// 计算安全区域底部高度
const safeAreaBottomHeight = systemInfo.screenHeight - systemInfo.safeArea.bottom;
// 定义处理函数
const handleKeyboardHeightChange = (res) => {
let keyboardHeight = res.height;
// 仅在iOS端补偿安全区域高度
if (systemInfo.platform === 'ios') {
keyboardHeight = Math.max(0, keyboardHeight - safeAreaBottomHeight); // 避免负数
}
// 通过回调函数更新外部的响应式变量
updateCallback(keyboardHeight);
};
// 监听键盘高度变化
uni.onKeyboardHeightChange(handleKeyboardHeightChange);
// 返回取消监听的函数,方便组件卸载时清理
return () => {
uni.offKeyboardHeightChange(handleKeyboardHeightChange);
};
// #endif
}
export default {
getPageCache,
setPageCache,
+8 -18
View File
@@ -29,12 +29,10 @@
style="width: 100%; height: 100%"
></image>
</view>
<view class="text-btn" @click.stop="translateVoice()"></view>
<view class="text-btn" v-if="!textShow" @click.stop="translateVoice()"></view>
<view class="fl1"></view>
<view class="btns-cont-button-text" @click.stop="buutton_click('again')">重答</view>
<view class="btns-cont-button-text" @click.stop="buutton_click('complete')">完成</view>
<!-- <view class="icon text-btn" v-if="type === 1" @click.stop="translateVoice(dataInfo)"></view> -->
</view>
</view>
<!-- 01纯文字 -->
@@ -45,20 +43,6 @@
</text>
</view>
<view class="btns-cont">
<!-- <view class="play-btn">
<image
class="icon"
@click="playVoice"
src="@/static/images/course/play-blue.png"
style="width: 100%; height: 100%"
></image>
<image
class="icon"
@click.stop="pauseVoice"
src="@/static/images/course/stop-blue.png"
style="width: 100%; height: 100%"
></image>
</view> -->
<view class="fl1"></view>
<view class="btns-cont-button-text" @click.stop="buutton_click('again')">重答</view>
<view class="btns-cont-button-text" @click.stop="buutton_click('complete')">完成</view>
@@ -100,6 +84,10 @@
status: {
default: '',
type: String
},
isPreview: { // 是否是预览语音
default: false,
type: Boolean
}
});
@@ -151,9 +139,10 @@
console.log('点击播放');
audioStore.playAudio();
};
let unsubscribe = () =>{};
onMounted(() => {
// 2. 监听 Store 中 isPlaying 的变化,实时同步
const unsubscribe = audioStore.$subscribe((mutation, state) => {
unsubscribe = audioStore.$subscribe((mutation, state) => {
isPlaying.value = state.isPlaying;
});
// 注册播放完成回调
@@ -185,6 +174,7 @@
audioStore.stopAudio();
// 2. 移除当前组件注册的回调(避免内存泄漏)
audioStore.removeCallbacks();
unsubscribe();
});
</script>
+6 -5
View File
@@ -9,7 +9,7 @@
<view class="mark_and_feedback_div" v-if="['examination', 'practice'].includes(props.mode)">
<image
v-if="props.mode === 'examination'"
:src="markIcon(props.item.mark ? '#0066FF' : '#ABABAB')"
:src="markIcon(props.item.mark ? '#e8b531' : '#ABABAB')"
class="img"
@click="mark_click()"
></image>
@@ -32,8 +32,9 @@
<questionVue
:status="subject_data.es_status"
:dataInfo="props.item?.my_answer"
:isPreview="props.isPreview"
:activeVoiceId="subject_data.qnsId"
@buutton_click="questionBuuttonClick"
@buutton_click="questionButtonClick"
></questionVue>
</template>
<template v-else>
@@ -212,8 +213,8 @@
set: (val) => {}
});
// 按钮
const questionBuuttonClick = (type, submitObj) => {
// 语音播放组件小按钮
const questionButtonClick = (type, submitObj) => {
console.log('type', type, submitObj);
// 判断点击的是什么
if (type === 'complete') {
@@ -224,7 +225,7 @@
emit('subject_click', type, {
qnsTyp: props.item.qnsTyp,
qnsId: props.item.qnsId,
answer: item_answer.value,
answer: submitObj,
answerItems: []
});
};
+18 -4
View File
@@ -1,12 +1,26 @@
<template>
<view style="width: 100%;" class="flex-c-c">
<image src="@/static/images/common/default_img.png" mode="aspectFit" style="width:400rpx"></image>
<view style="width: 100%;" class="no-data">
<view class="flex-c-c">
<image src="@/static/images/common/default_img.png" mode="aspectFit" style="width:400rpx"></image>
</view>
<view class="text">
<slot ></slot>
</view>
</view>
</template>
<script>
</script>
<style>
<style scoped lang="scss">
.no-data{
display: flex;
flex-direction: column;
align-items: center;
}
.text{
color: #666666;
font-size: 30rpx;
}
</style>
+139 -142
View File
@@ -1,24 +1,33 @@
<template>
<view class="comment_div">
<view class="message_div" v-for="(item,index) in message_list">
<view class="message_div" v-for="(item, index) in message_list">
<view class="head_div">
<image-preview v-if="item.userIconImgId" class="img-box img" :src="item.userIconImgId"></image-preview>
<image v-else src="/static/images/me/default_user_avatar.png" class="img"></image>
</view>
<view class="msg_content">
<view class="title_div">
<view class="name">{{item.userName}}</view>
<view class="title_tip">{{item.bbsTagDesc}}</view>
<view class="name">{{ item.userName }}</view>
<view class="title_tip">
<image class="img" v-if="item.bbsTag === 'ASK'" src="@/static/images/courseDetail/ASK.png" mode="widthFix"></image>
<image class="img" v-if="item.bbsTag === 'SUG'" src="@/static/images/courseDetail/SUG.png" mode="widthFix"></image>
</view>
<!-- <view class="title_tip">{{item.bbsTagDesc}}</view> -->
</view>
<view class="title">
{{item.bbsContent}}
{{ item.bbsContent }}
</view>
<view class="img_div pic-cell">
<image-preview v-for="img in item.imgIdList" @click="showPicture(item.imgIdList, img)" :src="img"
class="pic-item" mode="scaleToFill"></image-preview>
<image-preview
v-for="img in item.imgIdList"
@click="showPicture(item.imgIdList, img)"
:src="img"
class="pic-item"
mode="scaleToFill"
></image-preview>
</view>
<view class="time_and_reply">
<view class="time">{{item.bbsTm.substr(0,16)}}</view>
<view class="time">{{ item.bbsTm.substr(0, 16) }}</view>
<view class="reply" @click="click_reply(item, item.bbsId, index)">回复</view>
</view>
<view class="show_close_div" v-if="item.children?.length" @click="item.show = !item.show">
@@ -29,7 +38,7 @@
</view>
</template>
<template v-else>
<view>展开{{item.children?.length}}条回复</view>
<view>展开{{ item.children?.length }}条回复</view>
<view class="back_div">
<view class="back-icon"></view>
</view>
@@ -38,25 +47,27 @@
<view class="children" v-if="item.show">
<view class="message_div" v-for="childrenItem in item.children">
<view class="head_div">
<image-preview v-if="childrenItem.userIconImgId" class="img-box img"
:src="childrenItem.userIconImgId"></image-preview>
<image-preview
v-if="childrenItem.userIconImgId"
class="img-box img"
:src="childrenItem.userIconImgId"
></image-preview>
<image v-else src="/static/images/me/default_user_avatar.png" class="img"></image>
</view>
<view class="msg_content">
<view class="title_div">
<view class="name">{{childrenItem.userName}}</view>
<view class="name">{{ childrenItem.userName }}</view>
<view class="arrow"></view>
<view class="name">{{childrenItem.rtnUName}}</view>
<view class="name">{{ childrenItem.rtnUName }}</view>
</view>
<view class="title">
{{childrenItem.bbsContent}}
</view>
<view class="img_div">
{{ childrenItem.bbsContent }}
</view>
<view class="img_div"></view>
<view class="time_and_reply">
<view class="time">{{childrenItem.bbsTm.substr(0,16)}}</view>
<view class="reply" @click="click_reply(childrenItem, childrenItem.parentId, index)">回复
<view class="time">{{ childrenItem.bbsTm.substr(0, 16) }}</view>
<view class="reply" @click="click_reply(childrenItem, childrenItem.parentId, index)">
回复
</view>
</view>
</view>
@@ -64,23 +75,26 @@
</view>
</view>
</view>
<view class="empty_message_div" v-if="status=='nomore' && total == 0">
<view class="empty_message_div" v-if="status == 'nomore' && total == 0">
<image class="img" src="@/static/images/courseDetail/empty_message.png" mode="widthFix"></image>
<view class="text">
这里什么都没有
</view>
<view class="text">这里什么都没有</view>
</view>
<uv-load-more v-if="total != 0" :status="status" loadmore-text="轻轻上拉加载"></uv-load-more>
<uni-popup ref="popup" class="popup">
<view class="bottom_reply_input_div" :style="{marginBottom:popup_input_bottom}">
<uv-input v-model="reply_data.bbsContent" :adjustPosition="false"
placeholderStyle='color:#999999;font-size:26rpx' :placeholder="reply_data.placeholder" :focus="true"
:maxlength="100">
</uv-input>
<view class="" style="display: flex;flex-direction: column; margin:10rpx 20rpx;">
<view class="bottom_reply_input_div" :style="{ marginBottom: popup_input_bottom }">
<uv-input
v-model="reply_data.bbsContent"
:adjustPosition="false"
placeholderStyle="color:#999999;font-size:26rpx"
:placeholder="reply_data.placeholder"
:focus="true"
:maxlength="100"
></uv-input>
<view class="" style="display: flex; flex-direction: column; margin: 10rpx 20rpx">
<view class="fl1"></view>
<uv-button class="bottom_reply_button" type="primary" :throttleTime="500"
@click="reply_send">回复</uv-button>
<uv-button class="bottom_reply_button" type="primary" :throttleTime="500" @click="reply_send">
回复
</uv-button>
<view class="fl1"></view>
</view>
</view>
@@ -89,129 +103,120 @@
</template>
<script setup>
import {
ref,
reactive,
onMounted,
nextTick
} from 'vue'
import {
queryTraCrsBbsInfoByCrsId,
replyTraCrsBbsInfo,
qryChildTraCrsBbsInfo
} from '@/api/courseDetail.js';
import common from '@/common/common.js'
import {
get_base_url
} from '@/api/request.js'
import { ref, reactive, onMounted, nextTick } from 'vue';
import { queryTraCrsBbsInfoByCrsId, replyTraCrsBbsInfo, qryChildTraCrsBbsInfo } from '@/api/courseDetail.js';
import common from '@/common/common.js';
import { get_base_url } from '@/api/request.js';
const popup = ref(null)
const popup_input_bottom = ref('0px')
const inputValue = ref('')
const placeholder = ref('')
const message_list = reactive([])
const status = ref('') // loadmore - 加载前,loading - 加载中,nomore - 没有数据
const limit = 15
const total = ref(-1)
const page = ref(0)
const popup = ref(null);
const popup_input_bottom = ref('0px');
const inputValue = ref('');
const placeholder = ref('');
const message_list = reactive([]);
const status = ref(''); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
const limit = 15;
const total = ref(-1);
const page = ref(0);
const reply_data_init = {
"index": null,
"parentBbsId": null,
"bbsId": null,
"bbsContent": '',
"placeholder": '',
}
index: null,
parentBbsId: null,
bbsId: null,
bbsContent: '',
placeholder: ''
};
const reply_data = reactive({
...reply_data_init
})
});
const props = defineProps({
crsId: String,
imgId: String
})
});
const click_reply = (item, parentBbsId, index) => {
popup.value.open('bottom');
reply_data.placeholder = '回复 ' + item.userName + ""
reply_data.parentBbsId = parentBbsId
reply_data.bbsId = item.bbsId
reply_data.index = index
reply_data.placeholder = '回复 ' + item.userName + '';
reply_data.parentBbsId = parentBbsId;
reply_data.bbsId = item.bbsId;
reply_data.index = index;
const systemInfo = uni.getSystemInfoSync();
// 安全区域底部到屏幕底部的高度(即底部安全区域高度)
const safeAreaBottomHeight = systemInfo.screenHeight - systemInfo.safeArea.bottom;
nextTick(() => {
uni.onKeyboardHeightChange(res => {
let keyboardHeight = res.height;
// 仅在iOS端补偿安全区域高度
if (systemInfo.platform === 'ios') {
keyboardHeight = Math.max(0, keyboardHeight - safeAreaBottomHeight); // 避免负数
}
uni.onKeyboardHeightChange((res) => {
let keyboardHeight = res.height;
// 仅在iOS端补偿安全区域高度
if (systemInfo.platform === 'ios') {
keyboardHeight = Math.max(0, keyboardHeight - safeAreaBottomHeight); // 避免负数
}
popup_input_bottom.value = `${keyboardHeight}px`;
});
})
}
});
};
const reply_send = async () => {
if (reply_data.bbsContent === '') {
return common.msg('回复内容不能为空')
return common.msg('回复内容不能为空');
}
try {
popup.value.close()
common.loading('发送中...')
popup.value.close();
common.loading('发送中...');
await replyTraCrsBbsInfo({
parentBbsId: reply_data.parentBbsId,
bbsId: reply_data.bbsId,
bbsContent: reply_data.bbsContent,
imgIdList: []
})
common.msg('发送成功')
});
common.msg('发送成功');
const res = await qryChildTraCrsBbsInfo({
bbsId: reply_data.parentBbsId
})
message_list[reply_data.index]['children'] = res.body
Object.assign(reply_data, reply_data_init)
});
message_list[reply_data.index]['children'] = res.body;
Object.assign(reply_data, reply_data_init);
} catch (e) {
common.msg('发送失败')
common.msg('发送失败');
} finally {
common.hideLoading()
common.hideLoading();
}
}
};
const getData = (from = '') => {
if (from == 'submit') {
status.value = ''
total.value = -1
page.value = 1
message_list.length = 0
status.value = '';
total.value = -1;
page.value = 1;
message_list.length = 0;
} else {
if (status.value !== 'loadmore' && status.value !== '') return
status.value = 'loading'
page.value++
if (status.value !== 'loadmore' && status.value !== '') return;
status.value = 'loading';
page.value++;
}
queryTraCrsBbsInfoByCrsId({
crsId: props.crsId,
page: page.value,
limit: limit
}).then(res => {
total.value = res.total
message_list.push(...res.body)
}).finally(() => {
if (message_list.length >= total.value) {
status.value = 'nomore'
} else {
status.value = 'loadmore'
}
})
}
.then((res) => {
total.value = res.total;
message_list.push(...res.body);
})
.finally(() => {
if (message_list.length >= total.value) {
status.value = 'nomore';
} else {
status.value = 'loadmore';
}
});
};
// 大图展示
const showPicture = (urls, item) => {
const base_url = get_base_url()
const current = urls.findIndex(res => item === res)
const base_url = get_base_url();
const current = urls.findIndex((res) => item === res);
if (current === -1) {
return false
return false;
}
const urlsList = urls.map(res => base_url + res)
const urlsList = urls.map((res) => base_url + res);
console.log(urlsList, current);
uni.previewImage({
current: current || 0,
@@ -219,22 +224,22 @@
longPressActions: {
// itemList: ['发送给朋友', '保存图片', '收藏'],
itemList: ['保存图片'],
success: function(data) {
success: function (data) {
uni.saveImageToPhotosAlbum({
filePath: urlsList[data.index],
success: function() {}
success: function () {}
});
},
fail: function(err) {}
fail: function (err) {}
}
});
}
};
defineExpose({
getData
})
});
onMounted(() => {
getData()
})
getData();
});
</script>
<style lang="scss" scoped>
@@ -252,7 +257,7 @@
width: 20vw;
// height: 276rpx;
}
.text{
.text {
margin-top: 24rpx;
font-weight: 400;
font-size: 29rpx;
@@ -300,14 +305,13 @@
height: 92rpx;
}
}
}
// 顶部随着输入法弹出的框
.bottom_reply_input_div {
width: 100%;
height: 100%;
background-color: #FFFFFF;
background-color: #ffffff;
display: flex;
bottom: 40vh;
align-items: center;
@@ -316,8 +320,8 @@
.bottom_reply_button {
border: none;
border-radius: 4rpx;
background-color: #0066FF;
color: #FFFFFF;
background-color: #0066ff;
color: #ffffff;
overflow: hidden;
:deep(.uv-button) {
@@ -327,13 +331,12 @@
}
.back_div {
margin-left: 6rpx;
.back-icon {
position: relative;
width: 30rpx;
height: 30rpx;
width: 26rpx;
height: 26rpx;
cursor: pointer;
}
@@ -349,8 +352,8 @@
left: 25%;
width: 50%;
height: 50%;
border-top: 3rpx solid #0066FF;
border-left: 3rpx solid #0066FF;
border-top: 3rpx solid #0066ff;
border-left: 3rpx solid #0066ff;
transform: rotate(-135deg);
}
}
@@ -382,7 +385,7 @@
.title_div {
display: flex;
align-items: center;
.name {
height: 35rpx;
font-family: PingFangSC, PingFang SC;
@@ -392,21 +395,16 @@
line-height: 35rpx;
text-align: left;
font-style: normal;
}
.title_tip {
margin-left: 16rpx;
width: 76rpx;
height: 34rpx;
background: #FFFFFF;
border-radius: 8rpx;
border: 2rpx solid #999999;
font-family: PingFangSC;
font-weight: 400;
font-size: 23rpx;
color: #666666;
line-height: 36rpx;
text-align: center;
display: flex;
align-items: center;
.img {
width: 92rpx;
}
}
.arrow {
@@ -418,7 +416,7 @@
}
.arrow::after {
content: "";
content: '';
position: absolute;
background-color: #666666;
right: 4rpx;
@@ -439,7 +437,6 @@
text-overflow: ellipsis;
white-space: wrap;
overflow-wrap: anywhere;
}
.time_and_reply {
@@ -461,7 +458,7 @@
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 24rpx;
color: #0066FF;
color: #0066ff;
line-height: 33rpx;
text-align: left;
font-style: normal;
@@ -473,8 +470,8 @@
margin-bottom: 20rpx;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 30rpx;
color: #456A8E;
font-size: 24rpx;
color: #0066FF;
line-height: 30rpx;
text-align: left;
font-style: normal;
@@ -497,4 +494,4 @@
// height: calc(100vh - 88rpx - 162rpx - 256rpx - 70rpx);
// overflow: hidden;
}
</style>
</style>
@@ -99,8 +99,9 @@
const click_list_item = (list_item) => {
const examLenTm = 666;
const papersName = item.value.examName;
common.navigateTo(
`/pages/examination/result?execId=${list_item.execId}&examLenTm=${examLenTm}&papersName=${papersName}`
`/pages/examination/result?execId=${list_item.execId}&examLenTm=${examLenTm}&papersName=${papersName}&mode=record`
);
};
</script>
@@ -10,7 +10,7 @@
</view>
<view class="prompt_div">
<view class="prompt_div_left">
<view class="top">{{ formatSeconds(item.stdyTm) || '' }}</view>
<view class="top">{{ secondsToHours(item.stdyTm) }}h</view>
<view class="bottom">学习时长</view>
</view>
<view class="prompt_div_line"></view>
@@ -58,7 +58,6 @@
<script setup>
import { computed, ref, reactive } from 'vue';
import { formatSeconds } from '@/common/common';
import common from '@/common/common';
import { queryStdyBatchByCrsId } from '@/api/courseRecord.js';
const status = ref('loadmore'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
@@ -81,7 +80,14 @@
return data_list.length * 136 + 'rpx';
}
});
const secondsToHours = (seconds) => {
console.log('typeof seconds', typeof seconds);
if (typeof seconds === 'number') {
// 转换为小时并保留一位小数
return (seconds / 3600).toFixed(1);
}
return '0.0';
};
// 点击获取详情
const show_list_click = () => {
show_list_state.value = !show_list_state.value;
@@ -99,11 +105,10 @@
// 跳转到详情
const click_list_item = (list_item) => {
common.navigateTo(
`/pages/courseRecord/courseStudyRecordDetail?stdyId=${list_item.stdyBatch}&crsName=${item.value.crsName}`
`/pages/courseRecord/courseStudyRecordDetail?stdyId=${list_item.stdyBatch}&crsName=${item.value.crsName || ''}`
);
};
// 计算两个标准时间的时间差值
const formatDuration = (startTm, endTm) => {
// 解析时间字符串为时间戳(毫秒)
@@ -104,7 +104,6 @@
display: flex;
flex-direction: column;
height: 100vh;
padding-top: var(--status-bar-height);
.top-bg {
background: linear-gradient(16deg, rgba(234, 246, 255, 0) 0%, #e6eafd 100%);
height: 480rpx;
@@ -128,7 +127,8 @@
box-sizing: border-box;
display: flex;
flex-direction: column;
padding-top: v-bind(pageTopPadding);
padding-top: var(--status-bar-height);
.body-title {
height: 90rpx;
+1 -1
View File
@@ -50,7 +50,7 @@
import common from '@/common/common.js';
const listItemRefs = ref([]);
const taskRef = ref(null);
const tabAct = ref(1);
const tabAct = ref(0);
const tabList = ref([
{
name: '学习记录'
+120 -67
View File
@@ -1,106 +1,160 @@
<template>
<uni-popup ref="feedbackPopupRef" class="popup">
<view class="feedback_popup_div" :style="{marginBottom:feedback_popup_bottom}">
<view class="feedback_popup_div" :style="{ marginBottom: feedback_popup_bottom }">
<view class="title_div">
<view class="text">
反馈
</view>
<view class="text">反馈</view>
<view class="popup_back_div" @click="openFeedback(false)">
<image :src="optionErrorIcon('#000000')" class="img"></image>
</view>
</view>
<view class="feedback_item_div">
<view class="feedback_item"
:class="{'feedback_item_clidked':feedbackInfo.type.includes(feedback_type_item.value)}"
@click="feedback_item_click(feedback_type_item.value)"
v-for="feedback_type_item in feedbackTypeList">场景问题</view>
<view
class="feedback_item"
:class="{ feedback_item_clidked: feedbackInfo.type.includes(feedback_type_item.value) }"
@click="feedback_item_click(feedback_type_item.label)"
v-for="feedback_type_item in feedbackTypeList"
>
{{ feedback_type_item.label }}
</view>
</view>
<view class="feedback_text_area_div">
<uv-textarea height="124" count :maxlength="100" placeholder="请输入反馈内容..." :adjustPosition="false"
v-model="feedbackInfo.text"></uv-textarea>
<uv-textarea
height="124"
count
:maxlength="100"
placeholder="请输入反馈内容..."
:adjustPosition="false"
v-model="feedbackInfo.text"
></uv-textarea>
</view>
<view class="feedback_button">
<uv-button class="button" type="primary" :throttleTime="100" text="提交" color="#0066FF"
<uv-button
class="button"
type="primary"
:throttleTime="100"
text="提交"
color="#0066FF"
custom-style="color:#FFFFFF;borderRadius:16rpx;height:92rpx;"
@click="submit_feedback_fun()"></uv-button>
@click="submit_feedback_fun()"
></uv-button>
</view>
</view>
</uni-popup>
</template>
<script setup>
import {
ref,
reactive,
computed,
onMounted,
nextTick
} from 'vue';
import {
optionErrorIcon
} from '@/common/imgSvg'
const feedback_popup_bottom = ref('0px') // 反馈框下距离
const feedbackPopupRef = ref(null)
const feedbackTypeList = reactive([{
value: "SN",
label: "场景问题",
}, {
value: "GN",
label: "功能问题",
}, {
value: "PN",
label: "陪练内容",
}])
console.log('反馈组件');
import { ref, reactive, computed, onMounted, onUnmounted, nextTick } from 'vue';
import { optionErrorIcon } from '@/common/imgSvg';
import { saveTraQnsFeedback } from '@/api/examination.js';
import common from '@/common/common';
import { setupKeyboardHeightListener } from '@/common/common';
const feedback_popup_bottom = ref('0px'); // 反馈框下距离
const feedbackPopupRef = ref(null);
const feedbackTypeList = reactive([
{
value: '01',
label: '题干纠错'
},
{
value: '02',
label: '答案纠错'
},
{
value: '03',
label: '解析纠错'
}
]);
const feedbackInfo = reactive({
type: [], // 反馈类型
text: '', // 反馈内容
examId: '', // 考试ID
qnsId: '', // 试题IDID
})
qnsId: '' // 试题IDID
});
// 选择反馈类型
const feedback_item_click = (value) => {
if (feedbackInfo.type.includes(value)) {
feedbackInfo.type = feedbackInfo.type.filter(item => item !== value); // 如果已存在,则从数组中移除
feedbackInfo.type = feedbackInfo.type.filter((item) => item !== value); // 如果已存在,则从数组中移除
} else {
feedbackInfo.type.push(value); // 如果不存在,则添加到数组中
}
}
};
// 反馈提交
const submit_feedback_fun = (value) => {
// todo 待接口
console.log('反馈提交');
}
const openFeedback = (status) => {
if (status) {
feedbackPopupRef.value.open('bottom')
// feedbackInfo.examId
const systemInfo = uni.getSystemInfoSync();
// 安全区域底部到屏幕底部的高度(即底部安全区域高度)
const safeAreaBottomHeight = systemInfo.screenHeight - systemInfo.safeArea.bottom;
nextTick(() => {
uni.onKeyboardHeightChange(res => {
let keyboardHeight = res.height;
// 仅在iOS端补偿安全区域高度
if (systemInfo.platform === 'ios') {
keyboardHeight = Math.max(0, keyboardHeight - safeAreaBottomHeight); // 避免负数
}
feedback_popup_bottom.value = `${keyboardHeight}px`;
// 首先判断反馈类型是否
if (feedbackInfo.type.length === 0) {
return common.msg('请选择你要反馈的类型');
}
if (feedbackInfo.text.trim() === '') {
return common.msg('请输入你要反馈的反馈内容');
}
common.loading('提交反馈信息');
const startTime = Date.now();
saveTraQnsFeedback({
qnsId: feedbackInfo.qnsId,
fbComtent: feedbackInfo.text.trim(),
fbTyp: feedbackInfo.type.join(',')
})
.then(async (res) => {
// 计算接口已经消耗的时间
const elapsedTime = Date.now() - startTime;
// 计算需要补充的延迟时间(确保总耗时至少400ms)
const delayTime = Math.max(0, 500 - elapsedTime);
// 如果需要,补充延迟
if (delayTime > 0) {
await new Promise((resolve) => setTimeout(resolve, delayTime));
}
common.hideLoading();
nextTick(() => {
feedbackInfo.type = [];
feedbackInfo.text = '';
feedbackInfo.qnsId = '';
feedbackInfo.examId = '';
feedbackPopupRef.value.close();
setTimeout(() => {
common.msg('反馈信息提交成功');
}, 100);
});
})
.catch(() => {
common.hideLoading();
});
};
const openFeedback = (status) => {
if (status) {
feedbackPopupRef.value.open('bottom');
} else {
feedbackPopupRef.value.close()
feedbackPopupRef.value.close();
}
}
const open = () => openFeedback(true)
};
// 组件挂载时设置监听
let removeListener = () => {};
onMounted(() => {
console.log('组件挂载时设置监听');
removeListener = setupKeyboardHeightListener((height) => {
feedback_popup_bottom.value = `${height}px`;
});
// 组件卸载时移除监听
});
onUnmounted(() => {
removeListener();
});
const open = (qnsId) => {
feedbackInfo.qnsId = qnsId;
openFeedback(true);
};
defineExpose({
open
})
});
</script>
<style scoped lang="scss">
.feedback_popup_div {
width: 100%;
height: 100%;
background-color: #FFFFFF;
background-color: #ffffff;
padding: 10rpx 34rpx;
display: flex;
flex-direction: column;
@@ -118,7 +172,7 @@
color: #000000;
text-align: center;
font-style: normal;
border-bottom: 2rpx solid #EFEFEF;
border-bottom: 2rpx solid #efefef;
}
.popup_back_div {
@@ -138,7 +192,7 @@
}
.feedback_item.feedback_item_clidked {
border: 2rpx solid #0066FF !important;
border: 2rpx solid #0066ff !important;
background-color: #fff !important;
}
@@ -150,8 +204,8 @@
margin: 30rpx 0;
.feedback_item {
border: 2rpx solid #F0F0F0;
background-color: #F0F0F0;
border: 2rpx solid #f0f0f0;
background-color: #f0f0f0;
border-radius: 16rpx;
padding: 26rpx 36rpx;
font-family: PingFangSC;
@@ -159,7 +213,6 @@
font-size: 30rpx;
color: #000000;
text-align: center;
}
}
@@ -173,4 +226,4 @@
margin-bottom: 20rpx;
}
}
</style>
</style>
+2 -7
View File
@@ -48,7 +48,6 @@
:clearResult="true"
v-model="item.my_answer"
></Subject>
{{ item.my_answer }}
</scroll-view>
</view>
</swiper-item>
@@ -232,7 +231,7 @@
}
questionNumber.value = newNumber;
};
// 打开或者关闭弹出层
const openSheet = (status) => (status ? popupRef.value.open('bottom') : popupRef.value.close());
@@ -246,7 +245,7 @@
topicList[questionNumber.value]['mark'] = !topicList[questionNumber.value]['mark'];
} else if (type === 'feedback') {
console.log('feedbackRef.value', feedbackRef.value);
feedbackRef.value.open();
feedbackRef.value.open(params.qnsId);
}
};
@@ -280,7 +279,6 @@
} else if (type === 'text') {
topic.value.es_status = '01';
topic.value.anserResult = submitObj; // 正确答案文字内容
// submitProblemEssayQuestion({ anserResult: submitObj });
}
};
@@ -337,8 +335,6 @@
// 交卷按钮点击,打开交卷确认框
const hand_in_paper_button_click = () => {
console.log('点击交卷', paperData);
// console.log('点击交卷topicList', topicList);
// return;
// 判断是否完成所有题目
const completeList = topicList
.filter((res) => !!(Array.isArray(res.my_answer) ? res.my_answer.length : res.my_answer))
@@ -448,7 +444,6 @@
if (res.body.flagQuery === 'Y') {
// 需要查分
const examLenTm = 678;
common.redirectTo(
`/pages/examination/result?execId=${res.body.execId}&examLenTm=${examLenTm}&papersName=${paperData.papersName}&papersId=${paperData.papersId}&mode=${mode.value}&crsId=${paperData.crsId}`
);
+3 -2
View File
@@ -81,7 +81,7 @@
时长{{ result.examLenTm }}
</view>
<view class="fl1"></view>
<view class="examination" @click="goExamRanking">
<view class="examination" @click="goExamRanking" v-if="result.mode === 'examination'">
<view>考试排行榜</view>
<view class="back-icon"></view>
</view>
@@ -245,7 +245,8 @@
result.execId = e.execId;
result.papersName = e.papersName;
result.examLenTm = e.examLenTm;
result.mode = e.mode;
result.mode = e.mode || '';
result.papersId = e.papersId;
get_result();
});
@@ -102,7 +102,7 @@
const examLenTm = 666;
const papersName = item.value.examName;
common.navigateTo(
`/pages/examination/result?execId=${list_item.execId}&examLenTm=${examLenTm}&papersName=${papersName}`
`/pages/examination/result?execId=${list_item.execId}&examLenTm=${examLenTm}&papersName=${papersName}&mode=record`
);
};
</script>
+52 -96
View File
@@ -113,7 +113,7 @@
get: () => topicList[questionNumber.value],
set: (val) => (topicList[questionNumber.value] = val)
});
const showTouchBtn = computed(() => {
return topic.value?.qnsTyp === 'ES';
});
@@ -139,9 +139,10 @@
};
const subject_click = (type, params) => {
if (type === 'feedback') {
// 反馈
feedbackRef.value.open();
feedbackRef.value.open(params.qnsId);
} else if (type === 'answer') {
//多选点击按钮答题
if (params.qnsTyp === 'MU') {
@@ -156,9 +157,13 @@
}
} else if (type === 'complete') {
// 问答题点击完成
// ossAddr
// anserResult 作答结果
// ossKey 对象存储
submitProblem(params.answer);
} else if (type === 'again') {
// 问答题点击重答
// const topic = topicList[questionNumber.value];
topic.value.my_answer = {};
topic.value.isPreview = false;
topic.value.es_status = ''; // 取消转圈
}
@@ -175,127 +180,81 @@
qnsId: topic.value.qnsId,
...answer
})
.then((res) => {
common.hideLoading();
const body = res.body;
console.log('body', body);
.then(async (res) => {
topic.value.isPreview = true; // 不能在点击了,打开预览模式
topic.value.clearResult = false; // 不清除正确答案了
const traQnsInfoVo = body.traQnsInfoVo;
let traQnsInfoVo;
// 是问答题
console.log('是问答题', topic.value.qnsTyp);
if (topic.value.qnsTyp === 'ES') {
const result = await queryWithRetry(res.body.execLogId);
traQnsInfoVo = result.body.traQnsInfoVo;
} else {
traQnsInfoVo = res.body.traQnsInfoVo;
}
common.hideLoading();
topic.value.clearResult = false; // 不清除正确答案
topic.value.analyContent = traQnsInfoVo.analyContent; // 答案解析
console.log('答题结果', traQnsInfoVo);
// 更新选项正确项目
topic.value.itemVos = traQnsInfoVo.itemVos; // 答案选项(todo应该不这样替换)
topic.value.anserResult = traQnsInfoVo.anserResult; // 正确答案字符串分割
const judgeResultStatus = traQnsInfoVo.judgeResult === 'P'; // P为正确U为错误
if (!addProblem()) {
// 返回false说明到了最后一题
console.log('最后一题');
if (topic.value.qnsTyp === 'ES') {
// 最后一题是问答题,暂时不动
}
}
// 自动切换下一题的条件
if (
judgeResultStatus && // 条件1.答题正确
// ['JD', 'SN', 'MU'].includes(topic.qnsTyp) && // 条件2.单选多选判断(这里改成了单选多选判断专属,所有不用判断这一条了)
topic.value.qnsTyp !== 'ES' && // 问答题答对打答错都不切换
topicList.length < storageTopicList.value.length // 条件3.不是最后一题(暂定这样判断)
) {
questionNumber.value++;
} else {
console.log('为什么没自动跳转', judgeResultStatus);
console.log(
'22',
topicList.length < storageTopicList.value.length,
topicList.length,
storageTopicList.value.length
);
}
})
.catch(() => {
common.hideLoading();
});
};
// 问答题轮询结果方法
const queryWithRetry = (execLogId, maxRetries = 30) => {
// 递归终止条件:达到最大重试次数
if (maxRetries <= 0) {
return Promise.reject(new Error('超过最大重试次数,查询失败'));
}
return queryCrsPracticeAnswerResult({ execLogId }).then((resl) => {
const isWait = resl.body.isWait;
if (isWait === 'N') {
// 如果是Y,延迟2秒后重试,重试次数减1
return new Promise((resolve) => {
setTimeout(() => {
resolve(queryWithRetry(execLogId, maxRetries - 1));
}, 2000);
});
} else {
// 不是Y,直接返回结果
return resl;
}
});
};
// 单题回答(问答题专属)
const submitProblemEssayQuestion = (answer) => {
const topic = topicList[questionNumber.value];
const old_text = touchBtnRef.value?.clearinputText(); // 清除发送框数据
console.log('答题内容', answer);
console.log('答单题问答题专属', topic);
practiceAnswer({
exrId: paperData.exrId,
ossKey: '',
qnsId: topic.qnsId,
...answer
})
return queryCrsPracticeAnswerResult({ execLogId })
.then((res) => {
topic.isPreview = true; // 不能在点击了,打开预览模式
// touchBtnRef.value.clearinputText()
// topic.clearResult = false; // 不清除正确答案了
// 使用方式
queryWithRetry(res.body.execLogId)
.then((result) => {
console.log('查询成功', result);
const body = result.body;
const traQnsInfoVo = body.traQnsInfoVo;
topic.analyContent = traQnsInfoVo?.analyContent || ''; // 答案解析
topic.anserResult = traQnsInfoVo?.anserResult || answer.anserResult; // 正确答案文字内容
const judgeResultStatus = traQnsInfoVo?.judgeResult === 'P'; // P为正确U为错误
// 判断是语音回答还是文字回答, 通过是否存在语音地址判断 // todo 后续可能改成ossid判断
if (answer.voicePath) {
topic.es_status = '02';
} else {
// 纯文字
topic.es_status = '01';
}
// 处理成功结果
})
.catch((error) => {
console.log('查询失败', error);
topic.isPreview = false;
topic.es_status = ''; // 取消转圈
touchBtnRef.value?.clearinputText(old_text); // 清除发送框数据
// 处理失败情况
console.log('queryCrsPracticeAnswerResult', res.body);
const isWait = res.body.isWait;
if (isWait === 'Y') {
// 如果是Y,延迟2秒后重试,重试次数减1
return new Promise((resolve) => {
setTimeout(() => {
resolve(queryWithRetry(execLogId, maxRetries - 1));
}, 2000);
});
// const traQnsInfoVo = body.traQnsInfoVo;
// topic.analyContent = traQnsInfoVo.analyContent; // 答案解析
// console.log('答题结果', traQnsInfoVo);
// const judgeResultStatus = traQnsInfoVo.judgeResult === 'P'; // P为正确U为错误
// if (!addProblem()) {
// // 返回false说明到了最后一题
// console.log('最后一题');
// }
} else {
// 不是Y,直接返回结果
return res;
}
})
.catch(() => {
topic.es_status = ''; // 取消转圈
.catch((error) => {
// 对接口调用错误进行重试
if (maxRetries > 0) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(queryWithRetry(execLogId, maxRetries - 1));
}, 2000);
});
}
return Promise.reject(error);
});
};
// 录音组件提交
const touchBtnSubmit = (type, submitObj) => {
const old_text = touchBtnRef.value?.clearinputText(); // 清除发送框数据
@@ -325,7 +284,6 @@
} else if (type === 'text') {
topic.value.es_status = '01';
topic.value.anserResult = submitObj; // 正确答案文字内容
// submitProblemEssayQuestion({ anserResult: submitObj });
}
};
@@ -373,7 +331,7 @@
});
// #endif
});
const result_click = ({ key }) => {
console.log('res', key);
if (key === 'hand_in_paper') {
@@ -445,9 +403,7 @@
dialogRef.value.open();
};
// 执行交卷
const hand_in_paper = () => {
};
const hand_in_paper = () => {};
// 启动定时器
const startTimer = () => {
if (practiceTimeTimer) {
@@ -1,6 +1,6 @@
<template>
<view class="scroll_div">
<scroll-view class="scroll-Y" @scrolltolower="scrolltolower" :show-scrollbar="false">
<scroll-view class="scroll-Y" :show-scrollbar="false">
<view class="item">
<image src="/src/static/images/common/default_img_2.png" mode="aspectFit"></image>
</view>
@@ -1,7 +1,7 @@
<template>
<view class="scroll_div">
<scroll-view scroll-y="true" class="scroll-Y" @scrolltolower="scrolltolower" :show-scrollbar="false">
<view class="item" v-for="item in data_list">
<view class="item" v-for="item in data_list" @click="item_click(item)">
<view class="img_div">
<image-preview class="img" :imgId="item.imgId" mode="scaleToFill"></image-preview>
</view>
@@ -59,6 +59,10 @@
const scrolltolower = (item) => {
getData();
};
const item_click = (item) => {
};
defineExpose({
getData
});
+1 -1
View File
@@ -6,7 +6,7 @@
</view>
<view class="fixed_search_input_div fl1">
<uv-input v-model="inputValue" shape="circle" :customStyle="fixedCustomStyles" confirmType="search"
placeholderStyle='color:#999999;font-size:26rpx' placeholder="请输入关键字" :focus="true" :adjust-position="false"
placeholderStyle='color:#999999;font-size:26rpx' placeholder="请输入关键字" :adjust-position="false"
@confirm="search">
<template #suffix><uv-icon name="search" color="#2c8ef2" size="24" @click="search()"></uv-icon></template>
</uv-input>
+100 -226
View File
@@ -6,10 +6,20 @@
<view class="back-icon"></view>
</view>
<view class="fixed_search_input_div fl1">
<uv-input v-model="inputValue" shape="circle" :customStyle="fixedCustomStyles" confirmType="search"
placeholderStyle='color:#999999;font-size:26rpx' placeholder="请输入关键字" :focus="true" :adjust-position="false"
@confirm="search">
<template #suffix><uv-icon name="search" color="#2c8ef2" size="24" @click="search()"></uv-icon></template>
<uv-input
v-model="inputValue"
shape="circle"
:customStyle="fixedCustomStyles"
confirmType="search"
placeholderStyle="color:#999999;font-size:26rpx"
placeholder="请输入关键字"
:focus="true"
:adjust-position="false"
@confirm="search"
>
<template #suffix>
<uv-icon name="search" color="#2c8ef2" size="24" @click="search(inputValue)"></uv-icon>
</template>
</uv-input>
</view>
<view class="message_div" v-show="false">
@@ -19,253 +29,121 @@
</view>
</view>
<!-- 主体 -->
<view class="search_content">
<view class="search_content" v-show="!no_list_state">
<!-- 历史搜索 -->
<view class="title_div">
<view class="text">
历史搜索
</view>
<view class="fl1">
</view>
<view class="delete_img">
<view class="text">历史搜索</view>
<view class="fl1"></view>
<view class="delete_img" @click="del_all">
<image src="@/static/images/search/delete.png" class="img" mode="heightFix"></image>
</view>
</view>
<view class="history_div">
<view class="history_item" v-for="item in historyList">
{{item}}
</view>
<view class="history_item has-arrow" @click="show_all_history_fun">
<view class="down-corner-arrow" :class="show_all_history ? 'up' : 'down'"></view>
<view class="history_item" v-for="item in historyList" @click="search(item)">
{{ item }}
</view>
</view>
</view>
<view class="host_search_div">
</view>
<image class="bg_img" style="width: 718rpx;height: 1126rpx;" src="@/static/images/test/search_img.png">
</image>
<!-- 隐藏的计算容器 -->
<view class="measure-container">
<view v-for="(item, index) in hiddenHistorySearchList" :key="index" class="history_item">
{{ item }}
</view>
<view class="no_search" v-show="no_list_state">
<image class="img" src="@/static/images/search/no_search.png" mode="widthFix"></image>
<view class="text">暂无任何搜索记录</view>
</view>
</view>
</template>
<script setup>
import {
ref,
watchEffect,
nextTick,
onMounted
} from 'vue';
import common from '@/common/common.js'
import {
onShow,
onLoad
} from '@dcloudio/uni-app';
const tagRefs = ref([]) // 用于存储所有history_item的引用
import {
getCurrentInstance,
computed,
watch
} from 'vue';
const {
proxy
} = getCurrentInstance() // 获取当前组件实例
const currentHeight = ref(0); // 动态高度(单位:px
const visibleCount = ref(0)
const hiddenHistorySearchList = ref([]);
// 展开或者关闭
const show_all_history_fun = async () => {
show_all_history.value = !show_all_history.value
}
const show_all_history = ref(false)
const historyList = computed(() => show_all_history.value ? hiddenHistorySearchList.value : hiddenHistorySearchList
.value.slice(0, visibleCount.value));
onShow(() => {
const historySearchList = ['房贷审批', '小微贷条件', '对公开户', '反洗钱指引', '盗刷处理', '小微贷条件', '征信解读']
if (historySearchList) {
hiddenHistorySearchList.value = [...historySearchList]
nextTick(() => {
const widthPromises = hiddenHistorySearchList.value.map((res, index) => {
return new Promise(resolve => {
const query = uni.createSelectorQuery().in(proxy);
query.select(`.history_item:nth-child(${index + 1})`)
.boundingClientRect(data => {
resolve(data ? data.width : 0); // 解析宽度值
}).exec();
});
});
// 等待所有Promise完成
Promise.all(widthPromises).then(widths => {
console.log('所有宽度计算完成:', widths);
calculateLayout(widths); // 开始计算布局
});
})
}
})
const calculateLayout = (widths) => {
const gap = 12; // 项之间的间距
const expandBtnWidth = 80
const query = uni.createSelectorQuery().in(proxy);
query.select('.history_div')
.boundingClientRect(data => {
const containerWidth = data.width
let row1Count = 0; // 第一行可容纳数量
let row2Count = 0; // 第二行可容纳数量
let currentWidth = 0; // 当前行已用宽度
// 计算第一行可容纳数量
for (let i = 0; i < widths.length; i++) {
const itemWidth = widths[i] + (row1Count > 0 ? gap : 0);
if (currentWidth + itemWidth <= containerWidth) {
row1Count++;
currentWidth += itemWidth;
} else {
break;
}
}
// 计算第二行可容纳数量(预留展开按钮位置)
currentWidth = 0;
// 第二行总可用宽度 = 容器宽度 - 展开按钮宽度(含间距)
const row2MaxWidth = containerWidth - expandBtnWidth - gap;
for (let i = row1Count; i < widths.length; i++) {
const itemWidth = widths[i] + (row2Count > 0 ? gap : 0);
if (currentWidth + itemWidth <= row2MaxWidth) {
row2Count++;
currentWidth += itemWidth;
} else {
break;
}
}
console.log(`第一行: ${row1Count}个,第二行: ${row2Count}个(含展开按钮)`);
visibleCount.value = row1Count + row2Count;
}).exec();
}
import { ref, computed } from 'vue';
import common from '@/common/common.js';
import { onShow, onLoad } from '@dcloudio/uni-app';
// 静态样式配置
const fixedCustomStyles = {
backgroundColor: "#ffffff",
paddingLeft: "40rpx",
paddingTop: "5px",
paddingBottom: "5px",
border: "none"
}
const suffixIconStyle = {
color: "#2c8ef2",
fontSize: "28px"
}
backgroundColor: '#ffffff',
paddingLeft: '40rpx',
paddingTop: '5px',
paddingBottom: '5px',
border: 'none',
borderRadius: '6px'
};
const storageKey = 'history_search_list';
const asssss = ref(false);
const inputValue = ref('');
const fromType = ref('');
const historyList = ref([]);
const no_list_state = computed(() => historyList.value.length === 0);
const fromType = ref('')
onLoad((params) => {
fromType.value = params.from||'';
fromType.value = params.from || '';
});
onShow(() => {
let storageList = common.getValue(storageKey);
if (!Array.isArray(storageList)) {
storageList = [];
}
historyList.value = storageList;
});
const del_all = () => {
common.show('', '确认删除全部搜索历史').then((res) => {
if (res) {
common.setValue(storageKey, []);
historyList.value = [];
}
});
};
const measureRef = ref(null)
const measureItems = ref([])
const search=() => {
common.navigateTo('/pages/search/result?searchName='+ inputValue.value +'&from=' + fromType.value)
}
const search = (text) => {
inputValue.value = text;
const searchValue = text.trim();
if (searchValue) {
// 获取现有存储的搜索记录
let storageList = common.getValue(storageKey);
// 关键修复:如果不是数组,初始化为空数组
if (!Array.isArray(storageList)) {
storageList = [];
}
// 去重处理 - 移除已存在的相同记录
const uniqueList = storageList.filter((item) => item !== searchValue);
// 添加新记录到开头
uniqueList.unshift(searchValue);
// 限制存储的最大记录数,比如最多保存10条
const MAX_RECORDS = 10;
if (uniqueList.length > MAX_RECORDS) {
uniqueList.pop();
}
// 保存到本地存储
common.setValue(storageKey, uniqueList);
// 导航到搜索结果页,使用encodeURIComponent处理特殊字符
common.navigateTo(`/pages/search/result?searchName=${searchValue}&from=${fromType.value}`);
}
};
</script>
<style scoped lang="scss">
.history_div {
.no_search {
width: 100%;
display: flex;
flex-wrap: wrap;
flex-direction: column;
align-items: center;
margin-top: 100rpx;
.img {
width: 230rpx;
}
.text {
color: #999;
font-size: 30rpx;
}
}
//、、xxxxxxx
.history_div {
width: 100%;
}
.measure-container {
display: flex;
position: fixed;
top:-500rpx; // 藏起来,让他看不到
}
.history_item {
white-space: nowrap;
padding: 8rpx 22rpx;
border-radius: 40rpx 40rpx 40rpx 40rpx;
border: 1px solid #999;
padding: 8rpx 0;
color: #777;
}
.history_item {
margin-bottom: 16rpx;
}
/* 除最后一个子元素外,都添加右间距 */
.history_item:not(:last-child) {
margin-right: 12px;
}
.has-arrow {
border: 1px solid #bbb;
position: relative;
}
/* 朝下的拐角箭头容器 */
.down-corner-arrow {
padding: 10rpx 8rpx;
position: relative;
}
.down-corner-arrow.up {
transform: rotate(90deg);
top: 0%;
left: 0%;
}
.down-corner-arrow.down {
transform: rotate(-90deg);
top: 50%;
left: 0%;
}
/* 左半边箭头(向左旋转) */
.down-corner-arrow::before {
content: '';
position: absolute;
width: 20rpx;
/* 线段长度 */
height: 2rpx;
/* 线段粗细 */
background-color: #bbb;
transform-origin: right center;
/* 旋转中心在右侧 */
transform: rotate(-48deg);
/* 向左旋转50°,使总开口角100° */
}
/* 右半边箭头(向右旋转) */
.down-corner-arrow::after {
content: '';
position: absolute;
width: 20rpx;
/* 线段长度 */
height: 2rpx;
/* 线段粗细 */
background-color: #bbb;
transform-origin: right center;
/* 旋转中心在右侧 */
transform: rotate(48deg);
/* 向右旋转50°,使总开口角100° */
}
.title_div {
display: flex;
justify-content: space-between;
@@ -285,13 +163,10 @@
align-items: center;
justify-content: center;
padding: 20rpx 0 20rpx 32rpx;
// background-color: red;
.img {
height: 24rpx;
}
}
}
.search_content {
@@ -301,7 +176,7 @@
display: flex;
flex-direction: column;
align-items: center;
padding: 0 20rpx;
padding: 0 30rpx;
min-height: 200rpx;
transition: max-height 0.3s ease;
.bg_img {
@@ -312,7 +187,7 @@
.fixed_search_div {
padding: calc(10rpx + var(--status-bar-height)) 15rpx 24rpx 10rpx;
background: linear-gradient(90deg, #F1F7FF 0%, #D8EDFF 50%, #C3E6FF 100%);
background: linear-gradient(90deg, #f1f7ff 0%, #d8edff 50%, #c3e6ff 100%);
display: flex;
align-items: center;
@@ -340,8 +215,8 @@
left: 25%;
width: 40%;
height: 40%;
border-top: 4rpx solid #2B2C2E;
border-left: 4rpx solid #2B2C2E;
border-top: 4rpx solid #2b2c2e;
border-left: 4rpx solid #2b2c2e;
transform: rotate(-45deg);
}
}
@@ -350,6 +225,5 @@
.main_div {
display: flex;
flex-direction: column;
}
</style>
</style>
+1 -4
View File
@@ -73,13 +73,10 @@
}
queryTraExamPapersPage(params)
.then((res) => {
console.log('resresresresres', res);
total.value = res.total;
data_list.push(...res.body);
})
.catch((res) => {
console.log('谢谢谢谢谢谢', res);
})
.catch((res) => {})
.finally(() => {
if (data_list.length >= total.value) {
status.value = 'nomore';
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB