فهرست منبع

university detail - init

abpcoder 2 روز پیش
والد
کامیت
237eb21fbc

+ 14 - 0
src/api/modules/university.ts

@@ -460,4 +460,18 @@ export function getUniversityMajorList(params: { universityId: string }) {
 /*院校筛选条件*/
 export function getUniversityFilters() {
     return flyio.get('/front/university/filters') as Promise<ApiResponse<Record<string, string[]>>>
+}
+
+// GET
+// /prod-api/front/customer/university/add
+// 03 关注院校
+export function concernUniversity(params: any) {
+    return flyio.get('/front/customer/university/add', params)
+}
+
+// GET
+// /prod-api/front/customer/university/remove
+// 02 移除关注院校
+export function removeConcernedUniversity(params: any) {
+    return flyio.get('/front/customer/university/remove', params)
 }

+ 2 - 2
src/pagesMain/pages/volunteer/components/volunteer-tier.vue

@@ -44,8 +44,8 @@ const goCollegeListByTier = (t: UniversityTier) => {
 }
 
 const goCollegeDetail = (u: University) => {
-    const {id, code} = u
-    transferTo(routes.universityDetail, {data: {id, code}})
+    const {id, code, name} = u
+    transferTo(routes.universityDetail, {data: {id, code, name}})
 }
 
 onMounted(async () => {

+ 18 - 18
src/pagesOther/pages/major/detail/components/related-university.vue

@@ -1,35 +1,35 @@
 <template>
-  <z-paging ref="paging" v-model="list" :safe-area-inset-bottom="true" @query="handleQuery">
-    <view v-for="item in list" :key="item.id">
-      <university-item :data="item" @click="handleClick(item)" />
-    </view>
-  </z-paging>
+    <z-paging ref="paging" v-model="list" :safe-area-inset-bottom="true" @query="handleQuery">
+        <view v-for="item in list" :key="item.id">
+            <university-item :data="item" @click="handleClick(item)"/>
+        </view>
+    </z-paging>
 </template>
 <script lang="ts" setup>
-import { getUniversityByMajorCode } from '@/api/modules/major';
+import {getUniversityByMajorCode} from '@/api/modules/major';
 import UniversityItem from './university-item.vue';
-import { Major } from '@/types';
-import { useTransferPage } from '@/hooks/useTransferPage';
-const { transferTo, routes } = useTransferPage();
+import {Major} from '@/types';
+import {useTransferPage} from '@/hooks/useTransferPage';
+
+const {transferTo, routes} = useTransferPage();
 
 const props = defineProps<{
-  data: Major.MajorOverview;
+    data: Major.MajorOverview;
 }>();
 const list = ref<Major.University[]>([]);
 const paging = ref<ZPagingInstance>();
 
 const handleQuery = (page: number, size: number) => {
-  getUniversityByMajorCode({ code: props.data.code, pageNum: page, pageSize: size }).then(res => {
-    paging.value?.completeByTotal(res.rows, res.total);
-  }).catch(() => paging.value?.complete(false));
+    getUniversityByMajorCode({code: props.data.code, pageNum: page, pageSize: size}).then(res => {
+        paging.value?.completeByTotal(res.rows, res.total);
+    }).catch(() => paging.value?.complete(false));
 }
 
 const handleClick = (item: Major.University) => {
-  transferTo(routes.universityDetail, {
-    data: {
-      id: item.id,
-    }
-  });
+    const {id, code, name} = item
+    transferTo(routes.universityDetail, {
+        data: {id, code, name}
+    });
 }
 </script>
 <style lang="scss" scoped></style>

+ 118 - 0
src/pagesOther/pages/university/detail/components/college-info.vue

@@ -0,0 +1,118 @@
+<template>
+    <uv-skeleton v-if="loading" avatar loading rows="2"/>
+    <view v-else class="-mt-50 flex justify-between gap-20">
+        <view class="flex flex-col items-center gap-10">
+            <ie-image :src="info.logo" custom-class="w-140 h-140" :round="9999"/>
+            <uv-button v-if="!info.collected" type="primary" plain size="mini" shape="circle" icon="plus" text="关注"
+                       icon-size="12" icon-color="primary" @click="handleCollect"/>
+            <uv-button v-else type="primary" size="mini" shape="circle" text="已关注" icon-size="12"
+                       icon-color="primary" @click="handleCollectRemove"/>
+        </view>
+        <view class="mt-50 flex-1">
+            <view class="text-36 font-bold text-fore-title">{{ info.name }}</view>
+            <view v-if="bxTags.length" class="mt-8 flex flex-wrap gap-8">
+                <uv-tags v-for="t in bxTags" :text="t" v-bind="getHighlightBindings(t)" @click="handleTagClick(t)"/>
+            </view>
+            <uv-text type="tips" prefix-icon="empty-address" :icon-style="{color: '#999999'}"
+                     size="12" :text="info.address" margin="8px 0 0 0"/>
+        </view>
+    </view>
+    <scroll-view scroll-x class="mt-30">
+        <view class="inline-flex items-center gap-20 text-fore-title">
+            <view class="flex-none min-w-120 p-28 flex flex-col items-center bg-back-light rounded-xl">
+                <view>
+                    <text class="text-30 font-bold">{{ info.createdYear || '-' }}</text>
+                    <text class="ml-5 text-20">年</text>
+                </view>
+                <view class="text-24">建校时间</view>
+            </view>
+            <view class="flex-none min-w-120 p-28 flex flex-col items-center bg-back-light rounded-xl">
+                <view class="text-30 font-bold">{{ info.star || '-'}}</view>
+                <view class="text-24">竞争力</view>
+            </view>
+            <view class="flex-none min-w-120 p-28 flex flex-col items-center bg-back-light rounded-xl">
+                <view class="text-30 font-bold">{{ info.comScore || '-'}}</view>
+                <view class="text-24">综合评分</view>
+            </view>
+            <view class="flex-none min-w-120 p-28 flex flex-col items-center bg-back-light rounded-xl">
+                <view class="text-30 font-bold">{{ info.tierName || '-'}}</view>
+                <view class="text-24">院校实力</view>
+            </view>
+            <view class="flex-none min-w-120 p-28 flex flex-col items-center bg-back-light rounded-xl">
+                <view class="text-30 font-bold">{{ info.collect || '-'}}</view>
+                <view class="text-24">收藏量</view>
+            </view>
+        </view>
+    </scroll-view>
+</template>
+
+<script setup lang="ts">
+import {University} from "@/types/university";
+import _ from "lodash";
+import {concernUniversity, removeConcernedUniversity} from "@/api/modules/university";
+
+const props = defineProps<{
+    info: University
+    loading: boolean
+}>()
+const emits = defineEmits(['tag'])
+
+const isCultural = ref(false) //useUserStore() // 这是早先兼容河南文化类填报时的字段
+const highlights = ['双高']
+const tagAttrs = {
+    type: 'info',
+    plain: true,
+    size: 'tiny',
+    'class': 'pointer-events-none'
+}
+const starBinding = {
+    ...tagAttrs,
+    type: 'warning'
+}
+const tagHighlight = {
+    ...tagAttrs,
+    type: 'primary',
+    plainFill: true
+}
+
+const bxTags = computed(() => {
+    const {bxLevel, bxType} = props.info
+    const tags = bxLevel ? bxLevel.split(',') : []
+    if (bxType) {
+        _.pull(tags, '双高')
+        tags.push(bxType)
+    }
+    return tags
+})
+
+const isSpecialTag = (tag: string) => {
+    return !isCultural.value && tag == props.info.bxType
+}
+
+const isHighlight = (tag: string) => {
+    return highlights.includes(tag) || isSpecialTag(tag)
+}
+
+const getHighlightBindings = (tag: string) => {
+    const attrs = isHighlight(tag) ? tagHighlight : tagAttrs
+    return isSpecialTag(tag) ? {...attrs, icon: 'question-circle', reverse: true, 'class': ''} : attrs
+}
+
+const handleTagClick = (tag: string) => {
+    if (isSpecialTag(tag)) emits('tag')
+}
+
+const handleCollect = async () => {
+    await concernUniversity({universityId: props.info.id})
+    props.info.collected = true
+}
+
+const handleCollectRemove = async () => {
+    await removeConcernedUniversity({universityId: props.info.id})
+    props.info.collected = false
+}
+</script>
+
+<style scoped>
+
+</style>

+ 62 - 2
src/pagesOther/pages/university/detail/detail.vue

@@ -1,7 +1,67 @@
 <template>
-
+    <ie-page bg-color="#F6F8FA">
+        <ie-navbar :title="prevData.name" transparent bg-color="#FFFFFF" title-color="black" keep-title-color/>
+        <ie-image :src="baseInfo.logo" custom-class="w-full h-360" />
+        <view class="-mt-60 z-1 rounded-t-3xl p-30 bg-white">
+            <college-info :info="baseInfo" :loading="loading" />
+        </view>
+        <uv-gap height="10"/>
+        <uv-sticky :offset-top="baseStickyTop">
+            <ie-tabs-swiper v-model="current" :list="tabs" :scrollable="false">
+            </ie-tabs-swiper>
+        </uv-sticky>
+        <view style="height: 1000px"></view>
+    </ie-page>
 </template>
 <script lang="ts" setup>
 
+import {useTransferPage} from "@/hooks/useTransferPage";
+import {UniversityDetail, University} from "@/types/university";
+import {universityDetail} from "@/api/modules/university";
+import CollegeInfo from "@/pagesOther/pages/university/detail/components/college-info.vue";
+import {SwiperTabItem} from "@/types";
+import {useNavbar} from "@/hooks/useNavbar";
+
+const {prevData} = useTransferPage()
+const {baseStickyTop} = useNavbar()
+const detail = ref<UniversityDetail>({} as UniversityDetail)
+const baseInfo = computed<University>(() => detail.value.baseInfo || {} as University)
+const loading = ref(true)
+
+const current = ref(0)
+const tabs = ref<SwiperTabItem[]>([{
+    name: '概况',
+    slot: 'profile'
+}, {
+    name: '简章',
+    slot: 'brochure'
+}, {
+    name: '计划',
+    slot: 'plan'
+}, {
+    name: '录取',
+    slot: 'enroll'
+}, {
+    name: '考试大纲',
+    slot: 'exam'
+}])
+
+onMounted(() => {
+    uni.$ie.showLoading()
+    loading.value = true
+    universityDetail({code: prevData.value.code})
+        .then(res => detail.value = res.data)
+        .finally(() => {
+            uni.$ie.hideLoading()
+            loading.value = false
+        })
+})
+// 必须手动触发才能保证 navbar.transparent 正常工作
+onPageScroll(() => {})
 </script>
-<style lang="scss" scoped></style>
+
+<style lang="scss" scoped>
+::v-deep .uv-tabs__wrapper__nav__item__text {
+    white-space: nowrap;
+}
+</style>

+ 2 - 2
src/pagesOther/pages/university/index/components/college-list.vue

@@ -59,8 +59,8 @@ const handleQuery = (pageNum: number, pageSize: number) => {
 
 const handleDetail = (u: University) => {
     if (props.customItemClick) return emits('item-click', u)
-    const {id, code} = u
-    transferTo(routes.universityDetail, {data: {id, code}})
+    const {id, code, name} = u
+    transferTo(routes.universityDetail, {data: {id, code, name}})
 }
 
 provide(UNIVERSITY_FILTER, queryParams)

+ 3 - 2
src/pagesOther/pages/university/index/components/college-rank.vue

@@ -14,6 +14,7 @@ import {universityList} from "@/api/modules/university";
 import {University} from "@/types/university";
 import {useUserStore} from "@/store/userStore";
 import CollegeItem from "@/pagesOther/pages/university/index/components/plus/college-item.vue";
+import {routes} from "@/common/routes";
 
 const {transferTo} = useTransferPage()
 const paging = ref<ZPagingInstance>()
@@ -30,8 +31,8 @@ const handleQuery = (pageNum: number, pageSize: number) => {
 }
 
 const handleDetail = (college: University) => {
-    const {code} = college
-    transferTo('/pages/college-library/detail/detail', {code})
+    const {id, code, name} = college
+    transferTo(routes.universityDetail, {data: {id, code, name}})
 }
 
 </script>

+ 1 - 1
src/pagesOther/pages/university/index/components/plus/college-item.vue

@@ -33,7 +33,7 @@ const props = withDefaults(defineProps<{
     reverse?: boolean;
 }>(), {
     item: () => ({} as University),
-    addressLines: 2
+    addressLines: 1
 })
 const emits = defineEmits(['tag', 'click'])
 

+ 3 - 0
src/types/university.ts

@@ -6,6 +6,7 @@ export interface University {
     cityName: string;
     code: string;
     collect: string | number;
+    collected: boolean;
     comScore: string | number;
     enrollLocation: string;
     features: string;
@@ -18,6 +19,8 @@ export interface University {
     star: string;
     type: string;
     webSite: string;
+    tier: string;
+    tierName: string;
 }
 
 export interface UniversityDetail {