index.tsx 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. import { defineComponent } from 'vue'
  2. import styles from './index.module.less'
  3. import ColHeader from '@/components/col-header'
  4. import {
  5. Button,
  6. Icon,
  7. Popup,
  8. RadioGroup,
  9. Sticky,
  10. Radio,
  11. Tag,
  12. List,
  13. ActionSheet
  14. } from 'vant'
  15. import ColSearch from '@/components/col-search'
  16. import PracticeItem from './practice-item'
  17. import request from '@/helpers/request'
  18. import ColResult from '@/components/col-result'
  19. import AllSearch from './model/all-search'
  20. import OrganSearch from './model/organ-search'
  21. import { state } from '@/state'
  22. import { useRect } from '@vant/use'
  23. // {"subjectId":null,"search":"","sort":"starGrade ASC,expTime DESC,subjectPrice DESC"}
  24. const actions = [
  25. {
  26. name: '不限制',
  27. value: '',
  28. color: 'var(--van-primary)'
  29. },
  30. {
  31. name: '单价最高',
  32. value: 'subjectPrice DESC',
  33. color: '#333'
  34. },
  35. {
  36. name: '单价最低',
  37. value: 'subjectPrice ASC',
  38. color: '#333'
  39. },
  40. {
  41. name: '课时数最多',
  42. value: 'expTime DESC',
  43. color: '#333'
  44. },
  45. {
  46. name: '评分最高',
  47. value: 'starGrade DESC',
  48. color: '#333'
  49. }
  50. ]
  51. export default defineComponent({
  52. name: 'practiceClass',
  53. data() {
  54. return {
  55. openStatus: false,
  56. searchStatus: false,
  57. subjectList: [],
  58. list: [],
  59. dataShow: true, // 判断是否有数据
  60. loading: false,
  61. finished: false,
  62. searchType: 'organ' as 'organ' | 'all',
  63. tempSort: {
  64. starGrade: 'ALL',
  65. expTime: 'ALL',
  66. subjectPrice: 'ALL'
  67. },
  68. dataLoading: false,
  69. params: {
  70. search: '',
  71. sort: '',
  72. subjectName: '',
  73. isScreen: false,
  74. subjectId: null as any,
  75. page: 1,
  76. rows: 20
  77. },
  78. show: false,
  79. height: 'auto' as any
  80. }
  81. },
  82. async mounted() {
  83. this.params.subjectId = state.user.data?.subjectId || null
  84. this.params.subjectName = state.user.data?.subjectName || ''
  85. try {
  86. const res = await request.get('/api-student/subject/subjectSelect')
  87. this.subjectList = res.data || []
  88. } catch {}
  89. const { height } = useRect((this as any).$refs.headers)
  90. this.height = height
  91. this.getList()
  92. },
  93. methods: {
  94. onSearch(_search?: any) {
  95. this.params.search = _search
  96. this.onSort()
  97. },
  98. onSort() {
  99. this.params.page = 1
  100. this.list = []
  101. this.dataShow = true // 判断是否有数据
  102. this.loading = false
  103. this.finished = false
  104. this.searchStatus = false
  105. this.getList()
  106. },
  107. onSheetSelect(item: any) {
  108. actions.forEach((v: any) => {
  109. v.color = '#333'
  110. if (v.value === item.value) {
  111. v.color = 'var(--van-primary)'
  112. }
  113. })
  114. this.params.sort = item.value
  115. this.show = false
  116. this.onSort()
  117. },
  118. async getList() {
  119. try {
  120. if (this.dataLoading) {
  121. return
  122. }
  123. this.dataLoading = true
  124. const res = await request.post(
  125. '/api-student/courseSchedule/teacherList',
  126. {
  127. data: {
  128. ...this.params
  129. }
  130. }
  131. )
  132. this.dataLoading = false
  133. this.loading = false
  134. const result = res.data || {}
  135. // 处理重复请求数据
  136. if (this.list.length > 0 && result.pageNo === 1) {
  137. return
  138. }
  139. this.list = this.list.concat(result.rows || [])
  140. this.finished = result.pageNo >= result.totalPage
  141. this.params.page = result.pageNo + 1
  142. this.dataShow = this.list.length > 0
  143. } catch {
  144. this.dataShow = false
  145. this.finished = true
  146. }
  147. }
  148. },
  149. render() {
  150. return (
  151. <div style={{ overflow: 'hidden', minHeight: '100vh' }}>
  152. <Sticky
  153. class={'sticky'}
  154. offsetTop={0}
  155. style={{
  156. background: 'var(--van-primary)',
  157. height: this.height + 'px !important',
  158. width: '100%'
  159. }}
  160. >
  161. <div ref="headers">
  162. <ColHeader
  163. title="陪练课"
  164. isFixed={false}
  165. border={false}
  166. backIconColor="white"
  167. background="var(--van-primary)"
  168. color="#fff"
  169. />
  170. <ColSearch
  171. placeholder="请输入老师名称"
  172. inputBackground="white"
  173. background="var(--van-primary)"
  174. onSearch={this.onSearch}
  175. />
  176. <div class={styles.filterSection}>
  177. <div>
  178. <Button
  179. class={[styles.btn]}
  180. type="primary"
  181. size="small"
  182. round
  183. plain
  184. onClick={() => {
  185. this.searchStatus = !this.searchStatus
  186. this.openStatus = !this.openStatus
  187. this.searchType = 'organ'
  188. }}
  189. >
  190. {this.params.subjectName}
  191. <Icon
  192. classPrefix="iconfont"
  193. name="down"
  194. size={8}
  195. style={{ marginLeft: '4px' }}
  196. color="var(--van-primary)"
  197. />
  198. </Button>
  199. <Button
  200. class={[styles.btn]}
  201. size="small"
  202. type={this.params.isScreen ? 'primary' : 'default'}
  203. round
  204. plain
  205. onClick={() => {
  206. this.params.isScreen = !this.params.isScreen
  207. this.onSort()
  208. }}
  209. >
  210. 30天内未约满
  211. </Button>
  212. </div>
  213. <div>
  214. <div
  215. class={styles.dataItem}
  216. onClick={() => {
  217. this.show = true
  218. }}
  219. >
  220. 筛选
  221. <Icon
  222. classPrefix="iconfont"
  223. name="down"
  224. size={8}
  225. style={{ marginLeft: '4px' }}
  226. color="var(--van-primary)"
  227. />
  228. </div>
  229. </div>
  230. </div>
  231. </div>
  232. </Sticky>
  233. {this.dataShow ? (
  234. <List
  235. v-model:loading={this.loading}
  236. finished={this.finished}
  237. finishedText=" "
  238. immediateCheck={false}
  239. class={[styles.practiceList, 'mb12']}
  240. onLoad={this.getList}
  241. >
  242. {this.list.map((item: any) => (
  243. <PracticeItem
  244. item={item}
  245. onClick={() => {
  246. this.$router.push({
  247. path: '/teacherHome',
  248. query: {
  249. teacherId: item.teacherId,
  250. tabs: 'practice',
  251. subjectId: this.params.subjectId
  252. }
  253. })
  254. }}
  255. />
  256. ))}
  257. </List>
  258. ) : (
  259. <ColResult
  260. btnStatus={false}
  261. classImgSize="SMALL"
  262. tips="暂无陪练老师"
  263. />
  264. )}
  265. <ActionSheet
  266. v-model:show={this.show}
  267. actions={actions}
  268. cancelText="取消"
  269. onSelect={this.onSheetSelect}
  270. closeOnClickAction
  271. onCancel={() => (this.show = false)}
  272. />
  273. <Popup
  274. show={this.searchStatus}
  275. position="bottom"
  276. round
  277. closeable
  278. safe-area-inset-bottom
  279. onClose={() => (this.searchStatus = false)}
  280. onClosed={() => (this.openStatus = false)}
  281. >
  282. {/* {this.searchType === 'all' && <AllSearch onSort={this.onSort} />} */}
  283. {this.searchType === 'organ' && this.openStatus && (
  284. <OrganSearch
  285. subjectList={this.subjectList}
  286. onSort={this.onSort}
  287. v-model={this.params.subjectId}
  288. v-model:subjectName={this.params.subjectName}
  289. />
  290. )}
  291. </Popup>
  292. </div>
  293. )
  294. }
  295. })