ai-question-pro 0.0.1

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.
@@ -0,0 +1,536 @@
1
+ <template>
2
+ <div class="ai_contain">
3
+ <slot>
4
+ <span class="ai_button" @click="showAddQuestion">AI出题</span>
5
+ </slot>
6
+ <el-drawer :visible.sync="addShow" :direction="direction" :wrapperClosable="false" destroy-on-close>
7
+ <template slot="title">
8
+ <div class="add_question_title">
9
+ <span>AI出题</span>
10
+ <img src="../static/robot.png">
11
+ </div>
12
+ </template>
13
+ <div class="add_question_body">
14
+ <el-form ref="form" :model="form" :rules="rules" label-width="100px" label-position="left">
15
+ <el-form-item label="题型" prop="questionType">
16
+ <!-- <el-checkbox-group v-model="form.questionTypes">-->
17
+ <!-- <el-checkbox v-for="item in quesTypeList" :key="item.id" :label="item.id">-->
18
+ <!-- {{ item.name }}-->
19
+ <!-- </el-checkbox>-->
20
+ <!-- </el-checkbox-group>-->
21
+ <el-radio-group v-model="form.questionType" size="medium">
22
+ <el-radio-button v-for="item in quesTypeList" :key="item.id" :label="item.id">{{ item.name }}</el-radio-button>
23
+ </el-radio-group>
24
+ </el-form-item>
25
+ <el-form-item label="题目数量" prop="count">
26
+ <el-input class="number_input" v-model="form.count" min="1" max="10" type="number"
27
+ @input="handleInput" style="width: 20%;"></el-input>
28
+ <div class="remind">(为避免您等待时间过长,一次性最多生成10道题)</div>
29
+ </el-form-item>
30
+ <el-form-item label="关联知识点" prop="knowledgeIds">
31
+ <!-- <el-cascader v-model="form.knowledgeId" :options="knowledgeList" @change="closeDrowdown"-->
32
+ <!-- :show-all-levels="false" ref="cascader" :props="{ checkStrictly: true, ...propFormat }"-->
33
+ <!-- clearable></el-cascader>-->
34
+ <cy-tree-select v-model="form.knowledgeIds" filterable :data="knowledgeList"></cy-tree-select>
35
+ </el-form-item>
36
+ <el-form-item label="难度" prop="difficulty">
37
+ <!-- <el-checkbox-group v-model="form.difficultys">-->
38
+ <!-- <el-checkbox :label="item.id" v-for="item in difficultyList" :key="item.id">{{ item.name-->
39
+ <!-- }}</el-checkbox>-->
40
+ <!-- </el-checkbox-group>-->
41
+ <el-radio-group v-model="form.difficulty" size="medium">
42
+ <el-radio-button v-for="item in difficultyList" :key="item.id" :label="item.id">{{ item.name }}</el-radio-button>
43
+ </el-radio-group>
44
+ </el-form-item>
45
+ <el-form-item label="自定义提示语">
46
+ <el-input v-model="form.prompt" autosize placeholder="请输入" type="textarea"></el-input>
47
+ </el-form-item>
48
+ </el-form>
49
+ </div>
50
+ <div class="add_question_footer">
51
+ <el-button type="primary" style="background-color: #3E7BFA;border: none;"
52
+ @click="generate">生成题目</el-button>
53
+ <el-button @click="addShow = false">取 消</el-button>
54
+ </div>
55
+ </el-drawer>
56
+ <el-dialog :visible.sync="showQues" :close-on-click-modal="false">
57
+ <template slot="title">
58
+ <div class="question_title">
59
+ <img src="../static/robot.png">
60
+ <span>{{ title }}</span>
61
+ </div>
62
+ </template>
63
+ <div class="question_body" ref="generateDiv">
64
+ <questionItem v-if="aiResponse.questions && aiResponse.questions.length > 0" @agree="agree" @join="join"
65
+ v-for="item, idx in aiResponse.questions" :key="idx" :detail="item" :index="idx">
66
+ </questionItem>
67
+ </div>
68
+ <div class="question_footer" slot="footer">
69
+ <span class="question_remind">题目内容由人工智能大模型生成,请您审慎核查,确认内容准确,无不妥后再使用</span>
70
+ <el-button type="primary" @click="rebuild"
71
+ style="background-color: #3E7BFA;border: none;">重新生成</el-button>
72
+ </div>
73
+ </el-dialog>
74
+ </div>
75
+ </template>
76
+ <script>
77
+ import questionItem from './questionItem.vue'
78
+ import CyTreeSelect from './CyTreeSelect.vue'
79
+ // import {
80
+ // Button, Drawer, Form, FormItem, Checkbox, CheckboxGroup, Input, Cascader, Dialog, Loading, this.$message
81
+ // } from "element-ui"
82
+ import { getAiQuestion, agreeQuestion } from '../api/index'
83
+ import Cookies from 'js-cookie';
84
+ export default {
85
+ name: 'aiQuestion',
86
+ components: {
87
+ // 'el-button': Button,
88
+ // 'el-drawer': Drawer,
89
+ // 'el-form': Form,
90
+ // 'el-form-item': FormItem,
91
+ // 'el-checkbox': Checkbox,
92
+ // 'el-checkbox-group': CheckboxGroup,
93
+ // 'el-input': Input,
94
+ // 'el-cascader': Cascader,
95
+ // 'el-dialog': Dialog,
96
+ questionItem,
97
+ CyTreeSelect
98
+ },
99
+ props: {
100
+ top: {
101
+ type: [String, Number],
102
+ default: 0
103
+ },
104
+ knowledgeList: {
105
+ type: Array,
106
+ default: () => [
107
+ {
108
+ id: '1',
109
+ label: '大学英语',
110
+ children: [
111
+ {
112
+ id: '1-1',
113
+ label: '用英语打招呼',
114
+ }
115
+ ]
116
+ },
117
+ {
118
+ id: '2',
119
+ label: '大学物理',
120
+ children: [
121
+ {
122
+ id: '2-1',
123
+ label: '结构力学',
124
+ children: [
125
+ {
126
+ id: '2-1-1',
127
+ label: '力的构成',
128
+ }
129
+ ]
130
+ },
131
+ {
132
+ id: '2-2',
133
+ label: '流体力学',
134
+ }
135
+ ]
136
+ },
137
+ {
138
+ id: '3',
139
+ label: '高数'
140
+ }
141
+ ]
142
+ },
143
+ propFormat: {
144
+ type: Object,
145
+ default: () => ({
146
+ id: 'id',
147
+ label: 'label',
148
+ children: 'children'
149
+ })
150
+ },
151
+ },
152
+ data() {
153
+ return {
154
+ showQues: false,
155
+ addShow: false,
156
+ generateCount: 0,
157
+ direction: 'rtl',
158
+ form: {
159
+ questionTypes: [],
160
+ questionType: null,
161
+ count: 1,
162
+ knowledgeId: [],
163
+ knowledgeIds: '',
164
+ difficultys: [],
165
+ difficulty: null,
166
+ knowledge: []
167
+ },
168
+ quesTypeList: [
169
+ { name: '单选题', id: 'single' },
170
+ { name: '多选题', id: 'multiple' },
171
+ { name: '判断题', id: 'judge' },
172
+ { name: '填空题', id: 'gapfilling' },
173
+ { name: '简答题', id: 'shortanswer' },
174
+ ],
175
+ difficultyList: [
176
+ { name: '非常简单', id: 0 },
177
+ { name: '简单', id: 1 },
178
+ { name: '一般', id: 2 },
179
+ { name: '困难', id: 3 },
180
+ { name: '非常困难', id: 4 },
181
+ ],
182
+ rules: {
183
+ questionTypes: [{ required: true, message: '此项必填', trigger: 'change' }],
184
+ questionType: [{ required: true, message: '此项必填', trigger: 'change' }],
185
+ count: [{ required: true, message: '此项必填', trigger: 'blur' }],
186
+ knowledgeIds: [{ required: true, message: '此项必填', trigger: 'change' }],
187
+ difficultys: [{ required: true, message: '此项必填', trigger: 'change' }],
188
+ difficulty: [{ required: true, message: '此项必填', trigger: 'change' }],
189
+ },
190
+ loading: null,
191
+ aiResponse: {},
192
+ title: '单选题'
193
+ }
194
+ },
195
+ watch: {
196
+ showQues(e) {
197
+ if (!e) {
198
+ this.aiResponse = {}
199
+ }
200
+ }
201
+ },
202
+ mounted() {
203
+ let doc = document.getElementsByClassName('rtl')[0]
204
+ if (this.top) {
205
+ doc.style.top = this.top + 'px'
206
+ doc.style.height = `calc( 100% - ${this.top}px)`
207
+ }
208
+ },
209
+ methods: {
210
+ handleInput(value) {
211
+ value = parseFloat(value);
212
+ if (value < 1) {
213
+ this.form.count = 1;
214
+ } else if (value > 10) {
215
+ this.form.count = 10;
216
+ } else {
217
+ this.form.count = value;
218
+ }
219
+ },
220
+ //选中节点后关闭下拉框
221
+ closeDrowdown(e) {
222
+ this.$nextTick(() => {
223
+ this.$refs.cascader.dropDownVisible = false
224
+ });
225
+ },
226
+ //展示右边弹框
227
+ showAddQuestion() {
228
+ if (!Cookies.get("AiToken")) {
229
+ return this.$message.warning('未获取到登录信息,请重新登录')
230
+ }
231
+ this.form = {
232
+ questionTypes: [],
233
+ questionType: null,
234
+ count: 1,
235
+ knowledgeId: [],
236
+ knowledgeIds: '',
237
+ difficultys: [],
238
+ difficulty: null,
239
+ knowledge: []
240
+ }
241
+ this.addShow = !this.addShow
242
+ },
243
+ //生成题目
244
+ generate() {
245
+ this.$refs.form.validate(valid => {
246
+ if (valid) {
247
+ this.form.knowledgeId = this.form.knowledgeIds.split(',');
248
+ this.form.knowledgeId.forEach(item => {
249
+ this.getKnowledgeName(item, this.knowledgeList)
250
+ })
251
+ this.form.questionTypes.push(this.form.questionType);
252
+ this.form.difficultys.push(this.form.difficulty);
253
+ if (this.form.questionTypes.length > 1) {
254
+ this.title = '多类题'
255
+ } else {
256
+ this.title = this.quesTypeList.find(item => item.id == this.form.questionTypes[0]).name
257
+ }
258
+ this.showQues = true
259
+ this.addShow = !this.addShow
260
+ this.sendPost()
261
+ }
262
+ })
263
+ },
264
+ //重新生成
265
+ rebuild() {
266
+ this.sendPost()
267
+ },
268
+ showGenerateResult(){
269
+ this.generateCount++;
270
+ if(this.generateCount == this.form.count){
271
+ this.$message.success( '题目(' + this.form.count + '道)全部生成完毕!');
272
+ } else {
273
+ this.$message.success('生成' + this.generateCount + '道题目成功');
274
+ }
275
+ this.$nextTick(() => {
276
+ const generateDiv = this.$refs.generateDiv;
277
+ generateDiv.scrollTop = generateDiv.scrollHeight;
278
+ });
279
+ },
280
+ reSend() {
281
+ this.loading && this.loading.close()
282
+ this.loading = this.$loading({
283
+ target: '.el-dialog',
284
+ text: 'ai生成中...'
285
+ });
286
+ let obj = {
287
+ modelType: 'aliyun',
288
+ questionAddCmd: {
289
+ questionTypes: this.form.questionTypes,
290
+ // count: this.form.count,
291
+ count: 1,
292
+ knowledge: this.form.knowledge.join(' '),
293
+ knowledgeId: this.form.knowledgeId[this.form.knowledgeId.length - 1],
294
+ difficultys: this.form.difficultys,
295
+ prompt: this.form.prompt
296
+ },
297
+ sessionId: this.aiResponse.sessionId ? this.aiResponse.sessionId : ''
298
+ }
299
+ getAiQuestion(obj).then(res => {
300
+ if (res.success) {
301
+ this.loading && this.loading.close()
302
+ if (res.data && res.data.questions && res.data.questions.length > 0) {
303
+ if (this.aiResponse.questions && this.aiResponse.questions.length > 0) {
304
+ this.aiResponse.questions.push(res.data.questions[0]);
305
+ } else {
306
+ this.aiResponse = res.data;
307
+ }
308
+ this.$set(res.data.questions[0], 'evaluate', 0)
309
+ this.showGenerateResult();
310
+ } else {
311
+ this.$message.warning('生成' + this.generateCount + '道题目获取失败,重新生成中...')
312
+ return this.reSend()
313
+ }
314
+ } else {
315
+ this.loading && this.loading.close()
316
+ this.$message.warning('生成' + this.generateCount + '道题目获取失败')
317
+ }
318
+ }).catch(error => {
319
+ console.log("error:" + error);
320
+ this.loading && this.loading.close()
321
+ this.$message.warning('生成' + this.generateCount + '道题目获取失败')
322
+ })
323
+ },
324
+ //发送请求
325
+ sendPost() {
326
+ this.generateCount = 0;
327
+ this.aiResponse = {}
328
+ this.loading && this.loading.close()
329
+ this.loading = this.$loading({
330
+ target: '.el-dialog',
331
+ text: 'ai生成中...'
332
+ });
333
+ for(let i = 0; i<this.form.count; i++){
334
+ let obj = {
335
+ modelType: 'aliyun',
336
+ questionAddCmd: {
337
+ questionTypes: this.form.questionTypes,
338
+ // count: this.form.count,
339
+ count: 1,
340
+ knowledge: this.form.knowledge.join(' '),
341
+ knowledgeId: this.form.knowledgeId[this.form.knowledgeId.length - 1],
342
+ difficultys: this.form.difficultys,
343
+ prompt: this.form.prompt
344
+ },
345
+ sessionId: this.aiResponse.sessionId ? this.aiResponse.sessionId : ''
346
+ }
347
+ getAiQuestion(obj).then(res => {
348
+ // console.log("questions obj is :" + JSON.stringify(res.data.questions));
349
+ // console.log("res is :" + JSON.stringify(res));
350
+ if (res.success) {
351
+ this.loading && this.loading.close()
352
+ // this.aiResponse = {}
353
+ // this.aiResponse = res.data || {}
354
+ if (res.data && res.data.questions && res.data.questions.length > 0) {
355
+ // this.aiResponse.questions.forEach(item => {
356
+ // this.$set(item, 'evaluate', 0)
357
+ // })
358
+ if (this.aiResponse.questions && this.aiResponse.questions.length > 0) {
359
+ this.aiResponse.questions.push(res.data.questions[0]);
360
+ } else {
361
+ this.aiResponse = res.data;
362
+ }
363
+ this.$set(res.data.questions[0], 'evaluate', 0)
364
+ this.showGenerateResult();
365
+ } else {
366
+ this.$message.warning('生成' + this.generateCount + '道题目获取失败')
367
+ return this.reSend()
368
+ }
369
+ } else {
370
+ this.loading && this.loading.close()
371
+ this.$message.warning('生成' + this.generateCount + '道题目获取失败')
372
+ }
373
+ }).catch(error => {
374
+ console.log("error:" + error);
375
+ this.loading && this.loading.close()
376
+ this.$message.warning('生成' + this.generateCount + '道题目获取失败')
377
+ })
378
+ }
379
+
380
+ },
381
+ //获取知识点名称
382
+ getKnowledgeName(e, array) {
383
+ array.forEach(item => {
384
+ if (e == item.id) {
385
+ return this.form.knowledge.push(item.label)
386
+ } else if (item.children && item.children.length > 0) {
387
+ this.getKnowledgeName(e, item.children)
388
+ }
389
+ });
390
+ },
391
+ //点赞
392
+ agree(e, j) {
393
+ this.aiResponse.questions[e].evaluate = j
394
+ let obj = {
395
+ modelType: 'aliyun',
396
+ ...this.aiResponse
397
+ }
398
+ agreeQuestion(obj).then(res => {
399
+
400
+ }).catch(error => {
401
+ console.log(error);
402
+ })
403
+ },
404
+ //加入题库
405
+ join(e) {
406
+ this.$emit('joinQuestionBank', { ...e, knowledgePointsId: this.form.knowledgeId[this.form.knowledgeId.length - 1] })
407
+ }
408
+ }
409
+ }
410
+ </script>
411
+ <style lang="scss" scoped>
412
+ ::v-deep.ai_contain {
413
+ display: inline-block;
414
+
415
+ .el-drawer__header {
416
+ padding-top: 0;
417
+ height: 80px;
418
+ background-image: url('../static/addQuesTitBg.png');
419
+ background-size: 100% 100%;
420
+ }
421
+
422
+ .el-drawer__body {
423
+ padding: 0 20px;
424
+ }
425
+
426
+ .el-drawer__body {
427
+ display: flex;
428
+ flex-direction: column;
429
+ justify-content: space-between;
430
+ }
431
+
432
+ .el-form-item__label {
433
+ font-weight: 700;
434
+ }
435
+
436
+ .el-input__inner {
437
+ padding-right: 0;
438
+ }
439
+
440
+ .el-cascader {
441
+ width: 100%;
442
+ }
443
+
444
+ .ai_button {
445
+ cursor: pointer;
446
+ user-select: none;
447
+ padding: 9px 6px;
448
+ position: relative;
449
+ color: #fff;
450
+ background-color: #456BEA;
451
+ border-radius: 4px;
452
+ border: 1px solid #456BEA;
453
+ }
454
+
455
+ .add_question_title {
456
+ display: flex;
457
+ align-items: center;
458
+ font-size: 23px;
459
+ color: #333333;
460
+ }
461
+
462
+ .add_question_body {
463
+ .remind {
464
+ font-size: 14px;
465
+ color: #9BA1AE;
466
+ }
467
+ }
468
+
469
+ .add_question_footer {
470
+ padding: 20px 0;
471
+ border-top: 1px solid #E6E6E6;
472
+ display: flex;
473
+ justify-content: center;
474
+ align-items: center;
475
+ }
476
+
477
+ .el-loading-mask {
478
+ border-radius: 8px;
479
+ }
480
+
481
+ .el-dialog {
482
+ background: linear-gradient(327deg, #DBECFE 0%, #F9FCFF 100%);
483
+ border-radius: 8px;
484
+
485
+ .question_title {
486
+ display: flex;
487
+ align-items: center;
488
+ font-weight: 700;
489
+ font-size: 23px;
490
+ color: #333333;
491
+
492
+ img {
493
+ margin-right: 10px;
494
+ width: 35px;
495
+ height: 40px;
496
+ }
497
+ }
498
+
499
+ .question_body {
500
+ padding: 10px;
501
+ min-height: 500px;
502
+ max-height: 500px;
503
+ overflow: auto;
504
+
505
+ &::-webkit-scrollbar {
506
+ width: 4px;
507
+ }
508
+
509
+ &::-webkit-scrollbar-button {
510
+ display: none;
511
+ }
512
+
513
+ &::-webkit-scrollbar-track-piece {
514
+ background-color: transparent;
515
+ }
516
+
517
+ &::-webkit-scrollbar-thumb {
518
+ border-radius: 3px;
519
+ background: rgba(0, 0, 0, .5);
520
+ }
521
+ }
522
+
523
+ .question_footer {
524
+ display: flex;
525
+ justify-content: space-between;
526
+
527
+ .question_remind {
528
+ align-self: flex-end;
529
+ font-size: 14px;
530
+ color: #9BA1AE;
531
+ }
532
+ }
533
+
534
+ }
535
+ }
536
+ </style>
@@ -0,0 +1,146 @@
1
+ <template>
2
+ <div class="ai_question_contain">
3
+ <div class="question_contain_title">
4
+ <span class="question_contain_title_left">
5
+ <span>{{ index + 1 }}.</span>
6
+ <span class="difficult">{{ difficultyList.find(item => item.id == detail.difficulty).name }}</span>
7
+ <span>{{ detail.title }}</span>
8
+ </span>
9
+ <span class="question_contain_title_reght">
10
+ <img src="../static/zan_plain.png" v-if="detail.evaluate == 0 || detail.evaluate == 2"
11
+ @click="agree(1)">
12
+ <img src="../static/zan_bg.png" v-if="detail.evaluate == 1">
13
+ <img src="../static/unzan_plain.png" v-if="detail.evaluate == 0 || detail.evaluate == 1"
14
+ @click="agree(2)">
15
+ <img src="../static/unzan_bg.png" v-if="detail.evaluate == 2">
16
+ </span>
17
+ </div>
18
+ <div class="question_contain_question" v-if="detail.type == 'single' || detail.type == 'multiple' ">
19
+ <div v-for="item, idx in detail.options" :key="idx">
20
+ <!-- <span>{{ options.find(obj => obj.id == idx).name }}、</span>-->
21
+ <span>{{ item }}</span>
22
+ </div>
23
+ </div>
24
+ <div class="question_contain_answer">参考答案:
25
+ <span v-html="detail.answer"></span>
26
+ </div>
27
+ <div class="question_contain_parse">
28
+ <span class="question_contain_parse_analysis">题目解析: {{ detail.analysis }}</span>
29
+ <span class="join" @click="join">加入题库</span>
30
+ </div>
31
+ </div>
32
+ </template>
33
+ <script>
34
+ export default {
35
+ name: 'questionItem',
36
+ props: {
37
+ detail: {
38
+ type: Object,
39
+ default: () => { }
40
+ },
41
+ index: {
42
+ type: Number
43
+ }
44
+ },
45
+ data() {
46
+ return {
47
+ difficultyList: [
48
+ { name: '非常简单', id: 0 },
49
+ { name: '简单', id: 1 },
50
+ { name: '一般', id: 2 },
51
+ { name: '困难', id: 3 },
52
+ { name: '非常困难', id: 4 },
53
+ ],
54
+ options: [
55
+ { name: 'A', id: 0 },
56
+ { name: 'B', id: 1 },
57
+ { name: 'C', id: 2 },
58
+ { name: 'D', id: 3 },
59
+ { name: 'E', id: 4 },
60
+ { name: 'F', id: 5 },
61
+ { name: 'G', id: 6 },
62
+ { name: 'H', id: 7 },
63
+ { name: 'I', id: 8 },
64
+ ]
65
+ }
66
+ },
67
+ methods: {
68
+ agree(e) {
69
+ this.$emit('agree', this.index, e)
70
+ },
71
+ join(e) {
72
+ this.$emit('join', this.detail)
73
+ }
74
+ }
75
+ }
76
+ </script>
77
+ <style lang="scss" scoped>
78
+ .ai_question_contain {
79
+ margin-bottom: 10px;
80
+ padding: 10px;
81
+ border-radius: 8px;
82
+ background: rgba(255, 255, 255, .6);
83
+
84
+ .question_contain_title {
85
+ margin-bottom: 16px;
86
+ display: flex;
87
+ justify-content: space-between;
88
+
89
+ .question_contain_title_left {
90
+ color: #333333;
91
+ font-weight: 600;
92
+ font-size: 14px;
93
+ width: 80%;
94
+
95
+ .difficult {
96
+ margin: 0 6px;
97
+ font-weight: 400;
98
+ padding: 2px 4px;
99
+ color: #fff;
100
+ background: #3E7BFA;
101
+ font-size: 10px;
102
+ border-radius: 2px;
103
+ }
104
+ }
105
+
106
+ .question_contain_title_reght {
107
+ display: flex;
108
+ align-items: center;
109
+
110
+ img {
111
+ margin: 0 5px;
112
+ cursor: pointer;
113
+ }
114
+ }
115
+ }
116
+
117
+ .question_contain_question {
118
+ margin-bottom: 16px;
119
+
120
+ div {
121
+ margin: 5px 0;
122
+ }
123
+ }
124
+
125
+ .question_contain_answer {
126
+ margin-bottom: 16px;
127
+ }
128
+
129
+ .question_contain_parse {
130
+ margin-bottom: 16px;
131
+ display: flex;
132
+ justify-content: space-between;
133
+
134
+ .question_contain_parse_analysis {
135
+ width: 80%;
136
+ }
137
+
138
+ .join {
139
+ align-self: self-end;
140
+ user-select: none;
141
+ cursor: pointer;
142
+ color: #3E7BFA;
143
+ }
144
+ }
145
+ }
146
+ </style>
Binary file