detail.tsx 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. import OHeader from '@/components/o-header'
  2. import { Cell, CellGroup, Grid, GridItem, Image, List, Picker, Popup, Tag } from 'vant'
  3. import { defineComponent, onMounted, reactive } from 'vue'
  4. import styles from './index.module.less'
  5. import iconStudent from '@/common/images/icon_student.png'
  6. import request from '@/helpers/request'
  7. import OFullRefresh from '@/components/o-full-refresh'
  8. import OEmpty from '@/components/o-empty'
  9. import { useRoute } from 'vue-router'
  10. export default defineComponent({
  11. name: 'practice-detail',
  12. setup() {
  13. const route = useRoute()
  14. const state = reactive({
  15. subjectStatus: false,
  16. subjectList: [] as any,
  17. isClick: false,
  18. list: [] as any,
  19. listState: {
  20. dataShow: true, // 判断是否有数据
  21. loading: false,
  22. finished: false,
  23. refreshing: false,
  24. height: 0 // 页面头部高度,为了处理下拉刷新用的
  25. },
  26. subjectName: '全部声部',
  27. params: {
  28. type: null,
  29. subjectId: null,
  30. page: 1,
  31. rows: 20
  32. }
  33. })
  34. // 获取声部
  35. const getSubjects = async () => {
  36. try {
  37. const { data } = await request.post('/api-school/subjectBasicConfig/page', {
  38. data: {
  39. page: 1,
  40. rows: 50
  41. }
  42. })
  43. state.subjectList = data.rows || []
  44. state.subjectList.unshift({
  45. subjectId: '',
  46. subjectName: '全部声部'
  47. })
  48. } catch {
  49. //
  50. }
  51. }
  52. // api-school/schoolWeekSalaryRecord/detailInfo/trainingPage
  53. const getList = async () => {
  54. try {
  55. if (state.isClick) return
  56. state.isClick = true
  57. const res = await request.post(
  58. '/api-school/schoolWeekSalaryRecord/detailInfo/trainingPage',
  59. {
  60. data: {
  61. ...state.params,
  62. id: route.query.id
  63. }
  64. }
  65. )
  66. state.listState.loading = false
  67. state.listState.refreshing = false
  68. const result = res.data || {}
  69. console.log(result)
  70. // 处理重复请求数据
  71. if (state.list.length > 0 && result.current === 1) {
  72. return
  73. }
  74. const rows = result.rows || []
  75. rows.forEach((item: any) => {
  76. item.subjectNameList = item.subjectNames ? item.subjectNames.split(',') : []
  77. })
  78. state.list = state.list.concat(rows || [])
  79. state.listState.finished = result.current >= result.pages
  80. state.params.page = result.current + 1
  81. state.listState.dataShow = state.list.length > 0
  82. state.isClick = false
  83. } catch {
  84. state.listState.dataShow = false
  85. state.listState.finished = true
  86. state.listState.refreshing = false
  87. state.isClick = false
  88. }
  89. }
  90. const onRefresh = () => {
  91. state.params.page = 1
  92. state.list = []
  93. state.listState.dataShow = true // 判断是否有数据
  94. state.listState.loading = false
  95. state.listState.finished = false
  96. getList()
  97. }
  98. onMounted(() => {
  99. getSubjects()
  100. getList()
  101. })
  102. return () => (
  103. <>
  104. <OHeader />
  105. <div class={styles.item}>
  106. <Cell center>
  107. {{
  108. title: () => (
  109. <div class={styles.itemTitle}>
  110. <div class={styles.titleLine}></div>
  111. <span>练习奖励</span>
  112. </div>
  113. )
  114. }}
  115. </Cell>
  116. <Grid class={styles.grid} columnNum={3} border={false}>
  117. <GridItem class={styles.gridBorderRight}>
  118. <div class={styles.gridItem}>
  119. <div class={styles.gridItemTop}>
  120. <span class={styles.topNum} style={{ color: '#333' }}>
  121. 0
  122. </span>
  123. 元/人
  124. </div>
  125. <div>奖励标准</div>
  126. </div>
  127. </GridItem>
  128. <GridItem class={styles.gridBorderRight}>
  129. <div class={styles.gridItem}>
  130. <div class={styles.gridItemTop}>
  131. <span class={styles.topNum} style={{ color: '#333' }}>
  132. 0
  133. </span>
  134. </div>
  135. <div>练习达标人数</div>
  136. </div>
  137. </GridItem>
  138. <GridItem>
  139. <div class={styles.gridItem}>
  140. <div class={styles.gridItemTop}>
  141. <span class={styles.topNum}>0</span>元
  142. </div>
  143. <div>奖励金额</div>
  144. </div>
  145. </GridItem>
  146. </Grid>
  147. </div>
  148. <div class={'searchGroup-single'} style="padding-top: 0;">
  149. <div
  150. class={['searchItem', state.subjectStatus && styles['searchItem--active']]}
  151. onClick={() => {
  152. state.subjectStatus = !state.subjectStatus
  153. }}
  154. >
  155. {state.subjectName}
  156. </div>
  157. </div>
  158. {state.listState.dataShow ? (
  159. <OFullRefresh
  160. v-model:modelValue={state.listState.refreshing}
  161. onRefresh={onRefresh}
  162. style={{
  163. minHeight: 'auto' //`calc(100vh - ${state.listState.height}px)`
  164. }}
  165. >
  166. <List
  167. // v-model:loading={state.listState.loading}
  168. finished={state.listState.finished}
  169. finishedText=" "
  170. class={[styles.liveList]}
  171. onLoad={getList}
  172. immediateCheck={false}
  173. >
  174. <CellGroup inset class={styles.cellGroup}>
  175. {state.list.map((item: any) => (
  176. <Cell center>
  177. {{
  178. icon: () => <Image src={item.avatar || iconStudent} class={styles.img} />,
  179. title: () => (
  180. <div class={styles.userInfo}>
  181. <div class={styles.userName}>{item.nickname}</div>
  182. <div class={styles.subjectNames}>
  183. {item.subjectNameList.map((item: any) => (
  184. <Tag type="primary">{item}</Tag>
  185. ))}
  186. </div>
  187. </div>
  188. ),
  189. value: () => (
  190. <div class={styles.mins}>
  191. <div class={styles.nums}>
  192. <span>{item.practiceTimes}</span> 分钟
  193. </div>
  194. <div class={styles.text}>练习时长</div>
  195. </div>
  196. )
  197. }}
  198. </Cell>
  199. ))}
  200. </CellGroup>
  201. </List>
  202. </OFullRefresh>
  203. ) : (
  204. <OEmpty btnStatus={false} tips="暂无数据" />
  205. )}
  206. <Popup
  207. v-model:show={state.subjectStatus}
  208. position="bottom"
  209. round
  210. class={'popupBottomSearch'}
  211. >
  212. <Picker
  213. columns={state.subjectList}
  214. onCancel={() => (state.subjectStatus = false)}
  215. onConfirm={(val: any) => {
  216. console.log(val)
  217. const selectOptions = val.selectedOptions[0]
  218. state.subjectName = selectOptions.subjectName
  219. state.params.subjectId = selectOptions.subjectId
  220. onRefresh()
  221. state.subjectStatus = false
  222. }}
  223. columnsFieldNames={{ text: 'subjectName', value: 'subjectId' }}
  224. />
  225. </Popup>
  226. </>
  227. )
  228. }
  229. })