major-popup.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. <template>
  2. <uv-popup ref="popup" mode="bottom" closeable round="16" @change="handleChange">
  3. <view class="h-[50px] fx-row fx-cen-cen text-lg text-main font-bold">
  4. {{ group.university.name }}
  5. </view>
  6. <scroll-view scroll-y class="bg-bg" style="height: 50vh" lower-threshold="100"
  7. @scrolltolower="handleMajorScroll">
  8. <view class="p-30">
  9. <view v-for="item in pagedMajors" class="fx-col">
  10. <view class="fx-row fx-bet-cen">
  11. <view class="flex-1 fx-row items-center">
  12. <text :class="{'highlight-major': isSearchingMajorFired(item)}">
  13. {{ item.marjorName }}
  14. </text>
  15. ({{ item.marjorBelongs }})
  16. <text v-if="item.level" class="text-error">({{ item.level }})</text>
  17. <uv-tags v-if="item.enrollFluctuate" text="大小年" size="tiny" type="error"
  18. class="ml-5" @click="$emit('notify', '近两年录取分差较大')"/>
  19. </view>
  20. <uv-tags v-if="!readonly" :plain="!item.selected" :text="item.selected?'已填':'填报'"
  21. shape="circle" @click="handleApply(item)"/>
  22. </view>
  23. <view v-if="item.professionType||item.typeNames" class="mb-10 text-xs text-primary font-light">
  24. {{ item.professionType }}
  25. {{ item.typeNames }}
  26. </view>
  27. <view class="fx-row fx-sta-cen text-2xs mb-10">
  28. <text class="text-content mr-10">录取概率</text>
  29. <text class="text-sm font-bold">{{ item.enrollRatio || '-' }}</text>
  30. %
  31. <text class="text-content ml-10" :class="[getPickTypeColor(item.pickType)]">
  32. {{ item.enrollRatioText }}
  33. </text>
  34. </view>
  35. <view class="text-2xs">
  36. <view class="mb-5 text-main font-bold">
  37. {{
  38. `代码 ${item.marjorBelongs} ${headerPlanYear}计划 ${item.planCount}人 ${formatXueZhi(item.xuezhi)} ¥${item.xuefei || '-'}`
  39. }}
  40. </view>
  41. <view class="mb-5 text-content">
  42. {{ item.marjorDirection }}
  43. </view>
  44. <voluntary-history-list :container="item" @notify="$emit('notify', $event)"/>
  45. </view>
  46. <uv-divider/>
  47. </view>
  48. </view>
  49. </scroll-view>
  50. </uv-popup>
  51. </template>
  52. <script setup>
  53. import {ref, computed} from 'vue';
  54. import MxConst from "@/common/MxConst";
  55. import {createPropDefine} from "@/utils";
  56. import {toValue} from "@vueuse/core";
  57. import VoluntaryHistoryList from "@/pages/voluntary/index/components/voluntary-history-list.vue";
  58. import {useInjectVoluntaryHeader} from "@/pages/voluntary/hooks/useVoluntaryHeaderInjection";
  59. import {useInjectVoluntaryMajorHighlight} from "@/pages/voluntary/hooks/useVoluntaryMajorHighlightInjection";
  60. import {useInjectVoluntaryAssistant} from "@/pages/voluntary/hooks/useVoluntaryAssistantInjection";
  61. import {useInjectVoluntaryCart} from "@/pages/voluntary/hooks/useVoluntaryCartInjection";
  62. const props = defineProps({
  63. readonly: createPropDefine(false, Boolean)
  64. })
  65. const emits = defineEmits(['notify'])
  66. const popup = ref(null)
  67. const show = ref(false)
  68. const group = ref({})
  69. const localPageNum = ref(1)
  70. const localPageSize = ref(4)
  71. const {headerPlanYear} = useInjectVoluntaryHeader()
  72. const {toggleMajorSelected} = useInjectVoluntaryCart()
  73. const {isSearchingMajorFired, snapshotSearchingMajorWhenApply} = useInjectVoluntaryMajorHighlight()
  74. const {voluntaryDataCalculate} = useInjectVoluntaryAssistant(props.readonly)
  75. // 已填
  76. // const selectedCount = computed(() => {
  77. // if (empty(group.value.majors)) return 0
  78. // return _.countBy(group.value.majors, m => m.selected)[true]
  79. // })
  80. const pagedMajors = computed(() => {
  81. return group.value.majors?.slice(0, toValue(localPageNum) * toValue(localPageSize)) || []
  82. })
  83. const handleMajorScroll = () => {
  84. if (toValue(pagedMajors).length >= toValue(group).majors.length) return
  85. localPageNum.value += 1
  86. }
  87. const formatXueZhi = (val) => {
  88. if (!val) return val
  89. return val.endsWith('年') ? val : val + '年'
  90. }
  91. const getPickTypeColor = (pickType) => {
  92. return MxConst.enum.simulatePickTypes.find(t => t.value == pickType)?.color || ''
  93. }
  94. const handleApply = async (major) => {
  95. const majorGroup = group.value
  96. const voluntaryOptions = toValue(voluntaryDataCalculate)
  97. await toggleMajorSelected(major, majorGroup, voluntaryOptions)
  98. snapshotSearchingMajorWhenApply(major) // snapshot when toggle succeed.
  99. }
  100. const open = (item) => {
  101. localPageNum.value = 1
  102. group.value = item
  103. popup.value.open()
  104. }
  105. const close = () => {
  106. popup.value.close()
  107. }
  108. const handleChange = (e) => show.value = e.show
  109. defineExpose({open, close, show})
  110. </script>
  111. <style scoped lang="scss">
  112. ::v-deep(.uv-tags) {
  113. .uv-tags__text--medium {
  114. font-size: 12px !important;
  115. }
  116. }
  117. </style>