index.tsx 12 KB

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