teacher-follow.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. import { Cell, Dialog, Icon, Image, List, Rate, Sticky, Toast } from 'vant'
  2. import { defineComponent } from 'vue'
  3. import styles from './model/teacher-header.module.less'
  4. import iconTeacher from '@common/images/icon_teacher.png'
  5. import musicCert from '@common/images/music_cert.png'
  6. import teacherCert from '@common/images/teacher_cert.png'
  7. import request from '@/helpers/request'
  8. import ColResult from '@/components/col-result'
  9. import { postMessage } from '@/helpers/native-message'
  10. import ColSearch from '@/components/col-search'
  11. import IconXueli from '@common/images/icon-xueli.png'
  12. import IconJiaozi from '@common/images/icon-jiaozi.png'
  13. import dayjs from 'dayjs'
  14. export const getAssetsHomeFile = (fileName: string) => {
  15. const path = `./images/${fileName}`
  16. const modules = import.meta.globEager('./images/*')
  17. return modules[path].default
  18. }
  19. export default defineComponent({
  20. name: 'teacher-follow',
  21. data() {
  22. return {
  23. userInfo: {} as any,
  24. starGrade: 0,
  25. subjectNameList: [],
  26. list: [],
  27. dataShow: true, // 判断是否有数据
  28. loading: false,
  29. finished: false,
  30. params: {
  31. username: '',
  32. page: 1,
  33. rows: 20
  34. }
  35. }
  36. },
  37. mounted() {
  38. this.getList()
  39. },
  40. methods: {
  41. getSubjectNameList(subject: string) {
  42. const subjectList = subject.split(',')
  43. return subjectList || []
  44. },
  45. onSearch(val: string) {
  46. this.params.username = val
  47. this.onSort()
  48. },
  49. onSort() {
  50. this.params.page = 1
  51. this.list = []
  52. this.dataShow = true // 判断是否有数据
  53. this.loading = false
  54. this.finished = false
  55. this.getList()
  56. },
  57. async getList() {
  58. try {
  59. const params = this.params
  60. const res = await request.post('/api-student/student/queryMyFollow', {
  61. data: {
  62. ...params
  63. }
  64. })
  65. this.loading = false
  66. const result = res.data || {}
  67. // 处理重复请求数据
  68. if (this.list.length > 0 && result.pageNo === 1) {
  69. return
  70. }
  71. this.list = this.list.concat(result.rows || [])
  72. this.finished = result.pageNo >= result.totalPage
  73. this.params.page = result.pageNo + 1
  74. this.dataShow = this.list.length > 0
  75. } catch {
  76. this.dataShow = false
  77. this.finished = true
  78. }
  79. },
  80. async onUnLike(item: any) {
  81. Dialog.confirm({
  82. message: '确定取消关注吗?',
  83. confirmButtonColor: 'var(--van-primary)'
  84. }).then(async () => {
  85. try {
  86. await request.get('/api-student/teacher/starOrUnStar', {
  87. params: {
  88. userId: item.userId,
  89. starStatus: 0
  90. }
  91. })
  92. Toast('取消关注成功')
  93. setTimeout(() => {
  94. this.onSort()
  95. }, 1000)
  96. } catch {}
  97. })
  98. },
  99. // 检验是否有对应徽章
  100. checkBadge(type: string, item: any) {
  101. // tag : 老师点亮图标
  102. // STYLE:个人风采
  103. // VIDEO:视频课
  104. // LIVE:直播课,
  105. // MUSIC:曲目 逗号隔开
  106. let status = false
  107. switch (type) {
  108. case 'STYLE':
  109. case 'VIDEO':
  110. case 'LIVE':
  111. case 'MUSIC':
  112. if (item.tag) {
  113. status = item.tag.indexOf(type) > -1
  114. }
  115. break
  116. case 'VIP':
  117. if (item.membershipStartTime && item.membershipEndTime) {
  118. const startTime = dayjs(item.membershipStartTime).valueOf()
  119. const endTime = dayjs(item.membershipEndTime).valueOf()
  120. const nowTime = dayjs().valueOf()
  121. status = nowTime >= startTime && nowTime <= endTime
  122. } else {
  123. status = false
  124. }
  125. break
  126. case 'DEGREE':
  127. case 'TEACHER':
  128. status = item.tag.includes(type)
  129. break
  130. default:
  131. status = false
  132. break
  133. }
  134. return status
  135. }
  136. },
  137. render() {
  138. return (
  139. <div class={styles.teacherFollow}>
  140. <Sticky position="top" offsetTop={0}>
  141. <ColSearch onSearch={this.onSearch} />
  142. </Sticky>
  143. {this.dataShow ? (
  144. <List
  145. class={styles.liveList}
  146. v-model:loading={this.loading}
  147. immediateCheck={false}
  148. finished={this.finished}
  149. finishedText="没有更多了"
  150. >
  151. {this.list.map((item: any) => (
  152. <div
  153. class={[styles.headerCount, styles.headerFollow]}
  154. onClick={(e: MouseEvent) => {
  155. e.stopPropagation()
  156. sessionStorage.removeItem('teacherHomeTabs')
  157. this.$router.push({
  158. path: '/teacherHome',
  159. query: {
  160. teacherId: item.userId,
  161. tabs: 'single'
  162. }
  163. })
  164. }}
  165. >
  166. <div class={styles.followContainer}>
  167. <div class={styles.teacherContent}>
  168. <div
  169. class={styles.teacherIcon}
  170. onClick={e => {
  171. // 判断是否在直播中
  172. if (item.liveFlag === 1) {
  173. e.stopPropagation()
  174. postMessage({
  175. api: 'joinLiveRoom',
  176. content: {
  177. roomId: item.roomUid,
  178. teacherId: item.userId
  179. }
  180. })
  181. }
  182. }}
  183. >
  184. <Image
  185. class={[
  186. styles.avatar,
  187. this.checkBadge('VIP', item.teacher) &&
  188. styles.avatarActive
  189. ]}
  190. round
  191. src={item.avatar || iconTeacher}
  192. fit="cover"
  193. />
  194. {item.liveFlag === 1 && (
  195. <p class={styles.liveTag}>直播中</p>
  196. )}
  197. <Image
  198. class={styles.teacherIconVip}
  199. src={
  200. this.checkBadge('VIP', item.teacher)
  201. ? getAssetsHomeFile('vip_active.png')
  202. : getAssetsHomeFile('vip_default.png')
  203. }
  204. />
  205. </div>
  206. </div>
  207. <div>
  208. <div class={styles.teacherInfo}>
  209. <div class={styles.teacherInfoName}>
  210. {item.userName || `游客${item.userId || ''}`}
  211. </div>
  212. {this.checkBadge('TEACHER', item.teacher) && (
  213. <img src={IconXueli} />
  214. )}
  215. {this.checkBadge('DEGREE', item.teacher) && (
  216. <img src={IconJiaozi} />
  217. )}
  218. </div>
  219. <div class={styles.teacherHonor}>
  220. <div>勋章:</div>
  221. <div class={styles.teacherIcons}>
  222. <Image
  223. class={styles.iconOther}
  224. src={
  225. this.checkBadge('STYLE', item.teacher)
  226. ? getAssetsHomeFile('cert_active.png')
  227. : getAssetsHomeFile('cert_default.png')
  228. }
  229. />
  230. <Image
  231. class={styles.iconOther}
  232. src={
  233. this.checkBadge('VIDEO', item.teacher)
  234. ? getAssetsHomeFile('video_active.png')
  235. : getAssetsHomeFile('video_default.png')
  236. }
  237. />
  238. <Image
  239. class={styles.iconOther}
  240. src={
  241. this.checkBadge('LIVE', item.teacher)
  242. ? getAssetsHomeFile('live_active.png')
  243. : getAssetsHomeFile('live_default.png')
  244. }
  245. />
  246. <Image
  247. class={styles.iconOther}
  248. src={
  249. this.checkBadge('MUSIC', item.teacher)
  250. ? getAssetsHomeFile('music_active.png')
  251. : getAssetsHomeFile('music_default.png')
  252. }
  253. />
  254. </div>
  255. <div class={styles.score}>评分: </div>
  256. <div class={styles.level}>
  257. {this.starGrade ? (
  258. <Rate
  259. readonly
  260. modelValue={this.starGrade}
  261. iconPrefix="iconfont"
  262. color="#FFC459"
  263. void-icon="star_default"
  264. icon="star_active"
  265. size={15}
  266. />
  267. ) : (
  268. <span style={{ fontSize: '12px', color: '#999999' }}>
  269. 暂无评分
  270. </span>
  271. )}
  272. </div>
  273. </div>
  274. <div class={styles.piNameSubject}>
  275. <Image
  276. class={styles.subjectSection}
  277. src={getAssetsHomeFile('icon_subject.png')}
  278. fit="contain"
  279. />
  280. <div class={styles.subjectList}>
  281. {this.getSubjectNameList(item.subjectName).map(
  282. (item: any) => (
  283. <span class={styles.subject}>{item}</span>
  284. )
  285. )}
  286. </div>
  287. </div>
  288. </div>
  289. </div>
  290. <div class={styles['teacher-bottom']}>
  291. <div class={styles['teacher-data']}>
  292. <div class={styles['teacher-data_item']}>
  293. 粉丝 <span>{item.fansNum || 0}</span>
  294. </div>
  295. <div class={styles['teacher-data_item']}>
  296. 已上课时 <span>{item.expTime || 0}</span>
  297. </div>
  298. </div>
  299. <div
  300. class={styles.unlinkeBtn}
  301. onClick={(e: MouseEvent) => {
  302. e.stopPropagation()
  303. this.onUnLike(item)
  304. }}
  305. >
  306. 取消关注
  307. </div>
  308. </div>
  309. </div>
  310. ))}
  311. </List>
  312. ) : (
  313. <ColResult btnStatus={false} classImgSize="SMALL" tips="暂无关注" />
  314. )}
  315. </div>
  316. )
  317. }
  318. })