companion-detail.tsx 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. import OHeader from '@/components/o-header'
  2. import {
  3. Button,
  4. Cell,
  5. CellGroup,
  6. Grid,
  7. GridItem,
  8. Icon,
  9. Image,
  10. Popup,
  11. showDialog,
  12. showToast,
  13. Tag
  14. } from 'vant'
  15. import { defineComponent, onMounted, reactive } from 'vue'
  16. import styles from './companion-detail.module.less'
  17. import { postMessage } from '@/helpers/native-message'
  18. import iconTeacher from '@common/images/icon_teacher.png'
  19. import iconMessage from '@common/images/icon-message.png'
  20. import iconCallPhone from '@common/images/icon-call-phone.png'
  21. import iconCallMessage from '@common/images/icon-call-message.png'
  22. import OSticky from '@/components/o-sticky'
  23. import request from '@/helpers/request'
  24. import { state as baseState } from '@/state'
  25. import { useRoute, useRouter } from 'vue-router'
  26. import OEmpty from '@/components/o-empty'
  27. export default defineComponent({
  28. name: 'companion-detail',
  29. setup(props, { slots, attrs, emit }) {
  30. const route = useRoute()
  31. const router = useRouter()
  32. const state = reactive({
  33. showMessage: false,
  34. detail: {} as any,
  35. classList: [] as any
  36. })
  37. const getDetail = async () => {
  38. try {
  39. const query = route.query
  40. const { data } = await request.post('/api-school/teacher/detail', {
  41. data: {
  42. teacherId: query.id,
  43. schoolId: baseState.user.data.school.id
  44. }
  45. })
  46. state.detail = data
  47. const subjects = data.subjectName ? data.subjectName.split(',') : []
  48. state.detail.subjectNames = subjects
  49. } catch {
  50. //
  51. }
  52. }
  53. const getClassDetail = async () => {
  54. try {
  55. const query = route.query
  56. const { data } = await request.post('/api-school/classGroup/page', {
  57. data: {
  58. teacherId: query.id,
  59. schoolId: baseState.user.data.school.id,
  60. page: 1,
  61. rows: 100
  62. }
  63. })
  64. state.classList = data.rows || []
  65. } catch {
  66. //
  67. }
  68. }
  69. const onDetail = async () => {
  70. if (state.classList.length > 0) {
  71. router.push({
  72. path: '/companion-unbind',
  73. query: { id: route.query.id }
  74. })
  75. return
  76. }
  77. try {
  78. showDialog({
  79. title: '提示',
  80. message: '是否解除绑定',
  81. showCancelButton: true
  82. }).then(async () => {
  83. await request.post('/api-school/classGroup/handoverTeacher', {
  84. data: {
  85. teacherId: route.query.id
  86. }
  87. })
  88. setTimeout(() => {
  89. showToast('解绑成功')
  90. }, 100)
  91. setTimeout(() => {
  92. router.back()
  93. }, 1000)
  94. })
  95. } catch {
  96. //
  97. }
  98. }
  99. onMounted(() => {
  100. getDetail()
  101. getClassDetail()
  102. })
  103. return () => (
  104. <>
  105. <OHeader />
  106. <CellGroup inset class={styles.detailCellGroup}>
  107. <Cell center class={styles.detailCell}>
  108. {{
  109. icon: () => <Image class={styles.img} src={state.detail.avatar || iconTeacher} />,
  110. title: () => (
  111. <div class={styles.teacherContent}>
  112. <div class={styles.content}>
  113. <p class={[styles.name, 'van-ellipsis']}>{state.detail.nickname}</p>
  114. {state.detail.subjectName ? (
  115. <p class={styles.subjects}>
  116. {state.detail.subjectNames.map((subject: any) => (
  117. <Tag type="primary">{subject}</Tag>
  118. ))}
  119. </p>
  120. ) : (
  121. ''
  122. )}
  123. </div>
  124. <div class={styles.classNum}>
  125. <p class={styles.num}>
  126. {state.detail.completedCourseScheduleNum || 0}/
  127. {state.detail.totalCourseScheduleNum || 0}
  128. </p>
  129. <p class={styles.numText}>课时</p>
  130. </div>
  131. </div>
  132. ),
  133. value: () => (
  134. <Image
  135. class={styles.messageImg}
  136. src={iconMessage}
  137. onClick={() => (state.showMessage = true)}
  138. />
  139. )
  140. }}
  141. </Cell>
  142. </CellGroup>
  143. <div class={styles.sectionTitle}>
  144. <i></i>
  145. 基本信息
  146. </div>
  147. <CellGroup inset class={styles.detailCellGroup}>
  148. <Cell title="手机号码" value={state.detail.phone}></Cell>
  149. <Cell title="性别" value={state.detail.gender ? '男' : '女'}></Cell>
  150. <Cell title="声部" value={state.detail.subjectName}></Cell>
  151. </CellGroup>
  152. <div class={styles.sectionTitle}>
  153. <i></i>
  154. 所在班级
  155. </div>
  156. <CellGroup inset class={styles.detailCellGroup}>
  157. {state.classList.map((item: any) => (
  158. <Cell center class={styles.companionCell}>
  159. {{
  160. title: () => (
  161. <div class={styles.classInfo}>
  162. <p class={styles.className}>{item.name}</p>
  163. <p class={styles.musicName}>{item.orchestraName}</p>
  164. </div>
  165. ),
  166. value: () => (
  167. <div class={styles.num}>
  168. <p class={styles.nums}>
  169. {item.completeCourseScheduleNum}/{item.courseScheduleNum}
  170. </p>
  171. <p class={styles.numTip}>总课时</p>
  172. </div>
  173. )
  174. }}
  175. </Cell>
  176. ))}
  177. {state.classList.length <= 0 && <OEmpty btnStatus={false} tips="暂无班级" />}
  178. </CellGroup>
  179. <OSticky position="bottom">
  180. <div class={['btnGroup']} style={{ paddingLeft: '13px', paddingRight: '13px' }}>
  181. <Button type="primary" round block onClick={onDetail}>
  182. 解除绑定
  183. </Button>
  184. </div>
  185. </OSticky>
  186. <Popup
  187. v-model:show={state.showMessage}
  188. position="bottom"
  189. style={{ background: 'transparent' }}
  190. safeAreaInsetBottom={true}
  191. >
  192. <div class={styles.codeContainer}>
  193. <div class={styles.codeBottom}>
  194. <Icon
  195. name="cross"
  196. size={22}
  197. class={styles.close}
  198. color="#666"
  199. onClick={() => (state.showMessage = false)}
  200. />
  201. <h3 class={styles.title}>
  202. <i></i>联系方式
  203. </h3>
  204. <Grid columnNum={2} border={false}>
  205. <GridItem
  206. onClick={() => {
  207. postMessage({
  208. api: 'joinChatGroup',
  209. content: {
  210. type: 'single', // single 单人 multi 多人
  211. id: state.detail.id
  212. }
  213. })
  214. state.showMessage = false
  215. }}
  216. >
  217. {{
  218. icon: () => <Image class={styles.shareImg} src={iconCallMessage} />,
  219. text: () => <div class={styles.shareText}>发送消息</div>
  220. }}
  221. </GridItem>
  222. <GridItem
  223. onClick={() => {
  224. postMessage({
  225. api: 'callPhone',
  226. content: {
  227. id: state.detail.phone
  228. }
  229. })
  230. state.showMessage = false
  231. }}
  232. >
  233. {{
  234. icon: () => <Image class={styles.shareImg} src={iconCallPhone} />,
  235. text: () => <div class={styles.shareText}>拨打电话</div>
  236. }}
  237. </GridItem>
  238. </Grid>
  239. </div>
  240. </div>
  241. </Popup>
  242. </>
  243. )
  244. }
  245. })