Files
pj_h5_cloud/src/uni_modules/tm-ui/components/tm-picker-view/tm-picker-view.vue
T
2024-11-18 08:03:34 +08:00

273 lines
8.1 KiB
Vue

<script lang="ts" setup>
import { ref, computed, onMounted, onBeforeUnmount, watch, type PropType, getCurrentInstance, type ComponentInstance, onUpdated, nextTick, VueElement, inject } from 'vue';
import { arrayNumberValid, arrayNumberValidByStyleMP, covetUniNumber, arrayNumberValidByStyleBorderColor, linearValid, getUnit, getUid } from "../../libs/tool";
import { getDefaultColor, getDefaultColorObj, getOutlineColorObj, getTextColorObj, getThinColorObj } from "../../libs/colors";
import { useTmConfig } from "../../libs/config";
import pickerItem from './picker-item.vue';
type TM_PICKER_X_ITEM = Record<string, any>
type TM_PICKER_ITEM_INFO = Record<string, any>
const proxy = getCurrentInstance()?.proxy ?? null;
/**
* @displayName 选择器容器
* @exportName tm-picker-view
* @category 表单组件
* @description 可单列或者多列
* @constant 平台兼容
* | H5 | uniAPP | 小程序 | version |
| --- | --- | --- | --- |
| ☑️| ☑️ | ☑️ | ☑️ | ☑️ | 1.0.0 |
*/
defineOptions({ name: 'TmPickerView' });
const { config } = useTmConfig()
const nowValue = ref<Array<string | number>>([])
const _modelValueIndex = ref<Array<number>>([])
const tid = ref(0)
const emits = defineEmits([
/**
* 选项变化时触发
* @param {string[]} ids - 当前选中项的id
*/
'change',
/**
* 等同v-model:model-str
* 只对外输出当前回选区的选中项的文本,不要外部改变此值。
*/
'update:modelStr',
'update:modelValue'
])
const props = defineProps({
/**
* 数据项
* 格式类型为:PICKER_ITEM_INFO
*/
list: {
type: Array as PropType<TM_PICKER_ITEM_INFO[]>,
default: (): TM_PICKER_ITEM_INFO[] => [] as TM_PICKER_ITEM_INFO[]
},
/**
* 当前选中项的id值
*/
modelValue: {
type: Array<string | number>,
default: (): string[] => [] as string[]
},
/**
* 当前选中项的标题文本组
*/
modelStr: {
type: String,
default: ""
},
/**
* 显示在顶部的单位名称
*/
cellUnits: {
type: Array as PropType<string[]>,
default: (): string[] => [] as string[]
},
/**
* 项目的字体号大小
*/
fontSize: {
type: String,
default: "32"
},
/**
* 自定义标识id
*/
rangKey: {
type: String,
default: "id"
},
/**
* 自定义标识文本字段名
*/
rangText: {
type: String,
default: "title"
}
})
const _cellUnits = computed(() => props.cellUnits)
const _list = computed(() => props.list)
const _nowShowList = ref<Record<string, any>[][]>([])
const _maxDeep = computed(() => {
if (_list.value.length == 0) return 0;
function getdiepWidth(list: TM_PICKER_X_ITEM[]): number {
let deepIndex = 1;
const node = list[0];
if (node?.children?.length > 0) {
deepIndex += getdiepWidth(node.children);
}
return deepIndex;
}
return getdiepWidth(_list.value.slice(0));
})
const oninitFun = () => {
nowValue.value = props.modelValue.slice(0)
let currneinexs = getIndexsByids(nowValue.value).indexs;
_modelValueIndex.value = nowValue.value.length == 0 || currneinexs.length == 0 ? new Array(_maxDeep.value).fill(0) : currneinexs;
const { data, strs, ids } = getIdsByindexs(_modelValueIndex.value)
_nowShowList.value = data.slice(0)
if (nowValue.value.length == 0) {
nowValue.value = ids.slice(0)
nextTick(() => {
emits('update:modelStr', strs.join(","))
emits('update:modelValue', ids.slice(0))
})
}
}
const change = (ixs: number[]) => {
const { ids, data, strs } = getIdsByindexs(ixs)
_modelValueIndex.value = getIndexsByids(ids).indexs;
_nowShowList.value = data.slice(0)
nowValue.value = ids;
/**
* 等同v-model
*/
emits('update:modelValue', ids.slice(0))
emits('update:modelStr', strs.join(","))
if (strs.join('') == props.modelValue.join('')) return;
emits('change', ids.slice(0))
}
// 根据id返回索引
const getIndexsByids = (ids: Array<string | number>): { indexs: Array<number>, data: TM_PICKER_X_ITEM[][], strs: string[] } => {
let index = 0;
let val = ids.slice(0)
let indexs = [] as number[]
let data = [] as TM_PICKER_X_ITEM[][]
let strs = [] as string[]
if (_list.value.length == 0 || ids.length == 0) return { indexs: [], data: [], strs: [] }
function getIndex(nodes: TM_PICKER_X_ITEM[]) {
if (val.length <= index || val.length == 0) return;
let id = val[index]
let sindex = 0
for (let i = 0; i < nodes.length; i++) {
let item = nodes[i]
if (item[props.rangKey] == id) {
sindex = i;
indexs.push(sindex)
data.push(nodes)
strs.push(item[props.rangText])
if (item?.children?.length > 0) {
index += 1
getIndex(item.children)
}
}
}
}
getIndex(_list.value)
return { indexs, data, strs }
}
//根据索引返回ids
const getIdsByindexs = (indexs: number[]): { ids: Array<string | number>, data: TM_PICKER_X_ITEM[][], strs: string[] } => {
let ids = [] as string[]
let data = [] as TM_PICKER_X_ITEM[][]
let index = 0;
let val = indexs.slice(0)
let strs = [] as string[]
if (_list.value.length == 0 || indexs.length == 0) return { ids: [], data: [], strs: [] }
function getIds(nodes: TM_PICKER_X_ITEM[]) {
if (val.length <= index || val.length == 0) return;
let currentsIndex = val[index]
let id = ''
let str = ''
let children = [];
if (nodes.length - 1 >= currentsIndex) {
id = nodes[currentsIndex][props.rangKey]
str = nodes[currentsIndex][props.rangText]
children = nodes[currentsIndex]?.children ?? []
} else {
id = nodes[0][props.rangKey]
str = nodes[0][props.rangText]
children = nodes[0]?.children ?? []
}
ids.push(id)
data.push(nodes)
strs.push(str)
if (children.length > 0) {
index += 1
getIds(children)
}
}
getIds(_list.value)
return { ids, data, strs };
}
const getNowCurrent = () => {
return getIdsByindexs(_modelValueIndex.value)
}
// 获取相关数据。
onMounted(() => {
oninitFun();
uni.$on('onResize', oninitFun)
})
onBeforeUnmount(() => {
clearTimeout(tid.value);
uni.$off('onResize', oninitFun)
})
watch(() => props.modelValue, (newValue: Array<string | number>) => {
if (newValue.join('') == nowValue.value.join('')) return;
nowValue.value = newValue.slice(0);
let defauleindexs = nowValue.value.length == 0 ? new Array(_maxDeep.value).fill(0) : getIndexsByids(nowValue.value).indexs;
_modelValueIndex.value = defauleindexs;
const { data, strs } = getIdsByindexs(_modelValueIndex.value)
_nowShowList.value = data.slice(0)
emits('update:modelStr', strs.join(","))
}, { deep: true })
watch(() => props.list, (newValue) => {
oninitFun()
}, { deep: true })
defineExpose({ getIndexsByids, getIdsByindexs, getNowCurrent, onInit: oninitFun })
</script>
<script lang="ts">
export default {
options: {
styleIsolation: "apply-shared",
virtualHost: true,
addGlobalClass: true,
multipleSlots: true,
},
};
</script>
<template>
<view class="tmPickerView">
<picker-item :rangKey="props.rangKey" :rangText="props.rangText" :font-size="props.fontSize"
:cellUnits="_cellUnits" @changeDeep="change" :selectedIndex="_modelValueIndex" :list="_nowShowList"
class="tmPickerViewItem"></picker-item>
</view>
</template>
<style scoped>
.tmPickerView {}
</style>