shmily1213 1 dzień temu
rodzic
commit
1a1bf2c536

+ 3 - 0
components.d.ts

@@ -12,6 +12,9 @@ declare module 'vue' {
     IeButtonIeButton: typeof import('./src/components/ie-button/ie-button.vue')['default']
     IeCardIeCard: typeof import('./src/components/ie-card/ie-card.vue')['default']
     IeDictIeDict: typeof import('./src/components/ie-dict/ie-dict.vue')['default']
+    IeDropdownIeDropdown: typeof import('./src/components/ie-dropdown/ie-dropdown.vue')['default']
+    IeDropdownIeDropdownItem: typeof import('./src/components/ie-dropdown/ie-dropdown-item.vue')['default']
+    IeDropdownIeDropdownPopup: typeof import('./src/components/ie-dropdown/ie-dropdown-popup.vue')['default']
     IeEmptyIeEmpty: typeof import('./src/components/ie-empty/ie-empty.vue')['default']
     IeGapIeGap: typeof import('./src/components/ie-gap/ie-gap.vue')['default']
     IeImageIeImage: typeof import('./src/components/ie-image/ie-image.vue')['default']

+ 1 - 2
package.json

@@ -90,8 +90,7 @@
     "unplugin-auto-import": "^19.3.0",
     "unplugin-vue-components": "^28.7.0",
     "vite": "5.2.8",
-    "vite-plugin-compression": "^0.5.1",
-    "vite-plugin-uni-polyfill": "^0.1.0"
+    "vite-plugin-compression": "^0.5.1"
   },
   "packageManager": "yarn@1.22.22+sha1.ac34549e6aa8e7ead463a7407e1c7390f61a6610"
 }

+ 39 - 0
src/components/ie-dropdown/ie-dropdown-hooks.ts

@@ -0,0 +1,39 @@
+import type { Dropdown } from "@/types";
+import type { InjectionKey } from "vue";
+
+export const DROPDOWN_SYMBOL = Symbol('DROPDOWN_SYMBOL') as InjectionKey<ReturnType<typeof useDropdown>>;
+
+export const useDropdown = (configs: Dropdown.DropdownItem[]) => {
+  const list = computed(() => configs);
+  const form = ref<Record<string, any>>({});
+  const openIndex = ref<number>(-1);
+
+  const open = (index: number) => {
+    openIndex.value = index;
+  }
+  const close = () => {
+    openIndex.value = -1;
+  }
+  const submit = (index: number, value: any) => {
+    form.value[list.value[index].prop] = value;
+  }
+  const reset = (index: number) => {
+    form.value[list.value[index].prop] = list.value[index].value;
+  }
+  const init = (initValue: Record<string, any>) => {
+    form.value = initValue;
+    list.value.forEach(item => {
+      item.value = initValue[item.prop] || item.value;
+    });
+  }
+
+  return {
+    init,
+    form,
+    openIndex,
+    open,
+    close,
+    submit,
+    reset
+  }
+}

+ 165 - 0
src/components/ie-dropdown/ie-dropdown-item.vue

@@ -0,0 +1,165 @@
+<template>
+  <view class=" h-full">
+    <view :id="`dropdown-trigger-${config.prop}`" class="w-full flex items-center justify-center gap-10 h-full relative"
+      @click="handleClick">
+      <view class="relative">
+        <view class="text-xs text-center ellipsis-1" :class="[show ? 'text-primary' : 'text-fore-title ']">
+          {{ config.label }}
+        </view>
+        <view class="absolute -top-4 -right-4 w-6 h-6 bg-red-500 rounded-full" v-if="hasValue"></view>
+      </view>
+      <view :class="['transition-transform duration-300 ease-out', { 'rotate-180': show }]">
+        <uv-icon name="arrow-down" :color="show ? 'primary' : 'info'" size="14" />
+      </view>
+    </view>
+    <view v-show="isOpen" class="fixed left-0 right-0" :style="containerStyle">
+      <view class="fixed z-0 overflow-hidden" :id="`dropdown-content-${config.prop}`" :style="maskStyle"
+        @click="handleMaskClick">
+      </view>
+      <view class="relative z-1 overflow-hidden ">
+        <view
+          class="left-0 right-0 z-1 w-full bg-white max-h-300 overflow-auto p-24 box-border transition-transform duration-300 ease-out"
+          :style="contentStyle" @click="">
+          <view>
+            <uv-checkbox-group v-model="checkboxValue" placement="column" iconPlacement="right" borderBottom>
+              <uv-checkbox :customStyle="{ marginBottom: '8px' }" v-for="(item, index) in config.options" :key="index"
+                :label="item.label" :name="item.value"></uv-checkbox>
+            </uv-checkbox-group>
+          </view>
+          <view class="mt-10 flex items-center justify-between gap-24">
+            <view class="flex-1">
+              <uv-button type="primary" plain shape="circle" @click="handleReset">重置</uv-button>
+            </view>
+            <view class="flex-1">
+              <uv-button type="primary" shape="circle" @click="handleSubmit">确定</uv-button>
+            </view>
+          </view>
+        </view>
+      </view>
+    </view>
+
+  </view>
+</template>
+<script lang="ts" setup>
+import { type Dropdown } from '@/types';
+import { DROPDOWN_SYMBOL } from './ie-dropdown-hooks';
+import { getCurrentInstance } from 'vue';
+
+const instance = getCurrentInstance();
+
+const props = defineProps<{
+  config: Dropdown.DropdownItem;
+  index: number;
+}>();
+const dropdown = inject(DROPDOWN_SYMBOL);
+const triggerSelector = `#dropdown-trigger-${props.config.prop}`;
+const isOpen = ref(false);
+const show = ref(false);
+const isMeasuringHeight = ref(false);
+const top = ref(0);
+const hasValue = computed(() => {
+  return dropdown?.form.value[props.config.prop] && dropdown?.form.value[props.config.prop].length > 0;
+});
+
+const checkboxValue = ref([]);
+const containerStyle = computed(() => {
+  return {
+    top: `${top.value + 1}px`,
+  }
+});
+const maskStyle = computed(() => {
+  return {
+    top: `${top.value + 1}px`,
+    left: 0,
+    right: 0,
+    bottom: 0,
+    backgroundColor: 'rgba(0, 0, 0, 0.3)',
+    opacity: show.value ? 1 : 0,
+    transition: 'opacity 0.3s ease-out',
+  }
+});
+const contentStyle = computed(() => {
+  return {
+    transform: `translateY(${show.value ? '0' : '-100%'})`,
+  }
+});
+
+watch(() => dropdown?.openIndex.value, (newVal) => {
+  if (newVal === props.index) {
+    open();
+  } else {
+    if (isOpen.value) {
+      close();
+    }
+  }
+});
+
+const handleReset = () => {
+  checkboxValue.value = [];
+}
+const handleSubmit = () => {
+  dropdown?.submit(props.index, checkboxValue.value);
+  dropdown?.close();
+}
+
+const open = async () => {
+  checkboxValue.value = dropdown?.form.value[props.config.prop] || [];
+  isOpen.value = true;
+  const triggerRect = await getRect(triggerSelector);
+  top.value = triggerRect.top + triggerRect.height;
+  setTimeout(() => {
+    nextTick(() => {
+      show.value = true;
+    });
+  }, 20);
+}
+
+const close = () => {
+  show.value = false;
+  setTimeout(() => {
+    isOpen.value = false;
+  }, 300);
+}
+
+const getRect = (selector: string) => {
+  return new Promise((resolve: (rect: { top: number, height: number }) => void) => {
+    const query = uni.createSelectorQuery().in(instance?.proxy);
+    query.select(selector).boundingClientRect(function (rect) {
+      resolve(rect as { top: number, height: number });
+    }).exec();
+  });
+}
+
+const measureHeight = (selector: string) => {
+  return new Promise((resolve: (height: number) => void) => {
+    isMeasuringHeight.value = true;
+    setTimeout(() => {
+      nextTick(() => {
+        getRect(selector).then((res: any) => {
+          isMeasuringHeight.value = false;
+          setTimeout(() => {
+            nextTick(() => {
+              resolve(res?.height ?? 0);
+            });
+          }, 50);
+        });
+      });
+    }, 50);
+  });
+}
+
+const handleMaskClick = () => {
+  if (isOpen.value) {
+    dropdown?.close();
+  }
+}
+
+const handleClick = () => {
+  if (isOpen.value) {
+    dropdown?.close();
+  } else {
+    dropdown?.open(props.index);
+  }
+}
+</script>
+<style lang="scss" scoped></style>

+ 7 - 0
src/components/ie-dropdown/ie-dropdown-popup.vue

@@ -0,0 +1,7 @@
+<template>
+
+</template>
+<script lang="ts" setup>
+
+</script>
+<style lang="scss" scoped></style>

+ 33 - 0
src/components/ie-dropdown/ie-dropdown.vue

@@ -0,0 +1,33 @@
+<template>
+  <view class="flex items-center gap-20 px-20 h-[44px] border-0 border-b border-solid border-border-light">
+    <view v-for="(item, index) in configs" :key="item.prop" class="flex-1 min-w-1 h-full">
+      <ie-dropdown-item :config="item" :index="index" />
+    </view>
+  </view>
+</template>
+<script lang="ts" setup>
+import IeDropdownItem from './ie-dropdown-item.vue';
+import { type Dropdown } from '@/types';
+import { useDropdown, DROPDOWN_SYMBOL } from './ie-dropdown-hooks';
+
+const emit = defineEmits<{
+  (e: 'change', value: any): void;
+}>();
+const modelValue = defineModel<Record<string, any>>();
+const props = defineProps<{
+  configs: Dropdown.DropdownItem[];
+}>();
+const dropdown = useDropdown(props.configs);
+
+watch(() => dropdown.form.value, (newVal) => {
+  modelValue.value = newVal;
+  emit('change', newVal);
+}, {
+  deep: true
+});
+provide(DROPDOWN_SYMBOL, dropdown);
+onMounted(() => {
+  dropdown.init(modelValue.value || {});
+});
+</script>
+<style lang="scss" scoped></style>

+ 6 - 6
src/pages.json

@@ -87,6 +87,12 @@
             "navigationBarTitleText": ""
           }
         },
+        {
+          "path": "pages/university/picker/picker",
+          "style": {
+            "navigationBarTitleText": ""
+          }
+        },
         {
           "path": "pages/career/index/index",
           "style": {
@@ -129,12 +135,6 @@
             "navigationBarTitleText": ""
           }
         },
-        {
-          "path": "pages/university/picker/picker",
-          "style": {
-            "navigationBarTitleText": ""
-          }
-        },
         {
           "path": "pages/university/intro/intro",
           "style": {

+ 1 - 1
src/pagesMain/pages/index/components/index-banner.vue

@@ -15,7 +15,7 @@
 </template>
 <script lang="ts" setup>
 import { useTransferPage } from '@/hooks/useTransferPage';
-const { transferTo } = useTransferPage();
+const { transferTo, routes } = useTransferPage();
 import { useUserStore } from '@/store/userStore';
 import { Transfer } from '@/types';
 import {routes} from "@/common/routes";

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

@@ -1,88 +1,85 @@
 <template>
-    <view class="h-full">
-        <z-paging ref="paging" v-model="list" @query="handleQuery">
-            <template #top>
-                <slot name="top"/>
-                <college-conditions-picker :options="filterOptions"/>
-                <ie-search v-model="queryParams.name" placeholder="输入院校名称" @search="handleSearch"
-                           @clear="handleSearch"/>
-            </template>
-            <view class="p-20 flex flex-col gap-20">
-                <college-item v-for="i in list" :key="i.code" :item="i" @click="handleDetail(i)"/>
-            </view>
-        </z-paging>
-    </view>
+  <view class="h-full">
+    <z-paging ref="paging" v-model="list" @query="handleQuery">
+      <template #top>
+        <slot name="top" />
+        <college-conditions-picker :options="filterOptions" />
+        <ie-search v-model="queryParams.name" placeholder="输入院校名称" @search="handleSearch" @clear="handleSearch" />
+      </template>
+      <view class="p-20 flex flex-col gap-20">
+        <college-item v-for="i in list" :key="i.code" :item="i" @click="handleDetail(i)" />
+      </view>
+    </z-paging>
+  </view>
 </template>
 
 <script setup lang="ts">
-import {useTransferPage} from "@/hooks/useTransferPage";
-import {getUniversityFilters, universityList} from "@/api/modules/university";
-import {University, UniversityQueryDto} from "@/types/university";
-import {UNIVERSITY_FILTER} from "@/types/injectionSymbols";
+import { useTransferPage } from "@/hooks/useTransferPage";
+import { getUniversityFilters, universityList } from "@/api/modules/university";
+import { University, UniversityQueryDto } from "@/types/university";
+import { UNIVERSITY_FILTER } from "@/types/injectionSymbols";
 import CollegeConditionsPicker from "@/pagesOther/pages/university/index/components/plus/college-conditions-picker.vue";
 import CollegeItem from "@/pagesOther/pages/university/index/components/plus/college-item.vue";
-import {routes} from "@/common/routes";
+import { routes } from "@/common/routes";
 
 const props = withDefaults(defineProps<{
-    customItemClick: boolean;
-    extraFilter: Record<string, any>;
+  customItemClick?: boolean;
+  extraFilter?: Record<string, any>;
 }>(), {
-    customItemClick: false,
-    extraFilter: () => ({})
+  customItemClick: false,
+  extraFilter: () => ({})
 })
 const emits = defineEmits(['item-click'])
 
-const {prevData, transferTo} = useTransferPage()
+const { prevData, transferTo } = useTransferPage()
 const paging = ref<ZPagingInstance>()
 const list = ref<University[]>([])
 const filterOptions = ref<Record<string, any>>({})
 const queryParams = ref<UniversityQueryDto>({
-    name: '',
-    features: [],
-    type: [],
-    natureTypeCN: [],
-    location: [],
-    level: [],
-    tier: []
+  name: '',
+  features: [],
+  type: [],
+  natureTypeCN: [],
+  location: [],
+  level: [],
+  tier: []
 })
 
 const handleSearch = async () => {
-    paging.value?.reload();
+  paging.value?.reload();
 }
 
 const handleQuery = (pageNum: number, pageSize: number) => {
-    const query = {pageNum, pageSize, ...props.extraFilter, ...queryParams.value}
-    universityList(query)
-        .then(res => paging.value?.completeByTotal(res.rows, res.total))
-        .catch(e => paging.value?.complete(false))
+  const query = { pageNum, pageSize, ...props.extraFilter, ...queryParams.value }
+  universityList(query)
+    .then(res => paging.value?.completeByTotal(res.rows, res.total))
+    .catch(e => paging.value?.complete(false))
 }
 
 const handleDetail = (u: University) => {
-    if (props.customItemClick) return emits('item-click', u)
-    const {id, code, name} = u
-    transferTo(routes.universityDetail, {data: {id, code, name}})
+  if (props.customItemClick) return emits('item-click', u)
+  const { id, code, name } = u
+  transferTo(routes.universityDetail, { data: { id, code, name } })
 }
 
 provide(UNIVERSITY_FILTER, queryParams)
 
 watch([
-    () => queryParams.value.features,
-    () => queryParams.value.type,
-    () => queryParams.value.natureTypeCN,
-    () => queryParams.value.location,
-    () => queryParams.value.level,
-    () => queryParams.value.tier
+  () => queryParams.value.features,
+  () => queryParams.value.type,
+  () => queryParams.value.natureTypeCN,
+  () => queryParams.value.location,
+  () => queryParams.value.level,
+  () => queryParams.value.tier
 ], () => handleSearch())
 
 onMounted(async () => {
-    const {data} = await getUniversityFilters()
-    filterOptions.value = data
-    // accept default query parameters
-    if (prevData.tier) queryParams.value.tier = [prevData.tier]
+  const { data } = await getUniversityFilters()
+  filterOptions.value = data
+  // accept default query parameters
+  if (prevData.value.tier) queryParams.value.tier = [prevData.value.tier]
 })
 
 </script>
 
-<style scoped>
-
-</style>
+<style scoped></style>

+ 159 - 160
src/pagesStudy/pages/targeted-add/targeted-add.vue

@@ -1,206 +1,205 @@
 <template>
-    <ie-page bg-color="#F6F8FA" :fix-height="true">
-        <ie-navbar :title="title"/>
-        <view class="mt-16 bg-white py-10">
-            <view class="">
-                <uv-cell-group :border="false">
-                    <uv-cell isLink :border="true" :cellStyle="cellStyle" :rightIconStyle="rightIconStyle"
-                             @click="handleUniversitySelect">
-                        <template #title>
-                            <text class="text-30 text-fore-subtitle whitespace-nowrap">选择院校</text>
-                        </template>
-                        <template #value>
-                            <text v-if="form.universityName" class="mx-10 text-30 text-fore-title">
-                                {{ form.universityName }}
-                            </text>
-                            <text v-else class="mr-10 text-30 text-fore-placeholder">请选择</text>
-                        </template>
-                    </uv-cell>
-                    <uv-cell isLink :border="false" :cellStyle="cellStyle" :rightIconStyle="rightIconStyle"
-                             @click="handleMajorSelect">
-                        <template #title>
-                            <text class="text-30 text-fore-subtitle whitespace-nowrap">选择专业</text>
-                        </template>
-                        <template #value>
-                            <text v-if="form.majorName" class="mx-10 text-30 text-fore-title">
-                                {{ form.majorName }}
-                            </text>
-                            <text v-else class="mr-10 text-30 text-fore-placeholder">请选择</text>
-                        </template>
-                    </uv-cell>
-                </uv-cell-group>
-            </view>
+  <ie-page bg-color="#F6F8FA" :fix-height="true">
+    <ie-navbar :title="title" />
+    <view class="mt-16 bg-white py-10">
+      <view class="">
+        <uv-cell-group :border="false">
+          <uv-cell isLink :border="true" :cellStyle="cellStyle" :rightIconStyle="rightIconStyle"
+            @click="handleUniversitySelect">
+            <template #title>
+              <text class="text-30 text-fore-subtitle whitespace-nowrap">选择院校</text>
+            </template>
+            <template #value>
+              <text v-if="form.universityName" class="mx-10 text-30 text-fore-title">
+                {{ form.universityName }}
+              </text>
+              <text v-else class="mr-10 text-30 text-fore-placeholder">请选择</text>
+            </template>
+          </uv-cell>
+          <uv-cell isLink :border="false" :cellStyle="cellStyle" :rightIconStyle="rightIconStyle"
+            @click="handleMajorSelect">
+            <template #title>
+              <text class="text-30 text-fore-subtitle whitespace-nowrap">选择专业</text>
+            </template>
+            <template #value>
+              <text v-if="form.majorName" class="mx-10 text-30 text-fore-title">
+                {{ form.majorName }}
+              </text>
+              <text v-else class="mr-10 text-30 text-fore-placeholder">请选择</text>
+            </template>
+          </uv-cell>
+        </uv-cell-group>
+      </view>
+    </view>
+    <ie-safe-toolbar :height="84" :shadow="false">
+      <view class="px-46 pt-24">
+        <ie-button type="primary" @click="handleAdd">确认</ie-button>
+      </view>
+    </ie-safe-toolbar>
+    <ie-popup ref="popupRef" title="选择专业" @confirm="handleConfirm">
+      <view class="h-[50vh] bg-white px-30 pt-20 flex flex-col">
+        <view>
+          <uv-search v-model="keyword" shape="square" :showAction="false" placeholder="请输入专业名称" />
         </view>
-        <ie-safe-toolbar :height="84" :shadow="false">
-            <view class="px-46 pt-24">
-                <ie-button type="primary" @click="handleAdd">确认</ie-button>
-            </view>
-        </ie-safe-toolbar>
-        <ie-popup ref="popupRef" title="选择专业" @confirm="handleConfirm">
-            <view class="h-[50vh] bg-white px-30 pt-20 flex flex-col">
-                <view>
-                    <uv-search v-model="keyword" shape="square" :showAction="false" placeholder="请输入专业名称"/>
+        <view class="mt-20 flex-1 min-h-1">
+          <scroll-view scroll-y class="h-full">
+            <view v-for="item in filteredMajorList" :key="item.id"
+              class="px-20 py-16 bg-white sibling-border-top flex items-center gap-x-20" @click="handleSelect(item)">
+              <view class="flex-1 min-w-1 flex-shrink-0">
+                <view class="flex items-center gap-x-10 text-fore-title">
+                  <span class="text-30 " :class="[isActive(item) ? 'text-primary' : 'text-fore-title']">{{
+                    item.name
+                  }}</span>
+                  <span v-if="item.notice" class="text-22 text-fore-light flex-1 min-w-1 ellipsis-1"
+                    :class="[isActive(item) ? 'text-primary' : 'text-fore-title']">{{
+                      `(${item.notice})`
+                    }}</span>
                 </view>
-                <view class="mt-20 flex-1 min-h-1">
-                    <scroll-view scroll-y class="h-full">
-                        <view v-for="item in filteredMajorList" :key="item.id"
-                              class="px-20 py-16 bg-white sibling-border-top flex items-center gap-x-20"
-                              @click="handleSelect(item)">
-                            <view class="flex-1 min-w-1 flex-shrink-0">
-                                <view class="flex items-center gap-x-10 text-fore-title">
-                                <span class="text-30 " :class="[isActive(item) ? 'text-primary' : 'text-fore-title']">{{
-                                        item.name
-                                    }}</span>
-                                    <span v-if="item.notice" class="text-22 text-fore-light flex-1 min-w-1 ellipsis-1"
-                                          :class="[isActive(item) ? 'text-primary' : 'text-fore-title']">{{
-                                            `(${item.notice})`
-                                        }}</span>
-                                </view>
-                                <view class="mt-6 text-22 text-fore-light"
-                                      :class="[isActive(item) ? 'text-primary' : 'text-fore-light']">
-                                    {{
-                                        item.ancestors
-                                    }}
-                                </view>
-                            </view>
-                            <uv-icon v-if="isActive(item)" name="checkmark" size="20" color="#31A0FC"/>
-                        </view>
-                    </scroll-view>
+                <view class="mt-6 text-22 text-fore-light"
+                  :class="[isActive(item) ? 'text-primary' : 'text-fore-light']">
+                  {{
+                    item.ancestors
+                  }}
                 </view>
+              </view>
+              <uv-icon v-if="isActive(item)" name="checkmark" size="20" color="#31A0FC" />
             </view>
-        </ie-popup>
-    </ie-page>
+          </scroll-view>
+        </view>
+      </view>
+    </ie-popup>
+  </ie-page>
 </template>
 
 <script lang="ts" setup>
-import {useTransferPage} from '@/hooks/useTransferPage';
-import {University} from '@/types/university';
-import {DirectedSchool, UniversityMajor} from '@/types/study';
-import {SelectedUniversityMajor} from '@/types/voluntary';
-import {getUniversityMajorList} from '@/api/modules/university';
-import {useUserStore} from '@/store/userStore';
-import {routes} from "@/common/routes";
-import {UniversityPickerPageOptions} from "@/types/transfer";
+import { useTransferPage } from '@/hooks/useTransferPage';
+import { University } from '@/types/university';
+import { DirectedSchool, UniversityMajor } from '@/types/study';
+import { SelectedUniversityMajor } from '@/types/voluntary';
+import { getUniversityMajorList } from '@/api/modules/university';
+import { useUserStore } from '@/store/userStore';
+import { routes } from "@/common/routes";
+import { UniversityPickerPageOptions } from "@/types/transfer";
 
 const userStore = useUserStore();
-const {prevData, transferTo, transferBack} = useTransferPage<UniversityPickerPageOptions, any>();
-const {directedSchoolList} = toRefs(userStore);
+const { prevData, transferTo, transferBack } = useTransferPage<UniversityPickerPageOptions, any>();
+const { directedSchoolList } = toRefs(userStore);
 const form = ref<Partial<SelectedUniversityMajor>>({});
 const keyword = ref('');
 const cellStyle = {
-    padding: '20rpx 40rpx'
+  padding: '20rpx 40rpx'
 }
 const rightIconStyle = {
-    fontSize: '14px'
+  fontSize: '14px'
 }
 const majorList = ref<UniversityMajor[]>([]);
 const filteredMajorList = computed(() => {
-    return majorList.value.filter(item => item.name.includes(keyword.value));
+  return majorList.value.filter(item => item.name.includes(keyword.value));
 });
 const title = computed(() => prevData.value.title || '添加定向院校')
 const handleUniversitySelect = () => {
-    transferTo(routes.universityPicker).then((res: any) => {
-        if (res) {
-            const university = res as University;
-            if (university.code !== form.value.universityId) {
-                selectedMajor.value = null;
-                form.value.majorId = '';
-                form.value.majorName = '';
-            }
-            form.value.universityId = university.code;
-            form.value.universityName = university.name;
-            form.value.universityLogo = university.logo;
-            form.value.info = university;
-            loadMajorList(university.code);
-        }
-    });
+  transferTo(routes.universityPicker).then((res: any) => {
+    if (res) {
+      const university = res as University;
+      if (university.code !== form.value.universityId) {
+        selectedMajor.value = null;
+        form.value.majorId = '';
+        form.value.majorName = '';
+      }
+      form.value.universityId = university.code;
+      form.value.universityName = university.name;
+      form.value.universityLogo = university.logo;
+      form.value.info = university;
+      loadMajorList(university.code);
+    }
+  });
 }
 
 const popupRef = ref();
 const selectedMajor = ref<Pick<UniversityMajor, 'ancestors' | 'code' | 'id' | 'name'> | null>(null);
 const handleMajorSelect = () => {
-    if (!form.value.universityId) {
-        uni.$ie.showToast('请选择院校');
-        return;
+  if (!form.value.universityId) {
+    uni.$ie.showToast('请选择院校');
+    return;
+  }
+  keyword.value = '';
+  if (form.value.majorId) {
+    selectedMajor.value = {
+      ancestors: form.value.majorAncestors || '',
+      code: form.value.majorId || '',
+      id: Number(form.value.majorId),
+      name: form.value.majorName || ''
     }
-    keyword.value = '';
-    if (form.value.majorId) {
-        selectedMajor.value = {
-            ancestors: form.value.majorAncestors || '',
-            code: form.value.majorId || '',
-            id: Number(form.value.majorId),
-            name: form.value.majorName || ''
-        }
-    } else {
-        selectedMajor.value = null;
-    }
-    popupRef.value.open();
+  } else {
+    selectedMajor.value = null;
+  }
+  popupRef.value.open();
 }
 
 const handleConfirm = () => {
-    if (!selectedMajor.value) {
-        uni.$ie.showToast('请选择专业');
-        return;
-    }
-    form.value.majorAncestors = selectedMajor.value.ancestors;
-    form.value.majorId = selectedMajor.value.id.toString();
-    form.value.majorName = selectedMajor.value.name;
-    popupRef.value.close();
+  if (!selectedMajor.value) {
+    uni.$ie.showToast('请选择专业');
+    return;
+  }
+  form.value.majorAncestors = selectedMajor.value.ancestors;
+  form.value.majorId = selectedMajor.value.id.toString();
+  form.value.majorName = selectedMajor.value.name;
+  popupRef.value.close();
 }
 const handleSelect = (item: UniversityMajor) => {
-    selectedMajor.value = item;
+  selectedMajor.value = item;
 }
 
 const handleAdd = async () => {
-    if (!form.value.universityId) {
-        uni.$ie.showToast('请选择院校');
-        return;
-    }
-    if (!form.value.majorId) {
-        uni.$ie.showToast('请选择专业');
-        return;
+  if (!form.value.universityId) {
+    uni.$ie.showToast('请选择院校');
+    return;
+  }
+  if (!form.value.majorId) {
+    uni.$ie.showToast('请选择专业');
+    return;
+  }
+  if (prevData.value.fromVoluntary === true) {
+    // 志愿类
+    if (prevData.value.selectedUniversityId === form.value.universityId &&
+      prevData.value.selectedMajorId === form.value.majorId) {
+      return uni.$ie.showToast('请勿选择相同院校专业')
     }
-    if (prevData.value.fromVoluntary === true) {
-        // 志愿类
-        if (prevData.value.selectedUniversityId === form.value.universityId &&
-            prevData.value.selectedMajorId === form.value.majorId) {
-            return uni.$ie.showToast('请勿选择相同院校专业')
-        }
-        return transferBack(form.value)
-    }
-    // 检查数据是否已存在
-    const historyData = directedSchoolList.value;
-    const isExist = historyData.some(item => item.universityId === form.value.universityId && item.majorId === form.value.majorId);
-    if (isExist) {
-        uni.$ie.showToast('该院校专业已存在');
-        return;
-    }
-    uni.$ie.showLoading();
-    const params = {
-        ...form.value,
-        code: form.value.universityId
-    } as DirectedSchool;
-    await userStore.saveDirectedSchoolList([params, ...directedSchoolList.value]);
-    uni.$ie.hideLoading();
-    uni.$ie.showSuccess('保存成功');
-    setTimeout(() => {
-        transferTo('/pagesStudy/pages/targeted-setting/targeted-setting', {
-            type: 'redirectTo'
-        });
-    }, 600);
+    return transferBack(form.value)
+  }
+  // 检查数据是否已存在
+  const historyData = directedSchoolList.value;
+  const isExist = historyData.some(item => item.universityId === form.value.universityId && item.majorId === form.value.majorId);
+  if (isExist) {
+    uni.$ie.showToast('该院校专业已存在');
+    return;
+  }
+  uni.$ie.showLoading();
+  const params = {
+    ...form.value,
+    code: form.value.universityId
+  } as DirectedSchool;
+  await userStore.saveDirectedSchoolList([params, ...directedSchoolList.value]);
+  uni.$ie.hideLoading();
+  uni.$ie.showSuccess('保存成功');
+  setTimeout(() => {
+    transferTo('/pagesStudy/pages/targeted-setting/targeted-setting', {
+      type: 'redirectTo'
+    });
+  }, 600);
 }
 const isActive = (item: UniversityMajor) => {
-    return selectedMajor.value && selectedMajor.value.id === item.id;
+  return selectedMajor.value && selectedMajor.value.id === item.id;
 }
 const loadMajorList = async (universityId: string) => {
-    uni.$ie.showLoading();
-    const {data} = await getUniversityMajorList({universityId});
-    majorList.value = data;
-    uni.$ie.hideLoading();
+  uni.$ie.showLoading();
+  const { data } = await getUniversityMajorList({ universityId });
+  majorList.value = data;
+  uni.$ie.hideLoading();
 }
 
 onLoad(() => {
-    handleUniversitySelect();
+  handleUniversitySelect();
 });
 </script>
 

+ 14 - 0
src/types/dropdown.ts

@@ -0,0 +1,14 @@
+export interface DropdownItem {
+  placeholder?: string;
+  label: string;
+  value: string | number;
+  prop: string;
+  keyName?: string;
+  keyValue?: string;
+  options?: DropdownOption[];
+}
+
+export interface DropdownOption {
+  label: string;
+  value: string | number;
+}

+ 3 - 4
src/types/index.ts

@@ -8,9 +8,12 @@ import * as Career from "./career";
 import * as Tree from "./tree";
 import * as Voluntary from "./voluntary";
 import * as University from "./university";
+import * as Dropdown from "./dropdown";
 import { VipCardInfo } from "./user";
 import { EnumExamMode, EnumExamType, EnumReviewMode } from "@/common/enum";
 
+export { Study, User, News, Transfer, System, Major, Career, Tree, Voluntary, Dropdown, University };
+
 /// 接口响应
 export interface ApiResponse<T> {
   code: number;
@@ -143,7 +146,3 @@ export interface Entity {
   updateBy: string | null;
   updateTime: string | null;
 }
-
-
-
-export { Study, User, News, Transfer, System, Major, Career, Tree, Voluntary, University };

+ 4 - 4
src/types/injectionSymbols.ts

@@ -1,7 +1,7 @@
-import type {InjectionKey} from 'vue'
-import {StudyPlan, StudyPlanStats} from './study';
-import {Study, Transfer, University, Voluntary, Major} from '.';
-import {useExam} from '@/composables/useExam';
+import type { InjectionKey } from 'vue'
+import { StudyPlan, StudyPlanStats } from './study';
+import { Study, Transfer, University, Voluntary, Major } from '.';
+import { useExam } from '@/composables/useExam';
 
 /**
  * 打开知识点记录详情

+ 0 - 2
vite.config.js

@@ -6,7 +6,6 @@ import uniTailwind from '@uni-helper/vite-plugin-uni-tailwind';
 import AutoImport from 'unplugin-auto-import/vite';
 import Components from 'unplugin-vue-components/vite';
 import { resolve } from 'node:path';
-import uniPolyfill from 'vite-plugin-uni-polyfill';
 import viteCompression from "vite-plugin-compression";
 import { env as envConfig } from './src/config';
 // https://vitejs.dev/config/
@@ -67,7 +66,6 @@ export default defineConfig(({ mode }) => ({
     }),
     uni(),
     uniTailwind(),
-    uniPolyfill(), // 解决vueuse/core10版本及以上运行到小程序报错
   ],
   css: {
     postcss: {