plan-enroll-list.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. <template>
  2. <z-paging ref="paging" v-model="results" :auto="false" bg-color="white" :refresher-enabled="false"
  3. @query="handleQuery">
  4. <template #top>
  5. <view class="fx-row items-center gap-40 px-40" :style="{height: tag?'60px': '44px'}">
  6. <uv-tags v-if="tag" :text="tag" plain plain-fill/>
  7. <uv-form ref="form" :model="queryParams" :rules="rules" error-type="toast">
  8. <mx-condition/>
  9. </uv-form>
  10. </view>
  11. </template>
  12. <view v-for="([label, values], idx) in groupedResults" class="fx-col px-20">
  13. <view v-if="label" class="text-primary font-bold mb-20">{{ label }}</view>
  14. <view v-for="(item,i) in values" class="px-20 fx-col">
  15. <view class="font-bold text-main">
  16. {{ item.majorName }}
  17. <template v-if="item.groupName">({{ item.groupName }})</template>
  18. <template v-if="item.specialProject">({{ item.specialProject }})</template>
  19. </view>
  20. <view v-if="item.marjorDirection" class="font-[PingFang] text-2xs text-content">
  21. {{ item.marjorDirection }}
  22. </view>
  23. <view class="mt-10 grid gap-20" :class="`grid-cols-`+descriptors.length">
  24. <plan-enroll-descriptor v-for="d in descriptors" :title="d.title" :value="item[d.key]"
  25. :title-only="d.titleOnly" @click="handleRuleClick(d, item)"/>
  26. </view>
  27. <uv-divider v-if="i<values.length-1" dashed/>
  28. </view>
  29. <uv-divider v-if="idx<groupedResults.length-1"/>
  30. </view>
  31. </z-paging>
  32. </template>
  33. <script setup>
  34. import {computed, ref} from 'vue';
  35. import _ from 'lodash';
  36. import {createPropDefine} from "@/utils";
  37. import {useUserStore} from "@/hooks/useUserStore";
  38. import {conditionSharedConfig} from "@/components/mx-condition/modules/conditionSharedConfig";
  39. import {useProvideSearchModel} from "@/components/mx-condition/useSearchModelInjection";
  40. import PlanEnrollDescriptor from "@/pages/college-library/components/plan-enroll-descriptor.vue";
  41. const props = defineProps({
  42. list: createPropDefine([], Array),
  43. mode: createPropDefine('plan', String, v => ['plan', 'enroll'].includes(v))
  44. })
  45. const emits = defineEmits(['rule'])
  46. const paging = ref(null)
  47. const {currentUser, isCultural} = useUserStore()
  48. const tag = computed(() => isCultural.value && currentUser.value.examMajorName)
  49. const descriptors = computed(() => {
  50. const enrollShared = [{title: '录取', key: 'realNum'}, {title: '最低分', key: 'minScore'}]
  51. const cols = props.mode == 'plan'
  52. ? [{title: '计划', key: 'planNum'}, {title: '学制', key: 'xueZhi'}, {title: '学费', key: 'fee'}]
  53. : isCultural.value
  54. ? [...enrollShared, {title: '最低位', key: 'minSeat'}]
  55. : [...enrollShared]
  56. if (!isCultural.value) cols.push({title: '录取规则', key: '', titleOnly: true})
  57. return cols
  58. })
  59. const results = ref([])
  60. const groupedResults = computed(() => Object.entries(_.groupBy(results.value, i => i.majorGroup)))
  61. const queryParams = ref({year: '', level: '', group: ''})
  62. const years = computed(() => _.orderBy(_.uniq(_.map(props.list, i => i.year)), [], ['desc']))
  63. const conditionYear = {
  64. ...conditionSharedConfig,
  65. key: 'year',
  66. handler: () => years.value,// 这个页面能渲染,即说明有数据源,可以直接取值
  67. required: true
  68. }
  69. const conditionLevel = {
  70. ...conditionSharedConfig,
  71. key: 'level',
  72. dependentKeys: ['year'],
  73. handler: ({year}) => _.uniq(_.map(props.list.filter(i => i.year == year), i => i.level)),
  74. required: true
  75. }
  76. const conditionGroup = {
  77. ...conditionSharedConfig,
  78. key: 'group',
  79. title: '专业组',
  80. dependentKeys: ['level'],
  81. independentKeys: ['year'],
  82. handler: (payload) => _.uniq(_.map(props.list.filter(i => i.year == payload.year && i.level == payload.level), i => i.majorGroup))
  83. .map(g => ({name: g, value: g})), // 构建name/value是为了兼容`不限选项`
  84. keyName: 'name',
  85. keyValue: 'value',
  86. hidden: isCultural.value
  87. }
  88. const form = ref(null)
  89. const {onSearch, rules} = useProvideSearchModel([conditionYear, conditionLevel, conditionGroup], queryParams, form)
  90. const listOfYear = computed(() => queryParams.value.year ? props.list.filter(i => i.year == queryParams.value.year) : [])
  91. const listOfLevel = computed(() => queryParams.value.level ? listOfYear.value.filter(i => i.level == queryParams.value.level) : [])
  92. const listOfGroup = computed(() => !queryParams.value.group ? listOfLevel.value : listOfLevel.value.filter(i => i.majorGroup == queryParams.value.group))
  93. onSearch(() => paging.value.reload())
  94. const handleQuery = () => {
  95. // 到这里时listOfLevel应该已经动态计算完毕了
  96. // onSearch, results结构都是多余的,这里只是为了实验z-paging的虚拟列表
  97. paging.value.completeByNoMore(listOfGroup.value, true)
  98. }
  99. const handleRuleClick = (descriptor, history) => {
  100. if (descriptor.titleOnly) emits('rule', history.totalRule)
  101. }
  102. </script>
  103. <style scoped>
  104. </style>