order.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. <template>
  2. <div class="order">
  3. <header>缴费详情
  4. <van-dropdown-menu>
  5. <van-dropdown-item @change="onChange" v-model="voicyPart" :options="voicyPartList" />
  6. </van-dropdown-menu>
  7. </header>
  8. <h2>{{musicGroupName}}</h2>
  9. <van-tabs color="#14928a">
  10. <van-tab title="缴费信息">
  11. <div class="table">
  12. <div class="title">
  13. <span></span>
  14. <span>姓名</span>
  15. <span>声部</span>
  16. <span>支付金额</span>
  17. <span>到账时间</span>
  18. </div>
  19. <div class="content">
  20. <div v-for="(data, index) in dataList" :key="data.id">
  21. <!-- <div> -->
  22. <span> {{ ++index }} </span>
  23. <span> {{ data.userName }} </span>
  24. <span> {{ data.subjectName }} </span>
  25. <span> {{ data.paymentAmount }} </span>
  26. <span> {{ data.payTime }} </span>
  27. </div>
  28. <p style="padding: 8px 8px 20px">缴费总额:{{ (amountCount).toFixed(2) }}元</p>
  29. </div>
  30. </div>
  31. </van-tab>
  32. <van-tab title="报名信息">
  33. <div class="table">
  34. <div class="title">
  35. <span></span>
  36. <span>姓名</span>
  37. <span>班级</span>
  38. <span>声部</span>
  39. <span>备注</span>
  40. <span>调剂</span>
  41. </div>
  42. <div class="content">
  43. <div v-for="(data, index) in studentList" :key="data.id">
  44. <!-- <div> -->
  45. <span> {{ ++index }} </span>
  46. <span> {{ data.userName }} </span>
  47. <span> {{ data.currentClass }} </span>
  48. <span> {{ data.subjectName }} </span>
  49. <span> {{ data.remark }} </span>
  50. <span><van-button
  51. :disabled="data.paymentStatus == 2 ? true : false"
  52. round
  53. @click = "adjust(data)"
  54. type = "danger"
  55. size = "small">调剂</van-button> </span>
  56. </div>
  57. </div>
  58. </div>
  59. <van-action-sheet
  60. v-model="adjustStatus"
  61. :actions="couresList"
  62. cancel-text="取消"
  63. @cancel="adjustStatus = false"
  64. @select="adjustSelect" />
  65. </van-tab>
  66. <van-tab title="数据统计">
  67. <van-cell class="countInfo" title="报名总人数" :value="config.regNum + '人'"></van-cell>
  68. <van-cell class="countInfo" title="缴费总人数" :value="config.payNum + '人'"></van-cell>
  69. <van-cell class="countInfo" title="家长会当日缴费人数" :value="config.firstDayPayNum + '人'"></van-cell>
  70. <van-cell class="countInfo" :value="config.payScale + '%'">
  71. <template #title>
  72. <div style="display: flex;align-items: center;">家长会当日缴费人数占比
  73. <van-icon name="question-o" @click="onTip" style="padding-left: .05rem;" />
  74. </div>
  75. </template>
  76. </van-cell>
  77. <div style="width: 100%;overflow-x: auto;">
  78. <div class="table" style="width: 145%;">
  79. <van-row style="border: 1px solid #eaeaea">
  80. <van-col span="1">&nbsp;</van-col>
  81. <van-col span="3">学员编号</van-col>
  82. <van-col span="2">姓名</van-col>
  83. <van-col span="2">声部</van-col>
  84. <van-col span="4">
  85. <div style="display: flex;align-items: center;justify-content: center;" @click="onChangeSort('1')">
  86. 预报名时间
  87. <div>
  88. <i class="box box-up" :class="[orderByPerRegister == 'ASC' ? 'active' : null]" style="margin-bottom: .02rem;"></i>
  89. <i class="box box-down" :class="[orderByPerRegister == 'DESC' ? 'active' : null]"></i>
  90. </div>
  91. </div>
  92. </van-col>
  93. <van-col span="4">预报名时间差</van-col>
  94. <van-col span="4">
  95. <div style="display: flex;align-items: center;justify-content: center;" @click="onChangeSort('2')">
  96. 缴费时间
  97. <div>
  98. <i class="box box-up" :class="[orderByPayTime == 'ASC' ? 'active' : null]" style="margin-bottom: .02rem;"></i>
  99. <i class="box box-down" :class="[orderByPayTime == 'DESC' ? 'active' : null]"></i>
  100. </div>
  101. </div>
  102. </van-col>
  103. <van-col span="4">缴费时间差</van-col>
  104. </van-row>
  105. <van-row v-for="(data, index) in countList" :key="data.id" style="border: 1px solid #ebedf0">
  106. <van-col span="1">{{ ++index }}</van-col>
  107. <van-col span="3">{{ data.userId }}</van-col>
  108. <van-col span="2">{{ data.studentName }}</van-col>
  109. <van-col span="2">{{ data.actualSubjectName }}</van-col>
  110. <van-col span="4">{{ data.perRegisterTime }}</van-col>
  111. <van-col span="4">{{ data.perRegIntervalStr }}</van-col>
  112. <van-col span="4">{{ data.payTime }}</van-col>
  113. <van-col span="4">{{ data.payIntervalStr }}</van-col>
  114. </van-row>
  115. </div>
  116. </div>
  117. </van-tab>
  118. </van-tabs>
  119. </div>
  120. </template>
  121. <script>
  122. import { queryStudentApply, querySubByMusicGroupId, getRegisterOrPreList, updateSubject } from '@/api/teacher'
  123. import setLoading from '@/utils/loading'
  124. import cleanDeep from 'clean-deep'
  125. export default {
  126. name: 'order',
  127. data() {
  128. return {
  129. musicGroupId: this.$route.query.musicGroupId,
  130. musicGroupName: this.$route.query.musicGroupName,
  131. dataList: {}, // 订单列表
  132. amountCount: 0, // 总额
  133. studentList: {}, // 学生列表
  134. couresList: [],
  135. countList: [],
  136. voicyPart: 0,
  137. voicyPartList: [{
  138. text: '全部声部',
  139. value: 0
  140. }],
  141. adjustStatus: false, //
  142. changeStudent: null, // 修改的学生对象
  143. orderByPerRegister: null, // 预报名时间排序状态
  144. orderByPayTime: null, // 缴费时间排序状态
  145. config: {
  146. regNum: 0,
  147. firstDayPayNum: 0,
  148. payScale: 0,
  149. payNum: 0
  150. }
  151. }
  152. },
  153. async mounted() {
  154. window.localStorage.removeItem('userInfo') // 删除用户信息
  155. window.localStorage.removeItem('Authorization') // 删除用户信息
  156. setLoading(true)
  157. await querySubByMusicGroupId({ musicGroupId: this.musicGroupId }).then(res => {
  158. let result = res.data
  159. if(result.code == 200) {
  160. result.data.forEach(r => {
  161. this.voicyPartList.push({
  162. text: r.name,
  163. value: r.id
  164. })
  165. this.couresList.push({
  166. name: r.name,
  167. id: r.id
  168. })
  169. })
  170. }
  171. })
  172. setLoading(false)
  173. // 获取订单信息
  174. this.getOrderList()
  175. this.getOrderStudentList()
  176. this.getRegisterOrPreList()
  177. },
  178. methods: {
  179. adjust(item) {
  180. // 开始调剂
  181. if(item.paymentStatus != 2) {
  182. this.adjustStatus = true
  183. this.changeStudent = item
  184. }
  185. },
  186. adjustSelect(item) { // 修改专业
  187. updateSubject({
  188. musicGroupId: this.musicGroupId,
  189. subId: item.id,
  190. userId: this.changeStudent.userId
  191. }).then(res => {
  192. let result = res.data
  193. if(result.code == 200) {
  194. this.$toast('修改成功')
  195. this.adjustStatus = false
  196. this.getOrderStudentList()
  197. } else {
  198. this.$toast(result.msg)
  199. }
  200. })
  201. },
  202. getOrderList() {
  203. // 获取订单信息
  204. queryStudentApply({
  205. musicGroupId: this.musicGroupId,
  206. rows: 9999,
  207. subjectId: this.voicyPart ? this.voicyPart : '',
  208. paymentStatus: 2,
  209. page: 1
  210. }).then(res => {
  211. let result = res.data
  212. this.amountCount = 0
  213. if(result.code == 200) {
  214. this.dataList = result.data.rows
  215. result.data.rows.forEach(item => {
  216. this.amountCount += item.paymentAmount
  217. })
  218. }
  219. })
  220. },
  221. getOrderStudentList() {
  222. // 获取订单信息
  223. queryStudentApply({
  224. musicGroupId: this.musicGroupId,
  225. rows: 9999,
  226. subjectId: this.voicyPart ? this.voicyPart : '',
  227. page: 1
  228. }).then(res => {
  229. let result = res.data
  230. if(result.code == 200) {
  231. this.studentList = result.data.rows
  232. }
  233. })
  234. },
  235. async getRegisterOrPreList() {
  236. setLoading(true)
  237. // 获取订单信息
  238. await getRegisterOrPreList(cleanDeep({
  239. musicGroupId: this.musicGroupId,
  240. rows: 9999,
  241. subjectId: this.voicyPart ? this.voicyPart : '',
  242. orderByPerRegister: this.orderByPerRegister,
  243. orderByPayTime: this.orderByPayTime,
  244. page: 1
  245. })).then(res => {
  246. let result = res.data
  247. if(result.code == 200) {
  248. let tempDate = result.data
  249. let scale = ((tempDate.firstDayPayNum / tempDate.payNum) * 100).toFixed(2)
  250. this.config = {
  251. regNum: tempDate.regNum,
  252. firstDayPayNum: tempDate.firstDayPayNum,
  253. payScale: scale,
  254. payNum: tempDate.payNum
  255. }
  256. this.countList = tempDate.rows
  257. }
  258. })
  259. setLoading(false)
  260. },
  261. onChange() {
  262. // 切换声部时
  263. // let subId = value ? value : ''
  264. this.getOrderList(this.voicyPart)
  265. this.getOrderStudentList(this.voicyPart)
  266. this.getRegisterOrPreList(this.voicyPart)
  267. },
  268. onTip() {
  269. this.$dialog.alert({
  270. message: '家长会当日缴费人数 / 缴费总人数',
  271. }).then(() => {
  272. // on close
  273. });
  274. },
  275. async onChangeSort(sort) {
  276. if(sort == 1) {
  277. this.orderByPayTime = null
  278. if(this.orderByPerRegister == 'ASC') {
  279. this.orderByPerRegister = 'DESC'
  280. } else if(this.orderByPerRegister == 'DESC') {
  281. this.orderByPerRegister = null
  282. } else {
  283. this.orderByPerRegister = 'ASC'
  284. }
  285. } else if(sort == 2) {
  286. this.orderByPerRegister = null
  287. if(this.orderByPayTime == 'ASC') {
  288. this.orderByPayTime = 'DESC'
  289. } else if(this.orderByPayTime == 'DESC') {
  290. this.orderByPayTime = null
  291. } else {
  292. this.orderByPayTime = 'ASC'
  293. }
  294. }
  295. await this.getRegisterOrPreList()
  296. }
  297. }
  298. }
  299. </script>
  300. <style lang="less" scoped>
  301. .order {
  302. background: #fff;
  303. min-height: 100vh;
  304. }
  305. header {
  306. height: .40rem;
  307. line-height: .40rem;
  308. color: #000;
  309. font-size: .17rem;
  310. background: #fff;
  311. box-shadow: 0px 1px 8px 0px rgba(0,0,0,0.07);
  312. text-align: center;
  313. }
  314. h2 {
  315. font-size: .16rem;
  316. color: #fff;
  317. padding: .1rem 0;
  318. text-align: center;
  319. background: #14928a;
  320. }
  321. .table {
  322. .title {
  323. display: flex;
  324. align-items: center;
  325. text-align: center;
  326. border-bottom: 1px solid #eaeaea;
  327. }
  328. span {
  329. flex: 1;
  330. padding: .08rem 0;
  331. font-size: .14rem;
  332. &:first-child {
  333. width: .3rem;
  334. flex: inherit;
  335. }
  336. }
  337. .content > div{
  338. width: 100%;
  339. display: flex;
  340. align-items: center;
  341. text-align: center;
  342. &:nth-child(2n+2) {
  343. background: #eaeaea;
  344. }
  345. }
  346. }
  347. /deep/.van-dropdown-menu {
  348. height: .4rem;
  349. position: absolute;
  350. right: .15rem;
  351. top: 0;
  352. .van-dropdown-menu__bar {
  353. height: .4rem;
  354. box-shadow: none;
  355. }
  356. }
  357. /deep/.van-col {
  358. font-size: 0.14rem;
  359. text-align: center;
  360. padding: .08rem 0;
  361. }
  362. /deep/.van-row {
  363. &:nth-child(2n+3) {
  364. background: #eaeaea;
  365. }
  366. }
  367. .box {
  368. display: flex;
  369. flex-direction: row;
  370. align-items: center;
  371. margin-left: .02rem;
  372. }
  373. .box-up {
  374. width: 0;
  375. height: 0;
  376. border-left: 4px solid transparent;
  377. border-right: 4px solid transparent;
  378. border-bottom: 6px solid #ccc;
  379. &.active {
  380. border-bottom-color: #14928a;
  381. }
  382. }
  383. .box-down {
  384. width: 0;
  385. height: 0;
  386. border-left: 4px solid transparent;
  387. border-right: 4px solid transparent;
  388. border-top: 6px solid #ccc;
  389. &.active {
  390. border-top-color: #14928a;
  391. }
  392. }
  393. .countInfo {
  394. /deep/.van-cell__title {
  395. flex: 1 auto;
  396. }
  397. /deep/.van-cell__value {
  398. color: #14928a;
  399. }
  400. }
  401. </style>