|
|
@@ -0,0 +1,205 @@
|
|
|
+<template>
|
|
|
+ <view class="bg-white flex flex-col h-[350px]">
|
|
|
+ <view class="flex flex-1 min-h-1">
|
|
|
+ <scroll-view scroll-y class="h-full w-[80px] bg-back-light">
|
|
|
+ <view v-for="(item, index) in list" :key="item.name" class="h-[36px] px-20 flex items-center"
|
|
|
+ :class="[currentIndex === index ? 'bg-white text-primary' : 'text-fore-title']" @click="handleClick(index)">
|
|
|
+ <view class="text-[13px] ellipsis-1">{{ item.name }}</view>
|
|
|
+ </view>
|
|
|
+ </scroll-view>
|
|
|
+ <scroll-view scroll-y class="flex-1 min-w-1 h-full bg-white">
|
|
|
+ <view class="grid grid-cols-3 gap-20 p-20">
|
|
|
+ <view v-for="item in childrenList" :key="item.name"
|
|
|
+ class="h-[34px] px-20 flex items-center rounded-6 bg-back-light border border-solid relative overflow-hidden"
|
|
|
+ :class="[isSelected(item) ? 'border-primary text-primary' : 'border-transparent text-fore-title']"
|
|
|
+ @click="handleChildrenClick(item)">
|
|
|
+ <view v-if="isSelected(item)" class="absolute bottom-0 -right-2 p-2 bg-primary rounded-tl-4 rounded-br-6">
|
|
|
+ <uv-icon name="checkmark" size="10" color="#fff" />
|
|
|
+ </view>
|
|
|
+ <view class="flex-1 min-w-1 text-[13px] text-center ellipsis-1">{{ item.name }}</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </scroll-view>
|
|
|
+ </view>
|
|
|
+ <view class="flex items-center justify-between gap-24 p-[12px]">
|
|
|
+ <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">
|
|
|
+ <text>确定</text>
|
|
|
+ </uv-button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+<script lang="ts" setup>
|
|
|
+import { getUniversityLocation } from "@/api/modules/university";
|
|
|
+import type { Dropdown } from '@/types';
|
|
|
+import { DROPDOWN_SYMBOL } from '@/components/ie-dropdown/ie-dropdown-hooks';
|
|
|
+
|
|
|
+const props = defineProps<{
|
|
|
+ index: number;
|
|
|
+}>();
|
|
|
+const dropdown = inject(DROPDOWN_SYMBOL);
|
|
|
+
|
|
|
+type LocationItem = {
|
|
|
+ name: string;
|
|
|
+ parent?: string;
|
|
|
+ children: LocationItem[];
|
|
|
+}
|
|
|
+const list = ref<LocationItem[]>([]);
|
|
|
+const currentIndex = ref(0);
|
|
|
+const childrenList = computed(() => {
|
|
|
+ return list.value[currentIndex.value]?.children || [];
|
|
|
+});
|
|
|
+
|
|
|
+const selectedProvince = ref<string>('');
|
|
|
+const selectedCity = ref<string[]>([]);
|
|
|
+const selected = ref<LocationItem[]>([]);
|
|
|
+
|
|
|
+watch(() => dropdown?.openIndex.value, (newVal) => {
|
|
|
+ if (newVal === props.index) {
|
|
|
+ initValue();
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+const isSelected = (item: LocationItem) => {
|
|
|
+ const currentProvince = selected.value.find(province => province.name === item.parent);
|
|
|
+ if (currentProvince) {
|
|
|
+ return currentProvince.children.some(city => city.name === item.name);
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+const initValue = () => {
|
|
|
+ const { location } = dropdown?.form.value || {};
|
|
|
+ if (location) {
|
|
|
+ // eg. 湖南:长沙,张家界;河南:开封,郑州; 还原成 selected 数据
|
|
|
+ const locationParams: LocationItem[] = location.split(';').filter((item: string) => item).map((item: string) => {
|
|
|
+ return {
|
|
|
+ name: item.split(':')[0],
|
|
|
+ children: item.split(':')[1].split(',').map(city => {
|
|
|
+ return {
|
|
|
+ name: city,
|
|
|
+ parent: item.split(':')[0],
|
|
|
+ children: []
|
|
|
+ }
|
|
|
+ }),
|
|
|
+ }
|
|
|
+ });
|
|
|
+ const aar: LocationItem[] = [];
|
|
|
+ locationParams.forEach(item => {
|
|
|
+ aar.push({
|
|
|
+ name: item.name,
|
|
|
+ children: item.children
|
|
|
+ });
|
|
|
+ })
|
|
|
+ selected.value = aar;
|
|
|
+ // 找到第一个选中的省份
|
|
|
+ const firstIndex = list.value.findIndex(item => item.name === selected.value[0].name);
|
|
|
+ if (firstIndex !== -1) {
|
|
|
+ currentIndex.value = firstIndex;
|
|
|
+ } else {
|
|
|
+ currentIndex.value = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const handleReset = () => {
|
|
|
+ selected.value = [];
|
|
|
+};
|
|
|
+const handleSubmit = () => {
|
|
|
+ // eg. 湖南:长沙,张家界;河南:开封,郑州;
|
|
|
+ const value = selected.value.reduce((acc, item) => {
|
|
|
+ return acc + item.name + ':' + item.children.map(city => city.name).join(',') + ';';
|
|
|
+ }, '');
|
|
|
+ dropdown?.submit(props.index, value);
|
|
|
+ dropdown?.close();
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+const handleClick = (index: number) => {
|
|
|
+ currentIndex.value = index;
|
|
|
+ selectedProvince.value = list.value[index]?.name ?? '';
|
|
|
+ selectedCity.value = [];
|
|
|
+}
|
|
|
+
|
|
|
+const handleChildrenClick = (item: LocationItem) => {
|
|
|
+ selected.value = selected.value.filter(province => province.name === selectedProvince.value);
|
|
|
+ if (item.name === '不限') {
|
|
|
+ const currentProvince = list.value[currentIndex.value];
|
|
|
+ const currentSelected = selected.value.find(province => province.name === currentProvince.name);
|
|
|
+ if (currentSelected) {
|
|
|
+ currentSelected.children = [{
|
|
|
+ name: '不限',
|
|
|
+ children: []
|
|
|
+ }];
|
|
|
+ } else {
|
|
|
+ selected.value.push({
|
|
|
+ name: currentProvince.name,
|
|
|
+ children: [{
|
|
|
+ name: '不限',
|
|
|
+ children: []
|
|
|
+ }]
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ const currentProvince = list.value[currentIndex.value];
|
|
|
+ const currentSelected = selected.value.find(province => province.name === currentProvince.name);
|
|
|
+ if (currentSelected) {
|
|
|
+ currentSelected.children = currentSelected!.children.filter(city => city.name !== '不限');
|
|
|
+ if (currentSelected.children.findIndex(city => city.name === item.name) === -1) {
|
|
|
+ currentSelected.children.push(item);
|
|
|
+ } else {
|
|
|
+ currentSelected.children = currentSelected.children.filter(city => city.name !== item.name);
|
|
|
+ // 如果没有选中的,就自动选中不限
|
|
|
+ if (currentSelected.children.length === 0) {
|
|
|
+ currentSelected.children.push({
|
|
|
+ name: '不限',
|
|
|
+ parent: currentProvince.name,
|
|
|
+ children: []
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ selected.value.push({
|
|
|
+ name: currentProvince.name,
|
|
|
+ children: [item]
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+const loadData = () => {
|
|
|
+ getUniversityLocation().then(res => {
|
|
|
+ list.value = res.data.map(item => {
|
|
|
+ return {
|
|
|
+ name: item.location,
|
|
|
+ children: [
|
|
|
+ {
|
|
|
+ name: '不限',
|
|
|
+ parent: item.location,
|
|
|
+ children: []
|
|
|
+ },
|
|
|
+ ...item.cityName.map(city => {
|
|
|
+ return {
|
|
|
+ name: city,
|
|
|
+ parent: item.location,
|
|
|
+ children: []
|
|
|
+ }
|
|
|
+ })
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ selectedProvince.value = '';
|
|
|
+ selectedCity.value = [];
|
|
|
+ currentIndex.value = 0;
|
|
|
+});
|
|
|
+loadData();
|
|
|
+</script>
|
|
|
+<style lang="scss" scoped></style>
|