|
@@ -4,177 +4,222 @@
|
|
|
scroll-x
|
|
|
:scroll-into-view="`item-${nowIndex}`"
|
|
|
class="topic-scroll"
|
|
|
+ :scroll-with-animation="true"
|
|
|
+ :scroll-anchoring="true"
|
|
|
+ :show-scrollbar="false"
|
|
|
>
|
|
|
- <view
|
|
|
- v-for="(item, parindex) in topics"
|
|
|
- :key="parindex"
|
|
|
- :id="`item-${parindex}`"
|
|
|
- class="topic-item"
|
|
|
- :style="{
|
|
|
- flexShrink: 0
|
|
|
- }"
|
|
|
- >
|
|
|
- <!-- 头部 -->
|
|
|
- <view class="topic-header">
|
|
|
- <view class="topic-header-left">
|
|
|
- <view class="topic-type">
|
|
|
- {{ answerList[parindex]?.length > 1 ? '多选题' : '单选题' }}
|
|
|
+ <template v-for="(item, parindex) in topics.ques" :key="parindex">
|
|
|
+ <view
|
|
|
+ :id="`item-${parindex}`"
|
|
|
+ class="topic-item"
|
|
|
+ :style="{
|
|
|
+ width: `${windowWidth}px`,
|
|
|
+ height: `${windowHeight}px`,
|
|
|
+ flexShrink: 0,
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <!-- 头部 -->
|
|
|
+ <view class="topic-header">
|
|
|
+ <view class="topic-header-left">
|
|
|
+ <view class="topic-type">
|
|
|
+ {{ answerList[parindex]?.length > 1 ? "多选题" : "单选题" }}
|
|
|
+ </view>
|
|
|
+ <view class="topic-count">
|
|
|
+ 第{{ parindex + 1 }}题/共{{ topics.ques.length }}题
|
|
|
+ </view>
|
|
|
</view>
|
|
|
- <view class="topic-count">
|
|
|
- 第{{ parindex + 1 }}题/共{{ topics.length }}题
|
|
|
+ <view class="star-icon" @tap="handleStar(item)">
|
|
|
+ <text
|
|
|
+ class="iconfont"
|
|
|
+ :class="starIcon === 'star' ? 'icon-star' : 'icon-star-filled'"
|
|
|
+ ></text>
|
|
|
</view>
|
|
|
</view>
|
|
|
- <view class="star-icon" @tap="handleStar(item)">
|
|
|
- <text class="iconfont" :class="starIcon === 'star' ? 'icon-star' : 'icon-star-filled'"></text>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
|
|
|
- <!-- 问题内容 -->
|
|
|
- <view class="topic-content">
|
|
|
- <view class="question-text">请问图片里那个才是党参?</view>
|
|
|
- <questions
|
|
|
- v-for="(_, index) in 5"
|
|
|
- :key="index"
|
|
|
- :answer-list="answerList[parindex] || []"
|
|
|
- :index="index"
|
|
|
- :select-count="selectIndexList"
|
|
|
- @select="handleSelect"
|
|
|
- @show-answer="setShowAnswer"
|
|
|
- />
|
|
|
- </view>
|
|
|
+ <!-- 问题内容 -->
|
|
|
+ <view class="topic-content">
|
|
|
+ <view class="question-text">{{ item.title }}</view>
|
|
|
+ <questions
|
|
|
+ v-for="(question, index) in item.questions"
|
|
|
+ :key="index"
|
|
|
+ :answer-list="
|
|
|
+ Array.isArray(item.anslist) ? item.anslist : [item.anslist]
|
|
|
+ "
|
|
|
+ :index="index"
|
|
|
+ :select-count="selectIndexList[parindex] || []"
|
|
|
+ :question="question"
|
|
|
+ :parindex="parindex"
|
|
|
+ @select="handleSelect"
|
|
|
+ @show-answer="(index) => setShowAnswer(index, parindex)"
|
|
|
+ />
|
|
|
+ </view>
|
|
|
|
|
|
- <!-- 答案展示 -->
|
|
|
- <view v-if="showAnswer" class="answer-section">
|
|
|
- <view class="answer-content">
|
|
|
- <view class="answer-row">
|
|
|
- <view class="answer-item">
|
|
|
- 正确答案:
|
|
|
- <text class="answer-text">{{ getRightAnswer(parindex) }}</text>
|
|
|
- </view>
|
|
|
- <view class="answer-item">
|
|
|
- 我的答案:
|
|
|
- <text class="answer-text">{{ getMyAnswer() }}</text>
|
|
|
+ <!-- 答案展示 -->
|
|
|
+ <view v-if="showAnswer[parindex]" class="answer-section">
|
|
|
+ <view class="answer-content">
|
|
|
+ <view class="answer-row">
|
|
|
+ <view class="answer-item">
|
|
|
+ 正确答案:
|
|
|
+ <text class="answer-text">{{
|
|
|
+ getRightAnswer(parindex)
|
|
|
+ }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="answer-item">
|
|
|
+ 我的答案:
|
|
|
+ <text class="answer-text">{{ getMyAnswer(parindex) }}</text>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
- </view>
|
|
|
|
|
|
- <!-- 底部按钮 -->
|
|
|
- <view class="button-group">
|
|
|
- <button
|
|
|
- v-if="parindex >= 1 && parindex < topics.length - 1"
|
|
|
- class="prev-btn"
|
|
|
- @tap="handlePrevPage(item, parindex)"
|
|
|
- >
|
|
|
- 上一题
|
|
|
- </button>
|
|
|
- <button
|
|
|
- v-if="parindex < topics.length - 1"
|
|
|
- class="next-btn"
|
|
|
- @tap="handleNextPage(item, parindex)"
|
|
|
- >
|
|
|
- 下一题
|
|
|
- </button>
|
|
|
+ <!-- 底部按钮 -->
|
|
|
+ <view class="button-group">
|
|
|
+ <button
|
|
|
+ v-if="parindex >= 1 && parindex < topics.ques.length - 1"
|
|
|
+ class="prev-btn"
|
|
|
+ @tap="handlePrevPage(item, parindex)"
|
|
|
+ >
|
|
|
+ 上一题
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ v-if="parindex < topics.ques.length - 1"
|
|
|
+ class="next-btn"
|
|
|
+ @tap="handleNextPage(item, parindex)"
|
|
|
+ >
|
|
|
+ 下一题
|
|
|
+ </button>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
- </view>
|
|
|
+ </template>
|
|
|
</scroll-view>
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, onMounted } from 'vue'
|
|
|
-import Questions from './Questions.vue'
|
|
|
+import { ref, onMounted } from "vue";
|
|
|
+import Questions from "./Questions.vue";
|
|
|
|
|
|
-const TopicMapList = ['A', 'B', 'C', 'D', 'E']
|
|
|
+const TopicMapList = ["A", "B", "C", "D", "E"];
|
|
|
|
|
|
// Props 定义
|
|
|
const props = defineProps({
|
|
|
topics: {
|
|
|
- type: Array,
|
|
|
- default: () => Array(3).fill(0)
|
|
|
+ type: Object,
|
|
|
+ default: () => ({}),
|
|
|
},
|
|
|
onStar: {
|
|
|
type: Function,
|
|
|
- default: null
|
|
|
+ default: null,
|
|
|
},
|
|
|
type: {
|
|
|
type: String,
|
|
|
- default: 'radio'
|
|
|
- }
|
|
|
-})
|
|
|
+ default: "radio",
|
|
|
+ },
|
|
|
+});
|
|
|
|
|
|
// Emits 定义
|
|
|
-const emit = defineEmits(['prevPage', 'nextPage'])
|
|
|
+const emit = defineEmits(["prevPage", "nextPage"]);
|
|
|
|
|
|
// 响应式数据
|
|
|
-const answerList = ref([])
|
|
|
-const nowIndex = ref(0)
|
|
|
-const windowWidth = ref(0)
|
|
|
-const windowHeight = ref(0)
|
|
|
-const starIcon = ref('star')
|
|
|
-const showAnswer = ref(false)
|
|
|
-const selectIndexList = ref([])
|
|
|
+const answerList = ref([]);
|
|
|
+const nowIndex = ref(0);
|
|
|
+const windowWidth = ref(0);
|
|
|
+const windowHeight = ref(0);
|
|
|
+const starIcon = ref("star");
|
|
|
+const showAnswer = ref([]);
|
|
|
+const selectIndexList = ref([]);
|
|
|
|
|
|
// 生命周期钩子
|
|
|
onMounted(() => {
|
|
|
- const systemInfo = uni.getSystemInfoSync()
|
|
|
- windowWidth.value = systemInfo.windowWidth
|
|
|
- windowHeight.value = systemInfo.windowHeight
|
|
|
- answerList.value = [[1, 3], [2], [3]]
|
|
|
-})
|
|
|
+ const systemInfo = uni.getSystemInfoSync();
|
|
|
+ windowWidth.value = systemInfo.windowWidth;
|
|
|
+ windowHeight.value = systemInfo.windowHeight;
|
|
|
+ selectIndexList.value = Array(props.topics.ques.length)
|
|
|
+ .fill()
|
|
|
+ .map(() => []);
|
|
|
+ showAnswer.value = Array(props.topics.ques.length).fill(false);
|
|
|
+});
|
|
|
|
|
|
// 方法
|
|
|
const handleStar = (item) => {
|
|
|
- if (!props.onStar) return
|
|
|
- props.onStar(item).then(res => {
|
|
|
- if (!res) return
|
|
|
- starIcon.value = starIcon.value === 'star' ? 'star-2' : 'star'
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-const handleSelect = (index) => {
|
|
|
- selectIndexList.value.push(index)
|
|
|
-}
|
|
|
+ if (!props.onStar) return;
|
|
|
+ props.onStar(item).then((res) => {
|
|
|
+ if (!res) return;
|
|
|
+ starIcon.value = starIcon.value === "star" ? "star-2" : "star";
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const handleSelect = (value, parindex) => {
|
|
|
+ const arr = selectIndexList.value[parindex];
|
|
|
+ const currentTopic = props.topics.ques[parindex];
|
|
|
+ const max = Array.isArray(currentTopic.anslist)
|
|
|
+ ? currentTopic.anslist.length
|
|
|
+ : 1;
|
|
|
+
|
|
|
+ if (arr.includes(value)) return;
|
|
|
+ if (arr.length >= max) return;
|
|
|
+
|
|
|
+ if (max > 1) {
|
|
|
+ arr.push(value);
|
|
|
+ } else {
|
|
|
+ selectIndexList.value[parindex] = [value];
|
|
|
+ }
|
|
|
+};
|
|
|
|
|
|
-const setShowAnswer = (value) => {
|
|
|
- showAnswer.value = value
|
|
|
-}
|
|
|
+const setShowAnswer = (value, parindex) => {
|
|
|
+ showAnswer.value[parindex] = value;
|
|
|
+};
|
|
|
|
|
|
const getRightAnswer = (index) => {
|
|
|
- return (answerList.value[index] || [])
|
|
|
- .map(item => TopicMapList[item])
|
|
|
- .join('')
|
|
|
-}
|
|
|
-
|
|
|
-const getMyAnswer = () => {
|
|
|
- return selectIndexList.value
|
|
|
- .map(item => TopicMapList[item])
|
|
|
- .join('')
|
|
|
-}
|
|
|
+ const topic = props.topics.ques[index];
|
|
|
+ const answers = Array.isArray(topic.anslist)
|
|
|
+ ? topic.anslist
|
|
|
+ : [topic.anslist];
|
|
|
+ return answers
|
|
|
+ .map((value) => {
|
|
|
+ const question = topic.questions.find((q) => q.value === value);
|
|
|
+ return question ? TopicMapList[topic.questions.indexOf(question)] : "";
|
|
|
+ })
|
|
|
+ .join("");
|
|
|
+};
|
|
|
+
|
|
|
+const getMyAnswer = (parindex) => {
|
|
|
+ const topic = props.topics.ques[parindex];
|
|
|
+ return (selectIndexList.value[parindex] || [])
|
|
|
+ .map((value) => {
|
|
|
+ const question = topic.questions.find((q) => q.value === value);
|
|
|
+ return question ? TopicMapList[topic.questions.indexOf(question)] : "";
|
|
|
+ })
|
|
|
+ .join("");
|
|
|
+};
|
|
|
|
|
|
const handlePrevPage = (item, index) => {
|
|
|
- nowIndex.value = index - 1
|
|
|
- emit('prevPage', item, index)
|
|
|
-}
|
|
|
+ nowIndex.value = index - 1;
|
|
|
+ emit("prevPage", item, index);
|
|
|
+};
|
|
|
|
|
|
const handleNextPage = (item, index) => {
|
|
|
- nowIndex.value = index + 1
|
|
|
- emit('nextPage', item, index)
|
|
|
-}
|
|
|
+ nowIndex.value = index + 1;
|
|
|
+ emit("nextPage", item, index);
|
|
|
+};
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-@import '@/uni.scss';
|
|
|
+@import "@/uni.scss";
|
|
|
|
|
|
.topic-container {
|
|
|
width: 100vw;
|
|
|
overflow: hidden;
|
|
|
+ position: relative;
|
|
|
}
|
|
|
|
|
|
.topic-scroll {
|
|
|
display: flex;
|
|
|
white-space: nowrap;
|
|
|
padding: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ -webkit-overflow-scrolling: touch;
|
|
|
}
|
|
|
|
|
|
.topic-item {
|
|
@@ -183,6 +228,7 @@ const handleNextPage = (item, index) => {
|
|
|
gap: 12px;
|
|
|
padding: 12px;
|
|
|
position: relative;
|
|
|
+ box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
.topic-header {
|
|
@@ -226,7 +272,7 @@ const handleNextPage = (item, index) => {
|
|
|
.answer-section {
|
|
|
flex: 1;
|
|
|
border-radius: 16rpx;
|
|
|
- border: 1px solid $uni-primary;
|
|
|
+ border: 1px solid #ddd;
|
|
|
padding: 24rpx;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
@@ -272,4 +318,4 @@ const handleNextPage = (item, index) => {
|
|
|
background-color: $uni-primary;
|
|
|
color: #fff;
|
|
|
}
|
|
|
-</style>
|
|
|
+</style>
|