Initial commit of akmon project
This commit is contained in:
72
uni_modules/lime-picker/components/l-picker-item/index.scss
Normal file
72
uni_modules/lime-picker/components/l-picker-item/index.scss
Normal file
@@ -0,0 +1,72 @@
|
||||
@import '~@/uni_modules/lime-style/index.scss';
|
||||
$prefix: l !default;
|
||||
$item: #{$prefix}-picker-item;
|
||||
|
||||
$picker-group-height: create-var(picker-group-height, 400rpx);
|
||||
$picker-indicator-bg-color: create-var(picker-indicator-bg-color, $fill-4);
|
||||
$picker-indicator-border-radius: create-var(picker-indicator-border-radius, 12rpx);
|
||||
|
||||
$picker-item-height: create-var(picker-item-height, 50px);
|
||||
$picker-item-active-color: create-var(picker-item-active-color, $text-color-1);
|
||||
$picker-item-active-font-weight: create-var(picker-item-active-font-weight, 700);
|
||||
$picker-item-color: create-var(picker-item-color, $text-color-1);
|
||||
$picker-item-font-size: create-var(picker-item-font-size, $font-size-md);
|
||||
|
||||
/* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY */
|
||||
:host {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
|
||||
.#{$item} {
|
||||
&__group {
|
||||
/* #ifdef WEB */
|
||||
:deep(.uni-picker-view-content) {
|
||||
// 300ms
|
||||
transition-duration: var(--picker-duration, 0);
|
||||
}
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
// height: $picker-group-height;
|
||||
&-item {
|
||||
height: $picker-item-height;
|
||||
line-height: $picker-item-height;
|
||||
text-align: center;
|
||||
/* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
/* #endif */
|
||||
transition-duration: 100ms;
|
||||
transition-property: font-weight, color;
|
||||
transition-timing-function: linear;
|
||||
font-weight: 400;
|
||||
color: $picker-item-color;
|
||||
font-size: $picker-item-font-size;
|
||||
white-space: nowrap;
|
||||
&--active {
|
||||
color: $picker-item-active-color;
|
||||
font-weight: $picker-item-active-font-weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
&__indicator {
|
||||
// position: absolute;
|
||||
left: 0rpx;
|
||||
right: 0rpx;
|
||||
|
||||
width: auto;
|
||||
height: $picker-item-height;
|
||||
// top: 144rpx;
|
||||
pointer-events: none;
|
||||
background-color: $picker-indicator-bg-color;
|
||||
// border-radius: $picker-indicator-border-radius;
|
||||
/* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY */
|
||||
&:after,&:before{
|
||||
display: none;
|
||||
}
|
||||
/* #endif */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
<template>
|
||||
<picker-view
|
||||
class="l-picker-item__group"
|
||||
:style="{opacity: options.length > 0 ? 1 : 0}"
|
||||
:indicator-style="indicatorStyles"
|
||||
:value="innerIndex"
|
||||
@change="handlePick"
|
||||
indicator-class="l-picker-item__indicator">
|
||||
<picker-view-column class="l-picker-item__wrapper">
|
||||
<!-- #ifdef APP-ANDROID -->
|
||||
<view ref="itemRef"></view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-ANDROID -->
|
||||
<text class="l-picker-item__group-item" v-for="(item, i) in options"
|
||||
:style="[itemStyles, curIndex == i ? itemActiveStyles: {}]"
|
||||
:class="{'l-picker-item__group-item--active': curIndex == i}" :key="item.value">{{item.label}}</text>
|
||||
<!-- #endif -->
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</template>
|
||||
<script lang="uts" setup>
|
||||
/**
|
||||
* PickerItem 选择器子项组件
|
||||
* @description 用于构建多列选择器的单个列项,通常作为 Picker 组件的子组件使用
|
||||
* <br>插件类型:LPickerItemComponentPublicInstance
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?name=lime-picker
|
||||
*
|
||||
* @property {PickerColumnItem[]} options 当前列的选项列表(必填)
|
||||
* @property {PickerValue} value 当前选中值
|
||||
* @property {number} column 列索引标识(从0开始计数)
|
||||
* @property {string | number} name 列名称标识符
|
||||
*/
|
||||
import { unitConvert } from '@/uni_modules/lime-shared/unitConvert'
|
||||
import { clamp } from '@/uni_modules/lime-shared/clamp'
|
||||
import { PickerItemProps, ManageChildInList, OnPick, UpdateItems } from './type';
|
||||
import { PickerColumnItem, PickerValue } from '../l-picker/type';
|
||||
const instance = getCurrentInstance()!;
|
||||
const props = withDefaults(defineProps<PickerItemProps>(), {
|
||||
options: [] as PickerColumnItem[],
|
||||
column: -1,
|
||||
resetIndex: false
|
||||
})
|
||||
const picker = inject<LPickerComponentPublicInstance | null>('limePicker', null);
|
||||
const pickerItemInstanceArray = inject<LPickerItemComponentPublicInstance[] | null>('limePickerItems', null);
|
||||
const manageChildInList = inject<ManageChildInList | null>('limePickerManageChildInList', null);
|
||||
manageChildInList?.(instance.proxy! as LPickerItemComponentPublicInstance, true)
|
||||
const onPick = inject<OnPick | null>('limePickerOnPick', null);
|
||||
const updateItems = inject<UpdateItems | null>('limePickerUpdateItems', null);
|
||||
// web 如果初始是0 当数据加载后 无法指向0
|
||||
// #ifdef WEB
|
||||
const curIndex = ref(-1)
|
||||
// #endif
|
||||
// #ifndef WEB
|
||||
const curIndex = ref(0)
|
||||
// #endif
|
||||
const curValue = ref<PickerValue | null>(props.value);
|
||||
const column = computed(() : number => props.column != -1 ? props.column : pickerItemInstanceArray?.indexOf(instance.proxy! as LPickerItemComponentPublicInstance) ?? props.column);
|
||||
|
||||
const elementPosition = computed(() : boolean[] => {
|
||||
const totalElements = pickerItemInstanceArray?.length ?? 0;
|
||||
return [column.value == 0, column.value == totalElements - 1]
|
||||
});
|
||||
const innerIndex = computed(() : number[] => [curIndex.value])
|
||||
const indicatorStyles = computed(() : string => {
|
||||
const [isFirst, isLast] = elementPosition.value
|
||||
let style = ``
|
||||
|
||||
if(isFirst) {
|
||||
style+= 'border-top-left-radius:12rpx; border-bottom-left-radius:12rpx;'
|
||||
}
|
||||
if(isLast) {
|
||||
style+= 'border-top-right-radius:12rpx; border-bottom-right-radius:12rpx;'
|
||||
}
|
||||
return `
|
||||
${style}
|
||||
height: ${picker?.itemHeight ?? '50px'};
|
||||
background-color: rgba(0, 0, 0, 0.04); ${picker?.indicatorStyle}`
|
||||
})
|
||||
const itemStyles = computed(() : Map<string, any> => {
|
||||
const style = new Map<string, any>();
|
||||
if (picker?.itemColor != null) {
|
||||
style.set('color', picker.itemColor!)
|
||||
}
|
||||
if (picker?.itemFontSize != null) {
|
||||
style.set('font-size', picker.itemFontSize!)
|
||||
}
|
||||
if(picker?.itemHeight != null) {
|
||||
style.set('line-height', picker.itemHeight!)
|
||||
style.set('height', picker.itemHeight!)
|
||||
}
|
||||
return style
|
||||
})
|
||||
const itemActiveStyles = computed(() : Map<string, any> => {
|
||||
const style = new Map<string, any>();
|
||||
if (picker?.itemActiveColor != null) {
|
||||
style.set('color', picker.itemActiveColor!)
|
||||
}
|
||||
if (picker?.itemActiveFontWeight != null) {
|
||||
style.set('font-weight', picker.itemActiveFontWeight!)
|
||||
}
|
||||
return style
|
||||
})
|
||||
|
||||
|
||||
const getIndexByValue = (val : PickerValue | null) => {
|
||||
let defaultIndex = 0;
|
||||
if (val != null) {
|
||||
defaultIndex = props.options.findIndex((item) => item.value == val);
|
||||
}
|
||||
return defaultIndex < 0 ? 0 : defaultIndex;
|
||||
};
|
||||
|
||||
const setIndex = (index : number) => {
|
||||
let lastIndex = curIndex.value
|
||||
let _index = clamp(index, 0, props.options.length - 1)
|
||||
if(props.options.length > _index) {
|
||||
curIndex.value = _index;
|
||||
curValue.value = props.options[_index].value
|
||||
}
|
||||
// #ifdef WEB
|
||||
if(lastIndex == _index || lastIndex == -1) return
|
||||
if (instance.proxy!.$el) {
|
||||
const childs = Array.from(instance.proxy!.$el.parentElement.children).slice(column.value + 1);
|
||||
childs.forEach((child) => {
|
||||
(child as HTMLElement).style.setProperty('--picker-duration', '300ms');
|
||||
setTimeout(function () {
|
||||
(child as HTMLElement).style.setProperty('--picker-duration', '0ms');
|
||||
}, 299);
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
|
||||
}
|
||||
const setValue = (value : PickerValue | null) => {
|
||||
if (value == curValue.value) return
|
||||
curValue.value = value
|
||||
const index = getIndexByValue(value)
|
||||
setIndex(index)
|
||||
}
|
||||
const setOptions = () => { }
|
||||
const setUpdateItems = () => {
|
||||
const index = clamp(curIndex.value, 0, props.options.length - 1)
|
||||
const curItem = props.options.length > index ? props.options[index] : null;
|
||||
if (curItem == null) return
|
||||
updateItems?.(curItem, index, column.value);
|
||||
}
|
||||
|
||||
const handlePick = (e : UniPickerViewChangeEvent) => {
|
||||
if(props.options.length == 0) return
|
||||
const index = clamp(e.detail.value[0], 0, props.options.length - 1);
|
||||
const curItem = props.options[index];
|
||||
if(index == curIndex.value) return
|
||||
setIndex(index)
|
||||
onPick?.(curItem, index, column.value);
|
||||
}
|
||||
|
||||
const stopValue = watch(() : PickerValue | null => props.value, (v : PickerValue | null) => {
|
||||
setValue(v);
|
||||
setUpdateItems();
|
||||
}, { immediate: true })
|
||||
|
||||
// #ifdef APP-ANDROID
|
||||
const itemRef = ref<UniElement | null>(null)
|
||||
const updateItemStyle = () => {
|
||||
if (itemRef.value != null) {
|
||||
const ctx = itemRef.value!.getDrawableContext()!
|
||||
const height = unitConvert(picker?.itemHeight ?? 50);
|
||||
const fontSize = unitConvert(picker?.itemFontSize ?? '32rpx');
|
||||
const rect = itemRef.value!.getBoundingClientRect()
|
||||
const x = itemRef.value!.offsetWidth / 2;
|
||||
const itemActiveFontWeight = picker?.itemActiveFontWeight ?? 700
|
||||
itemRef.value!.style.setProperty('height', height * props.options.length);
|
||||
ctx.reset()
|
||||
ctx.fillStyle = picker?.itemActiveColor ?? 'rgba(0,0,0,0.88)';
|
||||
ctx.font = `${fontSize}px`;
|
||||
ctx.textAlign = 'center'
|
||||
ctx.lineWidth = 0.5
|
||||
|
||||
props.options.forEach((item, index) => {
|
||||
const y = height * index + fontSize + (height - fontSize) * 0.4; //(height - fontSize * 1.1)
|
||||
ctx.fillText(item.label, x, y)
|
||||
if (index == curIndex.value && itemActiveFontWeight > 600) {
|
||||
ctx.strokeText(item.label, x, y)
|
||||
}
|
||||
})
|
||||
ctx.update()
|
||||
}
|
||||
}
|
||||
// 防止更新后尺寸不对
|
||||
watchEffect(()=> {
|
||||
if(curIndex.value > 0){}
|
||||
nextTick(updateItemStyle)
|
||||
})
|
||||
const stop = watch(() : PickerColumnItem[] => props.options, (v : PickerColumnItem[], o : PickerColumnItem[]) => {
|
||||
nextTick(updateItemStyle)
|
||||
})
|
||||
|
||||
const resizeObserver = new UniResizeObserver((entries : Array<UniResizeObserverEntry>) => {
|
||||
updateItemStyle()
|
||||
})
|
||||
const stopWatch = watch(():UniElement|null => itemRef.value, (el:UniElement|null) => {
|
||||
if(el== null) return
|
||||
resizeObserver.observe(el)
|
||||
})
|
||||
// onMounted(() => {
|
||||
// nextTick(updateItemStyle)
|
||||
// })
|
||||
|
||||
// #endif
|
||||
onBeforeUnmount(() => {
|
||||
manageChildInList?.(instance.proxy! as LPickerItemComponentPublicInstance, false)
|
||||
|
||||
// #ifdef APP-ANDROID
|
||||
stop()
|
||||
stopWatch()
|
||||
resizeObserver.disconnect()
|
||||
// #endif
|
||||
})
|
||||
// onMounted(()=>{
|
||||
// if(props.options.length > 0 && curIndex.value == -1) {
|
||||
// curIndex.value = 0
|
||||
// }
|
||||
// })
|
||||
defineExpose({
|
||||
setIndex,
|
||||
setValue,
|
||||
// setOptions,
|
||||
// setUpdateItems,
|
||||
getIndexByValue
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import './index';
|
||||
</style>
|
||||
@@ -0,0 +1,204 @@
|
||||
<template>
|
||||
<picker-view
|
||||
class="l-picker-item__group"
|
||||
:style="{opacity: options.length > 0 ? 1 : 0}"
|
||||
:indicator-style="indicatorStyles"
|
||||
:value="innerIndex"
|
||||
@change="handlePick"
|
||||
indicator-class="l-picker-item__indicator">
|
||||
<picker-view-column class="l-picker-item__wrapper">
|
||||
<text
|
||||
class="l-picker-item__group-item"
|
||||
v-for="(item, i) in options"
|
||||
:style="[itemStyles, curIndex == i ? itemActiveStyles: {}]"
|
||||
:class="{'l-picker-item__group-item--active': curIndex == i}"
|
||||
:key="item.value">{{item.label}}</text>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* PickerItem 选择器子项组件
|
||||
* @description 用于构建多列选择器的单个列项,通常作为 Picker 组件的子组件使用
|
||||
* <br>插件类型:LPickerItemComponentPublicInstance
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?name=lime-picker
|
||||
*
|
||||
* @property {PickerColumnItem[]} options 当前列的选项列表(必填)
|
||||
* @property {PickerValue} value 当前选中值
|
||||
* @property {number} column 列索引标识(从0开始计数)
|
||||
* @property {string | number} name 列名称标识符
|
||||
*/
|
||||
import { defineComponent, getCurrentInstance, inject, ref, computed, watch, onBeforeUnmount } from '@/uni_modules/lime-shared/vue';
|
||||
import { unitConvert } from '@/uni_modules/lime-shared/unitConvert';
|
||||
import { clamp } from '@/uni_modules/lime-shared/clamp'
|
||||
import type { PickerItemProps, ManageChildInList, OnPick, UpdateItems } from './type';
|
||||
import type { PickerColumnItem, PickerValue } from '../l-picker/type';
|
||||
|
||||
import pickerItemProps from './props';
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
name: 'l-picker-item',
|
||||
props: pickerItemProps,
|
||||
setup(props, {expose}) {
|
||||
const instance = getCurrentInstance()!;
|
||||
const picker = inject<LPickerComponentPublicInstance|null>('limePicker', null);
|
||||
const pickerItemInstanceArray = inject<Ref<LPickerItemComponentPublicInstance[]>|null>('limePickerItems', null);
|
||||
const manageChildInList = inject<ManageChildInList|null>('limePickerManageChildInList', null);
|
||||
manageChildInList?.(instance.proxy! as LPickerItemComponentPublicInstance , true)
|
||||
|
||||
const onPick = inject<OnPick|null>('limePickerOnPick', null);
|
||||
const updateItems = inject<UpdateItems|null>('limePickerUpdateItems', null);
|
||||
|
||||
const curIndex = ref(-1)
|
||||
const curValue = ref<PickerValue|null>(null);
|
||||
const column = computed(() : number => props.column != -1 ? props.column : pickerItemInstanceArray?.value.indexOf(instance.proxy! as LPickerItemComponentPublicInstance) ?? props.column);
|
||||
|
||||
const elementPosition = computed(() : boolean[] => {
|
||||
const totalElements = pickerItemInstanceArray?.value.length || 0;
|
||||
return [column.value == 0, column.value == totalElements - 1]
|
||||
});
|
||||
const innerIndex = computed(():number[] => [curIndex.value])
|
||||
|
||||
const indicatorStyles = computed(() : string => {
|
||||
const [isFirst, isLast] = elementPosition.value
|
||||
let style = ``
|
||||
|
||||
if(isFirst) {
|
||||
style+= 'border-top-left-radius:12rpx; border-bottom-left-radius:12rpx;'
|
||||
}
|
||||
if(isLast) {
|
||||
style+= 'border-top-right-radius:12rpx; border-bottom-right-radius:12rpx;'
|
||||
}
|
||||
return `
|
||||
${style}
|
||||
height: ${picker?.itemHeight || '50px'};
|
||||
background-color: rgba(0, 0, 0, 0.04); ${picker?.indicatorStyle}`
|
||||
})
|
||||
const itemStyles = computed(()=>{
|
||||
const style:Record<string, any> = {};
|
||||
if(picker?.itemColor) {
|
||||
style['color'] = picker.itemColor!
|
||||
}
|
||||
if(picker?.itemFontSize) {
|
||||
style['font-size'] = picker.itemFontSize!
|
||||
}
|
||||
return style
|
||||
})
|
||||
|
||||
const itemActiveStyles = computed(() =>{
|
||||
const style:Record<string, any> = {};
|
||||
if(picker?.itemActiveColor) {
|
||||
style['color'] = picker.itemActiveColor!
|
||||
}
|
||||
if (picker?.itemActiveFontWeight) {
|
||||
style['font-weight'] = picker.itemActiveFontWeight!
|
||||
}
|
||||
return style
|
||||
})
|
||||
|
||||
const getIndexByValue = (val: PickerValue | null) => {
|
||||
let defaultIndex = 0;
|
||||
if (val != null) {
|
||||
defaultIndex = props.options.findIndex((item) => item.value == val);
|
||||
}
|
||||
return defaultIndex < 0 ? 0 : defaultIndex;
|
||||
};
|
||||
|
||||
const setIndex = (index: number) =>{
|
||||
let lastIndex = curIndex.value
|
||||
let _index = clamp(index, 0, props.options.length - 1)
|
||||
if(props.options.length > _index) {
|
||||
curIndex.value = _index;
|
||||
curValue.value = props.options[_index].value
|
||||
}
|
||||
// #ifdef WEB
|
||||
if(lastIndex == _index || lastIndex == -1) return
|
||||
if(instance.proxy!.$el) {
|
||||
const childs = Array.from(instance.proxy!.$el.parentElement.children).slice(column.value + 1);
|
||||
childs.forEach((child) => {
|
||||
(child as HTMLElement).style.setProperty('--picker-duration', '300ms');
|
||||
setTimeout(function() {
|
||||
(child as HTMLElement).style.setProperty('--picker-duration', '0ms');
|
||||
}, 299);
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
|
||||
const setValue = (value: PickerValue|null) =>{
|
||||
if(value == curValue.value) return
|
||||
curValue.value = value
|
||||
const index = getIndexByValue(value)
|
||||
setIndex(index)
|
||||
}
|
||||
const setOptions = () => {}
|
||||
const setUpdateItems = () => {
|
||||
const curItem = props.options.length > curIndex.value ? props.options[curIndex.value] : null;
|
||||
if(curItem == null) return
|
||||
updateItems?.(curItem, curIndex.value, column.value);
|
||||
}
|
||||
|
||||
const handlePick = (e: UniPickerViewChangeEvent) => {
|
||||
if(props.options.length == 0) return
|
||||
const index = clamp(e.detail.value[0], 0, props.options.length - 1);
|
||||
const curItem = props.options[index];
|
||||
if(index == curIndex.value) return
|
||||
setIndex(index)
|
||||
onPick?.(curItem, index, column.value);
|
||||
}
|
||||
|
||||
|
||||
// const stop = watch(():PickerColumnItem[] => props.options, ()=> {
|
||||
// if(JSON.stringify(o) == JSON.stringify(v)) return
|
||||
// const index = (picker?.resetIndex || false) ? 0 : Math.max( Math.min(props.options.length - 1, curIndex.value), 0)
|
||||
// const curItem = props.options[index];
|
||||
// setIndex(index)
|
||||
// setUpdateItems();
|
||||
// // nextTick(()=>{
|
||||
// // onPick?.(curItem, index, column.value);
|
||||
// // })
|
||||
// }) // ,{immediate: true}
|
||||
|
||||
const stopValue = watch(():PickerValue|null => props.value, (v : PickerValue|null)=>{
|
||||
setValue(v);
|
||||
setUpdateItems();
|
||||
},{immediate: true})
|
||||
|
||||
onBeforeUnmount(()=>{
|
||||
manageChildInList?.(instance.proxy! as LPickerItemComponentPublicInstance, false)
|
||||
// stop()
|
||||
stopValue()
|
||||
})
|
||||
|
||||
// #ifdef VUE3
|
||||
expose({
|
||||
setIndex,
|
||||
setValue,
|
||||
// setOptions,
|
||||
// setUpdateItems,
|
||||
getIndexByValue
|
||||
})
|
||||
// #endif
|
||||
|
||||
return {
|
||||
indicatorStyles,
|
||||
innerIndex,
|
||||
curIndex,
|
||||
handlePick,
|
||||
itemStyles,
|
||||
itemActiveStyles,
|
||||
// #ifdef VUE2
|
||||
setIndex,
|
||||
setValue,
|
||||
getIndexByValue
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import './index';
|
||||
</style>
|
||||
15
uni_modules/lime-picker/components/l-picker-item/props.ts
Normal file
15
uni_modules/lime-picker/components/l-picker-item/props.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
// @ts-nocheck
|
||||
export default {
|
||||
options: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
value: {
|
||||
type: [String, Number],
|
||||
default: null
|
||||
},
|
||||
column: {
|
||||
type: Number,
|
||||
default: -1
|
||||
}
|
||||
}
|
||||
13
uni_modules/lime-picker/components/l-picker-item/type.ts
Normal file
13
uni_modules/lime-picker/components/l-picker-item/type.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// @ts-nocheck
|
||||
import type{ PickerColumnItem, PickerValue } from '../l-picker/type';
|
||||
|
||||
export type ManageChildInList = (child: LPickerItemComponentPublicInstance, shouldAdd: boolean) => void;
|
||||
export type OnPick = (value: PickerValue, index:number, column: number) => void;
|
||||
export type UpdateItems = (value: PickerValue, index:number, column: number) => void;
|
||||
|
||||
export interface PickerItemProps {
|
||||
options: PickerColumnItem[]
|
||||
value?: PickerValue;
|
||||
column: number
|
||||
name?: string|number
|
||||
}
|
||||
Reference in New Issue
Block a user