2025/2/8第一次更新

This commit is contained in:
爱吃咸鱼小猫咪
2025-02-08 18:50:38 +08:00
commit d7af560866
26519 changed files with 5046029 additions and 0 deletions
@@ -0,0 +1 @@
export * from './use-region-picker'
@@ -0,0 +1,179 @@
import { nextTick, ref, watch } from 'vue'
import regionJsonData from '../../libs/region-data.json'
import { CHANGE_EVENT, UPDATE_MODEL_EVENT } from '../../../../constants'
import { cloneDeep } from '../../../../utils'
import type { SetupContext } from 'vue'
import type { RegionDataItem } from '../../libs'
import type {
RegionPickerEmits,
RegionPickerModelValueType,
RegionPickerProps,
} from '../region-picker'
type RegionModelValueMode = 'code' | 'name'
export const useRegionPicker = (
porps: RegionPickerProps,
emits: SetupContext<RegionPickerEmits>['emit']
) => {
// 列表数据
const pickerSelectData = regionJsonData
// 显示/隐藏地址选择器
const showPicker = ref(false)
watch(
() => porps.open,
(val) => {
showPicker.value = val
}
)
const _closePicker = () => {
emits('update:open', false)
}
// picker关闭事件
const handlePickerCloseEvent = () => {
_closePicker()
emits('close')
}
// 当前选中的值
const currentSelectValue = ref<RegionPickerModelValueType>([])
// 标记当前传递的值的类型
let userRegionValueMode: RegionModelValueMode = 'code'
// 根据name获取code
const getCodeByNames = (names: string[]): string[] => {
const code: string[] = []
let data: RegionDataItem[] = regionJsonData
do {
const name = names.shift()
const regionItem: RegionDataItem =
data.find((item) => item.name === name) || data[0]
if (regionItem) {
code.push(regionItem.code)
}
data = regionItem?.children || []
} while (data.length)
return code
}
// 根据code获取name
const getNameByCodes = (codes: string[]): string[] => {
const name: string[] = []
let data: RegionDataItem[] = regionJsonData
do {
const code = codes.shift()
const regionItem: RegionDataItem =
data.find((item) => item.code === code) || data[0]
if (regionItem) {
name.push(regionItem.name)
}
data = regionItem?.children || []
} while (data.length)
return name
}
/**
* 填充code
* @example 传递的是['44', '4401'] 返回 ['44', '4401', '440113']
*/
const fillCode = (codes: string[]): string[] => {
const result: string[] = []
let data: RegionDataItem[] = regionJsonData
do {
const code = codes.shift()
const regionItem: RegionDataItem =
data.find((item) => item.code === code) || data[0]
if (regionItem) {
result.push(regionItem.code)
}
data = regionItem?.children || []
} while (data.length)
return result
}
// 标记是否内部更新
let isInnerUpdate = false
watch(
() => porps.modelValue,
(val) => {
if (isInnerUpdate) {
isInnerUpdate = false
return
}
const chineseReg = /^[\u4E00-\u9FA5]+$/ // 中文正则
const codeReg = /^\d{2,6}$/ // 地区编码正则
if (val.length) {
const value = cloneDeep(val)
if (chineseReg.test(value[0])) {
userRegionValueMode = 'name'
currentSelectValue.value = getCodeByNames(value)
isInnerUpdate = true
emits(
UPDATE_MODEL_EVENT,
getNameByCodes(cloneDeep(currentSelectValue.value))
)
} else if (codeReg.test(value[0])) {
userRegionValueMode = 'code'
currentSelectValue.value = fillCode(value)
isInnerUpdate = true
emits(UPDATE_MODEL_EVENT, currentSelectValue.value)
}
}
},
{
immediate: true,
}
)
// picker发生改变回调
const handlePickerChangeEvent = (
value: string | number | (string | number)[],
index: number,
item: any
) => {
if (userRegionValueMode === 'name') {
value = getNameByCodes(value as string[])
}
isInnerUpdate = true
emits(CHANGE_EVENT, value as string[], item)
}
// picker确认事件
const handlePickerConfirmEvent = (
value: string | number | (string | number)[],
item: any
) => {
currentSelectValue.value = cloneDeep(value as string[])
if (userRegionValueMode === 'name') {
value = getNameByCodes(value as string[])
}
emits(UPDATE_MODEL_EVENT, value as string[])
nextTick(() => {
emits('confirm', value as string[], item)
})
_closePicker()
}
// picker取消事件
const handlePickerCancelEvent = () => {
_closePicker()
emits('cancel')
}
return {
pickerSelectData,
showPicker,
currentSelectValue,
handlePickerCloseEvent,
handlePickerChangeEvent,
handlePickerConfirmEvent,
handlePickerCancelEvent,
}
}
@@ -0,0 +1,3 @@
import type RegionPicker from './region-picker.vue'
export type TnRegionPickerInstance = InstanceType<typeof RegionPicker>
@@ -0,0 +1,36 @@
import { CHANGE_EVENT, UPDATE_MODEL_EVENT } from '../../../constants'
import { buildProps, definePropType, isArray, isBoolean } from '../../../utils'
import { pickerBaseProps } from '../../base/common-props/picker'
import type { ExtractPropTypes } from 'vue'
export type RegionPickerModelValueType = Array<string>
export const regionPickerProps = buildProps({
...pickerBaseProps,
/**
* @description 地区选择器绑定的值,可以传递省市区的code和name["11", "1101", "110101"] || ["广东省", "广州市", "天河区"]
*/
modelValue: {
type: definePropType<RegionPickerModelValueType>(Array),
default: [],
},
/**
* @description 显示/隐藏地区选择器
*/
open: Boolean,
})
export const regionPickerEmits = {
[UPDATE_MODEL_EVENT]: (value: RegionPickerModelValueType) => isArray(value),
'update:open': (value: boolean) => isBoolean(value),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
[CHANGE_EVENT]: (value: RegionPickerModelValueType, item: any) => true,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
confirm: (value: RegionPickerModelValueType, item: any) => true,
cancel: () => true,
close: () => true,
}
export type RegionPickerProps = ExtractPropTypes<typeof regionPickerProps>
export type RegionPickerEmits = typeof regionPickerEmits
@@ -0,0 +1,42 @@
<script lang="ts" setup>
import TnPicker from '../../picker/src/picker.vue'
import { regionPickerEmits, regionPickerProps } from './region-picker'
import { useRegionPicker } from './composables'
const props = defineProps(regionPickerProps)
const emits = defineEmits(regionPickerEmits)
const {
pickerSelectData,
showPicker,
currentSelectValue,
handlePickerCloseEvent,
handlePickerChangeEvent,
handlePickerConfirmEvent,
handlePickerCancelEvent,
} = useRegionPicker(props, emits)
</script>
<template>
<TnPicker
v-model:open="showPicker"
:model-value="currentSelectValue"
:data="pickerSelectData"
label-key="name"
value-key="code"
:show-cancel="showCancel"
:show-confirm="showConfirm"
:mask="mask"
:cancel-text="cancelText"
:cancel-color="cancelColor"
:confirm-text="confirmText"
:confirm-color="confirmColor"
:z-index="zIndex"
@close="handlePickerCloseEvent"
@change="handlePickerChangeEvent"
@confirm="handlePickerConfirmEvent"
@cancel="handlePickerCancelEvent"
/>
</template>
<style lang="scss" scoped></style>