index.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. import OEmpty from '@/components/o-empty'
  2. import OHeader from '@/components/o-header'
  3. import OSearch from '@/components/o-search'
  4. import OSticky from '@/components/o-sticky'
  5. import { ActionSheet, Button, Cell, CellGroup, Icon, Image, List, Popup } from 'vant'
  6. import { defineComponent, onMounted, reactive, TransitionGroup } from 'vue'
  7. import styles from './index.module.less'
  8. import iconEdit from './images/icon-edit.png'
  9. import { useRouter } from 'vue-router'
  10. import request from '@/helpers/request'
  11. import { unitTestStatus } from '@/constant'
  12. import dayjs from 'dayjs'
  13. import NoticeStart from './model/notice-start'
  14. import OFullRefresh from '@/components/o-full-refresh'
  15. import ODialog from '@/components/o-dialog'
  16. import { setLogin, state } from '@/state'
  17. import OActionSheet from '@/components/o-action-sheet'
  18. export default defineComponent({
  19. name: 'unit-test',
  20. setup() {
  21. const router = useRouter()
  22. const form = reactive({
  23. oPopover: false,
  24. searchList: [] as any,
  25. list: [] as any,
  26. listState: {
  27. dataShow: true, // 判断是否有数据
  28. loading: false,
  29. finished: false,
  30. refreshing: false,
  31. height: 0 // 页面头部高度,为了处理下拉刷新用的
  32. },
  33. statusText: '全部测验',
  34. params: {
  35. keyword: null,
  36. status: null,
  37. page: 1,
  38. rows: 20
  39. },
  40. isClick: false,
  41. visiableNotice: false,
  42. unitExam: {} as any, // 测验详情
  43. selectUnitExam: {} as any,
  44. dialogMessage: '',
  45. dialogStatus: false
  46. })
  47. const getList = async (status = false) => {
  48. try {
  49. if (form.isClick) return
  50. form.isClick = true
  51. const res = await request.post('/api-student/studentUnitExamination/queryPageByStudent', {
  52. // hideLoading: status,
  53. data: {
  54. ...form.params
  55. }
  56. })
  57. form.listState.loading = false
  58. form.listState.refreshing = false
  59. const result = res.data || {}
  60. // 处理重复请求数据
  61. if (form.list.length > 0 && result.current === 1) {
  62. return
  63. }
  64. form.list = form.list.concat(result.rows || [])
  65. form.listState.finished = result.current >= result.pages
  66. form.params.page = result.current + 1
  67. form.listState.dataShow = form.list.length > 0
  68. form.isClick = false
  69. } catch {
  70. form.listState.dataShow = false
  71. form.listState.finished = true
  72. form.listState.refreshing = false
  73. form.isClick = false
  74. }
  75. }
  76. const onSearch = (status = false) => {
  77. form.params.page = 1
  78. form.list = []
  79. form.listState.dataShow = true // 判断是否有数据
  80. form.listState.loading = false
  81. form.listState.finished = false
  82. getList(status)
  83. }
  84. // 开始测验
  85. const onUnitTestStart = async (item: any) => {
  86. try {
  87. // 判断是否是会员
  88. if (!state.user.data.vipMember) {
  89. form.dialogStatus = true
  90. form.dialogMessage = '您暂未开通团练宝,请开通后使用'
  91. return
  92. }
  93. // 判断是否是继续测验
  94. form.selectUnitExam = item || {}
  95. if (item.status === 'C_ING') {
  96. onExamStart()
  97. }
  98. // 是不是未开始
  99. if (item.status === 'D_NO_SUBMIT') {
  100. const { data } = await request.post(
  101. '/api-student/studentUnitExamination/getExaminationDetail',
  102. {
  103. requestType: 'form',
  104. hideLoading: false,
  105. data: {
  106. studentUnitExaminationId: item.id
  107. }
  108. }
  109. )
  110. form.unitExam = data || {}
  111. form.visiableNotice = true
  112. }
  113. } catch {
  114. //
  115. }
  116. }
  117. // 查看测验
  118. const onUnitTestLook = (item: any) => {
  119. //
  120. router.push({
  121. path: '/unit-detail',
  122. query: {
  123. id: item.id
  124. }
  125. })
  126. }
  127. const onExamStart = async () => {
  128. try {
  129. await request.post('/api-student/studentUnitExamination/startExamination', {
  130. requestType: 'form',
  131. hideLoading: false,
  132. data: {
  133. studentUnitExaminationId: form.selectUnitExam.id
  134. }
  135. })
  136. router.push({
  137. path: '/examination-mode',
  138. query: {
  139. id: form.selectUnitExam.id
  140. }
  141. })
  142. } catch {
  143. //
  144. }
  145. }
  146. onMounted(async () => {
  147. const unitType = sessionStorage.getItem('unit-test-search-type')
  148. const temp: any = [{ name: '全部测验', id: 'ALL', selected: true }]
  149. let selectItem = {} as any
  150. for (const i in unitTestStatus) {
  151. temp.push({
  152. name: unitTestStatus[i],
  153. id: i
  154. })
  155. if (i === unitType) {
  156. selectItem = {
  157. name: unitTestStatus[i],
  158. id: i
  159. }
  160. }
  161. }
  162. form.searchList = temp
  163. if (selectItem.id && selectItem.id !== 'ALL') {
  164. form.statusText = selectItem.name
  165. form.params.status = selectItem.id
  166. }
  167. try {
  168. // 重新初始化用户信息
  169. const userCash = await request.get(state.platformApi + '/user/getUserInfo')
  170. setLogin(userCash.data)
  171. } catch {
  172. //
  173. }
  174. await getList()
  175. })
  176. return () => (
  177. <div class={[styles.unitTest, !form.listState.dataShow && 'emptyRootContainer']}>
  178. <OSticky
  179. position="top"
  180. onGetHeight={(height: any) => {
  181. form.listState.height = height
  182. }}
  183. >
  184. <OSearch
  185. placeholder="请输入测验名称"
  186. // inputBackground="white"
  187. // background="#f6f8f9"
  188. onSearch={(val: any) => {
  189. form.params.keyword = val
  190. onSearch()
  191. }}
  192. v-slots={{
  193. left: () => (
  194. <div
  195. class={['searchItem-left', form.oPopover ? 'searchItem-active' : '']}
  196. onClick={() => (form.oPopover = true)}
  197. >
  198. <span>{form.statusText}</span>
  199. </div>
  200. )
  201. }}
  202. />
  203. </OSticky>
  204. {form.listState.dataShow ? (
  205. <OFullRefresh
  206. v-model:modelValue={form.listState.refreshing}
  207. onRefresh={() => onSearch(true)}
  208. style={{
  209. minHeight: `calc(100vh - ${form.listState.height}px)`
  210. }}
  211. >
  212. <List
  213. // v-model:loading={form.listState.loading}
  214. finished={form.listState.finished}
  215. finishedText=" "
  216. class={[styles.liveList]}
  217. style={{
  218. paddingTop: '12px'
  219. }}
  220. onLoad={getList}
  221. immediateCheck={false}
  222. >
  223. {form.list.map((item: any) => (
  224. <CellGroup inset class={styles.cellGroup} border={false}>
  225. <Cell
  226. center
  227. // isLink
  228. clickable={false}
  229. titleStyle={{ flex: '1 auto' }}
  230. valueClass={[
  231. styles['no-start'],
  232. item.status === 'A_PASS' && styles.pass,
  233. item.status === 'B_NO_PASS' && styles['no-pass']
  234. ]}
  235. >
  236. {{
  237. icon: () => <Image src={iconEdit} class={styles.img} />,
  238. title: () => (
  239. <div class={[styles.unitTitle, 'van-ellipsis']}>{item.name}</div>
  240. ),
  241. value: () => unitTestStatus[item.status]
  242. }}
  243. </Cell>
  244. <Cell center class={styles.unitSection}>
  245. {{
  246. title: () => (
  247. <div class={styles.unitInformation}>
  248. <div>
  249. <div class={styles.name}>{item.orchestraName}</div>
  250. <div class={styles.endTime}>
  251. 截止时间:
  252. {dayjs(item.expiryDate || new Date()).format('YYYY-MM-DD')}
  253. </div>
  254. </div>
  255. {item.status === 'A_PASS' || item.status === 'B_NO_PASS' ? (
  256. <span>
  257. {item.score || 0}
  258. <i>分</i>
  259. </span>
  260. ) : (
  261. ''
  262. )}
  263. </div>
  264. ),
  265. label: () => (
  266. <div class={styles.unitBtnGroup}>
  267. <Button
  268. color="#FFF0E6"
  269. round
  270. block
  271. style={{ color: '#F67146' }}
  272. onClick={() => {
  273. router.push({
  274. path: '/test-exercise',
  275. query: {
  276. id: item.unitExaminationId
  277. }
  278. })
  279. }}
  280. >
  281. 练习模式
  282. </Button>
  283. {item.status === 'A_PASS' || item.status === 'B_NO_PASS' ? (
  284. <Button type="primary" round block onClick={() => onUnitTestLook(item)}>
  285. 查看测验
  286. </Button>
  287. ) : (
  288. <Button
  289. type="primary"
  290. round
  291. block
  292. disabled={dayjs(dayjs().format('YYYY-MM-DD')).isAfter(
  293. dayjs(item.expiryDate)
  294. )}
  295. onClick={() => onUnitTestStart(item)}
  296. >
  297. {item.status === 'C_ING' ? '继续测验' : '开始测验'}
  298. </Button>
  299. )}
  300. </div>
  301. )
  302. }}
  303. </Cell>
  304. </CellGroup>
  305. ))}
  306. </List>
  307. </OFullRefresh>
  308. ) : (
  309. <OEmpty tips="暂无阶段自测" />
  310. )}
  311. {/* 测验须知 */}
  312. <Popup
  313. v-model:show={form.visiableNotice}
  314. round
  315. style={{ width: '90%' }}
  316. closeOnClickOverlay={false}
  317. >
  318. <NoticeStart
  319. data={form.unitExam}
  320. onClose={() => {
  321. form.visiableNotice = false
  322. }}
  323. onConfirm={onExamStart}
  324. />
  325. </Popup>
  326. <ODialog
  327. message={form.dialogMessage}
  328. v-model:show={form.dialogStatus}
  329. showCancelButton
  330. cancelButtonText="取消"
  331. confirmButtonText="立即开通"
  332. onConfirm={() => {
  333. router.push('/memberCenter')
  334. }}
  335. />
  336. <OActionSheet
  337. v-model:show={form.oPopover}
  338. actions={form.searchList}
  339. onSelect={(val: any) => {
  340. form.searchList.forEach((child: any) => {
  341. child.selected = false
  342. })
  343. val.selected = true
  344. form.statusText = val.name
  345. form.params.status = val.id === 'ALL' ? null : val.id
  346. sessionStorage.setItem('unit-test-search-type', val.id)
  347. form.oPopover = false
  348. onSearch()
  349. }}
  350. />
  351. </div>
  352. )
  353. }
  354. })