vue3-quiz-lib 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/style.css +1 -0
- package/dist/vue-quiz-exam.js +277 -0
- package/dist/vue-quiz-exam.umd.cjs +1 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Vue 3 + TypeScript + Vite
|
|
2
|
+
|
|
3
|
+
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
|
4
|
+
|
|
5
|
+
Learn more about the recommended Project Setup and IDE Support in the [Vue Docs TypeScript Guide](https://vuejs.org/guide/typescript/overview.html#project-setup).
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.opt-item[data-v-f714d90e],.opt-item[data-v-196575e1]{display:block;margin:8px 0;cursor:pointer}.tip-text[data-v-036982ce]{color:#999;padding:10px 0}.quiz-card[data-v-f266e716]{padding:16px;border:1px solid #eee;border-radius:8px;margin-bottom:14px;background:#fff}.quiz-title[data-v-f266e716]{font-size:15px;margin-bottom:12px}.score-tag[data-v-f266e716]{color:#666;font-size:13px}.wrong[data-v-f266e716]{border-color:#f53f3f;background-color:#fff2f2}.right[data-v-f266e716]{border-color:#00b42a;background-color:#f0fff4}.analysis[data-v-f266e716]{margin-top:12px;padding-top:10px;border-top:1px dashed #eee;font-size:13px;color:#666}.sheet-wrap[data-v-c150eab2]{width:180px;border:1px solid #eee;padding:16px;border-radius:8px;position:sticky;top:20px;background:#fff}.sheet-title[data-v-c150eab2]{margin:0 0 12px;font-size:15px}.num-list[data-v-c150eab2]{display:flex;flex-wrap:wrap;gap:6px}.num-item[data-v-c150eab2]{width:28px;height:28px;line-height:28px;text-align:center;border:1px solid #ccc;border-radius:4px;font-size:13px;cursor:pointer}.num-item.ok[data-v-c150eab2]{background:#00b42a;color:#fff;border-color:#00b42a}.num-item.err[data-v-c150eab2]{background:#f53f3f;color:#fff;border-color:#f53f3f}.result-mask[data-v-9d92d531]{position:fixed;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.55);display:flex;align-items:center;justify-content:center;z-index:9999}.result-box[data-v-9d92d531]{background:#fff;padding:30px;border-radius:12px;min-width:320px}.btn-group[data-v-9d92d531]{margin-top:20px;display:flex;gap:12px;justify-content:center}button[data-v-9d92d531]{padding:6px 16px;border-radius:4px;border:none;cursor:pointer}.close-btn[data-v-9d92d531]{background:#eee}.reset-btn[data-v-9d92d531]{background:#409eff;color:#fff}.submit-btn[data-v-2cc1922f]{padding:6px 18px;background:#1989fa;color:#fff;border:none;border-radius:4px;cursor:pointer}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { ref as g, onMounted as R, onUnmounted as q, openBlock as c, createElementBlock as u, Fragment as y, renderList as x, createElementVNode as r, toDisplayString as m, normalizeClass as I, createTextVNode as A, createBlock as z, resolveDynamicComponent as N, createCommentVNode as S, unref as h, createVNode as L } from "vue";
|
|
2
|
+
function E(e = 3600) {
|
|
3
|
+
const l = g(e), s = g("00:00:00");
|
|
4
|
+
let n = null;
|
|
5
|
+
const i = (t) => {
|
|
6
|
+
const _ = Math.floor(t / 3600), v = Math.floor(t % 3600 / 60), f = t % 60;
|
|
7
|
+
return `${String(_).padStart(2, "0")}:${String(v).padStart(2, "0")}:${String(f).padStart(2, "0")}`;
|
|
8
|
+
}, d = () => {
|
|
9
|
+
n = setInterval(() => {
|
|
10
|
+
if (l.value <= 0) {
|
|
11
|
+
clearInterval(n);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
l.value--, s.value = i(l.value);
|
|
15
|
+
}, 1e3);
|
|
16
|
+
}, a = () => {
|
|
17
|
+
n && clearInterval(n);
|
|
18
|
+
}, o = () => {
|
|
19
|
+
l.value = e, s.value = i(e);
|
|
20
|
+
};
|
|
21
|
+
return R(() => d()), q(() => a()), {
|
|
22
|
+
formatTime: s,
|
|
23
|
+
stopTimer: a,
|
|
24
|
+
resetTimer: o
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function j(e) {
|
|
28
|
+
const l = g({}), s = g([]), n = g([]), i = g(0), d = () => e.reduce((t, _) => t + _.score, 0), a = () => {
|
|
29
|
+
s.value = [], n.value = [], i.value = 0, e.forEach((t) => {
|
|
30
|
+
const _ = l.value[t.id];
|
|
31
|
+
if (!_) {
|
|
32
|
+
s.value.push(t.id);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
let v = !1;
|
|
36
|
+
if (t.type === "radio" && (v = _ === t.answer), t.type === "checkbox") {
|
|
37
|
+
const f = [..._].sort().join(","), $ = [...t.answer].sort().join(",");
|
|
38
|
+
v = f === $;
|
|
39
|
+
}
|
|
40
|
+
v ? (i.value += t.score, n.value.push(t.id)) : s.value.push(t.id);
|
|
41
|
+
});
|
|
42
|
+
}, o = () => {
|
|
43
|
+
l.value = {}, s.value = [], n.value = [], i.value = 0;
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
userAnswer: l,
|
|
47
|
+
wrongList: s,
|
|
48
|
+
rightList: n,
|
|
49
|
+
totalScore: i,
|
|
50
|
+
fullScore: d(),
|
|
51
|
+
checkAnswer: a,
|
|
52
|
+
resetAnswer: o
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const p = (e, l) => {
|
|
56
|
+
const s = e.__vccOpts || e;
|
|
57
|
+
for (const [n, i] of l)
|
|
58
|
+
s[n] = i;
|
|
59
|
+
return s;
|
|
60
|
+
}, D = { class: "radio-wrap" }, B = ["name", "value", "checked", "onChange"], M = {
|
|
61
|
+
__name: "QuizRadio",
|
|
62
|
+
props: ["id", "options", "modelValue"],
|
|
63
|
+
emits: ["update:modelValue"],
|
|
64
|
+
setup(e, { emit: l }) {
|
|
65
|
+
return (s, n) => (c(), u("div", D, [
|
|
66
|
+
(c(!0), u(y, null, x(e.options, (i) => (c(), u("label", {
|
|
67
|
+
key: i,
|
|
68
|
+
class: "opt-item"
|
|
69
|
+
}, [
|
|
70
|
+
r("input", {
|
|
71
|
+
type: "radio",
|
|
72
|
+
name: `q_${e.id}`,
|
|
73
|
+
value: i,
|
|
74
|
+
checked: e.modelValue === i,
|
|
75
|
+
onChange: (d) => s.$emit("update:modelValue", i)
|
|
76
|
+
}, null, 40, B),
|
|
77
|
+
r("span", null, m(i), 1)
|
|
78
|
+
]))), 128))
|
|
79
|
+
]));
|
|
80
|
+
}
|
|
81
|
+
}, F = /* @__PURE__ */ p(M, [["__scopeId", "data-v-f714d90e"]]);
|
|
82
|
+
const O = { class: "checkbox-wrap" }, U = ["value", "checked", "onChange"], W = {
|
|
83
|
+
__name: "QuizCheckbox",
|
|
84
|
+
props: ["id", "options", "modelValue"],
|
|
85
|
+
emits: ["update:modelValue"],
|
|
86
|
+
setup(e, { emit: l }) {
|
|
87
|
+
const s = e, n = l, i = (d, a) => {
|
|
88
|
+
const o = [...s.modelValue || []];
|
|
89
|
+
if (d.target.checked)
|
|
90
|
+
o.push(a);
|
|
91
|
+
else {
|
|
92
|
+
const t = o.indexOf(a);
|
|
93
|
+
t > -1 && o.splice(t, 1);
|
|
94
|
+
}
|
|
95
|
+
n("update:modelValue", o);
|
|
96
|
+
};
|
|
97
|
+
return (d, a) => (c(), u("div", O, [
|
|
98
|
+
(c(!0), u(y, null, x(e.options, (o) => (c(), u("label", {
|
|
99
|
+
key: o,
|
|
100
|
+
class: "opt-item"
|
|
101
|
+
}, [
|
|
102
|
+
r("input", {
|
|
103
|
+
type: "checkbox",
|
|
104
|
+
value: o,
|
|
105
|
+
checked: (e.modelValue || []).includes(o),
|
|
106
|
+
onChange: (t) => i(t, o)
|
|
107
|
+
}, null, 40, U),
|
|
108
|
+
r("span", null, m(o), 1)
|
|
109
|
+
]))), 128))
|
|
110
|
+
]));
|
|
111
|
+
}
|
|
112
|
+
}, G = /* @__PURE__ */ p(W, [["__scopeId", "data-v-196575e1"]]);
|
|
113
|
+
const H = {}, J = { class: "tip-text" };
|
|
114
|
+
function K(e, l) {
|
|
115
|
+
return c(), u("div", J, " 该题型暂未支持,后续版本拓展开放 ");
|
|
116
|
+
}
|
|
117
|
+
const P = /* @__PURE__ */ p(H, [["render", K], ["__scopeId", "data-v-036982ce"]]);
|
|
118
|
+
const X = ["id"], Y = { class: "quiz-title" }, Z = { class: "score-tag" }, ee = {
|
|
119
|
+
key: 0,
|
|
120
|
+
class: "analysis"
|
|
121
|
+
}, te = {
|
|
122
|
+
__name: "QuizCard",
|
|
123
|
+
props: ["item", "answerData", "wrongIds", "rightIds", "showResult"],
|
|
124
|
+
setup(e) {
|
|
125
|
+
const l = e, s = () => l.wrongIds.includes(l.item.id), n = () => l.rightIds.includes(l.item.id), i = (d) => ({
|
|
126
|
+
radio: F,
|
|
127
|
+
checkbox: G
|
|
128
|
+
})[d] || P;
|
|
129
|
+
return (d, a) => (c(), u("div", {
|
|
130
|
+
class: I(["quiz-card", { wrong: s, right: n }]),
|
|
131
|
+
id: `quiz_${e.item.id}`
|
|
132
|
+
}, [
|
|
133
|
+
r("div", Y, [
|
|
134
|
+
A(m(e.item.title) + " ", 1),
|
|
135
|
+
r("span", Z, "(" + m(e.item.score) + "分)", 1)
|
|
136
|
+
]),
|
|
137
|
+
(c(), z(N(i(e.item.type)), {
|
|
138
|
+
modelValue: e.answerData[e.item.id],
|
|
139
|
+
"onUpdate:modelValue": a[0] || (a[0] = (o) => e.answerData[e.item.id] = o),
|
|
140
|
+
id: e.item.id,
|
|
141
|
+
options: e.item.options
|
|
142
|
+
}, null, 8, ["modelValue", "id", "options"])),
|
|
143
|
+
e.showResult && e.item.analysis ? (c(), u("div", ee, " 答案解析:" + m(e.item.analysis), 1)) : S("", !0)
|
|
144
|
+
], 10, X));
|
|
145
|
+
}
|
|
146
|
+
}, se = /* @__PURE__ */ p(te, [["__scopeId", "data-v-f266e716"]]);
|
|
147
|
+
const ne = { class: "sheet-wrap" }, oe = { class: "num-list" }, ie = ["onClick"], le = {
|
|
148
|
+
__name: "AnswerSheet",
|
|
149
|
+
props: ["list", "wrongIds", "rightIds"],
|
|
150
|
+
emits: ["jump"],
|
|
151
|
+
setup(e, { emit: l }) {
|
|
152
|
+
const s = e, n = l, i = (a) => s.wrongIds.includes(a) ? "err" : s.rightIds.includes(a) ? "ok" : "", d = (a) => {
|
|
153
|
+
n("jump", a);
|
|
154
|
+
const o = document.getElementById(`quiz_${a}`);
|
|
155
|
+
o && o.scrollIntoView({ behavior: "smooth" });
|
|
156
|
+
};
|
|
157
|
+
return (a, o) => (c(), u("div", ne, [
|
|
158
|
+
o[0] || (o[0] = r("h4", { class: "sheet-title" }, "答题卡", -1)),
|
|
159
|
+
r("div", oe, [
|
|
160
|
+
(c(!0), u(y, null, x(e.list, (t) => (c(), u("span", {
|
|
161
|
+
key: t.id,
|
|
162
|
+
class: I(["num-item", i(t.id)]),
|
|
163
|
+
onClick: (_) => d(t.id)
|
|
164
|
+
}, m(t.id), 11, ie))), 128))
|
|
165
|
+
])
|
|
166
|
+
]));
|
|
167
|
+
}
|
|
168
|
+
}, ae = /* @__PURE__ */ p(le, [["__scopeId", "data-v-c150eab2"]]);
|
|
169
|
+
const re = { class: "result-mask" }, ce = { class: "result-box" }, ue = { class: "btn-group" }, de = {
|
|
170
|
+
__name: "QuizResult",
|
|
171
|
+
props: ["score", "fullScore", "rightNum", "wrongNum"],
|
|
172
|
+
emits: ["close", "reset"],
|
|
173
|
+
setup(e, { emit: l }) {
|
|
174
|
+
return (s, n) => (c(), u("div", re, [
|
|
175
|
+
r("div", ce, [
|
|
176
|
+
n[2] || (n[2] = r("h3", null, "答题结束", -1)),
|
|
177
|
+
r("p", null, "试卷总分:" + m(e.fullScore) + " 分", 1),
|
|
178
|
+
r("p", null, "本次得分:" + m(e.score) + " 分", 1),
|
|
179
|
+
r("p", null, "答对题数:" + m(e.rightNum) + " 道", 1),
|
|
180
|
+
r("p", null, "答错题数:" + m(e.wrongNum) + " 道", 1),
|
|
181
|
+
r("div", ue, [
|
|
182
|
+
r("button", {
|
|
183
|
+
class: "close-btn",
|
|
184
|
+
onClick: n[0] || (n[0] = (i) => s.$emit("close"))
|
|
185
|
+
}, "查看试卷"),
|
|
186
|
+
r("button", {
|
|
187
|
+
class: "reset-btn",
|
|
188
|
+
onClick: n[1] || (n[1] = (i) => s.$emit("reset"))
|
|
189
|
+
}, "重新答题")
|
|
190
|
+
])
|
|
191
|
+
])
|
|
192
|
+
]));
|
|
193
|
+
}
|
|
194
|
+
}, me = /* @__PURE__ */ p(de, [["__scopeId", "data-v-9d92d531"]]);
|
|
195
|
+
const _e = {
|
|
196
|
+
class: "quiz-exam-wrap",
|
|
197
|
+
style: { display: "flex", gap: "24px", padding: "20px", "box-sizing": "border-box" }
|
|
198
|
+
}, he = { style: { flex: "1", "min-width": "0" } }, ve = {
|
|
199
|
+
class: "exam-head",
|
|
200
|
+
style: { display: "flex", "justify-content": "space-between", "align-items": "center", "margin-bottom": "20px" }
|
|
201
|
+
}, ge = { class: "time-text" }, pe = { class: "quiz-content" }, fe = {
|
|
202
|
+
__name: "QuizExam",
|
|
203
|
+
props: {
|
|
204
|
+
// 题库数据
|
|
205
|
+
quizList: {
|
|
206
|
+
type: Array,
|
|
207
|
+
required: !0,
|
|
208
|
+
default: () => []
|
|
209
|
+
},
|
|
210
|
+
// 考试时长 单位:秒
|
|
211
|
+
limitTime: {
|
|
212
|
+
type: Number,
|
|
213
|
+
default: 3600
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
emits: ["finish"],
|
|
217
|
+
setup(e, { emit: l }) {
|
|
218
|
+
const s = e, n = l, { formatTime: i, stopTimer: d } = E(s.limitTime), {
|
|
219
|
+
userAnswer: a,
|
|
220
|
+
wrongList: o,
|
|
221
|
+
rightList: t,
|
|
222
|
+
totalScore: _,
|
|
223
|
+
fullScore: v,
|
|
224
|
+
checkAnswer: f,
|
|
225
|
+
resetAnswer: $
|
|
226
|
+
} = j(s.quizList), Q = a, b = _, w = g(!1), V = () => {
|
|
227
|
+
d(), f(), w.value = !0, n("finish", {
|
|
228
|
+
answers: a.value,
|
|
229
|
+
score: b.value,
|
|
230
|
+
wrongIds: o.value,
|
|
231
|
+
rightIds: t.value,
|
|
232
|
+
fullScore: v.value
|
|
233
|
+
});
|
|
234
|
+
}, T = () => {
|
|
235
|
+
w.value = !1, $();
|
|
236
|
+
};
|
|
237
|
+
return (we, C) => (c(), u("div", _e, [
|
|
238
|
+
r("div", he, [
|
|
239
|
+
r("div", ve, [
|
|
240
|
+
r("div", ge, "考试剩余时间:" + m(h(i)), 1),
|
|
241
|
+
r("button", {
|
|
242
|
+
class: "submit-btn",
|
|
243
|
+
onClick: V
|
|
244
|
+
}, "提交试卷")
|
|
245
|
+
]),
|
|
246
|
+
r("div", pe, [
|
|
247
|
+
(c(!0), u(y, null, x(e.quizList, (k) => (c(), z(se, {
|
|
248
|
+
key: k.id,
|
|
249
|
+
item: k,
|
|
250
|
+
"answer-data": h(Q),
|
|
251
|
+
"wrong-ids": h(o),
|
|
252
|
+
"right-ids": h(t),
|
|
253
|
+
"show-result": w.value
|
|
254
|
+
}, null, 8, ["item", "answer-data", "wrong-ids", "right-ids", "show-result"]))), 128))
|
|
255
|
+
])
|
|
256
|
+
]),
|
|
257
|
+
L(ae, {
|
|
258
|
+
list: e.quizList,
|
|
259
|
+
"wrong-ids": h(o),
|
|
260
|
+
"right-ids": h(t)
|
|
261
|
+
}, null, 8, ["list", "wrong-ids", "right-ids"]),
|
|
262
|
+
w.value ? (c(), z(me, {
|
|
263
|
+
key: 0,
|
|
264
|
+
score: h(b),
|
|
265
|
+
"full-score": h(v),
|
|
266
|
+
"right-num": h(t).length,
|
|
267
|
+
"wrong-num": h(o).length,
|
|
268
|
+
onClose: C[0] || (C[0] = (k) => w.value = !1),
|
|
269
|
+
onReset: T
|
|
270
|
+
}, null, 8, ["score", "full-score", "right-num", "wrong-num"])) : S("", !0)
|
|
271
|
+
]));
|
|
272
|
+
}
|
|
273
|
+
}, xe = /* @__PURE__ */ p(fe, [["__scopeId", "data-v-2cc1922f"]]);
|
|
274
|
+
export {
|
|
275
|
+
xe as QuizExam,
|
|
276
|
+
xe as default
|
|
277
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(m,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(m=typeof globalThis<"u"?globalThis:m||self,e(m.VueQuizExam={},m.Vue))})(this,function(m,e){"use strict";function E(t=3600){const c=e.ref(t),s=e.ref("00:00:00");let o=null;const i=n=>{const d=Math.floor(n/3600),u=Math.floor(n%3600/60),p=n%60;return`${String(d).padStart(2,"0")}:${String(u).padStart(2,"0")}:${String(p).padStart(2,"0")}`},a=()=>{o=setInterval(()=>{if(c.value<=0){clearInterval(o);return}c.value--,s.value=i(c.value)},1e3)},r=()=>{o&&clearInterval(o)},l=()=>{c.value=t,s.value=i(t)};return e.onMounted(()=>a()),e.onUnmounted(()=>r()),{formatTime:s,stopTimer:r,resetTimer:l}}function x(t){const c=e.ref({}),s=e.ref([]),o=e.ref([]),i=e.ref(0),a=()=>t.reduce((n,d)=>n+d.score,0),r=()=>{s.value=[],o.value=[],i.value=0,t.forEach(n=>{const d=c.value[n.id];if(!d){s.value.push(n.id);return}let u=!1;if(n.type==="radio"&&(u=d===n.answer),n.type==="checkbox"){const p=[...d].sort().join(","),h=[...n.answer].sort().join(",");u=p===h}u?(i.value+=n.score,o.value.push(n.id)):s.value.push(n.id)})},l=()=>{c.value={},s.value=[],o.value=[],i.value=0};return{userAnswer:c,wrongList:s,rightList:o,totalScore:i,fullScore:a(),checkAnswer:r,resetAnswer:l}}const ee="",_=(t,c)=>{const s=t.__vccOpts||t;for(const[o,i]of c)s[o]=i;return s},V={class:"radio-wrap"},$=["name","value","checked","onChange"],B=_({__name:"QuizRadio",props:["id","options","modelValue"],emits:["update:modelValue"],setup(t,{emit:c}){return(s,o)=>(e.openBlock(),e.createElementBlock("div",V,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.options,i=>(e.openBlock(),e.createElementBlock("label",{key:i,class:"opt-item"},[e.createElementVNode("input",{type:"radio",name:`q_${t.id}`,value:i,checked:t.modelValue===i,onChange:a=>s.$emit("update:modelValue",i)},null,40,$),e.createElementVNode("span",null,e.toDisplayString(i),1)]))),128))]))}},[["__scopeId","data-v-f714d90e"]]),ne="",S={class:"checkbox-wrap"},z=["value","checked","onChange"],N=_({__name:"QuizCheckbox",props:["id","options","modelValue"],emits:["update:modelValue"],setup(t,{emit:c}){const s=t,o=c,i=(a,r)=>{const l=[...s.modelValue||[]];if(a.target.checked)l.push(r);else{const n=l.indexOf(r);n>-1&&l.splice(n,1)}o("update:modelValue",l)};return(a,r)=>(e.openBlock(),e.createElementBlock("div",S,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.options,l=>(e.openBlock(),e.createElementBlock("label",{key:l,class:"opt-item"},[e.createElementVNode("input",{type:"checkbox",value:l,checked:(t.modelValue||[]).includes(l),onChange:n=>i(n,l)},null,40,z),e.createElementVNode("span",null,e.toDisplayString(l),1)]))),128))]))}},[["__scopeId","data-v-196575e1"]]),oe="",b={},C={class:"tip-text"};function I(t,c){return e.openBlock(),e.createElementBlock("div",C," 该题型暂未支持,后续版本拓展开放 ")}const Q=_(b,[["render",I],["__scopeId","data-v-036982ce"]]),le="",D=["id"],T={class:"quiz-title"},q={class:"score-tag"},R={key:0,class:"analysis"},L=_({__name:"QuizCard",props:["item","answerData","wrongIds","rightIds","showResult"],setup(t){const c=t,s=()=>c.wrongIds.includes(c.item.id),o=()=>c.rightIds.includes(c.item.id),i=a=>({radio:B,checkbox:N})[a]||Q;return(a,r)=>(e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(["quiz-card",{wrong:s,right:o}]),id:`quiz_${t.item.id}`},[e.createElementVNode("div",T,[e.createTextVNode(e.toDisplayString(t.item.title)+" ",1),e.createElementVNode("span",q,"("+e.toDisplayString(t.item.score)+"分)",1)]),(e.openBlock(),e.createBlock(e.resolveDynamicComponent(i(t.item.type)),{modelValue:t.answerData[t.item.id],"onUpdate:modelValue":r[0]||(r[0]=l=>t.answerData[t.item.id]=l),id:t.item.id,options:t.item.options},null,8,["modelValue","id","options"])),t.showResult&&t.item.analysis?(e.openBlock(),e.createElementBlock("div",R," 答案解析:"+e.toDisplayString(t.item.analysis),1)):e.createCommentVNode("",!0)],10,D))}},[["__scopeId","data-v-f266e716"]]),ce="",A={class:"sheet-wrap"},j={class:"num-list"},F=["onClick"],M=_({__name:"AnswerSheet",props:["list","wrongIds","rightIds"],emits:["jump"],setup(t,{emit:c}){const s=t,o=c,i=r=>s.wrongIds.includes(r)?"err":s.rightIds.includes(r)?"ok":"",a=r=>{o("jump",r);const l=document.getElementById(`quiz_${r}`);l&&l.scrollIntoView({behavior:"smooth"})};return(r,l)=>(e.openBlock(),e.createElementBlock("div",A,[l[0]||(l[0]=e.createElementVNode("h4",{class:"sheet-title"},"答题卡",-1)),e.createElementVNode("div",j,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.list,n=>(e.openBlock(),e.createElementBlock("span",{key:n.id,class:e.normalizeClass(["num-item",i(n.id)]),onClick:d=>a(n.id)},e.toDisplayString(n.id),11,F))),128))])]))}},[["__scopeId","data-v-c150eab2"]]),ae="",O={class:"result-mask"},U={class:"result-box"},P={class:"btn-group"},W=_({__name:"QuizResult",props:["score","fullScore","rightNum","wrongNum"],emits:["close","reset"],setup(t,{emit:c}){return(s,o)=>(e.openBlock(),e.createElementBlock("div",O,[e.createElementVNode("div",U,[o[2]||(o[2]=e.createElementVNode("h3",null,"答题结束",-1)),e.createElementVNode("p",null,"试卷总分:"+e.toDisplayString(t.fullScore)+" 分",1),e.createElementVNode("p",null,"本次得分:"+e.toDisplayString(t.score)+" 分",1),e.createElementVNode("p",null,"答对题数:"+e.toDisplayString(t.rightNum)+" 道",1),e.createElementVNode("p",null,"答错题数:"+e.toDisplayString(t.wrongNum)+" 道",1),e.createElementVNode("div",P,[e.createElementVNode("button",{class:"close-btn",onClick:o[0]||(o[0]=i=>s.$emit("close"))},"查看试卷"),e.createElementVNode("button",{class:"reset-btn",onClick:o[1]||(o[1]=i=>s.$emit("reset"))},"重新答题")])])]))}},[["__scopeId","data-v-9d92d531"]]),me="",G={class:"quiz-exam-wrap",style:{display:"flex",gap:"24px",padding:"20px","box-sizing":"border-box"}},H={style:{flex:"1","min-width":"0"}},J={class:"exam-head",style:{display:"flex","justify-content":"space-between","align-items":"center","margin-bottom":"20px"}},K={class:"time-text"},X={class:"quiz-content"},k=_({__name:"QuizExam",props:{quizList:{type:Array,required:!0,default:()=>[]},limitTime:{type:Number,default:3600}},emits:["finish"],setup(t,{emit:c}){const s=t,o=c,{formatTime:i,stopTimer:a}=E(s.limitTime),{userAnswer:r,wrongList:l,rightList:n,totalScore:d,fullScore:u,checkAnswer:p,resetAnswer:h}=x(s.quizList),Y=r,y=d,f=e.ref(!1),Z=()=>{a(),p(),f.value=!0,o("finish",{answers:r.value,score:y.value,wrongIds:l.value,rightIds:n.value,fullScore:u.value})},v=()=>{f.value=!1,h()};return(_e,w)=>(e.openBlock(),e.createElementBlock("div",G,[e.createElementVNode("div",H,[e.createElementVNode("div",J,[e.createElementVNode("div",K,"考试剩余时间:"+e.toDisplayString(e.unref(i)),1),e.createElementVNode("button",{class:"submit-btn",onClick:Z},"提交试卷")]),e.createElementVNode("div",X,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.quizList,g=>(e.openBlock(),e.createBlock(L,{key:g.id,item:g,"answer-data":e.unref(Y),"wrong-ids":e.unref(l),"right-ids":e.unref(n),"show-result":f.value},null,8,["item","answer-data","wrong-ids","right-ids","show-result"]))),128))])]),e.createVNode(M,{list:t.quizList,"wrong-ids":e.unref(l),"right-ids":e.unref(n)},null,8,["list","wrong-ids","right-ids"]),f.value?(e.openBlock(),e.createBlock(W,{key:0,score:e.unref(y),"full-score":e.unref(u),"right-num":e.unref(n).length,"wrong-num":e.unref(l).length,onClose:w[0]||(w[0]=g=>f.value=!1),onReset:v},null,8,["score","full-score","right-num","wrong-num"])):e.createCommentVNode("",!0)]))}},[["__scopeId","data-v-2cc1922f"]]);m.QuizExam=k,m.default=k,Object.defineProperties(m,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vue3-quiz-lib",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Vue3通用在线做题组件库,支持单选多选、计时计分、答题卡、错题解析",
|
|
5
|
+
"main": "./dist/vue-quiz-exam.umd.cjs",
|
|
6
|
+
"module": "./dist/vue-quiz-exam.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/vue-quiz-exam.js",
|
|
10
|
+
"require": "./dist/vue-quiz-exam.umd.cjs"
|
|
11
|
+
},
|
|
12
|
+
"./dist/style.css": "./dist/style.css"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "vite build"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"vue": "^3.3.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@vitejs/plugin-vue": "^4.0.0",
|
|
25
|
+
"vite": "^4.0.0",
|
|
26
|
+
"vue": "^3.4.0"
|
|
27
|
+
}
|
|
28
|
+
}
|