Initial commit of akmon project
This commit is contained in:
113
uni_modules/lime-picker/components/l-cascade/l-cascade.uvue
Normal file
113
uni_modules/lime-picker/components/l-cascade/l-cascade.uvue
Normal file
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<l-picker
|
||||
v-model="innerValue"
|
||||
:cancelBtn="cancelBtn"
|
||||
:cancelStyle="cancelStyle"
|
||||
:confirmBtn="confirmBtn"
|
||||
:confirmStyle="confirmStyle"
|
||||
:title="title"
|
||||
:titleStyle="titleStyle"
|
||||
:loading="loading"
|
||||
:loadingColor="loadingColor"
|
||||
:loadingMaskColor="loadingMaskColor"
|
||||
:loadingSize="loadingSize"
|
||||
:itemHeight="itemHeight"
|
||||
:itemColor="itemColor"
|
||||
:itemFontSize="itemFontSize"
|
||||
:itemActiveColor="itemActiveColor"
|
||||
:indicatorStyle="indicatorStyle"
|
||||
:bgColor="bgColor"
|
||||
:groupHeight="groupHeight"
|
||||
:radius="radius"
|
||||
:resetIndex="resetIndex"
|
||||
:columns="innerColumns"
|
||||
@cancel="onCancel"
|
||||
@confirm="onConfirm"
|
||||
@pick="onPick">
|
||||
</l-picker>
|
||||
</template>
|
||||
|
||||
<script lang="uts" setup>
|
||||
/**
|
||||
* Cascade 级联选择器组件
|
||||
* @description 支持多层级联数据选择,适用于地址选择、分类选择等场景
|
||||
* <br>插件类型:LCascadeComponentPublicInstance
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?name=lime-cascade
|
||||
*
|
||||
* @property {string} cancelBtn 取消按钮文字(默认:"取消")
|
||||
* @property {string} cancelStyle 取消按钮样式(支持CSS字符串)
|
||||
* @property {string} confirmBtn 确定按钮文字(默认:"确定")
|
||||
* @property {string} confirmStyle] 确定按钮样式(支持CSS字符串)
|
||||
* @property {string} title 标题文字
|
||||
* @property {string} titleStyle 标题样式(支持CSS字符串)
|
||||
* @property {UTSJSONObject} keys 字段别名配置(参考KeysType结构)
|
||||
* @property {UTSJSONObject]} columns 级联数据源(必填)
|
||||
* @property {PickerValue]} modelValue 选中值(支持v-model)
|
||||
* @property {PickerValue]} defaultValue 默认选中值
|
||||
* @property {PickerValue]} value 选中值(兼容旧版)
|
||||
* @property {boolean} loading 是否显示加载状态
|
||||
* @property {string} loadingColor 加载图标颜色(默认:主题色)
|
||||
* @property {string} loadingMaskColor 加载遮罩颜色(默认:rgba(255,255,255,0.8))
|
||||
* @property {string} loadingSize 加载图标尺寸(支持CSS单位)
|
||||
* @property {string} itemHeight 选项行高(默认:44px)
|
||||
* @property {string} itemColor 选项文字颜色(默认:#333)
|
||||
* @property {string} itemFontSize 选项文字大小(默认:16px)
|
||||
* @property {string} itemActiveColor 选中项高亮颜色(默认:主题色)
|
||||
* @property {string} indicatorStyle 指示器样式(支持CSS字符串)
|
||||
* @property {string} bgColor 背景颜色(默认:#ffffff)
|
||||
* @property {string} groupHeight 选项组高度(默认:240px)
|
||||
* @property {string} radius 圆角半径(支持CSS单位)
|
||||
* @property {boolean} resetIndex 是否重置选中索引(用于动态更新数据时)
|
||||
* @event {Function} change 选项变化时触发(返回当前选中路径)
|
||||
* @event {Function} cancel 点击关闭时触发
|
||||
* @event {Function} confirm 点击确定时触发(返回最终选中值)
|
||||
*/
|
||||
import { PickerValue, PickerColumn, PickerColumnItem, PickerPickEvent, PickerConfirmEvent } from '../l-picker/type';
|
||||
import { CascadeProps } from './type';
|
||||
import { parseKeys, formatCascadeColumns } from './utils';
|
||||
|
||||
const emit = defineEmits(['change', 'cancel', 'pick', 'confirm', 'update:modelValue', 'update:value'])
|
||||
const props = withDefaults(defineProps<CascadeProps>(), {
|
||||
columns: [] as PickerColumnItem[],
|
||||
loading: false,
|
||||
resetIndex: false,
|
||||
loadingSize: '64rpx'
|
||||
})
|
||||
const keys = parseKeys(props.keys)
|
||||
const innerValue = ref<PickerValue[]>(props.value ?? props.modelValue ?? props.defaultValue ?? []);
|
||||
// const innerValue = computed({
|
||||
// set(value : PickerValue[]) {
|
||||
// curValueArray.value = value;
|
||||
// emit('update:modelValue', value)
|
||||
// },
|
||||
// get() : PickerValue[] {
|
||||
// return props.value ?? props.modelValue ?? curValueArray.value
|
||||
// }
|
||||
// } as WritableComputedOptions<PickerValue[]>)
|
||||
|
||||
|
||||
const innerColumns = computed(() : PickerColumn[] => {
|
||||
return formatCascadeColumns(props.columns, keys, innerValue)
|
||||
})
|
||||
|
||||
const onPick = ({ values, column, index } : PickerPickEvent) => {
|
||||
innerValue.value = [...values]
|
||||
}
|
||||
|
||||
const onConfirm = (options : PickerConfirmEvent) => {
|
||||
emit('confirm', options)
|
||||
}
|
||||
const onCancel = () => {
|
||||
emit('cancel')
|
||||
}
|
||||
|
||||
watchEffect(()=>{
|
||||
emit('update:modelValue', innerValue.value)
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
124
uni_modules/lime-picker/components/l-cascade/l-cascade.vue
Normal file
124
uni_modules/lime-picker/components/l-cascade/l-cascade.vue
Normal file
@@ -0,0 +1,124 @@
|
||||
<template>
|
||||
<l-picker
|
||||
v-model="innerValue"
|
||||
:cancelBtn="cancelBtn"
|
||||
:cancelStyle="cancelStyle"
|
||||
:confirmBtn="confirmBtn"
|
||||
:confirmStyle="confirmStyle"
|
||||
:title="title"
|
||||
:titleStyle="titleStyle"
|
||||
:loading="loading"
|
||||
:loadingColor="loadingColor"
|
||||
:loadingMaskColor="loadingMaskColor"
|
||||
:loadingSize="loadingSize"
|
||||
:itemHeight="itemHeight"
|
||||
:itemColor="itemColor"
|
||||
:itemFontSize="itemFontSize"
|
||||
:itemActiveColor="itemActiveColor"
|
||||
:indicatorStyle="indicatorStyle"
|
||||
:bgColor="bgColor"
|
||||
:groupHeight="groupHeight"
|
||||
:radius="radius"
|
||||
:resetIndex="resetIndex"
|
||||
:columns="innerColumns"
|
||||
@cancel="onCancel"
|
||||
@confirm="onConfirm"
|
||||
@pick="onPick">
|
||||
</l-picker>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* Cascade 级联选择器组件
|
||||
* @description 支持多层级联数据选择,适用于地址选择、分类选择等场景
|
||||
* <br>插件类型:LCascadeComponentPublicInstance
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?name=lime-cascade
|
||||
*
|
||||
* @property {string} cancelBtn 取消按钮文字(默认:"取消")
|
||||
* @property {string} cancelStyle 取消按钮样式(支持CSS字符串)
|
||||
* @property {string} confirmBtn 确定按钮文字(默认:"确定")
|
||||
* @property {string} confirmStyle] 确定按钮样式(支持CSS字符串)
|
||||
* @property {string} title 标题文字
|
||||
* @property {string} titleStyle 标题样式(支持CSS字符串)
|
||||
* @property {UTSJSONObject} keys 字段别名配置(参考KeysType结构)
|
||||
* @property {UTSJSONObject]} columns 级联数据源(必填)
|
||||
* @property {PickerValue]} modelValue 选中值(支持v-model)
|
||||
* @property {PickerValue]} defaultValue 默认选中值
|
||||
* @property {PickerValue]} value 选中值(兼容旧版)
|
||||
* @property {boolean} loading 是否显示加载状态
|
||||
* @property {string} loadingColor 加载图标颜色(默认:主题色)
|
||||
* @property {string} loadingMaskColor 加载遮罩颜色(默认:rgba(255,255,255,0.8))
|
||||
* @property {string} loadingSize 加载图标尺寸(支持CSS单位)
|
||||
* @property {string} itemHeight 选项行高(默认:44px)
|
||||
* @property {string} itemColor 选项文字颜色(默认:#333)
|
||||
* @property {string} itemFontSize 选项文字大小(默认:16px)
|
||||
* @property {string} itemActiveColor 选中项高亮颜色(默认:主题色)
|
||||
* @property {string} indicatorStyle 指示器样式(支持CSS字符串)
|
||||
* @property {string} bgColor 背景颜色(默认:#ffffff)
|
||||
* @property {string} groupHeight 选项组高度(默认:240px)
|
||||
* @property {string} radius 圆角半径(支持CSS单位)
|
||||
* @property {boolean} resetIndex 是否重置选中索引(用于动态更新数据时)
|
||||
* @event {Function} change 选项变化时触发(返回当前选中路径)
|
||||
* @event {Function} cancel 点击关闭时触发
|
||||
* @event {Function} confirm 点击确定时触发(返回最终选中值)
|
||||
*/
|
||||
import { defineComponent, ref, computed} from '@/uni_modules/lime-shared/vue';
|
||||
import { PickerValue, PickerColumn, PickerColumnItem, PickerPickEvent} from '../l-picker/type';
|
||||
import { CascadeProps } from './type';
|
||||
import { parseKeys, formatCascadeColumns } from './utils';
|
||||
import cascadeProps from '../l-picker/props';
|
||||
export default defineComponent({
|
||||
name: 'l-cascade',
|
||||
props:cascadeProps,
|
||||
emits: ['change', 'cancel', 'pick', 'confirm', 'update:modelValue', 'update:value', 'input'],
|
||||
setup(props, {emit}) {
|
||||
type UTSJSONObject = Record<string, any>
|
||||
|
||||
const keys = parseKeys(props.keys)
|
||||
const curValueArray = ref(props.value || props.modelValue || props.defaultValue||[]);
|
||||
const innerValue = computed({
|
||||
set(value: PickerValue[]) {
|
||||
curValueArray.value = value;
|
||||
emit('update:modelValue', value)
|
||||
// #ifdef VUE2
|
||||
emit('input', value)
|
||||
// #endif
|
||||
},
|
||||
get(): PickerValue[]{
|
||||
return props.value || props.modelValue || curValueArray.value
|
||||
}
|
||||
} as WritableComputedOptions<PickerValue[]>)
|
||||
|
||||
|
||||
const innerColumns = computed((): PickerColumn[] => {
|
||||
return formatCascadeColumns(props.columns, keys, innerValue)
|
||||
})
|
||||
|
||||
const onPick = ({values, column, index} : PickerPickEvent) => {
|
||||
innerValue.value = values
|
||||
}
|
||||
|
||||
const onConfirm = (options: PickerConfirmEvent) => {
|
||||
emit('confirm', options)
|
||||
}
|
||||
const onCancel = () => {
|
||||
emit('cancel')
|
||||
}
|
||||
|
||||
return {
|
||||
innerValue,
|
||||
innerColumns,
|
||||
onPick,
|
||||
onConfirm,
|
||||
onCancel
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
57
uni_modules/lime-picker/components/l-cascade/type.ts
Normal file
57
uni_modules/lime-picker/components/l-cascade/type.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
// @ts-nocheck
|
||||
import {PickerColumn, PickerColumnItem ,PickerValue} from '../l-picker/type';
|
||||
export type KeysType = {
|
||||
value: string;
|
||||
label: string;
|
||||
children:string;
|
||||
disabled?: string;
|
||||
}
|
||||
export interface CascadeProps {
|
||||
/**
|
||||
* 取消按钮文字
|
||||
*/
|
||||
cancelBtn ?: string;
|
||||
cancelStyle ?: string;
|
||||
/**
|
||||
* 确定按钮文字
|
||||
*/
|
||||
confirmBtn ?: string;
|
||||
confirmStyle ?: string;
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
title ?: string;
|
||||
titleStyle ?: string;
|
||||
/**
|
||||
* 用来定义 value / label 在 `options` 中对应的字段别名
|
||||
*/
|
||||
keys?: UTSJSONObject;
|
||||
/**
|
||||
* 配置每一列的选项
|
||||
*/
|
||||
columns : UTSJSONObject[];
|
||||
/**
|
||||
* 选中值
|
||||
*/
|
||||
modelValue ?: PickerValue[];
|
||||
defaultValue ?: PickerValue[];
|
||||
value ?: PickerValue[];
|
||||
/**
|
||||
* 是否为加载状态
|
||||
*/
|
||||
loading: boolean;
|
||||
loadingColor?: string;
|
||||
loadingMaskColor ?: string;
|
||||
loadingSize: string;
|
||||
|
||||
itemHeight?: string;
|
||||
itemColor?: string;
|
||||
itemFontSize?: string;
|
||||
itemActiveColor?: string;
|
||||
|
||||
indicatorStyle?: string;
|
||||
bgColor?: string;
|
||||
groupHeight?: string;
|
||||
radius?: string;
|
||||
resetIndex: boolean
|
||||
}
|
||||
122
uni_modules/lime-picker/components/l-cascade/utils.uts
Normal file
122
uni_modules/lime-picker/components/l-cascade/utils.uts
Normal file
@@ -0,0 +1,122 @@
|
||||
// @ts-nocheck
|
||||
import { clamp } from '@/uni_modules/lime-shared/clamp'
|
||||
import { PickerValue, PickerColumn, PickerColumnItem, PickerPickEvent } from '../l-picker/type';
|
||||
import { KeysType } from './type';
|
||||
// #ifndef UNI-APP-X
|
||||
import type { Ref } from '@/uni_modules/lime-shared/vue'
|
||||
type UTSJSONObject = Record<string, any>
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* 解析键配置对象,生成用于访问选项属性的键映射。
|
||||
*
|
||||
* @param {UTSJSONObject|null} keys - 配置对象,包含 label、value 和 children 的键名。
|
||||
* @returns {KeysType} 包含 label、value 和 children 键名的映射对象。
|
||||
*/
|
||||
export function parseKeys(keys : UTSJSONObject | null) : KeysType {
|
||||
const _labelKey = `${keys?.['label'] ?? 'label'}`
|
||||
const _valueKey = `${keys?.['value'] ?? 'value'}`
|
||||
const _childrenKey = `${keys?.['children'] ?? 'children'}`
|
||||
|
||||
return {
|
||||
label: _labelKey,
|
||||
value: _valueKey,
|
||||
children: _childrenKey,
|
||||
} as KeysType
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取选项数组中第一个未被禁用的选项。
|
||||
*
|
||||
* @param {UTSJSONObject[]} options - 选项对象数组。
|
||||
* @returns {UTSJSONObject|null} 第一个未被禁用的选项对象,如果所有选项都被禁用则返回第一个选项。
|
||||
*/
|
||||
export const getFirstEnabledOption = (
|
||||
options : UTSJSONObject[],
|
||||
) : UTSJSONObject | null =>
|
||||
options.find((option) : boolean => option['disabled'] != true) ?? options[0];
|
||||
|
||||
/**
|
||||
* 在选项数组中查找指定索引之后或之前的第一个未被禁用的选项的索引。
|
||||
*
|
||||
* @param {UTSJSONObject[]} options - 选项对象数组。
|
||||
* @param {number} index - 当前索引位置。
|
||||
* @returns {number} 第一个未被禁用的选项的索引,如果不存在则返回 0。
|
||||
*/
|
||||
export function findIndexOfEnabledOption(
|
||||
options : UTSJSONObject[],
|
||||
index : number,
|
||||
) {
|
||||
index = clamp(index, 0, options.length);
|
||||
|
||||
// for (let i = index; i < options.length; i++) {
|
||||
// if (options[i]['disabled'] != true) return i;
|
||||
// }
|
||||
// for (let i = index - 1; i >= 0; i--) {
|
||||
// if (options[i]['disabled'] != true) return i;
|
||||
// }
|
||||
|
||||
// return 0;
|
||||
return index
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据指定的值在选项数组中查找对应的选项对象。
|
||||
*
|
||||
* @param {UTSJSONObject[]} options - 选项对象数组。
|
||||
* @param {PickerValue} value - 要查找的值。
|
||||
* @param {KeysType} fields - 包含 label、value 和 children 键名的映射对象。
|
||||
* @returns {UTSJSONObject|null} 找到的选项对象,如果未找到则返回 null。
|
||||
*/
|
||||
export function findOptionByValue(
|
||||
options : UTSJSONObject[],
|
||||
value : PickerValue,
|
||||
fields : KeysType,
|
||||
) : UTSJSONObject | null {
|
||||
const index = options.findIndex((option) : boolean => option[fields.value] == value);
|
||||
const enabledIndex = findIndexOfEnabledOption(options, index);
|
||||
return options[enabledIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化级联选择器的列数据。
|
||||
*
|
||||
* @param {UTSJSONObject[]} columns - 初始的列数据数组。
|
||||
* @param {KeysType} fields - 包含 label、value 和 children 键名的映射对象。
|
||||
* @param {Ref<PickerValue[]>} selectedValues - 当前选中的值数组。
|
||||
* @returns {PickerColumn[]} 格式化后的级联列数据数组。
|
||||
*/
|
||||
export function formatCascadeColumns(
|
||||
columns : UTSJSONObject[],
|
||||
fields : KeysType,
|
||||
selectedValues : Ref<PickerValue[]>
|
||||
) {
|
||||
const formatted : PickerColumn[] = [];
|
||||
|
||||
let cursor : UTSJSONObject | null = {};
|
||||
cursor![fields.children] = columns;
|
||||
let columnIndex = 0;
|
||||
|
||||
while (cursor != null && cursor[fields.children] != null) {
|
||||
const options : UTSJSONObject[] = cursor[fields.children]! as UTSJSONObject[];
|
||||
const value = selectedValues.value.length > columnIndex ? selectedValues.value[columnIndex] : null;
|
||||
cursor = value != null
|
||||
? findOptionByValue(options, value, fields)
|
||||
: null;
|
||||
|
||||
if (cursor == null && options.length > 0) {
|
||||
const firstValue = getFirstEnabledOption(options)![fields.value]!;
|
||||
cursor = findOptionByValue(options, firstValue, fields);
|
||||
}
|
||||
|
||||
columnIndex++;
|
||||
formatted.push(
|
||||
options.map((option : UTSJSONObject) : PickerColumnItem => ({
|
||||
label: `${option['label']}`,
|
||||
value: `${option['value']}`,
|
||||
} as PickerColumnItem))
|
||||
);
|
||||
}
|
||||
return formatted;
|
||||
}
|
||||
Reference in New Issue
Block a user