123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- <template>
- <uv-popup ref="popup" mode="bottom">
- <scroll-view scroll-y class="bg-bg" style="height: 60vh">
- <uv-sticky custom-nav-height="0">
- <view class="mx-border-b fx-row fx-bet-cen bg-white h-[44px]">
- <view class="text-tips px-30" @click="close">取消</view>
- <view class="text-center flex-1 text-main truncate">
- {{ detail.baseInfo && detail.baseInfo.name }}
- </view>
- <view class="text-primary px-30" @click="handleConfirm">确定</view>
- </view>
- <view v-if="false&&localMajors.length&&limit>1" class="p-20 fx-row flex-wrap bg-bg">
- <view v-for="m in localMajors" :key="m.code">
- <uv-tags size="mini" type="primary" :text="m.name" plain plain-fill closable
- class="keep-all" @close="handleDelete(m)"></uv-tags>
- </view>
- </view>
- </uv-sticky>
- <view v-if="!loading" class="px-20 py-8 text-2xs text-tips fx-row fx-bet-cen">
- <view>
- 共
- <text class="text-error mx-5">{{ filteredProfessions.length }}</text>
- 个专业
- </view>
- <view v-if="categoryNode">
- 仅显示
- <text class="text-error mx-5">{{ categoryNode.name }}</text>
- 包含的专业
- </view>
- </view>
- <uv-loading-icon v-if="loading" custom-style="margin-top: 20px"/>
- <view v-else-if="filteredProfessions.length">
- <common-picker-cell v-for="p in filteredProfessions" :icon="p.hot?'/static/ie/entry/hot.png':''"
- :title="p.name" :label="p.majorDirection" :selected="isSelected(p)"
- @click="handleAdd(p)"/>
- <uv-gap height="20"/>
- </view>
- <uv-empty v-else margin-top="20"/>
- </scroll-view>
- </uv-popup>
- </template>
- <script>
- import {computed, ref, watch} from 'vue';
- import _ from 'lodash';
- import {findTreeNode} from "@/utils/tree-helper";
- import CommonPickerCell from "@/pages/ie/components/picker/common-picker-cell.vue";
- import {useCacheStore} from "@/hooks/useCacheStore";
- import {universityDetail} from "@/api/webApi/collegemajor";
- import {toast} from "@/uni_modules/uv-ui-tools/libs/function";
- import {useInjectMajorTreeService} from "@/pages/ie/hooks/useMajorTreeInjection";
- export default {
- name: "major-picker",
- components: {CommonPickerCell},
- emits: ['confirm'],
- props: {
- universityCode: {
- type: String,
- default: ''
- },
- majors: {
- // default majors selected
- type: Array,
- default: null
- },
- limit: {
- type: Number,
- default: 4
- },
- majorCategory: {
- type: [String, Number],
- default: ''
- }
- },
- setup(props, {emit}) {
- const popup = ref(null)
- const loading = ref(true)
- const localMajors = ref([])
- const detail = ref({})
- const {dispatchCache} = useCacheStore()
- const {majorTree, findNodeByCode} = useInjectMajorTreeService()
- const categoryNode = computed(() => {
- if (!props.majorCategory) return null
- return findNodeByCode(props.majorCategory)
- })
- const filteredProfessions = computed(() => {
- if (!categoryNode.value) return detail.value?.professions || []
- return detail.value?.professions?.filter(p => findTreeNode([categoryNode.value], n => n.code == p.code)) || []
- })
- watch(() => props.universityCode, async code => {
- if (code) {
- loading.value = true
- const res = await dispatchCache(universityDetail, {code})
- detail.value = res.data
- loading.value = false
- }
- })
- watch(() => props.majors, (values) => localMajors.value = [...values])
- const isSelected = (p) => {
- return localMajors.value.some(m => m.code == p.code && m.enrollCode == p.enrollCode)
- }
- const handleAdd = (p) => {
- if (props.limit == 1) {
- emit('confirm', p)
- return close()
- }
- if (localMajors.value.length >= props.limit && !isSelected(p)) {
- toast('最多选择' + props.limit + '个专业')
- return
- }
- if (isSelected(p)) handleDelete(p);
- else localMajors.value.push(p)
- }
- const handleDelete = (m) => {
- _.remove(localMajors.value, item => item.code == m.code)
- }
- const handleConfirm = () => {
- emit('confirm', localMajors.value)
- close()
- }
- const open = () => {
- popup.value.open()
- }
- const close = () => {
- popup.value.close()
- }
- return {
- popup,
- open,
- close,
- loading,
- localMajors,
- majorTree,
- detail,
- categoryNode,
- filteredProfessions,
- isSelected,
- handleAdd,
- handleDelete,
- handleConfirm
- }
- }
- }
- </script>
- <style scoped lang="scss">
- .pop-command {
- width: 100vw;
- position: fixed;
- top: 0;
- }
- ::v-deep .uni-scroll-view-content {
- height: fit-content;
- }
- ::v-deep .uv-cell__label {
- color: var(--primary-light-color);
- }
- </style>
|