| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- <template>
- <div class="AdminAnswerBookShow"
- :style="localOptions.style">
- <q-card v-if="!answerBook.loading && answerBook.id">
- <q-card-section class="flex justify-between">
- <div>{{ answerBook.test_info.title }}</div>
- <q-btn v-if="!answerBook.loading && answerBook.ticket"
- outline
- color="primary"
- class="btn-need-installment"
- @click="scrollToObjectionBox">
- مشاهده اعتراض
- </q-btn>
- </q-card-section>
- <q-separator />
- <q-banner>
- <div class="row">
- <div class="col-md-6 col-12">
- وضعیت آزمون:
- {{ answerBook.status_info.label }}
- </div>
- <div v-if="answerBook.grader_info"
- class="col-md-6 col-12">
- مصحح:
- {{ answerBook.grader_info.firstname }}
- {{ answerBook.grader_info.lastname }}
- (کدملی: {{ answerBook.grader_info.national_code }})
- </div>
- </div>
- </q-banner>
- <q-separator />
- <q-banner>
- <div class="row">
- <div class="col-md-4 col-12">
- زمان شروع:
- {{ toShamsi(answerBook.attending_start_time) }}
- </div>
- <div class="col-md-4 col-12">
- {{ answerBook.owner_info.firstname }}
- {{ answerBook.owner_info.lastname }}
- (کدملی: {{ answerBook.owner_info.national_code }})
- </div>
- <div class="col-md-4 col-12">
- نمره نهایی
- <template v-if="answerBook.status === 'GRADING'">
- {{ totalScore }}
- </template>
- <template v-else>
- {{ answerBook.total_score }}
- </template>
- </div>
- </div>
- </q-banner>
- <q-list separator>
- <q-item v-for="(answerSheet, answerSheetIndex) in answerBook.answer_sheet_info.list"
- :key="answerSheetIndex"
- clickable>
- <div class="row full-width q-col-gutter-md">
- <div class="col-md-10 col-12">
- <div v-html="'<span>' + (answerSheetIndex + 1) + ' - </span>' + answerSheet.test_question_info.question_info.text" />
- <q-card class="q-mt-sm">
- <q-card-section>
- <div>
- پاسخ صحیح:
- </div>
- <div v-html="answerSheet.test_question_info.question_info.correct_answer" />
- </q-card-section>
- </q-card>
- <q-card class="q-mt-sm">
- <q-card-section>
- <div>
- متن پاسخ کاربر:
- </div>
- <div>
- {{ answerSheet.answer_text }}
- </div>
- <div v-if="answerSheet.answer_attachment">
- <q-separator class="q-my-md" />
- <q-btn outline
- color="primary"
- icon="attachment"
- label="فایل پیوست کاربر"
- :href="answerSheet.answer_attachment"
- target="_blank" />
- </div>
- </q-card-section>
- </q-card>
- </div>
- <div v-if="$route.query.classroom_type !== 'EVENT'"
- class="col-md-2 col-12">
- <q-badge v-if="answerSheet.score !== null">
- {{ answerSheet.score }}
- از
- {{ answerSheet.test_question_info.mark }}
- نمره
- </q-badge>
- <q-badge v-else>
- {{ answerSheet.test_question_info.question_info.mark }}
- نمره
- </q-badge>
- <div class="q-mt-md input-grate-question">
- <q-input v-model="scores[answerSheetIndex].score"
- :loading="scores[answerSheetIndex].loading"
- dense>
- <template v-slot:append>
- <q-btn color="primary"
- label="ثبت نمره"
- outline
- :loading="scores[answerSheetIndex].loading"
- @click="submitScore(answerSheetIndex)" />
- </template>
- </q-input>
- </div>
- </div>
- </div>
- </q-item>
- </q-list>
- <q-separator class="q-my-lg" />
- <div class="q-pa-lg">
- <entity-show v-if="mounted"
- ref="entityShow"
- v-model:value="overallAnswerInput"
- :loaded-data="answerBook"
- :show-close-button="false"
- :show-edit-button="false"
- :show-expand-button="false"
- :show-save-button="false"
- :show-index-button="false"
- :show-reload-button="false"
- :default-layout="false" />
- </div>
- <template v-if="answerBook.objection_request">
- <div>
- متن اعتراض:
- </div>
- <div v-html="answerBook.objection_request" />
- </template>
- <template v-if="answerBook.objection_request && !answerBook.objection_result">
- <q-separator class="q-my-xl" />
- <q-card-section>
- <entity-edit v-if="mounted"
- ref="objectionEntityEdit"
- v-model:value="objectionInputs"
- title="پاسخ به اعتراض"
- :api="objectionApi"
- :loaded-data="{}"
- :show-close-button="false"
- :show-edit-button="false"
- :show-expand-button="false"
- :show-save-button="false"
- :show-reload-button="false">
- <template #after-form-builder>
- <div class="flex justify-end q-mt-md">
- <q-btn color="primary"
- label="ثبت اعتراض"
- @click="sendObjection" />
- </div>
- </template>
- </entity-edit>
- </q-card-section>
- </template>
- <template v-else-if="answerBook.objection_result">
- <div>
- نتیجه اعتراض:
- </div>
- <div v-html="answerBook.objection_result" />
- </template>
- <q-banner>
- <q-input v-model="answerBook.grader_description"
- type="textarea"
- label="توضیحات مصحح"
- :loading="graderDescriptionLoading" />
- <div class="row justify-end q-py-md">
- <q-btn color="primary"
- label="ثبت توضیحات مصحح"
- outline
- :loading="graderDescriptionLoading"
- @click="submitGraderDescription" />
- </div>
- </q-banner>
- <q-card-actions v-if="answerBook.status === 'GRADING'">
- <q-btn color="primary"
- class="q-mr-lg"
- @click="confirmScores">
- تایید نهایی نمرات
- </q-btn>
- <q-btn color="red"
- @click="confirmUngradable">
- نیاز به رفع مشکل
- </q-btn>
- </q-card-actions>
- </q-card>
- <div v-else>
- کمی صبر کنید...
- </div>
- </div>
- <q-card v-if="mounted && !answerBook.loading && answerBook.id && answerBook.ticket"
- ref="objectionBox"
- class="q-mt-md">
- <q-card-section>
- <div class="row justify-center">
- <div class="full-width">
- <q-skeleton v-if="entityLoading"
- type="rect"
- width="100%"
- height="200px" />
- <template v-else>
- {{ answerBook.ticket_info.body }}
- <q-chat-message v-for="message in answerBook.ticket_info.replies_info.list"
- :key="message.id"
- :avatar="message.creator_info?.picture ? message.creator_info.picture : 'assets/images/web/sample-avatar.svg'"
- :name="message.creator_info?.firstname + ' ' + message.creator_info?.lastname"
- text-html
- :text="[message.body]"
- :sent="!isUserMessage(authenticatedUser, message)">
- <template v-slot:stamp>
- <div>
- {{ miladiToShamsi(message.creation_time) }}
- </div>
- <q-btn icon="clear"
- round
- color="red"
- flat
- size="xs"
- @click="removeMessage(message.id)" />
- <q-icon v-if="isUserMessage(authenticatedUser, message)"
- :name="message.read ? 'done_all' : 'done'" />
- </template>
- </q-chat-message>
- <div>
- <q-input v-model="replyText"
- bottom-slots
- autogrow
- :loading="entityLoading">
- <template v-slot:after>
- <q-btn round
- dense
- flat
- icon="send"
- :loading="entityLoading"
- @click="sendReply" />
- </template>
- </q-input>
- </div>
- </template>
- </div>
- </div>
- </q-card-section>
- </q-card>
- </template>
- <script>
- import Assist from 'src/assets/js/Assist.js'
- import { APIGateway } from 'src/api/APIGateway.js'
- import { EntityShow, EntityEdit } from 'quasar-crud'
- import { AnswerBook } from 'src/models/AnswerBook.js'
- import { mixinWidget, mixinAuth } from 'src/mixin/Mixins.js'
- import { User } from 'src/models/User.js'
- export default {
- name: 'AdminAnswerBookShow',
- components: { EntityShow, EntityEdit },
- mixins: [mixinWidget, mixinAuth],
- data () {
- return {
- mounted: false,
- replyText: null,
- entityLoading: true,
- authenticatedUser: new User(),
- graderDescriptionLoading: false,
- overallAnswerInput: [
- // { type: 'input', name: 'overall_answer_text', responseKey: 'overall_answer_text', label: 'متن پاسخ جامع', placeholder: ' ', inputType: 'textarea', col: 'col-12' },
- { type: 'file', name: 'overall_answer_attachment', responseKey: 'overall_answer_attachment', label: 'فایل پیوست جامع', placeholder: ' ', col: 'col-12' }
- ],
- questionInput: [
- { type: 'input', name: 'answer_text', responseKey: 'answer_text', label: 'متن پاسخ', placeholder: ' ', inputType: 'textarea', col: 'col-12' },
- { type: 'file', name: 'answer_attachment', responseKey: 'answer_attachment', label: 'فایل پیوست', placeholder: ' ', col: 'col-12' }
- ],
- questionInputs: [],
- scores: [],
- objectionInputs: [
- { type: 'input', name: 'objection_result', responseKey: 'objection_result', label: 'متن پاسخ', placeholder: ' ', inputType: 'textarea', col: 'col-12' }
- ],
- objectionApi: APIGateway.answerBook.APIAdresses.submitObjectionResult(this.$route.params.answer_book_id),
- answerBook: new AnswerBook()
- }
- },
- computed: {
- totalScore () {
- let totalScore = 0
- this.scores.forEach(item => {
- if (item.score) {
- totalScore += parseFloat(item.score)
- }
- })
- return totalScore
- }
- },
- mounted () {
- this.loadAuthData()
- this.getAnswerBook()
- this.mounted = true
- },
- methods: {
- scrollToObjectionBox() {
- this.$nextTick(() => {
- if (this.$refs.objectionBox && this.$refs.objectionBox.$el) {
- this.$refs.objectionBox.$el.scrollIntoView({ behavior: 'smooth', block: 'end' })
- }
- })
- },
- loadAuthData () {
- this.authenticatedUser = this.$store.getters['Auth/user']
- },
- closeTicket () {
- this.$q.dialog({
- title: 'توجه',
- message: 'آیا از بستن تیکت اطمینان دارید؟',
- cancel: true,
- persistent: true
- }).onOk(() => {
- this.entityLoading = true
- APIGateway.ticket.close(this.$route.params.id)
- .then(() => {
- this.$refs.entityEdit.getData()
- })
- .catch(() => {
- this.entityLoading = false
- })
- })
- },
- miladiToShamsi (miladi) {
- return Assist.miladiToShamsi(miladi)
- },
- isUserMessage (authenticatedUser, message) {
- return authenticatedUser.id === message.creator_info.id
- },
- removeMessage (replyMessageId) {
- this.$q.dialog({
- title: 'توجه',
- message: 'آیا از حذف پیام اطمینان دارید؟',
- cancel: true,
- persistent: true
- }).onOk(() => {
- this.entityLoading = true
- APIGateway.ticket.deleteReplyMessage(replyMessageId)
- .then(() => {
- this.getAnswerBook()
- })
- .catch(() => {
- this.entityLoading = false
- })
- })
- },
- sendReply() {
- this.entityLoading = true
- const body = this.replyText.replace(/\n/g, '<br>\n')
- APIGateway.ticket.reply({
- id: this.answerBook.ticket,
- body
- })
- .then(() => {
- this.replyText = null
- this.getAnswerBook()
- })
- .catch(() => {
- this.getAnswerBook()
- })
- },
- sendObjection () {
- this.answerBook.loading = true
- this.$refs.objectionEntityEdit.editEntity(false)
- .then(() => {
- this.getAnswerBook()
- })
- .catch(() => {
- this.getAnswerBook()
- })
- },
- toShamsi (miladi) {
- return Assist.miladiToShamsi(miladi)
- },
- loadAnswerBook (answerBook) {
- this.answerBook = new AnswerBook(answerBook)
- this.answerBook.answer_sheet_info.list.forEach((answerSheetItem) => {
- this.questionInputs.push(this.questionInput)
- this.scores.push({
- answerSheetId: answerSheetItem.id,
- score: answerSheetItem.score,
- loading: false
- })
- })
- },
- setGraderToMe () {
- this.answerBook.loading = true
- APIGateway.answerBook.setGraderToMe(this.$route.params.answer_book_id)
- .then((answerBook) => {
- this.loadAnswerBook(answerBook)
- this.answerBook.loading = false
- })
- .catch(() => {
- this.getAnswerBook()
- this.answerBook.loading = false
- })
- },
- submitGraderDescription () {
- this.graderDescriptionLoading = true
- APIGateway.answerBook.submitGraderDescription(this.answerBook.id, this.answerBook.grader_description)
- .then(() => {
- this.graderDescriptionLoading = false
- this.getAnswerBook()
- })
- .catch(() => {
- this.graderDescriptionLoading = false
- })
- },
- submitScore (index) {
- this.scores[index].loading = true
- APIGateway.answerSheet.submitScore(this.scores[index].answerSheetId, this.scores[index].score)
- .then(() => {
- this.scores[index].loading = false
- this.getAnswerBook()
- })
- .catch(() => {
- this.scores[index].loading = false
- })
- },
- getAnswerBook () {
- this.answerBook.loading = true
- this.entityLoading = true
- APIGateway.answerBook.get(this.$route.params.answer_book_id)
- .then((answerBook) => {
- this.loadAnswerBook(answerBook)
- this.answerBook.loading = false
- this.entityLoading = false
- })
- .catch(() => {
- this.answerBook.loading = false
- this.entityLoading = false
- })
- },
- confirmScores () {
- this.answerBook.loading = true
- APIGateway.answerBook.confirmScores(this.$route.params.answer_book_id)
- .then(() => {
- this.getAnswerBook()
- this.answerBook.loading = false
- })
- .catch(() => {
- this.getAnswerBook()
- this.answerBook.loading = false
- })
- },
- confirmUngradable () {
- this.answerBook.loading = true
- APIGateway.answerBook.confirmUngradable(this.$route.params.answer_book_id)
- .then(() => {
- this.getAnswerBook()
- this.answerBook.loading = false
- })
- .catch(() => {
- this.getAnswerBook()
- this.answerBook.loading = false
- })
- }
- }
- }
- </script>
- <style scoped lang="scss">
- .AdminAnswerBookShow {
- :deep(.q-banner) {
- background: #FCF9F4 0 0 no-repeat padding-box;
- padding: 20px;
- .q-banner__content {
- font-size: 16px;
- font-weight: normal;
- }
- }
- :deep(.q-list) {
- .q-item {
- .input-grate-question {
- .q-input {
- .q-field__inner .q-field__control {
- height: 40px;
- min-height: 40px;
- }
- }
- }
- .q-badge {
- background: #ACBCAE 0 0 no-repeat padding-box;
- border-radius: 18px;
- height: 32px;
- padding: 4px 16px;
- }
- }
- }
- }
- </style>
|