practiceResults.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. <!-- 自主练习——查看练习结果 -->
  2. <template>
  3. <div class="stu_practice_result">
  4. <div class="page_search">
  5. <div class="search_content">
  6. <div class="content_left">
  7. <div class="grade_title">练习记录</div>
  8. </div>
  9. </div>
  10. </div>
  11. <FiltersItem :filtersData="filtersData" @selectItem="ChangeFilters">
  12. <template #rowItem-time>
  13. <el-date-picker
  14. v-if="filtersData[0].value == 'custom'"
  15. style="height: 28px;flex-grow: 0;width: 225px;"
  16. v-model="startAndEndTime"
  17. type="daterange"
  18. range-separator="至"
  19. start-placeholder="开始日期"
  20. end-placeholder="结束日期"
  21. size="default"
  22. @change="GetTargetExerciseResult"
  23. />
  24. </template>
  25. </FiltersItem>
  26. <Table class="practice_table end_item"
  27. :currentPage="currentPage" :pageSize="pageSize" :totalNum="totalNum"
  28. :showPageSize="true"
  29. :tableData="tableData" :tableColumns="tableColumns"
  30. @paginationChange="HandlePaginationChange">
  31. <template v-slot:exerciseType="{row}">
  32. {{ HandlePracticeNumTypeToStr(row.exerciseType) }}
  33. </template>
  34. <template v-slot:exerciseStatus="{row}">
  35. <TableRowStatus :useStatus="row.exerciseStatus"
  36. :statusMsg="[
  37. {
  38. statusFlag:1,
  39. title:'未批阅',
  40. themeClass:'need_summary_icon'
  41. },
  42. {
  43. statusFlag:2,
  44. title:'批阅中',
  45. themeClass:'no_release_icon'
  46. },
  47. {
  48. statusFlag:3,
  49. title:'已批阅',
  50. themeClass:'normal_icon'
  51. },
  52. {
  53. statusFlag:4, // 已发布成绩
  54. title:'已批阅',
  55. themeClass:'normal_icon'
  56. },
  57. ]">
  58. </TableRowStatus>
  59. </template>
  60. <template v-slot:frontRate="{row}">
  61. {{ row.frontRate === '-' ? row.frontRate : row.frontRate + '%' }}
  62. </template>
  63. <!-- exerciseStatus 批阅状态(1未批阅 2批阅中 3\4已批阅) -->
  64. <template v-slot:afterRate="{row}">
  65. {{ row.afterRate ==='-' ?
  66. row.afterRate :
  67. (row.afterRate === null ? '-' : row.afterRate + '%' )}}
  68. </template>
  69. <!-- 提升情况 -->
  70. <template v-slot:difference="{row}">
  71. <img v-if="[3,4].includes(row.exerciseStatus)
  72. && row.afterRate !== '-'
  73. && row.afterRate !== null
  74. && row.frontRate !== '-'
  75. && Number(row.afterRate) - Number(row.frontRate) !== 0"
  76. width="16px" height="16px" style="margin-right: 2px;"
  77. :src="Number(row.afterRate) > Number(row.frontRate) ? upIcon : downIcon" alt="" />
  78. {{ [3,4].includes(row.exerciseStatus)
  79. && row.afterRate !== '-'
  80. && row.afterRate !== null
  81. && row.frontRate !== '-'
  82. && Number(row.afterRate) - Number(row.frontRate) !== 0
  83. ? row.difference + '%' : row.difference }}
  84. </template>
  85. <template v-slot:action="{row}">
  86. <div class="table_row_operation">
  87. <el-button type="text" @click="viewDetails(row)">查看</el-button>
  88. </div>
  89. </template>
  90. <template v-slot:paginationDesc>
  91. <span style="color:#666666;flex:1 1;">共 {{totalNum}} 条数据</span>
  92. </template>
  93. </Table>
  94. <div class="page_dialog">
  95. <el-dialog title=""
  96. :visible.sync="showPracticeResultDialog"
  97. class="preview_dialog"
  98. fullscreen height="100%">
  99. <PracticeDetail
  100. v-if="showPracticeResultDialog"
  101. :localPracticeDetail="practiceResultData"
  102. @CloseDialog="CloseDetailDialog">
  103. </PracticeDetail>
  104. </el-dialog>
  105. </div>
  106. </div>
  107. </template>
  108. <script>
  109. import dayjs from 'dayjs';
  110. // 1. 引入 isoWeek 插件
  111. import isoWeek from 'dayjs/plugin/isoWeek';
  112. import { mapState } from "vuex";
  113. import FiltersItem from "../components/FiltersItem_ruoyan.vue"//筛选组件
  114. import Table from "../components/Table.vue";
  115. import TableRowStatus from "../components/TableRowStatus.vue";
  116. import PracticeDetail from './practiceResults/practiceDetail.vue'
  117. import upIcon from '@/assets/arrow-up.png'
  118. import downIcon from '@/assets/arrow-down.png'
  119. // 2. 全局扩展插件(只需调用一次即可)
  120. dayjs.extend(isoWeek);
  121. export default ({
  122. components: {
  123. FiltersItem,
  124. Table,
  125. TableRowStatus,
  126. PracticeDetail,
  127. },
  128. data(){
  129. return {
  130. upIcon:upIcon,
  131. downIcon:downIcon,
  132. currentPage:1,
  133. pageSize:20,
  134. totalNum:0,
  135. tableColumns: [
  136. {
  137. name: 'submitTime',
  138. label: '练习时间',
  139. minWidth: '180',
  140. hidden: false,
  141. custom: false,
  142. },
  143. {
  144. name: 'exerciseType',
  145. label: '练习类型',
  146. minWidth: '120',
  147. align: 'center',
  148. hidden: false,
  149. custom: true,
  150. },
  151. {
  152. name: 'knowledgeName',
  153. label: '知识点名称',
  154. minWidth: '150',
  155. hidden: false,
  156. custom: false,
  157. },
  158. {
  159. name: 'questionNum',
  160. label: '试题数量',
  161. minWidth: '100',
  162. align: 'center',
  163. hidden: false,
  164. custom: false,
  165. },
  166. {
  167. name: 'exerciseStatus',
  168. label: '批阅状态',
  169. minWidth: '120',
  170. align: 'center',
  171. hidden: false,
  172. custom: true,
  173. },
  174. {
  175. name: 'frontRate',
  176. label: '练前得分率',
  177. minWidth: '120',
  178. align: 'center',
  179. hidden: false,
  180. custom: true,
  181. },
  182. {
  183. name: 'afterRate',
  184. label: '练后得分率',
  185. minWidth: '120',
  186. align: 'center',
  187. hidden: false,
  188. custom: true,
  189. },
  190. {
  191. name: 'difference',
  192. label: '提升情况',
  193. minWidth: '120',
  194. align: 'center',
  195. hidden: false,
  196. custom: true,
  197. },
  198. {
  199. name: 'action',
  200. label: '操作',
  201. minWidth: '100',
  202. fixed: 'right',
  203. align: 'center',
  204. hidden: false,
  205. custom: true,
  206. }
  207. ],
  208. tableData: [],
  209. filtersData: [
  210. {
  211. key:'time',
  212. name: '时间',
  213. value: 'all', // 默认选中项
  214. list: [
  215. { label: '全部', value: 'all' },
  216. { label: '本周', value: 'this_week' },
  217. { label: '最近1月', value: 'last_1_month' },
  218. { label: '最近3月', value: 'last_3_months' },
  219. { label: '自定义', value: 'custom' }
  220. ]
  221. },
  222. {
  223. key:'type',
  224. name: '类型',
  225. value: 'all', // 默认选中项
  226. list: [
  227. { label: '全部', value: 'all' },
  228. { label: '指定练习', value: '2' },
  229. { label: '自主练习', value: '1' }
  230. ]
  231. }
  232. ],
  233. startAndEndTime:undefined,
  234. // 查看练习结果弹窗有关数据
  235. showPracticeResultDialog:false,
  236. practiceResultData:{},
  237. }
  238. },
  239. methods: {
  240. // 处理练习类型转换
  241. HandlePracticeNumTypeToStr(num){
  242. switch(Number(num)){
  243. case 1:
  244. return '自主练习'
  245. case 2:
  246. return '指定练习'
  247. default:
  248. return ''
  249. }
  250. },
  251. // 筛选组件回调
  252. ChangeFilters(e) {
  253. // console.log('当前选中的信息',e)
  254. this.filtersData[e.index].value = e.value;
  255. this.GetTargetExerciseResult()
  256. },
  257. // 处理表格分页变化
  258. HandlePaginationChange(params){
  259. const {type, val} = params
  260. if(type == 'currentPage'){
  261. this.currentPage = Number(val)
  262. }else if(type == 'pageSize'){
  263. this.pageSize = Number(val)
  264. }
  265. this.GetTargetExerciseResult()
  266. },
  267. // 获取本周一(本周起始日)的 00:00:00
  268. getCurrentWeekStart(){
  269. return dayjs().startOf('isoWeek').format("YYYY-MM-DD HH:mm:ss");
  270. },
  271. // 获取一个月前的时间
  272. getOneMonthAgo(){
  273. return dayjs().subtract(1, 'month').format("YYYY-MM-DD HH:mm:ss");
  274. },
  275. // 获取三个月前的时间
  276. getThreeMonthsAgo(){
  277. return dayjs().subtract(3, 'month').format("YYYY-MM-DD HH:mm:ss");
  278. },
  279. // 获取练习结果列表
  280. GetTargetExerciseResult(){
  281. let startDate = ''
  282. let endDate = ''
  283. switch(this.filtersData[0].value){
  284. case 'all':
  285. startDate = ''
  286. endDate = ''
  287. break
  288. case 'this_week':
  289. startDate = this.getCurrentWeekStart()
  290. endDate = dayjs().format("YYYY-MM-DD HH:mm:ss")
  291. break
  292. case 'last_1_month':
  293. startDate = this.getOneMonthAgo()
  294. endDate = dayjs().format("YYYY-MM-DD HH:mm:ss")
  295. break
  296. case 'last_3_months':
  297. startDate = this.getThreeMonthsAgo()
  298. endDate = dayjs().format("YYYY-MM-DD HH:mm:ss")
  299. break
  300. case 'custom':
  301. startDate = this.startAndEndTime?.[0] ? dayjs(this.startAndEndTime?.[0]).format("YYYY-MM-DD HH:mm:ss") : ''
  302. endDate = this.startAndEndTime?.[1] ? dayjs(this.startAndEndTime?.[1]).format("YYYY-MM-DD HH:mm:ss") : ''
  303. break
  304. }
  305. let prams = {
  306. pageParam: {
  307. pageNum: this.currentPage,
  308. pageSize: this.pageSize,
  309. },
  310. beginAt: startDate, //开始时间
  311. endAt: endDate, //结束时间
  312. exerciseType: this.filtersData[1].value == 'all' ? '' : this.filtersData[1].value , // 练习类型0全部 1自主练习 2指定练习
  313. levelCode: this.$store.state.target.levelCode, // 学段code
  314. subjectCode: this.$store.state.target.subjectCode //学科code
  315. }
  316. this.$api.target.getTargetExerciseResult(prams).then(res=>{
  317. if(res?.code == 200){
  318. this.tableData = res.data.records
  319. this.totalNum = Number(res.data.total)
  320. }
  321. }).catch()
  322. },
  323. // 跳转练习结果详情
  324. viewDetails(row){
  325. let tmpStorage = {
  326. id:row.exerciseId,
  327. practiceTime:row.submitTime, //练习时间(提交时间)
  328. frontRate:row.frontRate, //练前得分率
  329. afterRate:row.afterRate, //练后得分率
  330. difference:row.difference, //提升情况
  331. exerciseStatus:row.exerciseStatus, // 批阅状态(1未批阅 2批阅中 3/4已批阅)
  332. knowledgeName:row.knowledgeName
  333. }
  334. this.practiceResultData = tmpStorage
  335. this.showPracticeResultDialog = true
  336. },
  337. CloseDetailDialog(){
  338. this.showPracticeResultDialog = false
  339. }
  340. },
  341. computed:{
  342. ...mapState("target", ["subjectCode"]),
  343. },
  344. mounted() {
  345. this.GetTargetExerciseResult();
  346. },
  347. watch:{
  348. subjectCode(newVal){
  349. this.GetTargetExerciseResult();
  350. }
  351. }
  352. })
  353. </script>
  354. <style lang="scss" scoped>
  355. .stu_practice_result{
  356. flex:1;
  357. display: flex;
  358. flex-direction: column;
  359. overflow: auto;
  360. width: 100%;
  361. box-sizing: border-box;
  362. background-color: #fff;
  363. border-radius: 10px;
  364. margin-bottom: 10px;
  365. padding: 10px;
  366. .end_item{
  367. flex-grow: 1;
  368. }
  369. .page_search{
  370. margin-bottom: 16px;
  371. }
  372. .practice_table{
  373. margin-top: 2px;
  374. ::v-deep .el-table {
  375. thead{
  376. height: 40px !important;
  377. }
  378. .el-table__cell {
  379. height: 40px;
  380. }
  381. }
  382. }
  383. }
  384. .page_dialog{
  385. ::v-deep .el-dialog{
  386. padding:10px !important;
  387. background-color: #f0f4fb !important;
  388. .el-dialog__body{
  389. box-sizing: border-box;
  390. overflow: auto;
  391. }
  392. }
  393. }
  394. </style>