CompleteList.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. <template>
  2. <el-dialog
  3. class="complete-list"
  4. :visible="dialogVisibleComplete"
  5. width="900px"
  6. title="答题统计"
  7. :close-on-click-modal="false"
  8. @close="dialogCompleteClose"
  9. >
  10. <div class="complete-list-top">
  11. <div class="material-name">{{ material_name }}</div>
  12. <div class="student-list">
  13. <i class="el-icon-arrow-left" @click="listMove('left')" />
  14. <div ref="avatar" class="avatar-list">
  15. <div ref="list" class="avatar-list-wrapper" :style="{ 'margin-left': marginLeft + 'px' }">
  16. <el-avatar
  17. v-for="item in student_list"
  18. :key="item.student_id"
  19. :class="{ active: curStudent === item.student_id }"
  20. icon="el-icon-user"
  21. :src="item.student_image_url"
  22. />
  23. </div>
  24. </div>
  25. <i class="el-icon-arrow-right" @click="listMove('right')" />
  26. </div>
  27. </div>
  28. <div class="complete-list-container">
  29. <template v-if="material_type === 'COURSEWARE'">
  30. <Bookquestion :context="context" />
  31. </template>
  32. <template v-else>
  33. <!-- pdf -->
  34. <template v-if="fileType === 'pdf'">
  35. <pdf v-for="i in numPages" :key="i" :src="pdfSrc" :page="i"></pdf>
  36. </template>
  37. <template v-else-if="isImage(fileType)">
  38. <el-image fit="contain" :src="file_url_https" />
  39. </template>
  40. <template v-else-if="fileType !== 'pdf'">
  41. <iframe
  42. :src="'https://view.officeapps.live.com/op/view.aspx?src=' + `${file_url_https}`"
  43. width="100%"
  44. height="490px"
  45. scrolling="no"
  46. >
  47. </iframe>
  48. </template>
  49. </template>
  50. </div>
  51. <div slot="footer"></div>
  52. </el-dialog>
  53. </template>
  54. <script>
  55. import pdf from 'vue-pdf';
  56. import { GetCurMaterialSent, GetStudentList_FinishMaterial } from '@/api/live';
  57. import { GetCoursewareContent_View } from '@/api/course';
  58. import { GetFileStoreInfo } from '@/api/app';
  59. export default {
  60. components: {
  61. pdf
  62. },
  63. props: {
  64. dialogVisibleComplete: {
  65. default: false,
  66. type: Boolean
  67. },
  68. taskId: {
  69. default: '',
  70. type: String
  71. }
  72. },
  73. data() {
  74. return {
  75. material_id: '',
  76. material_name: '',
  77. material_type: '',
  78. material_picture_url: '',
  79. context: null,
  80. file_relative_path: '',
  81. file_url_https: '',
  82. pdfSrc: '',
  83. numPages: 1,
  84. student_list: [],
  85. curStudent: '',
  86. listTimer: null,
  87. marginLeft: 0
  88. };
  89. },
  90. computed: {
  91. fileType() {
  92. return this.file_url_https.slice(
  93. this.file_url_https.lastIndexOf('.') + 1,
  94. this.file_url_https.length
  95. );
  96. }
  97. },
  98. watch: {
  99. dialogVisibleComplete(newVal) {
  100. if (newVal) {
  101. this.getCurMaterialSent();
  102. } else {
  103. // 对话框,关闭时清理
  104. clearInterval(this.listTimer);
  105. this.material_id = '';
  106. this.material_name = '';
  107. this.student_list = [];
  108. this.marginLeft = 0;
  109. }
  110. },
  111. material_id(newVal) {
  112. if (newVal) {
  113. this.listTimer = setInterval(() => {
  114. this.getStudentList_FinishMaterial();
  115. }, 3000);
  116. if (this.material_type === 'COURSEWARE') {
  117. this.getCoursewareContent_View();
  118. } else {
  119. this.getFileStoreInfo();
  120. }
  121. }
  122. }
  123. },
  124. methods: {
  125. getCurMaterialSent() {
  126. GetCurMaterialSent({ task_id: this.taskId }).then(
  127. ({ material_id, material_name, material_type, material_picture_url }) => {
  128. if (material_id !== undefined && material_id.length > 0) {
  129. this.material_id = material_id;
  130. this.material_name = material_name;
  131. this.material_type = material_type;
  132. this.material_picture_url = material_picture_url;
  133. }
  134. }
  135. );
  136. },
  137. getStudentList_FinishMaterial() {
  138. GetStudentList_FinishMaterial({
  139. task_id: this.taskId,
  140. material_id: this.material_id,
  141. material_type: this.material_type
  142. })
  143. .then(({ student_list }) => {
  144. this.student_list = student_list;
  145. })
  146. .catch(() => {
  147. clearInterval(this.listTimer);
  148. });
  149. },
  150. getCoursewareContent_View() {
  151. GetCoursewareContent_View({ id: this.material_id }).then(res => {
  152. if (res.content) {
  153. this.context = {
  154. id: this.currentCourse,
  155. ui_type: JSON.parse(res.content).question.ui_type,
  156. content: JSON.parse(res.content)
  157. };
  158. } else {
  159. this.context = null;
  160. }
  161. });
  162. },
  163. getFileStoreInfo() {
  164. GetFileStoreInfo({ file_id: this.material_id }).then(
  165. ({ file_relative_path, file_url_https }) => {
  166. this.file_relative_path = file_relative_path;
  167. this.file_url_https = file_url_https;
  168. let fileType = file_url_https.slice(
  169. file_url_https.lastIndexOf('.') + 1,
  170. file_url_https.length
  171. );
  172. if (fileType === 'pdf') {
  173. this.getNumPages(file_url_https);
  174. }
  175. }
  176. );
  177. },
  178. getNumPages(url) {
  179. let loadingTask = pdf.createLoadingTask(url);
  180. loadingTask.promise
  181. .then(pdf => {
  182. this.pdfSrc = loadingTask;
  183. this.numPages = pdf.numPages;
  184. })
  185. .catch(err => {
  186. console.error('pdf加载失败', err);
  187. });
  188. },
  189. dialogCompleteClose() {
  190. this.$emit('dialogCompleteClose');
  191. },
  192. isImage(type) {
  193. return ['jpeg', 'gif', 'jpg', 'png', 'bmp', 'pic', 'svg'].includes(type);
  194. },
  195. listMove(direction) {
  196. let w = this.$refs.list.clientWidth - this.$refs.avatar.clientWidth;
  197. if (w > 60) {
  198. let left = Number(this.$refs.list.style['margin-left'].slice(0, -2));
  199. let width = direction === 'right' ? left - 60 : left + 60;
  200. if (Math.abs(width) > w) width = -w;
  201. this.marginLeft = width > 0 ? 0 : width;
  202. }
  203. }
  204. }
  205. };
  206. </script>
  207. <style lang="scss">
  208. @import '~@/styles/mixin.scss';
  209. .complete-list {
  210. @include dialog;
  211. &-top {
  212. .material-name {
  213. font-size: 16px;
  214. font-weight: 700;
  215. color: #000;
  216. margin-bottom: 16px;
  217. }
  218. .student-list {
  219. display: flex;
  220. justify-content: space-between;
  221. height: 44px;
  222. align-items: center;
  223. margin-bottom: 24px;
  224. overflow: hidden;
  225. .avatar-list {
  226. width: calc(100% - 48px);
  227. overflow: hidden;
  228. &-wrapper {
  229. display: inline-block;
  230. white-space: nowrap;
  231. .el-avatar {
  232. cursor: pointer;
  233. margin: 0 9px;
  234. }
  235. }
  236. }
  237. > i {
  238. font-size: 18px;
  239. cursor: pointer;
  240. }
  241. }
  242. }
  243. &-container {
  244. overflow: auto;
  245. height: calc(55vh - 117px);
  246. .el-image {
  247. width: 100%;
  248. height: calc(100% - 4px);
  249. }
  250. }
  251. }
  252. </style>