This commit is contained in:
2024-05-17 18:02:49 +08:00
parent 8407d51fb6
commit b5264dc222
4056 changed files with 308094 additions and 41932 deletions

View File

@@ -0,0 +1,412 @@
<template>
<uni-popup ref="popup" type="bottom" @change="popChange">
<view class="sx-address-picker">
<view class="sx-address-picker__close">
<uni-icons
class="absolute"
size="20"
color="#ccc"
type="closeempty"
@click="$refs.popup.close"
></uni-icons>
</view>
<view class="sx-address-picker__title"> 请选择所在地区 </view>
<!-- 已选择区域 -->
<uni-list v-for="item in activeItems" :key="item.code" :border="false">
<uni-list-item show-arrow clickable @click="selectLevel(item)">
<template v-slot:header>
<view :class="activeLevel === item.level - 1 ? 'primary-text' : ''"
>{{ item.name || selectTitle }}
</view>
</template>
</uni-list-item>
</uni-list>
<view class="sx-address-picker--divider"></view>
<view class="sx-address-picker__list">
<template v-if="activeLevel === -1">
<!-- 中国/海外切换 -->
<!-- <radio-group class="sx-address-picker__list-tab" @change="typeChange">
<label
v-for="(item, index) in worlds"
:key="item"
:class="
world == index ? 'sx-address-picker__list-tab--active' : ''
"
>
<radio
class="sx-address-picker__list-tab--hide"
:checked="world === item"
:value="index + ''"
/><text>{{ item }}</text>
</label>
</radio-group> -->
<!-- 后续计划TODO 常用城市 -->
<!-- <view class="font-5 font-weight-500 mb-4">
{{quickTitle}}
</view>
<radio-group class="flex flex-wrap" @change="quickIndex = $event.detail.value">
<label class="mr-3" v-for="(item,index) in quickList" :key="item"
:class="world == index? 'active':''">
<radio class="none" :checked="world === item" :value="index + ''" />
<view class="radius bg-445 px-4 py-1 mb-3">{{item}}</view>
</label>
</radio-group> -->
</template>
<view class="sx-address-picker__list-title">
{{ selectTitle }}
</view>
<view class="sx-address-picker__list-content" @click="reGetList">
<uni-load-more
v-if="loadingStatus !== 'more'"
:status="loadingStatus"
:content-text="{ contentnomore: '加载失败请点击重试' }"
></uni-load-more>
<!-- 省市区选择 -->
<uni-list v-if="world == 0" :border="false">
<uni-list-item
v-for="(item, index) in currentList"
:key="item.code"
:title="item.name"
:border="false"
clickable
@click="selectHandle(item, index)"
>
<template v-slot:footer>
<uni-icons
v-if="
activeItems[item.level]
? activeItems[item.level].code === item.code
: false
"
type="checkmarkempty"
class="sx-address-picker__list-tab--active"
></uni-icons>
</template>
</uni-list-item>
</uni-list>
<!-- 国家地区列表选择 -->
<uni-list v-else :border="false">
<uni-list-item
v-for="(item, index) in country.filter((v, i) => v.value !== 0)"
:key="item.id"
:title="item.name"
:border="false"
clickable
@click="selectHandle(item, index, true)"
>
<template v-slot:footer>
<uni-icons
v-if="countryName == item.name"
type="checkmarkempty"
class="sx-address-picker__list-tab--active"
></uni-icons>
</template>
</uni-list-item>
</uni-list>
</view>
</view>
</view>
</uni-popup>
</template>
<script>
const cityDataUrl =
"https://static-mp-97eb3f65-f610-4509-81e4-a6cd5df3859b.next.bspapp.com/cos/data.json";
const countryDataUrl =
"https://static-mp-97eb3f65-f610-4509-81e4-a6cd5df3859b.next.bspapp.com/cos/country.json";
// 后续计划TODO 常用城市、国家
// const quickCitys = ['上海市', '北京市', '苏州市', '杭州市', '广州市', '深圳市', '南京市', '天津市']
// const quickCountys = ['中国香港', '中国澳门', '中国台湾', '新加坡']
export default {
props: {
value: Boolean,
selected: {
type: Array,
default() {
return [];
},
},
},
data() {
return {
// "港澳台地区及海外"
world: "0",
loading: true,
loadingStatus: "loading",
countryName: "",
country: [],
worlds: ["中国内地(大陆)", ],
quickIndex: "0",
list: [],
activeLevel: -1,
activeIndex: -1,
level0: "",
activeItems: [],
childList: [],
};
},
methods: {
clear() {
console.log(1111111111111111)
this.activeItems = [];
this.countryName = "";
this.level0 = "";
this.$forceUpdate()
},
// 弹窗是否显示状态事件
popChange(e) {
this.$emit("input", e.show);
},
// 已选择项切换事件
selectLevel(item) {
if (item.code && this.world === "0") {
this.activeLevel = item.level - 1;
}
},
typeChange(e) {
const value = e.detail.value;
this.world = value;
this.getList();
},
// 选择省市区/国家事件 isOhter区分选择省市区
selectHandle(item, index, isOhter = false) {
if (isOhter) {
// 选择国家
this.activeLevel = -1;
this.activeIndex = 0;
this.countryName = item.name;
this.activeItems = [item];
this.$refs.popup.close();
this.$emit("confirm", this.activeItems);
} else {
// 选择省市区
this.activeLevel = item.level;
this.activeIndex = index;
this.$set(this.activeItems, item.level, item);
this.activeItems.splice(item.level + 1);
if (item.children) {
this.$set(this.activeItems, item.level + 1, {});
} else {
this.$refs.popup.close();
this.$emit("confirm", [
{
code: "CN",
level: -1,
name: "中国",
},
...this.activeItems,
]);
}
}
},
// 获取中国省市区数据
getCityData() {
if (!this.list.length) {
this.loadingStatus = "loading";
// 循环给省市区增加level级别字段
const eachList = function (arr, level) {
arr.forEach((v) => {
v.level = level;
if (v.children) {
eachList(v.children, v.level + 1);
}
});
};
uni.request({
url: cityDataUrl,
success: (res) => {
const list = res.data;
if (Array.isArray(list)) {
eachList(list, 0);
this.list = list;
if (this.selected.length) {
const activeItems = [];
if (this.selected.length !== 1) {
activeItems[0] = this.list.find(
(v) => v.name === this.selected[1]
);
activeItems[1] = activeItems[0].children.find(
(v) => v.name === this.selected[2]
);
activeItems[2] = activeItems[1].children.find(
(v) => v.name === this.selected[3]
);
activeItems[3] = activeItems[2].children.find(
(v) => v.name === this.selected[4]
);
this.activeItems = activeItems;
this.activeLevel = 2;
} else {
this.activeLevel = -1;
}
}
this.loadingStatus = "more";
} else {
this.loadingStatus = "noMore";
}
},
fail: () => {
this.loadingStatus = "noMore";
},
});
} else {
this.loadingStatus = "more";
}
},
// 获取国家数据
getCountryData() {
if (this.world == 1 && !this.country.length) {
this.loadingStatus = "loading";
uni.request({
url: countryDataUrl,
success: (res) => {
const data = res.data;
if (data.others) {
const list = data.others.reduce((arr, v) => {
arr.push(...v.items);
return arr;
}, []);
this.country = list;
this.loadingStatus = "more";
} else {
this.loadingStatus = "noMore";
}
},
fail: () => {
this.loadingStatus = "noMore";
},
});
} else {
this.loadingStatus = "more";
}
},
reGetList() {
if (this.loadingStatus === "noMore") {
this.getList();
}
},
getList() {
switch (this.world) {
case "0":
this.getCityData();
break;
case "1":
this.getCountryData();
break;
}
},
},
computed: {
// 动态计算当前要选择的列表
currentList() {
if (this.activeLevel !== -1) {
return this.activeItems[this.activeLevel].children;
}
return this.list;
},
// 动态标题显示
selectTitle() {
const titles = {
"-1": "请选择省份/地区",
0: "请选择城市",
1: "请选择区/县",
2: "请选择街道",
};
return titles[this.activeLevel];
},
// TODO 后续更新
// quickTitle() {
// const items = {
// 0: '常用城市',
// 1: '常用国家/地区'
// }
// return items[this.world]
// },
// TODO 后续计划 常用选项
// quickList() {
// return this.world === '0' ? quickCitys : quickCountys
// }
},
watch: {
// 监听value触发弹窗显示状态以及事件处理
async value(val) {
if (val) {
this.$refs.popup.open();
const countyName = this.selected[0];
this.world = this.selected.length === 1 ? "1" : "0";
if (this.activeItems.length === 4) {
this.activeLevel = 2;
}
this.countryName = countyName;
this.getList();
} else {
this.$refs.popup.close();
}
},
},
};
</script>
<style lang="scss" scoped>
.sx-address-picker {
border-top-left-radius: 20px;
border-top-right-radius: 20px;
background-color: white;
padding-left: 8px;
padding-right: 8px;
padding-top: 16px;
font-size: 16px;
&__close {
text-align: right;
margin-right: 16px;
margin-top: 4px;
position: absolute;
left: 0;
right: 0;
}
&__title {
text-align: center;
font-weight: 500;
font-size: 18px;
margin-bottom: 20px;
}
&--divider {
border-top: 0.5px solid #ddd;
}
&__list {
max-height: 400px;
overflow-y: auto;
margin-top: 12px;
&-tab {
display: flex;
margin-bottom: 20px;
justify-content: space-between;
padding-left: 16px;
padding-right: 16px;
&--hide {
display: none;
}
&--active {
color: $uni-color-primary !important;
}
}
&-title {
font-weight: bold;
margin-bottom: 16px;
}
.uni-load-more {
padding: 100px 0;
}
}
}
</style>