major-popup.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <template>
  2. <uv-popup ref="popup" mode="bottom" closeable round="16" @change="handleChange">
  3. <view class="h-100 flex justify-center items-center 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="flex flex-col">
  10. <view class="flex justify-between items-center">
  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="flex justify-start items-center 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 {createPropDefine} from "@/utils";
  54. import {SimulatePickTypes} from "@/utils/common";
  55. import VoluntaryHistoryList from "@/pagesOther/pages/vhs/index/components/voluntary-history-list.vue";
  56. import {useInjectVoluntaryHeader} from "@/pagesOther/pages/vhs/hooks/useVoluntaryHeaderInjection";
  57. import {useInjectVoluntaryMajorHighlight} from "@/pagesOther/pages/vhs/hooks/useVoluntaryMajorHighlightInjection";
  58. import {useInjectVoluntaryAssistant} from "@/pagesOther/pages/vhs/hooks/useVoluntaryAssistantInjection";
  59. import {useInjectVoluntaryCart} from "@/pagesOther/pages/vhs/hooks/useVoluntaryCartInjection";
  60. const props = defineProps({
  61. readonly: createPropDefine(false, Boolean)
  62. })
  63. const emits = defineEmits(['notify'])
  64. const popup = ref(null)
  65. const show = ref(false)
  66. const group = ref({})
  67. const localPageNum = ref(1)
  68. const localPageSize = ref(4)
  69. const {headerPlanYear} = useInjectVoluntaryHeader()
  70. const {toggleMajorSelected} = useInjectVoluntaryCart()
  71. const {isSearchingMajorFired, snapshotSearchingMajorWhenApply} = useInjectVoluntaryMajorHighlight()
  72. const {voluntaryDataCalculate} = useInjectVoluntaryAssistant(props.readonly)
  73. // 已填
  74. // const selectedCount = computed(() => {
  75. // if (empty(group.value.majors)) return 0
  76. // return _.countBy(group.value.majors, m => m.selected)[true]
  77. // })
  78. const pagedMajors = computed(() => {
  79. return group.value.majors?.slice(0, toValue(localPageNum) * toValue(localPageSize)) || []
  80. })
  81. const handleMajorScroll = () => {
  82. if (toValue(pagedMajors).length >= toValue(group).majors.length) return
  83. localPageNum.value += 1
  84. }
  85. const formatXueZhi = (val) => {
  86. if (!val) return val
  87. return val.endsWith('年') ? val : val + '年'
  88. }
  89. const getPickTypeColor = (pickType) => {
  90. return SimulatePickTypes.find(t => t.value == pickType)?.color || ''
  91. }
  92. const handleApply = async (major) => {
  93. const majorGroup = group.value
  94. const voluntaryOptions = toValue(voluntaryDataCalculate)
  95. await toggleMajorSelected(major, majorGroup, voluntaryOptions)
  96. snapshotSearchingMajorWhenApply(major) // snapshot when toggle succeed.
  97. }
  98. const open = (item) => {
  99. localPageNum.value = 1
  100. group.value = item
  101. popup.value.open()
  102. }
  103. const close = () => {
  104. popup.value.close()
  105. }
  106. const handleChange = (e) => show.value = e.show
  107. defineExpose({open, close, show})
  108. </script>
  109. <style scoped lang="scss">
  110. ::v-deep(.uv-tags) {
  111. .uv-tags__text--medium {
  112. font-size: 12px !important;
  113. }
  114. }
  115. </style>