- 电子药箱: 药品库存管理 + 手动录入 + 今日用药打卡 - 药品百科: 搜索 + 分类筛选 + 20种药品静态数据 - 惠教中心: 4条药品使用指南课程 - 我的: 家庭成员信息管理 - 自定义TabBar + navigation-bar组件 - SVG药品分类插图
217 lines
6.1 KiB
TypeScript
217 lines
6.1 KiB
TypeScript
// 定义接口类型
|
|
interface Question {
|
|
id: number;
|
|
type: number;
|
|
question: string;
|
|
option: Record<string, any>;
|
|
}
|
|
|
|
interface AnswerItem {
|
|
queId: string;
|
|
ans: string[];
|
|
suc?: boolean;
|
|
}
|
|
|
|
interface QuizComponent {
|
|
properties: {
|
|
questions: Question[];
|
|
answerList: AnswerItem[];
|
|
};
|
|
data: {
|
|
selectedAnswers: Record<number, string[]>;
|
|
renderQuestions: Array<
|
|
Question & { options: Array<{ key: string; value: string }> }
|
|
>;
|
|
};
|
|
setData: (data: Partial<Record<string, any>>, callback?: () => void) => void;
|
|
triggerEvent: (name: string, data?: any) => void;
|
|
isSelected: (qid: string | number, key: string) => boolean;
|
|
getSelectedAnswer: (qid: string | number, index: number) => string;
|
|
isCorrect: (qid: string, key: string) => boolean;
|
|
isWrong: (qid: string, key: string) => boolean;
|
|
handleRadioChange: (e: WechatMiniprogram.RadioGroupChange) => void;
|
|
handleCheckboxChange: (e: WechatMiniprogram.CheckboxGroupChange) => void;
|
|
getFormattedAnswers: () => Array<{
|
|
questionId: number;
|
|
answers: string[];
|
|
questionType: number;
|
|
}>;
|
|
getAllAnswers: () => Array<{
|
|
questionId: number;
|
|
answers: string[];
|
|
questionType: number;
|
|
}>;
|
|
isAllAnswered: () => boolean;
|
|
getProgress: () => { answered: number; total: number; percentage: number };
|
|
}
|
|
|
|
// 定义常量
|
|
const QUESTION_TYPE = {
|
|
SINGLE: 1,
|
|
MULTIPLE: 2,
|
|
};
|
|
|
|
Component({
|
|
properties: {
|
|
questions: {
|
|
type: Array,
|
|
value: [],
|
|
},
|
|
answerList: {
|
|
type: Array,
|
|
value: [],
|
|
},
|
|
},
|
|
|
|
observers: {
|
|
"questions, answerList": function (this: QuizComponent) {
|
|
const renderQuestions = (this.properties.questions || []).map(
|
|
(q: Question) => ({
|
|
...q,
|
|
options: Object.keys(q.option || {}).map((k) => ({
|
|
key: k,
|
|
value: q.option[k],
|
|
})),
|
|
})
|
|
);
|
|
|
|
const answerList = Array.isArray(this.properties.answerList)
|
|
? this.properties.answerList
|
|
: [];
|
|
const selectedAnswers = answerList.reduce((acc, item) => {
|
|
if (item && item.queId && item.ans) {
|
|
acc[Number(item.queId)] = Array.isArray(item.ans)
|
|
? item.ans
|
|
: [item.ans];
|
|
}
|
|
return acc;
|
|
}, {} as Record<number, string[]>);
|
|
|
|
this.setData({
|
|
renderQuestions,
|
|
selectedAnswers,
|
|
});
|
|
},
|
|
},
|
|
|
|
data: {
|
|
selectedAnswers: {} as Record<number, string[]>,
|
|
renderQuestions: [] as Array<
|
|
Question & { options: Array<{ key: string; value: string }> }
|
|
>,
|
|
},
|
|
|
|
methods: {
|
|
isSelected(this: QuizComponent, qid: string | number, key: string) {
|
|
const selected = this.data.selectedAnswers[Number(qid)];
|
|
return Array.isArray(selected) && selected.includes(key);
|
|
},
|
|
|
|
getSelectedAnswer(this: QuizComponent, qid: string | number, index: number) {
|
|
const selected = this.data.selectedAnswers[Number(qid)];
|
|
return Array.isArray(selected) ? selected[index] : "";
|
|
},
|
|
|
|
isCorrect(this: QuizComponent, qid: string, key: string) {
|
|
const answerList = Array.isArray(this.properties.answerList)
|
|
? this.properties.answerList
|
|
: [];
|
|
return answerList.some((item: AnswerItem) => {
|
|
const answers = Array.isArray(item.ans) ? item.ans : [];
|
|
return String(item.queId) === String(qid) && answers.includes(key) && item.suc;
|
|
});
|
|
},
|
|
|
|
isWrong(this: QuizComponent, qid: string, key: string) {
|
|
const answerList = Array.isArray(this.properties.answerList)
|
|
? this.properties.answerList
|
|
: [];
|
|
return answerList.some((item: AnswerItem) => {
|
|
const answers = Array.isArray(item.ans) ? item.ans : [];
|
|
return String(item.queId) === String(qid) && answers.includes(key) && !item.suc;
|
|
});
|
|
},
|
|
|
|
// 处理单选变化 { queId: q.id, ans: selectedAnswers }
|
|
handleRadioChange(
|
|
this: QuizComponent,
|
|
e: WechatMiniprogram.RadioGroupChange
|
|
) {
|
|
const { questionId } = e.currentTarget.dataset;
|
|
const value = e.detail.value;
|
|
if (!questionId) return;
|
|
const numericQuestionId = Number(questionId);
|
|
const newAnswers = value ? [value] : [];
|
|
|
|
this.setData({
|
|
[`selectedAnswers.${numericQuestionId}`]: newAnswers,
|
|
});
|
|
this.triggerEvent("change", {
|
|
queId: numericQuestionId,
|
|
ans: newAnswers,
|
|
});
|
|
},
|
|
|
|
// 处理多选变化
|
|
handleCheckboxChange(
|
|
this: QuizComponent,
|
|
e: WechatMiniprogram.CheckboxGroupChange
|
|
) {
|
|
const { questionId } = e.currentTarget.dataset;
|
|
const values = Array.isArray(e.detail.value) ? e.detail.value : [];
|
|
if (!questionId) return;
|
|
const numericQuestionId = Number(questionId);
|
|
this.setData({
|
|
[`selectedAnswers.${numericQuestionId}`]: values,
|
|
});
|
|
|
|
this.triggerEvent("change", {
|
|
queId: numericQuestionId,
|
|
ans: values,
|
|
});
|
|
},
|
|
|
|
getFormattedAnswers(this: QuizComponent) {
|
|
const answers = [];
|
|
for (const [questionId, selectedOptions] of Object.entries(
|
|
this.data.selectedAnswers
|
|
)) {
|
|
if (selectedOptions && selectedOptions.length > 0) {
|
|
answers.push({
|
|
queId: Number(questionId),
|
|
ans: selectedOptions,
|
|
});
|
|
}
|
|
}
|
|
return answers;
|
|
},
|
|
|
|
getAllAnswers(this: QuizComponent) {
|
|
return this.getFormattedAnswers();
|
|
},
|
|
|
|
isAllAnswered(this: QuizComponent) {
|
|
const totalQuestions = this.properties.questions.length;
|
|
const answeredQuestions = Object.values(this.data.selectedAnswers).filter(
|
|
(answers) => answers && answers.length > 0
|
|
).length;
|
|
return totalQuestions === answeredQuestions;
|
|
},
|
|
|
|
getProgress(this: QuizComponent) {
|
|
const totalQuestions = this.data.renderQuestions.length;
|
|
const answeredQuestions = Object.values(this.data.selectedAnswers).filter(
|
|
(answers) => answers && answers.length > 0
|
|
).length;
|
|
return {
|
|
answered: answeredQuestions,
|
|
total: totalQuestions,
|
|
percentage:
|
|
totalQuestions > 0
|
|
? Math.round((answeredQuestions / totalQuestions) * 100)
|
|
: 0,
|
|
};
|
|
},
|
|
},
|
|
});
|