teacher-header.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. import { Button, Cell, Icon, Image, Popup, Rate, Toast } from 'vant'
  2. import { defineComponent } from 'vue'
  3. import styles from './teacher-header.module.less'
  4. import { postMessage } from '@/helpers/native-message'
  5. import iconTeacher from '@common/images/icon_teacher.png'
  6. import request from '@/helpers/request'
  7. import IconXueli from '@common/images/icon-xueli.png'
  8. import IconJiaozi from '@common/images/icon-jiaozi.png'
  9. import IconChat from '../images/icon-chat.png'
  10. export const getAssetsHomeFile = (fileName: string) => {
  11. const path = `../images/${fileName}`
  12. const modules = import.meta.globEager('../images/*')
  13. return modules[path].default
  14. }
  15. export default defineComponent({
  16. name: 'teacher-header',
  17. props: {
  18. userInfo: {
  19. type: Object,
  20. default: () => ({})
  21. },
  22. teacherId: {
  23. type: String || Number,
  24. default: ''
  25. }
  26. },
  27. emits: ['star'],
  28. data() {
  29. return {
  30. iconShow: false
  31. }
  32. },
  33. computed: {
  34. subjectNameList() {
  35. const userInfo: any = this.userInfo
  36. const subjectName = userInfo.subjectName
  37. return subjectName ? subjectName.split(',') : []
  38. },
  39. starGrade() {
  40. const { starGrade } = this.userInfo as any
  41. return Number(starGrade) || 0
  42. }
  43. },
  44. methods: {
  45. async onStart() {
  46. // 关注与取消关注
  47. try {
  48. const star = this.userInfo.isStar ? 0 : 1
  49. await request.get('/api-student/teacher/starOrUnStar', {
  50. params: {
  51. userId: this.teacherId,
  52. starStatus: star
  53. }
  54. })
  55. // const str = star ? '关注成功' : '已取消关注'
  56. // this.userInfo.isStar = star
  57. const count = star
  58. ? this.userInfo.fansNum + 1
  59. : this.userInfo.fansNum - 1
  60. // this.userInfo.fansNum = count <= 0 ? 0 : count
  61. this.$emit('star', {
  62. isStar: star,
  63. fansNum: count <= 0 ? 0 : count
  64. })
  65. // Toast(str)
  66. } catch {
  67. //
  68. }
  69. },
  70. // 检验是否有对应徽章
  71. checkBadge(type: string) {
  72. // tag : 老师点亮图标
  73. // STYLE:个人风采
  74. // VIDEO:视频课
  75. // LIVE:直播课,
  76. // MUSIC:曲目 逗号隔开
  77. let status = false
  78. const { userInfo } = this
  79. switch (type) {
  80. case 'STYLE':
  81. case 'VIDEO':
  82. case 'LIVE':
  83. case 'MUSIC':
  84. if (userInfo.tag) {
  85. status = userInfo.tag.indexOf(type) > -1
  86. }
  87. break
  88. case 'VIP':
  89. status = userInfo.userVip?.vipType === 'VIP'
  90. break
  91. case 'SVIP':
  92. status =
  93. userInfo.userVip?.vipType === 'SVIP' ||
  94. userInfo.userVip?.vipType === 'PERMANENT_SVIP'
  95. break
  96. default:
  97. status = false
  98. break
  99. }
  100. return status
  101. },
  102. openTeacherIcon() {
  103. this.iconShow = true
  104. }
  105. },
  106. render() {
  107. const iconList = [
  108. {
  109. icon: 'cert_active.png',
  110. title: '演奏Mlog达人',
  111. des: '个人风采中上传老师风采视频并通过审核'
  112. },
  113. {
  114. icon: 'video_active.png',
  115. title: '教学视频达人',
  116. des: '发布您制作的教学视频课程并通过审核'
  117. },
  118. {
  119. icon: 'live_active.png',
  120. title: '直播up达人',
  121. des: '达到开通直播权限标准并开通直播功能'
  122. },
  123. {
  124. icon: 'music_active.png',
  125. title: '乐谱歌单达人',
  126. des: '上传您制作的乐谱并通过审核'
  127. }
  128. ]
  129. return (
  130. <>
  131. <div class={styles.headerContent}>
  132. <div class={styles.headerCount}>
  133. <div class={styles.teacherContent}>
  134. <div
  135. class={styles.teacherIcon}
  136. onClick={() => {
  137. // 判断是否在直播中
  138. if (this.userInfo.liveing === 1) {
  139. postMessage({
  140. api: 'joinLiveRoom',
  141. content: {
  142. roomId: this.userInfo.roomUid,
  143. teacherId: this.userInfo.userId
  144. }
  145. })
  146. }
  147. }}
  148. >
  149. {/* iy */}
  150. <Image
  151. class={[
  152. styles.avatar,
  153. (this.checkBadge('SVIP') || this.checkBadge('VIP')) &&
  154. styles.avatarActive
  155. ]}
  156. round
  157. src={this.userInfo.heardUrl || iconTeacher}
  158. fit="cover"
  159. />
  160. {this.userInfo.liveing === 1 && (
  161. <p class={styles.liveTag}>直播中</p>
  162. )}
  163. {(this.checkBadge('SVIP') || this.checkBadge('VIP')) && (
  164. <Image
  165. class={styles.teacherIconVip}
  166. src={
  167. this.checkBadge('SVIP')
  168. ? getAssetsHomeFile('svip_active.png')
  169. : this.checkBadge('VIP')
  170. ? getAssetsHomeFile('vip_active.png')
  171. : ''
  172. }
  173. />
  174. )}
  175. </div>
  176. <div class={styles.teacherOperation}>
  177. <Button
  178. type="primary"
  179. size="small"
  180. plain
  181. round
  182. class={[
  183. styles.btn,
  184. this.userInfo.isStar ? styles.btnStar : ''
  185. ]}
  186. onClick={this.onStart}
  187. >
  188. {/* {!this.userInfo.isStar && <Icon name="plus" />} */}
  189. {this.userInfo.isStar ? '已关注' : '关注'}
  190. </Button>
  191. <Button
  192. type="primary"
  193. size="small"
  194. round
  195. style={{ marginLeft: '5px' }}
  196. class={styles.btn}
  197. icon={IconChat}
  198. onClick={() => {
  199. postMessage({
  200. api: 'joinChatGroup',
  201. content: {
  202. type: 'single', // single 单人 multi 多人
  203. id: this.userInfo.imUserId
  204. // id: this.teacherId
  205. }
  206. })
  207. }}
  208. >
  209. {/* <Icon name={} size="16" style={{ marginRight: '3px' }} /> */}
  210. 聊天
  211. </Button>
  212. </div>
  213. </div>
  214. <div class={styles.teacherInfo}>
  215. <div class={styles.teacherInfoName}>
  216. {this.userInfo.username || `游客${this.userInfo.userId || ''}`}
  217. </div>
  218. {this.userInfo.degreeFlag ? <img src={IconXueli} /> : null}
  219. {this.userInfo.teacherFlag ? <img src={IconJiaozi} /> : null}
  220. </div>
  221. <div class={styles.teacherHonor}>
  222. <div>勋章:</div>
  223. <div class={styles.teacherIcons} onClick={this.openTeacherIcon}>
  224. <Image
  225. class={styles.iconOther}
  226. src={
  227. this.checkBadge('STYLE')
  228. ? getAssetsHomeFile('cert_active.png')
  229. : getAssetsHomeFile('cert_default.png')
  230. }
  231. />
  232. <Image
  233. class={styles.iconOther}
  234. src={
  235. this.checkBadge('VIDEO')
  236. ? getAssetsHomeFile('video_active.png')
  237. : getAssetsHomeFile('video_default.png')
  238. }
  239. />
  240. <Image
  241. class={styles.iconOther}
  242. src={
  243. this.checkBadge('LIVE')
  244. ? getAssetsHomeFile('live_active.png')
  245. : getAssetsHomeFile('live_default.png')
  246. }
  247. />
  248. <Image
  249. class={styles.iconOther}
  250. src={
  251. this.checkBadge('MUSIC')
  252. ? getAssetsHomeFile('music_active.png')
  253. : getAssetsHomeFile('music_default.png')
  254. }
  255. />
  256. </div>
  257. <div class={styles.score}>评分:</div>
  258. <div class={styles.level}>
  259. {this.starGrade ? (
  260. <Rate
  261. readonly
  262. modelValue={this.starGrade}
  263. iconPrefix="iconfont"
  264. color="#FFC459"
  265. void-icon="star_default"
  266. icon="star_active"
  267. size={15}
  268. />
  269. ) : (
  270. <span style={{ fontSize: '12px', color: '#999999' }}>
  271. 暂无评分
  272. </span>
  273. )}
  274. </div>
  275. </div>
  276. <div class={styles.piNameSubject}>
  277. <Image
  278. class={styles.subjectSection}
  279. src={getAssetsHomeFile('icon_subject.png')}
  280. fit="contain"
  281. />
  282. <div class={styles.subjectList}>
  283. {this.subjectNameList.map((item: any) => (
  284. <span class={styles.subject}>{item}</span>
  285. ))}
  286. </div>
  287. </div>
  288. <div class={styles['teacher-bottom']}>
  289. <div class={styles['teacher-data']}>
  290. <div class={styles['teacher-data_item']}>
  291. 粉丝 <span>{this.userInfo.fansNum || 0}</span>
  292. </div>
  293. <div class={styles['teacher-data_item']}>
  294. 已上课时 <span>{this.userInfo.expTime || 0}</span>
  295. </div>
  296. </div>
  297. </div>
  298. </div>
  299. </div>
  300. <Popup class={styles['teaherPopup']} v-model:show={this.iconShow}>
  301. <Image src={getAssetsHomeFile('teacher-icon.png')} />
  302. <div class={styles.teacherIconWrap}>
  303. {iconList.map(n => {
  304. return (
  305. <div class={styles.teacherIconItem}>
  306. <div class={styles.teacherIconItemTop}>
  307. <Image src={getAssetsHomeFile(n.icon)} />
  308. <div class={styles.teacherIconTitle}>{n.title}</div>
  309. </div>
  310. <div class={styles.teacherIconDes}>{n.des}</div>
  311. </div>
  312. )
  313. })}
  314. </div>
  315. <Image
  316. onClick={() => (this.iconShow = false)}
  317. class={styles.closeIcon}
  318. src={getAssetsHomeFile('icon-close.png')}
  319. />
  320. </Popup>
  321. </>
  322. )
  323. }
  324. })