|
|
@@ -0,0 +1,773 @@
|
|
|
+<template>
|
|
|
+ <el-dialog
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ :visible.sync="addressView"
|
|
|
+ append-to-body
|
|
|
+ class="modal"
|
|
|
+ title="选择城市"
|
|
|
+ width="1100px">
|
|
|
+
|
|
|
+ <!-- 全选/清空操作栏 -->
|
|
|
+ <el-row :gutter="24" type="flex">
|
|
|
+ <el-col :span="24" class="item">
|
|
|
+ <div class="check-btn">
|
|
|
+ <el-checkbox v-model="iSselect" @change="allCheckbox">全选</el-checkbox>
|
|
|
+ <div class="empty" @click="empty">清空</div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 省市区三级展示 -->
|
|
|
+ <el-row :gutter="24" :loading="loading">
|
|
|
+ <el-col
|
|
|
+ :xl="6" :lg="6" :md="6" :sm="8" :xs="12"
|
|
|
+ class="province-item"
|
|
|
+ v-for="(province, provinceIndex) in cityList"
|
|
|
+ :key="province.cityId">
|
|
|
+
|
|
|
+ <!-- 省级复选框 -->
|
|
|
+ <div
|
|
|
+ class="province-wrapper"
|
|
|
+ @mouseenter="enter(provinceIndex)"
|
|
|
+ @mouseleave="leaveProvince(provinceIndex)"
|
|
|
+ :class="{ 'hovered': hoveredProvince === provinceIndex }">
|
|
|
+
|
|
|
+ <el-checkbox
|
|
|
+ v-model="province.checked"
|
|
|
+ :label="province.cityName"
|
|
|
+ :disabled="province.disabled"
|
|
|
+ @change="checkedProvince(provinceIndex)"
|
|
|
+ :class="{ 'disabled-checkbox': province.disabled }"
|
|
|
+ >
|
|
|
+ {{ province.cityName }}
|
|
|
+ <span v-if="province.count > 0" class="selected-count">(已选{{ province.count }}个)</span>
|
|
|
+ </el-checkbox>
|
|
|
+
|
|
|
+ <!-- 市级悬浮面板 -->
|
|
|
+ <div
|
|
|
+ class="city-panel"
|
|
|
+ v-show="activeCity === provinceIndex"
|
|
|
+ @mouseenter="enterCityPanel(provinceIndex)"
|
|
|
+ @mouseleave="leaveCityPanel(provinceIndex)">
|
|
|
+ <div class="checkBox">
|
|
|
+ <div class="arrow"></div>
|
|
|
+ <div class="city-list">
|
|
|
+ <div
|
|
|
+ class="city-item"
|
|
|
+ v-for="(city, cityIndex) in province.children"
|
|
|
+ :key="city.cityId">
|
|
|
+
|
|
|
+ <!-- 市级复选框 -->
|
|
|
+ <el-checkbox
|
|
|
+ v-model="city.checked"
|
|
|
+ :label="city.cityName"
|
|
|
+ :disabled="city.disabled"
|
|
|
+ @change="checkedCity(provinceIndex, cityIndex)"
|
|
|
+ :class="{ 'disabled-checkbox': city.disabled }"
|
|
|
+ >
|
|
|
+ {{ city.cityName }}
|
|
|
+ <span v-if="city.count > 0" class="selected-count">(已选{{ city.count }}个)</span>
|
|
|
+ </el-checkbox>
|
|
|
+
|
|
|
+ <!-- 县级列表 -->
|
|
|
+ <div v-if="city.children && city.children.length > 0" class="county-list">
|
|
|
+ <el-checkbox
|
|
|
+ v-for="(county, countyIndex) in city.children"
|
|
|
+ :key="county.cityId"
|
|
|
+ v-model="county.checked"
|
|
|
+ :label="county.cityName"
|
|
|
+ :disabled="county.disabled"
|
|
|
+ @change="checkedCounty(provinceIndex, cityIndex, countyIndex)"
|
|
|
+ class="county-item"
|
|
|
+ :class="{ 'disabled-checkbox': county.disabled }"
|
|
|
+ >
|
|
|
+ {{ county.cityName }}
|
|
|
+ </el-checkbox>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 对话框底部按钮 -->
|
|
|
+ <div slot="footer">
|
|
|
+ <el-button @click="close">取消</el-button>
|
|
|
+ <el-button type="primary" @click="confirm">确定</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { getAllList } from "@/api/hisStore/city";
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'CityZm',
|
|
|
+ props: {
|
|
|
+ type: {
|
|
|
+ type: Number,
|
|
|
+ default: 0
|
|
|
+ },
|
|
|
+ selectedCities: {
|
|
|
+ type: Array,
|
|
|
+ default: () => []
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ iSselect: false,
|
|
|
+ addressView: false,
|
|
|
+ cityList: [],
|
|
|
+ activeCity: -1,
|
|
|
+ loading: false,
|
|
|
+ // 增加相关状态
|
|
|
+ hoverTimer: null,
|
|
|
+ closeTimer: null,
|
|
|
+ hoveredProvince: -1,
|
|
|
+ hoveredPanel: false,
|
|
|
+ closeDelay: 300 // 延迟300ms关闭
|
|
|
+ };
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 打开对话框
|
|
|
+ open() {
|
|
|
+ this.addressView = true;
|
|
|
+ this.getCityList();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 鼠标进入省份
|
|
|
+ enter(index) {
|
|
|
+ clearTimeout(this.closeTimer);
|
|
|
+ this.hoveredProvince = index;
|
|
|
+ this.activeCity = index;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 鼠标离开省份
|
|
|
+ leaveProvince(index) {
|
|
|
+ // 延迟关闭,给用户时间移动到面板
|
|
|
+ this.closeTimer = setTimeout(() => {
|
|
|
+ if (!this.hoveredPanel || this.hoveredProvince !== index) {
|
|
|
+ this.activeCity = -1;
|
|
|
+ this.hoveredPanel = false;
|
|
|
+ this.hoveredProvince = -1;
|
|
|
+ }
|
|
|
+ }, this.closeDelay);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 鼠标进入面板
|
|
|
+ enterCityPanel(index) {
|
|
|
+ clearTimeout(this.closeTimer);
|
|
|
+ this.hoveredPanel = true;
|
|
|
+ this.hoveredProvince = index;
|
|
|
+ this.activeCity = index;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 鼠标离开面板
|
|
|
+ leaveCityPanel(index) {
|
|
|
+ this.closeTimer = setTimeout(() => {
|
|
|
+ this.activeCity = -1;
|
|
|
+ this.hoveredPanel = false;
|
|
|
+ this.hoveredProvince = -1;
|
|
|
+ }, this.closeDelay);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取省市区数据
|
|
|
+ async getCityList() {
|
|
|
+ this.loading = true;
|
|
|
+ try {
|
|
|
+ const res = await getAllList();
|
|
|
+ const allData = res.data || [];
|
|
|
+
|
|
|
+ // 分离三级数据
|
|
|
+ const provinces = allData.filter(item => item.level === 1);
|
|
|
+ const cities = allData.filter(item => item.level === 2);
|
|
|
+ const counties = allData.filter(item => item.level === 3);
|
|
|
+
|
|
|
+ // 构建省市区树形结构
|
|
|
+ this.cityList = provinces.map(province => {
|
|
|
+ const provinceCities = cities.filter(city => city.parentId === province.cityId);
|
|
|
+
|
|
|
+ const children = provinceCities.map(city => {
|
|
|
+ const cityCounties = counties.filter(county => county.parentId === city.cityId);
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...city,
|
|
|
+ checked: false,
|
|
|
+ disabled: false,
|
|
|
+ count: 0,
|
|
|
+ children: cityCounties.map(county => ({
|
|
|
+ ...county,
|
|
|
+ checked: false,
|
|
|
+ disabled: false
|
|
|
+ }))
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...province,
|
|
|
+ checked: false,
|
|
|
+ disabled: false,
|
|
|
+ count: 0,
|
|
|
+ children: children
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ // 标记已选择的数据
|
|
|
+ this.markSelectedCities();
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取城市数据失败:', error);
|
|
|
+ } finally {
|
|
|
+ this.loading = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 标记已选择的城市
|
|
|
+ markSelectedCities() {
|
|
|
+ if (!this.selectedCities || this.selectedCities.length === 0) return;
|
|
|
+
|
|
|
+ this.selectedCities.forEach(selectedProvince => {
|
|
|
+ const province = this.cityList.find(p => p.cityId === selectedProvince.cityId);
|
|
|
+ if (!province) return;
|
|
|
+
|
|
|
+ // 如果选择了整个省
|
|
|
+ if (!selectedProvince.children || selectedProvince.children.length === 0) {
|
|
|
+ province.disabled = true;
|
|
|
+ province.checked = true;
|
|
|
+ province.children?.forEach(city => {
|
|
|
+ city.disabled = true;
|
|
|
+ city.checked = true;
|
|
|
+ city.children?.forEach(county => {
|
|
|
+ county.disabled = true;
|
|
|
+ county.checked = true;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否选择了所有市
|
|
|
+ const allCitiesSelected = selectedProvince.children.length === province.children.length;
|
|
|
+
|
|
|
+ selectedProvince.children.forEach(selectedCity => {
|
|
|
+ const city = province.children.find(c => c.cityId === selectedCity.cityId);
|
|
|
+ if (!city) return;
|
|
|
+
|
|
|
+ // 如果选择了整个市
|
|
|
+ if (!selectedCity.children || selectedCity.children.length === 0) {
|
|
|
+ city.disabled = true;
|
|
|
+ city.checked = true;
|
|
|
+ city.children?.forEach(county => {
|
|
|
+ county.disabled = true;
|
|
|
+ county.checked = true;
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 选择了部分县
|
|
|
+ selectedCity.children.forEach(selectedCounty => {
|
|
|
+ const county = city.children.find(c => c.cityId === selectedCounty.cityId);
|
|
|
+ if (county) {
|
|
|
+ county.disabled = true;
|
|
|
+ county.checked = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 检查是否选择了所有县
|
|
|
+ const selectedCountyCount = selectedCity.children.length;
|
|
|
+ const totalCountyCount = city.children.length;
|
|
|
+ if (selectedCountyCount === totalCountyCount) {
|
|
|
+ city.disabled = true;
|
|
|
+ city.checked = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 如果选择了所有市,禁用省
|
|
|
+ if (allCitiesSelected) {
|
|
|
+ province.disabled = true;
|
|
|
+ province.checked = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 更新计数
|
|
|
+ this.updateAllCounts();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 全选/全不选
|
|
|
+ allCheckbox() {
|
|
|
+ this.cityList.forEach(province => {
|
|
|
+ if (!province.disabled) {
|
|
|
+ province.checked = this.iSselect;
|
|
|
+ this.updateProvinceCount(province);
|
|
|
+
|
|
|
+ province.children?.forEach(city => {
|
|
|
+ if (!city.disabled) {
|
|
|
+ city.checked = this.iSselect;
|
|
|
+ this.updateCityCount(city);
|
|
|
+
|
|
|
+ city.children?.forEach(county => {
|
|
|
+ if (!county.disabled) {
|
|
|
+ county.checked = this.iSselect;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 清空选择
|
|
|
+ empty() {
|
|
|
+ // 清除所有定时器
|
|
|
+ clearTimeout(this.hoverTimer);
|
|
|
+ clearTimeout(this.closeTimer);
|
|
|
+
|
|
|
+ this.cityList.forEach(province => {
|
|
|
+ if (!province.disabled) {
|
|
|
+ province.checked = false;
|
|
|
+ province.count = 0;
|
|
|
+
|
|
|
+ province.children?.forEach(city => {
|
|
|
+ if (!city.disabled) {
|
|
|
+ city.checked = false;
|
|
|
+ city.count = 0;
|
|
|
+
|
|
|
+ city.children?.forEach(county => {
|
|
|
+ if (!county.disabled) {
|
|
|
+ county.checked = false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ this.iSselect = false;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 选择省
|
|
|
+ checkedProvince(provinceIndex) {
|
|
|
+ const province = this.cityList[provinceIndex];
|
|
|
+ if (province.disabled) return;
|
|
|
+
|
|
|
+ const isChecked = province.checked;
|
|
|
+
|
|
|
+ province.children?.forEach(city => {
|
|
|
+ if (!city.disabled) {
|
|
|
+ city.checked = isChecked;
|
|
|
+ this.updateCityCount(city);
|
|
|
+
|
|
|
+ city.children?.forEach(county => {
|
|
|
+ if (!county.disabled) {
|
|
|
+ county.checked = isChecked;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ this.updateProvinceCount(province);
|
|
|
+ this.updateISselect();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 选择市
|
|
|
+ checkedCity(provinceIndex, cityIndex) {
|
|
|
+ const province = this.cityList[provinceIndex];
|
|
|
+ const city = province.children[cityIndex];
|
|
|
+ if (city.disabled) return;
|
|
|
+
|
|
|
+ const isChecked = city.checked;
|
|
|
+
|
|
|
+ // 选择/取消选择所有县
|
|
|
+ city.children?.forEach(county => {
|
|
|
+ if (!county.disabled) {
|
|
|
+ county.checked = isChecked;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ this.updateCityCount(city);
|
|
|
+ this.updateProvinceCount(province);
|
|
|
+ this.updateISselect();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 选择县
|
|
|
+ checkedCounty(provinceIndex, cityIndex, countyIndex) {
|
|
|
+ const province = this.cityList[provinceIndex];
|
|
|
+ const city = province.children[cityIndex];
|
|
|
+ const county = city.children[countyIndex];
|
|
|
+
|
|
|
+ if (county.disabled) return;
|
|
|
+
|
|
|
+ // 更新市的选择状态
|
|
|
+ this.updateCityCount(city);
|
|
|
+ // 更新省的选择状态
|
|
|
+ this.updateProvinceCount(province);
|
|
|
+ // 更新全选状态
|
|
|
+ this.updateISselect();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 更新市的选择计数
|
|
|
+ updateCityCount(city) {
|
|
|
+ if (!city.children || city.children.length === 0) return;
|
|
|
+
|
|
|
+ const selectedCounties = city.children.filter(county => county.checked && !county.disabled).length;
|
|
|
+ city.count = selectedCounties;
|
|
|
+
|
|
|
+ // 更新市的选中状态
|
|
|
+ const allCountiesSelected = selectedCounties === city.children.filter(c => !c.disabled).length;
|
|
|
+ city.checked = allCountiesSelected || selectedCounties > 0;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 更新省的选择计数
|
|
|
+ updateProvinceCount(province) {
|
|
|
+ if (!province.children || province.children.length === 0) return;
|
|
|
+
|
|
|
+ const selectedCities = province.children.filter(city => {
|
|
|
+ if (city.disabled) return true; // 已禁用的视为已选
|
|
|
+ return city.checked;
|
|
|
+ }).length;
|
|
|
+
|
|
|
+ province.count = selectedCities;
|
|
|
+
|
|
|
+ // 更新省的选中状态
|
|
|
+ const allCitiesSelected = selectedCities === province.children.filter(c => !c.disabled).length;
|
|
|
+ province.checked = allCitiesSelected || selectedCities > 0;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 更新全选状态
|
|
|
+ updateISselect() {
|
|
|
+ const enabledProvinces = this.cityList.filter(p => !p.disabled);
|
|
|
+ if (enabledProvinces.length === 0) {
|
|
|
+ this.iSselect = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const allProvincesSelected = enabledProvinces.every(province => province.checked);
|
|
|
+ this.iSselect = allProvincesSelected;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 更新所有计数
|
|
|
+ updateAllCounts() {
|
|
|
+ this.cityList.forEach(province => {
|
|
|
+ this.updateProvinceCount(province);
|
|
|
+ province.children?.forEach(city => {
|
|
|
+ this.updateCityCount(city);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ this.updateISselect();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 确定选择
|
|
|
+ confirm() {
|
|
|
+ const selectedData = this.getSelectedData();
|
|
|
+
|
|
|
+ if (selectedData.length === 0) {
|
|
|
+ this.$message.error('至少选择一个省份、城市或县区');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.$emit('selectCity', selectedData, this.type);
|
|
|
+ this.close();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取选择的数据
|
|
|
+ getSelectedData() {
|
|
|
+ const result = [];
|
|
|
+
|
|
|
+ this.cityList.forEach(province => {
|
|
|
+ // 检查省是否被选中(直接选中或通过选中所有市/县间接选中)
|
|
|
+ const isProvinceChecked = province.checked && !province.disabled;
|
|
|
+ const hasSelectedCities = province.children?.some(city =>
|
|
|
+ (city.checked && !city.disabled) ||
|
|
|
+ city.children?.some(county => county.checked && !county.disabled)
|
|
|
+ );
|
|
|
+
|
|
|
+ if (isProvinceChecked || hasSelectedCities) {
|
|
|
+ const provinceData = {
|
|
|
+ cityId: province.cityId,
|
|
|
+ name: province.cityName,
|
|
|
+ children: []
|
|
|
+ };
|
|
|
+
|
|
|
+ // 处理市级数据
|
|
|
+ province.children?.forEach(city => {
|
|
|
+ // 判断市是否被选中(直接选中或通过选中所有县间接选中)
|
|
|
+ const isCityChecked = city.checked && !city.disabled;
|
|
|
+ const selectedCounties = city.children?.filter(county => county.checked && !county.disabled) || [];
|
|
|
+ const hasSelectedCounties = selectedCounties.length > 0;
|
|
|
+
|
|
|
+ if (isCityChecked || hasSelectedCounties) {
|
|
|
+ const cityData = {
|
|
|
+ cityId: city.cityId,
|
|
|
+ name: city.cityName
|
|
|
+ };
|
|
|
+
|
|
|
+ // 如果有选中的县级,添加到市的 children 中
|
|
|
+ if (hasSelectedCounties && selectedCounties.length > 0) {
|
|
|
+ cityData.children = selectedCounties.map(county => ({
|
|
|
+ cityId: county.cityId,
|
|
|
+ name: county.cityName
|
|
|
+ }));
|
|
|
+ }
|
|
|
+
|
|
|
+ provinceData.children.push(cityData);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ result.push(provinceData);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return result;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 关闭对话框
|
|
|
+ close() {
|
|
|
+ // 清除所有定时器
|
|
|
+ clearTimeout(this.hoverTimer);
|
|
|
+ clearTimeout(this.closeTimer);
|
|
|
+
|
|
|
+ this.addressView = false;
|
|
|
+ this.cityList = [];
|
|
|
+ this.iSselect = false;
|
|
|
+ this.activeCity = -1;
|
|
|
+ this.hoveredProvince = -1;
|
|
|
+ this.hoveredPanel = false;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 清理定时器
|
|
|
+ beforeDestroy() {
|
|
|
+ clearTimeout(this.hoverTimer);
|
|
|
+ clearTimeout(this.closeTimer);
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.modal {
|
|
|
+ max-height: 80vh;
|
|
|
+ overflow-y: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.modal .province-item {
|
|
|
+ position: relative;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ min-height: 50px;
|
|
|
+}
|
|
|
+
|
|
|
+.province-wrapper {
|
|
|
+ position: relative;
|
|
|
+ padding: 8px 12px;
|
|
|
+ border-radius: 4px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: background-color 0.2s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.province-wrapper.hovered {
|
|
|
+ background-color: #f5f7fa;
|
|
|
+}
|
|
|
+
|
|
|
+.modal .city-panel {
|
|
|
+ position: absolute;
|
|
|
+ z-index: 1000;
|
|
|
+ top: 45px; /* 调整为刚好在复选框下方 */
|
|
|
+ left: 0;
|
|
|
+ width: 320px; /* 稍微加宽 */
|
|
|
+ min-height: 200px; /* 设置最小高度 */
|
|
|
+ background: #fff;
|
|
|
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
|
+ border: 1px solid #ebeef5;
|
|
|
+ border-radius: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.modal .checkBox {
|
|
|
+ padding: 15px;
|
|
|
+ border-radius: 4px;
|
|
|
+ max-height: 400px;
|
|
|
+ overflow-y: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.modal .arrow {
|
|
|
+ position: absolute;
|
|
|
+ top: -16px;
|
|
|
+ left: 20px;
|
|
|
+ width: 0;
|
|
|
+ height: 0;
|
|
|
+ border: 8px solid transparent;
|
|
|
+ border-bottom-color: #ebeef5;
|
|
|
+ z-index: 1001;
|
|
|
+}
|
|
|
+
|
|
|
+.modal .arrow:before {
|
|
|
+ position: absolute;
|
|
|
+ top: -7px;
|
|
|
+ left: -7px;
|
|
|
+ content: "";
|
|
|
+ width: 0;
|
|
|
+ height: 0;
|
|
|
+ border: 7px solid transparent;
|
|
|
+ border-bottom-color: #fff;
|
|
|
+ z-index: 1002;
|
|
|
+}
|
|
|
+
|
|
|
+.city-list {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 15px;
|
|
|
+}
|
|
|
+
|
|
|
+.city-item {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 8px;
|
|
|
+ padding: 4px;
|
|
|
+ border-radius: 4px;
|
|
|
+ transition: background-color 0.2s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.city-item:hover {
|
|
|
+ background-color: #f8f9fa;
|
|
|
+}
|
|
|
+
|
|
|
+.county-list {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 8px;
|
|
|
+ margin-left: 20px;
|
|
|
+ margin-top: 5px;
|
|
|
+ padding-left: 15px;
|
|
|
+ border-left: 1px dashed #dcdfe6;
|
|
|
+}
|
|
|
+
|
|
|
+.county-item {
|
|
|
+ width: calc(50% - 4px);
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.selected-count {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #409eff;
|
|
|
+ margin-left: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.empty {
|
|
|
+ cursor: pointer;
|
|
|
+ margin-left: 15px;
|
|
|
+ color: #f56c6c;
|
|
|
+ transition: color 0.2s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.empty:hover {
|
|
|
+ color: #f78989;
|
|
|
+}
|
|
|
+
|
|
|
+.check-btn {
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 15px;
|
|
|
+ padding: 10px 0;
|
|
|
+ border-bottom: 1px solid #ebeef5;
|
|
|
+}
|
|
|
+
|
|
|
+/* 禁用状态样式 */
|
|
|
+.disabled-checkbox {
|
|
|
+ opacity: 0.6;
|
|
|
+ cursor: not-allowed !important;
|
|
|
+}
|
|
|
+
|
|
|
+.disabled-checkbox /deep/ .el-checkbox__input.is-disabled {
|
|
|
+ cursor: not-allowed;
|
|
|
+}
|
|
|
+
|
|
|
+.disabled-checkbox /deep/ .el-checkbox__input.is-disabled .el-checkbox__inner {
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ border-color: #e4e7ed;
|
|
|
+}
|
|
|
+
|
|
|
+.disabled-checkbox /deep/ .el-checkbox__input.is-disabled + .el-checkbox__label {
|
|
|
+ color: #c0c4cc;
|
|
|
+}
|
|
|
+
|
|
|
+/* 鼠标悬停效果 */
|
|
|
+.province-wrapper:hover {
|
|
|
+ background-color: #f5f7fa;
|
|
|
+}
|
|
|
+
|
|
|
+/* 添加悬停提示 */
|
|
|
+.province-wrapper:hover:after {
|
|
|
+ content: "▼ 展开";
|
|
|
+ position: absolute;
|
|
|
+ right: 10px;
|
|
|
+ top: 50%;
|
|
|
+ transform: translateY(-50%);
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+ opacity: 0.8;
|
|
|
+}
|
|
|
+
|
|
|
+/* 确保复选框可点击区域足够大 */
|
|
|
+.province-wrapper /deep/ .el-checkbox {
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.province-wrapper /deep/ .el-checkbox__label {
|
|
|
+ display: inline-block;
|
|
|
+ width: calc(100% - 20px);
|
|
|
+ padding-right: 60px; /* 为悬停提示留出空间 */
|
|
|
+}
|
|
|
+
|
|
|
+/* 响应式设计 */
|
|
|
+@media (max-width: 1200px) {
|
|
|
+ .modal .city-panel {
|
|
|
+ width: 280px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@media (max-width: 992px) {
|
|
|
+ .modal .city-panel {
|
|
|
+ width: 250px;
|
|
|
+ left: -50px; /* 在小屏幕上调整位置 */
|
|
|
+ }
|
|
|
+
|
|
|
+ .modal .arrow {
|
|
|
+ left: 60px; /* 调整箭头位置 */
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@media (max-width: 768px) {
|
|
|
+ .modal {
|
|
|
+ width: 95% !important;
|
|
|
+ max-width: 600px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .modal .city-panel {
|
|
|
+ position: fixed;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ width: 90vw;
|
|
|
+ max-width: 400px;
|
|
|
+ max-height: 80vh;
|
|
|
+ z-index: 2000;
|
|
|
+ }
|
|
|
+
|
|
|
+ .county-item {
|
|
|
+ width: 100%; /* 小屏幕下一行一个 */
|
|
|
+ }
|
|
|
+
|
|
|
+ .modal .arrow {
|
|
|
+ display: none; /* 移动端隐藏箭头 */
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 为触摸设备优化 */
|
|
|
+@media (hover: none) and (pointer: coarse) {
|
|
|
+ .province-wrapper {
|
|
|
+ padding: 12px 15px; /* 增大点击区域 */
|
|
|
+ }
|
|
|
+
|
|
|
+ .city-panel {
|
|
|
+ border: 2px solid #409eff; /* 更明显的边框 */
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|