trainDetail.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. <template>
  2. <div class="trainDetail">
  3. <van-sticky>
  4. <m-header v-if="headerStatus" :isFixed="false" />
  5. </van-sticky>
  6. <div class="evaluation">
  7. <van-cell style="padding: 16px 12px; background-color: transparent" :center="true">
  8. <template #title>
  9. <div class="teacher_info">
  10. <img class="logo" v-if="avatar" :src="avatar" alt="" />
  11. <img class="logo" v-else src="../../assets/images/icon_student.png" alt="" />
  12. <div class="teacher_content">
  13. <p style="color: #1a1a1a; font-size: .18rem;">{{ username }}</p>
  14. <p style="font-size: 14px; color: #333;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;width: 2.4rem;">{{ musicGroupName }}</p>
  15. </div>
  16. </div>
  17. </template>
  18. <!-- <p style="font-size: 14px; color: #808080;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;">{{ musicGroupName }}</p> -->
  19. </van-cell>
  20. </div>
  21. <van-row class="dataSearch" type="flex">
  22. <van-col span="9" offset="1">
  23. <van-cell @click="onChangeDate('showStart')" is-link>
  24. <template #right-icon>
  25. <van-icon :name="arrowIcon" class="search-icon" size="10" />
  26. </template>
  27. <template v-if="searchList.startTime">{{ searchList.startTime }}</template>
  28. <span v-else style="color: #adadad;">开始日期</span>
  29. </van-cell>
  30. </van-col>
  31. <van-col span="1" class="flexCenter">-</van-col>
  32. <van-col span="9">
  33. <van-cell @click="onChangeDate('showEnd')">
  34. <template #right-icon>
  35. <van-icon :name="arrowIcon" class="search-icon" size="10" />
  36. </template>
  37. <template v-if="searchList.endTime">{{ searchList.endTime }}</template>
  38. <span v-else style="color: #adadad;">结束日期</span>
  39. </van-cell>
  40. </van-col>
  41. <van-col span="4" class="flexCenter">
  42. <span class="btn-search" @click="onSearch">搜索</span>
  43. </van-col>
  44. </van-row>
  45. <van-popup v-model="dataForm.status" position="bottom" round :style="{ height: '40%' }">
  46. <van-datetime-picker
  47. v-model="dataForm.currentDate"
  48. :min-date="dataForm.minDate"
  49. :max-date="dataForm.maxDate"
  50. :formatter="formatter"
  51. @cancel="dataForm.status = false"
  52. type="date"
  53. @confirm="chioseDate"
  54. />
  55. </van-popup>
  56. <div class="specialList">
  57. <van-list v-model="loading" v-if="show" key="trainDetail"
  58. :finished="finished"
  59. finished-text="- 没有更多内容 -"
  60. :immediate-check="false"
  61. @load="getList()">
  62. <van-cell-group class="data-content" v-for="(item, index) in dataList" :key="index">
  63. <van-cell style="padding: 16px 12px; 12px" :center="true">
  64. <template #title>
  65. <span style="font-size: .17rem; color:#333333; font-weight: 500; padding-right: .05rem;padding-bottom: .05rem;">{{ item.sysMusicScoreName }}</span>
  66. <p style="font-size: 14px; color: #808080;">{{ item.createTime }}</p>
  67. </template>
  68. <p>
  69. <img v-if="getLevelByScore(item.score) == 1" class="scoreImg" src="./images/1.png" alt="">
  70. <img v-if="getLevelByScore(item.score) == 2" class="scoreImg" src="./images/2.png" alt="">
  71. <img v-if="getLevelByScore(item.score) == 3" class="scoreImg" src="./images/3.png" alt="">
  72. </p>
  73. </van-cell>
  74. <van-cell :clickable="false" center style="padding: 12px 12px 16px">
  75. <template #title>
  76. <van-grid :border="false" column-num="4" :clickable="true">
  77. <van-grid-item text="综合得分" class="van-hairline--right">
  78. <template #icon>{{ item.score }}分</template>
  79. </van-grid-item>
  80. <van-grid-item text="音准" class="van-hairline--right">
  81. <template #icon><span style="color: #01C1B5">{{ item.intonation }}分</span></template>
  82. </van-grid-item>
  83. <van-grid-item text="节奏" class="van-hairline--right">
  84. <template #icon><span style="color: #01C1B5">{{ item.cadence }}分</span></template>
  85. </van-grid-item>
  86. <van-grid-item text="完成度">
  87. <template #icon><span style="color: #FF802C">{{ item.integrity }}分</span></template>
  88. </van-grid-item>
  89. </van-grid>
  90. </template>
  91. </van-cell>
  92. </van-cell-group>
  93. </van-list>
  94. <m-empty v-else key="trainDetail" msg="暂无训练详情" />
  95. <div class="button-group">
  96. <van-button type="primary" size="large" round @click="addVisited">添加回访</van-button>
  97. <div class="placeholder-btn"></div>
  98. </div>
  99. </div>
  100. </div>
  101. </template>
  102. <script>
  103. import MHeader from "@/components/MHeader";
  104. import MEmpty from '@/components/MEmpty';
  105. import dayjs from "dayjs";
  106. import { browser } from "@/common/common";
  107. import { queryMusicCompareRecord } from './api.js'
  108. export default {
  109. components: { MHeader, MEmpty },
  110. data() {
  111. const query = this.$route.query
  112. return {
  113. arrowIcon: require('./images/arrow_down.png'),
  114. headerStatus: true,
  115. show: true,
  116. avatar: query.avatar,
  117. username: query.username,
  118. musicGroupName: query.musicGroupName,
  119. searchList: {
  120. startTime: null,
  121. endTime: null,
  122. userId: query.userId,
  123. page: 1,
  124. rows: 20
  125. },
  126. dataForm: {
  127. // 时间下拉框
  128. type: null,
  129. status: false,
  130. minDate: new Date(2000, 0, 1),
  131. maxDate: new Date(2030, 11, 31),
  132. currentDate: new Date(),
  133. },
  134. dataList: [],
  135. loading: false,
  136. finished: false,
  137. }
  138. },
  139. mounted() {
  140. if (browser().android || browser().iPhone) {
  141. this.headerStatus = false;
  142. }
  143. document.title = '评测详情'
  144. this.getList()
  145. },
  146. methods: {
  147. addVisited() {
  148. this.$router.push({
  149. path: '/addVisit',
  150. query: {
  151. ...this.$route.query,
  152. type: 'train',
  153. name: '新增回访记录'
  154. }
  155. })
  156. },
  157. async getList() {
  158. try {
  159. let res = await queryMusicCompareRecord(this.searchList)
  160. let result = res.data
  161. this.loading = false
  162. // 重点这句,判断是不是重复请求了
  163. if (this.dataList.length > 0 && result.pageNo == 1) {
  164. return;
  165. }
  166. let rows = result.rows || []
  167. this.dataList.push(...rows)
  168. if(this.searchList.page >= result.totalPage) {
  169. this.finished = true
  170. }
  171. this.searchList.page++
  172. if(this.dataList.length <= 0) {
  173. this.show = false
  174. }
  175. } catch {
  176. this.show = false
  177. this.finished = true
  178. }
  179. },
  180. onSearch() {
  181. if(!this.searchList.startTime) {
  182. this.$toast('请选择开始时间')
  183. return
  184. } else if(!this.searchList.endTime) {
  185. this.$toast('请选择结束时间')
  186. return
  187. }
  188. this.dataList = [] // 重置数据
  189. this.show = true
  190. this.loading = true
  191. this.finished = false
  192. this.searchList.page = 1
  193. this.getList()
  194. },
  195. onChangeDate(type) {
  196. let dataForm = this.dataForm
  197. if(type == 'showEnd' && this.searchList.startTime) {
  198. dataForm.minDate = new Date(dayjs(this.searchList.startTime))
  199. dataForm.maxDate = new Date(2030, 11, 31)
  200. setTimeout(() => {
  201. dataForm.currentDate = this.searchList.endTime ? new Date(dayjs(this.searchList.endTime)) : new Date()
  202. }, 500)
  203. } else if(type == 'showStart' && this.searchList.endTime) {
  204. dataForm.minDate = new Date(2000, 0, 1)
  205. dataForm.maxDate = new Date(dayjs(this.searchList.endTime))
  206. setTimeout(() => {
  207. dataForm.currentDate = this.searchList.startTime ? new Date(dayjs(this.searchList.startTime)) : new Date()
  208. }, 500)
  209. }
  210. dataForm.status = true
  211. dataForm.type = type
  212. },
  213. chioseDate(value) {
  214. let dataForm = this.dataForm
  215. if(dataForm.type == 'showStart') {
  216. this.searchList.startTime = dayjs(value).format('YYYY-MM-DD')
  217. } else if(dataForm.type == 'showEnd') {
  218. this.searchList.endTime = dayjs(value).format('YYYY-MM-DD')
  219. }
  220. dataForm.status = false
  221. },
  222. formatter(type, val) {
  223. if (type === "year") {
  224. return `${val}年`;
  225. } else if (type === "month") {
  226. return `${val}月`;
  227. } else if (type == "day") {
  228. return `${val}日`;
  229. }
  230. return val;
  231. },
  232. getLevelByScore(score) {
  233. let level = 3
  234. if (score > 60 && score <= 80) {
  235. level = 2
  236. } else if (score > 80) {
  237. level = 1
  238. }
  239. return level
  240. }
  241. }
  242. }
  243. </script>
  244. <style lang="less" scoped>
  245. .trainDetail {
  246. background: #f5f5f5;
  247. min-height: 100vh;
  248. overflow: hidden;
  249. }
  250. .evaluation {
  251. display: flex;
  252. align-items: center;
  253. margin: .12rem .12rem 0;
  254. height: 1.05rem;
  255. border-radius: .1rem;
  256. background: url('./images/user_bg.png') no-repeat center #fff;
  257. background-size: contain;
  258. .teacher_info {
  259. display: flex;
  260. align-items: center;
  261. img {
  262. margin-right: .15rem;
  263. width: .6rem;
  264. height: .6rem;
  265. border-radius: 50%;
  266. }
  267. }
  268. }
  269. .search-icon {
  270. display: flex;
  271. align-items: center;
  272. }
  273. .scoreImg {
  274. width: 66px;
  275. height: 25px;
  276. }
  277. .data-content {
  278. margin: .15rem .15rem 0;
  279. border-radius: .1rem;
  280. overflow: hidden;
  281. &:first-child {
  282. margin-top: 0;
  283. }
  284. .van-row-item {
  285. display: flex;
  286. align-items: center;
  287. }
  288. /deep/.van-grid-item__content {
  289. padding: .03rem
  290. }
  291. /deep/.van-grid-item__content {
  292. background-color: transparent;
  293. }
  294. /deep/.van-grid-item__icon-wrapper {
  295. font-size: .15rem;
  296. color: #000;
  297. }
  298. /deep/.van-grid-item__text {
  299. font-size: .14rem;
  300. color: #808080;
  301. }
  302. .teacher_info {
  303. display: flex;
  304. align-items: center;
  305. img {
  306. margin-right: .1rem;
  307. width: .4rem;
  308. height: .4rem;
  309. border-radius: 50%;
  310. }
  311. }
  312. }
  313. .specialList {
  314. padding-top: .1rem;
  315. padding-bottom: 65px;
  316. // padding-bottom: calc(env(safe-area-inset-bottom) / 2);
  317. }
  318. .dataSearch {
  319. padding: .12rem;
  320. background-color: #F5F5F5;
  321. /deep/.van-cell {
  322. background: #fff;
  323. padding: .05rem .16rem;
  324. border-radius: 1rem;
  325. overflow: hidden;
  326. height: .34rem;
  327. }
  328. /deep/.van-cell__value--alone {
  329. text-align: center;
  330. }
  331. .flexCenter {
  332. display: flex;
  333. align-items: center;
  334. justify-content: center;
  335. }
  336. .btn-search {
  337. background: #01C1B5;
  338. font-size: 14px;
  339. color: #fff;
  340. padding: 4px 9px;
  341. border-radius: 15px;
  342. }
  343. }
  344. .button-group {
  345. overflow: hidden;
  346. position: fixed;
  347. bottom: 0;
  348. width: calc(100% - .24rem);
  349. z-index: 9;
  350. margin: 0 .12rem 12px;
  351. .van-button--primary {
  352. background: #01C1B5;
  353. border: 1px solid #01C1B5;
  354. font-size: .16rem;
  355. float: right;
  356. // padding-bottom: calc(env(safe-area-inset-bottom) / 2);
  357. height: auto;
  358. line-height: 48px;
  359. }
  360. }
  361. </style>