BaseHwTable.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. <template>
  2. <div class="component-hw-table">
  3. <Table border size='small' ref="selection" :columns="columns" :data="tableData" stripe></Table>
  4. <!-- 评分以及评价弹窗 -->
  5. <Modal v-model="setScoreModal"
  6. class-name="score-modal"
  7. title="教师点评"
  8. footer-hide
  9. width="600px">
  10. <div class="score-modal-container">
  11. <div class="score-modal-item">
  12. <span>评分</span>
  13. <InputNumber :max="100" :min="1" v-model="currentScore"></InputNumber>
  14. </div>
  15. <div class="score-modal-item">
  16. <span style="vertical-align: top;margin-top:6px;display: inline-block;">评语</span>
  17. <Input v-model="currentComment" type="textarea" :autosize="{minRows: 2,maxRows: 5}" placeholder="请输入评语" />
  18. <Checkbox v-model="isSaveComment">保存为常用评语</Checkbox>
  19. <div class="used-comments">
  20. <p>常用评语</p>
  21. <Select v-model="currentUsedComment" @on-change="onUsedCommentChange">
  22. <Option v-for="(item,index) in usedCommentList" :value="index" :key="index">{{ item.comment }}</Option>
  23. </Select>
  24. </div>
  25. </div>
  26. <div class="score-modal-item">
  27. <Button @click="onSetScore" :loading="isScoreLoading">提交</Button>
  28. </div>
  29. </div>
  30. </Modal>
  31. <!-- 查看互评弹窗 -->
  32. <Modal v-model="mutualEvaluationModal"
  33. class-name="score-modal mutual-modal"
  34. title="查看互评"
  35. footer-hide
  36. width="700px">
  37. <div v-if="commentList.length === 0">
  38. <EmptyBox :top="0"></EmptyBox>
  39. </div>
  40. <div class="mutual-comment-list" v-else>
  41. <vuescroll>
  42. <div style="padding:0 20px 50px 20px">
  43. <span>互评分数</span>
  44. <div class="mutual-comment-rate">
  45. <Rate v-model="currentRateValue" allow-half icon="md-star" disabled />
  46. <span class="mutual-score">{{currentRateValue}}</span>
  47. </div>
  48. <p>全部评论</p>
  49. <div class="comment-item" v-for="(item,index) in commentList" :key="index">
  50. <div class="comment-item-left">
  51. <img src="@/assets/icon/icon_header.png" width="40" />
  52. <p class="comment-item-left-name">{{ item.fromId }}</p>
  53. <p class="comment-item-left-level">{{ index + 1 }} 楼</p>
  54. </div>
  55. <div class="comment-item-right">
  56. <span class="comment-item-right-content">{{ item.comment }}</span>
  57. <span class="comment-item-right-time">发布时间:{{ $tools.formatTime(item.createTime) }}</span>
  58. <span class="comment-item-right-score">
  59. <span style="margin-right:10px;display: inline-block;margin-top: 5px;">评分:</span>
  60. <Rate v-model="item.score" icon="md-star" allow-half disabled />
  61. <span style="margin:0 10px;display: inline-block;margin-top: 5px;color:#E9A607">{{ parseInt(item.score) === item.score ? item.score + '.0' : item.score }}</span>
  62. </span>
  63. </div>
  64. </div>
  65. </div>
  66. </vuescroll>
  67. </div>
  68. </Modal>
  69. <!-- 下载附件弹窗 -->
  70. <Modal v-model="downloadModal"
  71. class-name="score-modal download-modal component-hw-table"
  72. title="提交详情"
  73. footer-hide
  74. width="600px">
  75. <p class="download-title">回复内容</p>
  76. <div class="download-hw-content" v-html="currentAnswer">
  77. </div>
  78. <p class="download-title">附件内容</p>
  79. <Table border size='small'
  80. ref="fileTable"
  81. :columns="fileColumns"
  82. :data="currentFileList"
  83. @on-selection-change="onFileSelectChange"
  84. stripe></Table>
  85. <div class="download-btn-wrap">
  86. <Button :disabled="downloadList.length !== 1" type="info" @click="onDownloadFile(downloadList)">下载所选文件</Button>
  87. <BasePackage v-show="downloadList.length > 1" text='打包下载' :urlList="downloadList" :student="currentStudent"></BasePackage>
  88. </div>
  89. </Modal>
  90. </div>
  91. </template>
  92. <script>
  93. import EmptyBox from '@/common/EmptyData'
  94. import BasePackage from '@/common/BasePackage'
  95. export default {
  96. props: ['studentsList'],
  97. components: { BasePackage , EmptyBox },
  98. data() {
  99. return {
  100. setScoreModal: false,
  101. downloadModal: false,
  102. sasString:'',
  103. mutualEvaluationModal: false,
  104. isSaveComment: false,
  105. currentUsedComment:null,
  106. userInfo: this.$store.state.userInfo,
  107. isScoreLoading: false,
  108. currentStudent: null,
  109. currentHw: null,
  110. currentScore: 100,
  111. currentComment: '',
  112. currentFileList: [],
  113. currentAnswer:'',
  114. currentRateValue:0,
  115. downloadList: [],
  116. filterData:[],
  117. usedCommentList: [],
  118. fileColumns: [
  119. {
  120. type: 'selection',
  121. width: 60,
  122. align: 'center'
  123. },
  124. {
  125. title: '文件名',
  126. key: 'fileName'
  127. },
  128. {
  129. title: '大小',
  130. width: 100,
  131. key: 'size',
  132. render: (h, params) => {
  133. return h('span', this.$tools.bytesToSize(params.row.size))
  134. }
  135. }
  136. ],
  137. columns: [
  138. {
  139. type: 'selection',
  140. width: 60,
  141. align: 'center'
  142. },
  143. {
  144. title: '姓名',
  145. width: 100,
  146. key: 'name'
  147. },
  148. {
  149. title: '班级',
  150. width: 100,
  151. filters: [],
  152. filterMultiple: false,
  153. filterMethod (val, row) {
  154. return row.classroom.code === val
  155. },
  156. render: (h, params) => {
  157. return h('span', params.row.classroom.name)
  158. },
  159. },
  160. {
  161. title: '缴交',
  162. width: 80,
  163. align: 'center',
  164. render: (h, params) => {
  165. return !params.row.submissionBool ?
  166. h('span', '——') :
  167. h('Icon', {
  168. props: {
  169. type: 'md-checkmark',
  170. color: '#07A856',
  171. size: 24
  172. },
  173. domProps: {
  174. title: '已提交'
  175. }
  176. })
  177. }
  178. },
  179. {
  180. title: '提交时间',
  181. key: 'submitTime',
  182. width: 180,
  183. render: (h, params) => {
  184. return h('span', params.row.submissionBool ? this.$tools.formatTime(params.row.submissionTime,'yyyy-MM-dd hh:mm') : '——')
  185. },
  186. },
  187. {
  188. title: '分数',
  189. width: 80,
  190. render: (h, params) => {
  191. let that = this
  192. return params.row.score > 0 ?
  193. h('span', {
  194. domProps: {
  195. title: '下载作业'
  196. },
  197. style: {
  198. cursor: 'pointer',
  199. color: '#07A856',
  200. fontWeight:'bold'
  201. },
  202. on: {
  203. click: function () {
  204. that.currentStudent = params.row
  205. that.currentScore = params.row.score
  206. that.currentComment = params.row.teacherComments ? params.row.teacherComments.comment : ''
  207. that.setScoreModal = true
  208. }
  209. },
  210. }, params.row.score) :
  211. h('Icon', {
  212. props: {
  213. type: 'md-create',
  214. size:18
  215. },
  216. style: {
  217. cursor:'pointer'
  218. },
  219. domProps: {
  220. title: '评分'
  221. },
  222. on: {
  223. click: function () {
  224. that.currentStudent = params.row
  225. that.currentScore = params.row.score
  226. that.currentComment = params.row.teacherComments ? params.row.teacherComments.comment : ''
  227. that.setScoreModal = true
  228. }
  229. },
  230. })
  231. }
  232. },
  233. {
  234. title: '评语',
  235. render: (h, params) => {
  236. let that = this
  237. return h('span', {
  238. domProps: {
  239. //title: '下载作业'
  240. },
  241. style: {
  242. cursor: 'pointer',
  243. //color: '#07A856',
  244. fontWeight:'bold'
  245. },
  246. on: {
  247. click: function () {
  248. that.currentStudent = params.row
  249. that.currentScore = params.row.score
  250. that.currentComment = params.row.teacherComments ? params.row.teacherComments.comment : ''
  251. that.setScoreModal = true
  252. }
  253. },
  254. }, params.row.teacherComments.comment)
  255. }
  256. },
  257. {
  258. title: '操作',
  259. key: '',
  260. width: 150,
  261. render: (h, params) => {
  262. let that = this
  263. return h('div',
  264. {
  265. domProps: {
  266. className: 'table-tools-icon'
  267. }
  268. }, [
  269. h('Icon', {
  270. props: {
  271. type: 'ios-list-box-outline',
  272. },
  273. domProps: {
  274. title: '下载作业'
  275. },
  276. on: {
  277. click: function () {
  278. if (params.row.submissionBool) {
  279. that.currentStudent = params.row
  280. that.downloadModal = true
  281. that.currentFileList = params.row.content.length ? params.row.content[0].resource : []
  282. that.currentAnswer = params.row.content.length ? params.row.content[0].answers : ''
  283. } else {
  284. that.$Message.warning('暂无提交内容')
  285. }
  286. }
  287. },
  288. }),
  289. h('Icon', {
  290. props: {
  291. type: 'ios-chatbubbles-outline'
  292. },
  293. domProps: {
  294. title: '查看互评'
  295. },
  296. on: {
  297. click: function () {
  298. that.mutualEvaluationModal = true
  299. that.commentList = params.row.studentComments
  300. if (that.commentList.length) {
  301. let nums = params.row.studentComments.map(i => i.score)
  302. that.currentRateValue = (nums.reduce((a, b) => a + b) / nums.length).toFixed(1)
  303. }
  304. }
  305. },
  306. })
  307. ]);
  308. }
  309. }
  310. ],
  311. tableData: [],
  312. commentList: []
  313. }
  314. },
  315. created() {
  316. this.getSasStr()
  317. },
  318. methods: {
  319. /**
  320. * 全选操作
  321. * @param status
  322. */
  323. handleSelectAll(status) {
  324. this.$refs.selection.selectAll(status);
  325. },
  326. /**
  327. * 文件表格选择回调
  328. * @param list
  329. */
  330. onFileSelectChange(list) {
  331. console.log(list)
  332. this.downloadList = list.map(item => item.blobUrl)
  333. },
  334. /**
  335. * 查询当前教师的评语罐头
  336. * @param teacherId
  337. */
  338. findTeacherComments(teacherId) {
  339. return new Promise((r, j) => {
  340. this.$api.learnActivity.FindTeacherComments({ TEAMModelId: teacherId }).then(res => {
  341. if (!res.error && res.result.data) {
  342. r(res.result.data)
  343. } else {
  344. j(500)
  345. }
  346. })
  347. })
  348. },
  349. /**
  350. * 常用评语切换
  351. * @param val
  352. */
  353. onUsedCommentChange(val) {
  354. this.currentComment = this.usedCommentList.length && val !== undefined ? this.usedCommentList[val].comment : ''
  355. },
  356. /**
  357. * 选择常用评语
  358. * @param e
  359. */
  360. onChooseComment(e) {
  361. this.currentComment = e.target.innerText
  362. },
  363. /** 设置作业点评分数 */
  364. onSetScore() {
  365. if (!this.currentComment || !this.currentScore) {
  366. this.$Message.warning('请填写完整!')
  367. } else {
  368. this.isScoreLoading = true
  369. let scoreParams = {
  370. id: this.currentStudent.id,
  371. homeWorkId: this.currentStudent.homeWorkId,
  372. TEAMModelId: this.userInfo.TEAMModelId,
  373. score: this.currentScore,
  374. comments: this.currentComment
  375. }
  376. if (this.isSaveComment) {
  377. let params = {
  378. TEAMModelId: this.userInfo.TEAMModelId,
  379. comment: this.currentComment
  380. }
  381. this.onSaveComment(params).then(res => {
  382. this.usedCommentList = res[0].comment
  383. this.$Message.success('保存成功')
  384. })
  385. }
  386. /* 同时发送评分以及评语请求 */
  387. this.onApiScore(scoreParams).then(res => {
  388. let curIndex = this.tableData.map(item => item.id).indexOf(this.currentStudent.id)
  389. this.$set(this.tableData, curIndex, res)
  390. this.$Message.success('点评成功!')
  391. this.isScoreLoading = false
  392. this.setScoreModal = false
  393. this.currentUsedComment = null
  394. }).catch(err => {
  395. console.log(err)
  396. })
  397. }
  398. },
  399. /**
  400. * 老师评分请求接口
  401. * @param params
  402. */
  403. onApiScore(params) {
  404. return new Promise((r, j) => {
  405. this.$api.learnActivity.TeacherScoring(params).then(res => {
  406. if (!res.error && res.result.data) {
  407. r(res.result.data)
  408. } else {
  409. j(500)
  410. }
  411. })
  412. })
  413. },
  414. /**
  415. * 保存为常用评语
  416. * @param params
  417. */
  418. onSaveComment(params) {
  419. return new Promise((r, j) => {
  420. this.$api.learnActivity.SaveOrUpdateTeacherComments(params).then(res => {
  421. if (!res.error && res.result.data) {
  422. r(res.result.data)
  423. } else {
  424. j(500)
  425. }
  426. })
  427. })
  428. },
  429. /**
  430. * 下载附件
  431. * @param blobUrl
  432. */
  433. onDownloadFile(downloadList) {
  434. downloadList.forEach(item => {
  435. window.location.href = item + this.sasString
  436. })
  437. },
  438. /**
  439. * 获取blob授权信息
  440. * */
  441. getSasStr() {
  442. this.$api.uploadFile.getContainerSAS().then(
  443. (res) => {
  444. if (res.error == null) {
  445. this.sasString = res.result.data.SAS
  446. } else {
  447. alert('API error!')
  448. }
  449. },
  450. (err) => {
  451. alert('API error!')
  452. }
  453. )
  454. },
  455. },
  456. mounted() {
  457. this.findTeacherComments('habook#0001').then(res => {
  458. this.usedCommentList = res.length ? res[0].comment : []
  459. })
  460. },
  461. watch: {
  462. studentsList: {
  463. handler(newValue) {
  464. /** 编辑回显 */
  465. if (newValue) {
  466. this.tableData = newValue
  467. this.filterData = []
  468. let list = newValue.map(item => item.classroom)
  469. list.forEach(i => {
  470. if (this.filterData.map(j => j.value).indexOf(i.code) === -1) {
  471. this.filterData.push({
  472. value: i.code,
  473. label:i.name
  474. })
  475. }
  476. })
  477. this.columns[2].filters = this.filterData
  478. }
  479. },
  480. deep: true
  481. }
  482. }
  483. }
  484. </script>
  485. <style lang="less">
  486. @import "./BaseHwTable.less";
  487. </style>