提交 b8da064c 作者: 方治民

refactor: 采用工厂模式重构 Widget Hook 使用方法

上级 c933db27
import { getBooleanOrDefault } from '../../utils' import { getBasicWidgetInstanceFunctions, getBooleanOrDefault, registerFactory } from '../../utils'
import type { BottomBarInstance, BottomBarProps } from './types' import type { BottomBarInstance, BottomBarProps } from './types'
import { isProdMode } from '/@/utils/env'
// 组件名称
export const name = 'BottomBarWidget'
/** /**
* 底部交互/展示小部件响应式 Hook * 底部交互/展示小部件响应式 Hook
* @param props 组件参数 * @param props 组件参数
* @returns 组件响应式数据 * @returns 组件响应式数据
*/ */
export function useBottomBarWidget<T extends BottomBarInstance>(props: BottomBarProps): [(instance: T) => void, T] { export function useBottomBarWidget<T extends BottomBarInstance, P extends BottomBarProps>(
const instanceRef = ref<Nullable<T>>(null) props: P,
const height = computed(() => instanceRef?.value?.height) ): [(instance: T) => void, BottomBarInstance] {
const instanceRef = ref<T>()
function register(instance: T) { const register = registerFactory(instanceRef, props)
if (isProdMode()) { const { get, setProps, toggleShow } = getBasicWidgetInstanceFunctions(instanceRef, name)
if (instance === unref(instanceRef)) {
return
}
onUnmounted(() => {
instanceRef.value = null
})
}
instanceRef.value = instance
props && instance.setProps(props)
}
function getInstance(): T {
const instance = unref(instanceRef)
if (!instance) {
console.warn('BottomBar 小部件还未加载完成')
}
return instance as T
}
return [ return [
register, register,
{ {
height, setProps,
setProps: (props: BottomBarProps) => { toggleShow,
getInstance()?.setProps(props) toggleExpand: (expand?: boolean) => get()?.toggleExpand(getBooleanOrDefault(expand)),
}, height: computed(() => instanceRef?.value?.height) as unknown as ComputedRef<string>,
toggleShow: (show?: boolean) => { },
getInstance()?.toggleShow(getBooleanOrDefault(show))
},
toggleExpand: (expand?: boolean) => {
getInstance()?.toggleExpand(getBooleanOrDefault(expand))
},
} as T,
] ]
} }
export interface BottomBarProps { import type { BasicWidgetInstance, BasicWidgetProps } from '../../utils'
// 是否显示
show?: boolean export interface BottomBarProps extends BasicWidgetProps {
// 是否展开 // 是否展开
expand?: boolean expand?: boolean
// 是否有展开按钮 // 是否有展开按钮
showExpandButton?: boolean showExpandButton?: boolean
// 高度 rpx // 高度 rpx
height?: number height: number
// 最大高度 rpx // 最大高度 rpx
maxHeight?: number maxHeight?: number
} }
export interface BottomBarInstance { export interface BottomBarInstance extends BasicWidgetInstance<BottomBarProps> {
setProps: (props: BottomBarProps) => void height: ComputedRef<string>
toggleShow: (show?: boolean) => void
toggleExpand: (expand?: boolean) => void toggleExpand: (expand?: boolean) => void
height?: ComputedRef<string>
} }
import { getBooleanOrDefault } from '../../utils' import { getBasicWidgetInstanceFunctions, getBooleanOrDefault, registerFactory } from '../../utils'
import type { LegendInstance, LegendProps, Option } from './types' import type { LegendInstance, LegendProps, Option } from './types'
import { isProdMode } from '/@/utils/env'
// 组件名称
export const name = 'LegendWidget'
/** /**
* 图例组件响应式 Hook * 图例组件响应式 Hook
* @param props 组件参数 * @param props 组件参数
* @returns 组件响应式数据 * @returns 组件响应式数据
*/ */
export function useLegendWidget<T extends LegendInstance>(props: LegendProps): [(instance: T) => void, T] { export function useLegendWidget<T extends LegendInstance, P extends LegendProps>(
const instanceRef = ref<Nullable<T>>(null) props: P,
): [(instance: T) => void, LegendInstance] {
function register(instance: T) { const instanceRef = ref<T>()
if (isProdMode()) { const register = registerFactory(instanceRef, props)
if (instance === unref(instanceRef)) { const { get, setProps, toggleShow } = getBasicWidgetInstanceFunctions(instanceRef, name)
return
}
onUnmounted(() => {
instanceRef.value = null
})
}
instanceRef.value = instance
props && instance?.setProps(props)
}
function getInstance(): T {
const instance = unref(instanceRef)
if (!instance) {
console.warn('图例小部件还未加载完成')
}
return instance as T
}
return [ return [
register, register,
{ {
setProps: (props: LegendProps) => { setProps,
getInstance()?.setProps(props) toggleShow,
}, setTitle: (title: string) => get()?.setTitle(title),
setTitle: (title: string) => { setOption: (option: Option) => get()?.setOption(option),
getInstance()?.setTitle(title) toggleExpand: (expand?: boolean) => get()?.toggleExpand(getBooleanOrDefault(expand)),
}, },
setOption: (option: Option) => {
getInstance()?.setOption(option)
},
toggleShow: (show?: boolean) => {
getInstance()?.toggleShow(getBooleanOrDefault(show))
},
toggleExpand: (expand?: boolean) => {
getInstance()?.toggleExpand(getBooleanOrDefault(expand))
},
} as T,
] ]
} }
import type { BasicWidgetInstance, BasicWidgetProps } from '../../utils'
export interface OptionItem { export interface OptionItem {
// 颜色 // 颜色
color?: string color?: string
...@@ -18,9 +20,7 @@ export interface Option { ...@@ -18,9 +20,7 @@ export interface Option {
blockStyle?: Recordable blockStyle?: Recordable
} }
export interface LegendProps { export interface LegendProps extends BasicWidgetProps {
// 是否显示
show?: boolean
// 是否展开 // 是否展开
expand?: boolean expand?: boolean
// 标题 // 标题
...@@ -29,10 +29,8 @@ export interface LegendProps { ...@@ -29,10 +29,8 @@ export interface LegendProps {
option: Option option: Option
} }
export interface LegendInstance { export interface LegendInstance extends BasicWidgetInstance<LegendProps> {
setProps: (props: LegendProps) => void
setTitle: (title: string) => void setTitle: (title: string) => void
setOption: (option: Option) => void setOption: (option: Option) => void
toggleShow: (show?: boolean) => void
toggleExpand: (expand?: boolean) => void toggleExpand: (expand?: boolean) => void
} }
import { getBooleanOrDefault } from '../../utils' import { getBasicWidgetInstanceFunctions, registerFactory } from '../../utils'
import type { SwitchControlInstance, SwitchControlProps } from './types' import type { SwitchControlInstance, SwitchControlProps } from './types'
import { isProdMode } from '/@/utils/env'
// 组件名称
export const name = 'SwitchControlWidget'
/** /**
* 前后切换组件响应式 Hook * 前后切换组件响应式 Hook
* @param props 组件参数 * @param props 组件参数
* @returns 组件响应式数据 * @returns 组件响应式数据
*/ */
export function useSwitchControlWidget<T extends SwitchControlInstance>( export function useSwitchControlWidget<T extends SwitchControlInstance, P extends SwitchControlProps>(
props: SwitchControlProps, props: P,
): [(instance: T) => void, T] { ): [(instance: T) => void, SwitchControlInstance] {
const instanceRef = ref<Nullable<T>>(null) const instanceRef = ref<T>()
const register = registerFactory(instanceRef, props)
function register(instance: T) { const { get, setProps, toggleShow } = getBasicWidgetInstanceFunctions(instanceRef, name)
if (isProdMode()) {
if (instance === unref(instanceRef)) {
return
}
onUnmounted(() => {
instanceRef.value = null
})
}
instanceRef.value = instance
props && instance?.setProps(props)
}
function getInstance(): T {
const instance = unref(instanceRef)
if (!instance) {
console.warn('前后切换小部件还未加载完成')
}
return instance as T
}
return [ return [
register, register,
{ {
setProps: (props: SwitchControlProps) => { setProps,
getInstance()?.setProps(props) toggleShow,
}, prev: () => get()?.prev(),
toggleShow: (show?: boolean) => { next: () => get()?.next(),
getInstance()?.toggleShow(getBooleanOrDefault(show)) },
},
prev: () => {
getInstance()?.prev()
},
next: () => {
getInstance()?.next()
},
} as T,
] ]
} }
export interface SwitchControlProps { import type { BasicWidgetInstance, BasicWidgetProps } from '../../utils'
// 是否显示
show?: boolean export interface SwitchControlProps extends BasicWidgetProps {
// 上一个 // 上一个
prev?: () => void prev?: () => void
// 下一个 // 下一个
next?: () => void next?: () => void
} }
export interface SwitchControlInstance { export interface SwitchControlInstance extends BasicWidgetInstance<SwitchControlProps> {
// 暴露方法,允许手动调用上一个
prev: () => void prev: () => void
// 暴露方法,允许手动调用下一个
next: () => void next: () => void
setProps: (props: SwitchControlProps) => void
toggleShow: (show?: boolean) => void
} }
<!-- 顶部时间栏 Bar 组件 --> <!-- 顶部时间栏 Bar 组件 -->
<script setup lang="ts"> <script setup lang="ts">
import type { Dayjs } from 'dayjs'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import type { TimeBarButton, TimeBarLabel, TimeBarTime } from './types' import type { TimeBarButton, TimeBarLabel, TimeBarTime } from './types'
import { formatTime } from './hook' import { formatTime } from './hook'
...@@ -25,7 +26,10 @@ ...@@ -25,7 +26,10 @@
// 标签 // 标签
label: { label: {
type: Object as PropType<TimeBarLabel>, type: Object as PropType<TimeBarLabel>,
default: () => ({}) as TimeBarLabel, default: () =>
({
text: '时间',
}) as TimeBarLabel,
}, },
// 时间 // 时间
time: { time: {
...@@ -47,9 +51,6 @@ ...@@ -47,9 +51,6 @@
label: props.label, label: props.label,
time: props.time, time: props.time,
buttons: props.buttons, buttons: props.buttons,
// 组件自身的数据
showDropdownMenu: false,
}) })
function toggleShow(show?: boolean) { function toggleShow(show?: boolean) {
...@@ -61,62 +62,67 @@ ...@@ -61,62 +62,67 @@
if (!data?.time?.value) { if (!data?.time?.value) {
const time = dayjs() const time = dayjs()
data.time.value = [time.subtract(1, 'days'), time] data.time.value = data.time.type === 'range' ? [time.subtract(1, 'days'), time] : [time]
} }
} }
const labelText = computed(() => { function getTime(): Dayjs[] {
let text: string return toRaw(data.time.value)
if (data.label.options?.length) { }
text = checkedLabelOption.value?.text
} else {
text = data.label.text
}
return text || '' function setTime(value: Dayjs[]) {
}) data.time.value = value
}
const timeText = computed(() => { function getCheckedOption() {
let text: string return toRaw(checkedLabelOption.value)
if (data.time) { }
const format = checkedLabelOption.value?.format || data.time.format
text = data.time.value.map((item) => dayjs(item).format(format)).join(' - ')
}
return text || '' function setCheckedOption(index: number) {
}) onLabelOptionChange((_, i) => i === index)
}
const timePickerType = computed(() => { function getTimeBarValue() {
let type: number return {
if (data.time) { option: getCheckedOption(),
type = checkedLabelOption.value?.timeType || data.time.timeType value: getTime(),
} }
}
return type || 3 const labelText = computed(() => checkedLabelOption.value?.text || data.label.text || '')
const timePickerType = computed(() => checkedLabelOption.value?.timeType || data.time?.timeType || 3)
const timeText = computed(() => {
const format = checkedLabelOption.value?.format || data.time?.format
return data.time.value.map((item) => dayjs(item).format(format)).join(' - ') || ''
}) })
// ================== Option 下拉选择相关开始 ===================
const dropdownMenu = ref(null) const dropdownMenu = ref(null)
const showDropdownMenu = ref(false)
const checkedLabelOption = computed(() => data.label?.options?.find((option) => option.checked) || {}) const checkedLabelOption = computed(() => data.label?.options?.find((option) => option.checked) || {})
function changeLabelOption(option: TimeBarLabel['options'][0]) { function changeLabelOption(option: TimeBarLabel['options'][0]) {
data.showDropdownMenu = false showDropdownMenu.value = false
data.label.options.forEach((item) => { onLabelOptionChange((item) => item.value === option.value)
item.checked = item.value === option.value }
function onLabelOptionChange(cb: (e: TimeBarLabel['options'][0], i: number) => boolean) {
data.label.options.forEach((item, index) => {
item.checked = cb(item, index)
if (item.checked) { if (item.checked) {
data.label?.onChange?.({ data.label?.onChange?.(getTimeBarValue())
option: { text: item.text, value: item.value },
value: toRaw(data.time.value),
})
} }
}) })
} }
function openDropdownMenu() { function openDropdownMenu() {
data.showDropdownMenu = true if (data.readonly) {
return
}
showDropdownMenu.value = true
dropdownMenu.value?.show() dropdownMenu.value?.show()
} }
function closeDropdownMenu() { // ================== Option 下拉选择相关结束 ===================
data.showDropdownMenu = false
}
// ================== TimePicker 选择相关开始 ===================
const showTimePicker = ref(false) const showTimePicker = ref(false)
function changeTime(e: Recordable) { function changeTime(e: Recordable) {
if (e.startDate) { if (e.startDate) {
...@@ -124,16 +130,28 @@ ...@@ -124,16 +130,28 @@
} else { } else {
data.time.value = [dayjs(e.result)] data.time.value = [dayjs(e.result)]
} }
data.time.onChange?.({
option: { text: checkedLabelOption.value.text, value: checkedLabelOption.value.value },
value: toRaw(data.time.value),
})
showTimePicker.value = false showTimePicker.value = false
} }
function openTimePicker() {
if (!data.readonly) {
showTimePicker.value = true
}
}
watch(
() => data.time.value,
() => data.time.onChange?.(getTimeBarValue()),
{ deep: true },
)
// ================== TimePicker 选择相关结束 ===================
emits('register', { emits('register', {
setProps, setProps,
toggleShow, toggleShow,
getTime,
setTime,
getCheckedOption,
setCheckedOption,
getTimeBarValue,
}) })
</script> </script>
...@@ -153,12 +171,12 @@ ...@@ -153,12 +171,12 @@
selectedColor="#465CFF" selectedColor="#465CFF"
:options="data.label.options" :options="data.label.options"
@click="changeLabelOption" @click="changeLabelOption"
@close="closeDropdownMenu" @close="showDropdownMenu = false"
ref="dropdownMenu" ref="dropdownMenu"
> >
<view class="fui-filter__item" @tap="openDropdownMenu"> <view class="fui-filter__item" @tap="openDropdownMenu">
<text>{{ checkedLabelOption.text }}</text> <text>{{ checkedLabelOption.text }}</text>
<view class="fui-filter__icon" :class="{ 'fui-icon__ani': data.showDropdownMenu }"> <view class="fui-filter__icon" :class="{ 'fui-icon__ani': showDropdownMenu }">
<fui-icon name="turningdown" :size="32" /> <fui-icon name="turningdown" :size="32" />
</view> </view>
</view> </view>
...@@ -169,14 +187,35 @@ ...@@ -169,14 +187,35 @@
</template> </template>
</view> </view>
<view class=""> <view class="flex flex-auto justify-between items-center">
<view class="time-wrap" @tap="showTimePicker = true"> <view class="time-wrap" :class="{ left: data.buttons?.length }" @tap="openTimePicker">
<!-- --> <view class="time" :class="{ readonly: data.readonly }">{{ timeText }}</view>
<view class="time">{{ timeText }}</view> <Icon icon="ic-baseline-keyboard-arrow-right" size="40" color="#666" />
</view> </view>
<view class="buttons" v-if="data.buttons?.length"> <view class="buttons" v-if="data.buttons?.length">
<!-- --> <!-- -->
<fui-button
bold
:size="24"
width="140rpx"
height="60rpx"
radius="8rpx"
color="#1890FF"
background="#E7F3FF"
v-for="(button, index) in data.buttons"
:key="`time_bar_button_${index}`"
@tap="button.onClick?.({ index, label: button.label }, getTimeBarValue())"
>
<fui-icon
v-if="button.icon"
:name="button.icon"
:size="28"
style="color: #1890ff !important; margin-right: 6rpx"
/>
<text>{{ button.label }}</text>
<Icon icon="ic-baseline-keyboard-arrow-right" size="32" color="#666" />
</fui-button>
</view> </view>
</view> </view>
...@@ -213,6 +252,7 @@ ...@@ -213,6 +252,7 @@
.time-bar { .time-bar {
padding: 20rpx; padding: 20rpx;
box-sizing: border-box;
width: 100%; width: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
...@@ -267,10 +307,21 @@ ...@@ -267,10 +307,21 @@
} }
.time-wrap { .time-wrap {
display: flex;
justify-content: space-between;
flex: auto; flex: auto;
&.left {
justify-content: flex-start;
flex: none;
}
.time { .time {
color: #1890ff; color: #1890ff;
&.readonly {
color: #666;
}
} }
} }
} }
......
import type { Dayjs } from 'dayjs' import type { Dayjs } from 'dayjs'
import { getBasicWidgetInstanceFunctions, registerFactory } from '../../utils'
import type { TimeBarInstance, TimeBarProps } from './types' import type { TimeBarInstance, TimeBarProps } from './types'
import { getBooleanOrDefault } from '../../utils'
import { isProdMode } from '/@/utils/env'
// 组件名称
export const name = 'TimeBarWidget'
/**
* 顶部时间栏组件响应式 Hook
* @param props 组件参数
* @returns 组件响应式数据
*/
export function useTimeBarWidget<T extends TimeBarInstance, P extends TimeBarProps>(
props: P,
): [(instance: T) => void, TimeBarInstance] {
const instanceRef = ref<T>()
const register = registerFactory(instanceRef, props)
const { get, setProps, toggleShow } = getBasicWidgetInstanceFunctions(instanceRef, name)
return [
register,
{
setProps,
toggleShow,
getTime: () => get()?.getTime(),
setTime: (time: Dayjs[]) => get()?.setTime(time),
getCheckedOption: () => get()?.getCheckedOption(),
setCheckedOption: (index: number) => get()?.setCheckedOption(index),
},
]
}
/**
* 格式化时间
* @param time 时间
* @param format 格式化
* @returns 格式化后的时间,如果时间为空则返回空字符串
*/
export function formatTime(time: Dayjs, format = 'YYYY-MM-DD HH:mm:ss') { export function formatTime(time: Dayjs, format = 'YYYY-MM-DD HH:mm:ss') {
return time?.format(format) ?? '' return time?.format(format) ?? ''
} }
/**
* 根据 type 属性返回对应的格式化字符串
* @param type fui-date-picker 组件的 type 属性
* @returns 根据 type 属性返回对应的格式化字符串
*/
export function getFormatByType(type: number) { export function getFormatByType(type: number) {
switch (type) { switch (type) {
case 1: case 1:
...@@ -16,56 +55,12 @@ export function getFormatByType(type: number) { ...@@ -16,56 +55,12 @@ export function getFormatByType(type: number) {
case 3: case 3:
return 'YYYY-MM-DD' return 'YYYY-MM-DD'
case 4: case 4:
return 'YYYY-MM-DD HH:00' return 'YYYY-MM-DD HH:00:00'
case 5: case 5:
return 'YYYY-MM-DD HH:mm' return 'YYYY-MM-DD HH:mm:00'
case 6: case 6:
return 'YYYY-MM-DD HH:mm:ss' return 'YYYY-MM-DD HH:mm:ss'
default: default:
return 'YYYY-MM-DD HH:mm:ss' return 'YYYY-MM-DD HH:mm:ss'
} }
} }
/**
* 顶部时间栏组件响应式 Hook
* @param props 组件参数
* @returns 组件响应式数据
*/
export function useTimeBarWidget<T extends TimeBarInstance>(props: TimeBarProps): [(instance: T) => void, T] {
const instanceRef = ref<Nullable<T>>(null)
function register(instance: T) {
if (isProdMode()) {
if (instance === unref(instanceRef)) {
return
}
onUnmounted(() => {
instanceRef.value = null
})
}
instanceRef.value = instance
props && instance?.setProps(props)
}
function getInstance(): T {
const instance = unref(instanceRef)
if (!instance) {
console.warn('时间栏小部件还未加载完成')
}
return instance as T
}
return [
register,
{
setProps: (props: TimeBarProps) => {
getInstance()?.setProps(props)
},
toggleShow: (show?: boolean) => {
getInstance()?.toggleShow(getBooleanOrDefault(show))
},
} as T,
]
}
import type { Dayjs } from 'dayjs' import type { Dayjs } from 'dayjs'
import type { BasicWidgetInstance, BasicWidgetProps } from '../../utils'
/**
* 对应 first-ui datePicker 组件 type 参数
*/
type FirstUIDatePickerType = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 type FirstUIDatePickerType = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
export interface TimeBarChangeEvent { export interface TimeBarChangeEvent {
value: Dayjs[] value: Dayjs[]
option?: { option?: TimeBarLabel['options'][0]
text?: string
value?: string
}
} }
export interface TimeBarLabel { export interface TimeBarLabel {
...@@ -19,9 +20,6 @@ export interface TimeBarLabel { ...@@ -19,9 +20,6 @@ export interface TimeBarLabel {
value?: string value?: string
checked?: boolean checked?: boolean
format?: string format?: string
/**
* 对应 first-ui datePicker 组件 type 参数
*/
timeType?: FirstUIDatePickerType timeType?: FirstUIDatePickerType
}[] }[]
onClick?: () => void onClick?: () => void
...@@ -30,9 +28,6 @@ export interface TimeBarLabel { ...@@ -30,9 +28,6 @@ export interface TimeBarLabel {
export interface TimeBarTime { export interface TimeBarTime {
type: 'single' | 'range' type: 'single' | 'range'
/**
* 对应 first-ui datePicker 组件 type 参数
*/
timeType: FirstUIDatePickerType timeType: FirstUIDatePickerType
format?: string format?: string
value?: Dayjs[] value?: Dayjs[]
...@@ -40,14 +35,15 @@ export interface TimeBarTime { ...@@ -40,14 +35,15 @@ export interface TimeBarTime {
} }
export interface TimeBarButton { export interface TimeBarButton {
/**
* 图标,仅支持 fui-icon name
*/
icon?: string icon?: string
label: string label: string
onClick?: (e: { index: number; label: string }, time: string | { start?: string; end?: string }) => void onClick?: (e: { index: number; label: string }, time: TimeBarChangeEvent) => void
} }
export interface TimeBarProps { export interface TimeBarProps extends BasicWidgetProps {
// 是否显示
show?: boolean
// 是否只读 // 是否只读
readonly?: boolean readonly?: boolean
// 对齐方式 // 对齐方式
...@@ -60,7 +56,9 @@ export interface TimeBarProps { ...@@ -60,7 +56,9 @@ export interface TimeBarProps {
buttons?: TimeBarButton[] buttons?: TimeBarButton[]
} }
export interface TimeBarInstance { export interface TimeBarInstance extends BasicWidgetInstance<TimeBarProps> {
setProps: (props: TimeBarProps) => void getTime: () => Dayjs[]
toggleShow: (show?: boolean) => void setTime: (time: Dayjs[]) => void
getCheckedOption: () => TimeBarChangeEvent
setCheckedOption: (index: number) => void
} }
import { isBoolean } from 'lodash-es' import { isBoolean } from 'lodash-es'
import { isProdMode } from '@/utils/env'
export interface BasicWidgetProps {
// 是否显示
show?: boolean
}
export interface BasicWidgetInstance<T extends BasicWidgetProps = BasicWidgetProps> {
/**
* 设置小部件属性
* @param props 小部件属性
*/
setProps: (props: Partial<T>) => void
/**
* 切换显示状态
* @param show 是否显示,强制指定显示状态
*/
toggleShow: (show?: boolean) => void
}
/**
* 获取 Boolean 值或默认值
* @param value Boolean 值
* @param def 默认值
* @returns 值或默认值
*/
export function getBooleanOrDefault(value: any, def = null): boolean { export function getBooleanOrDefault(value: any, def = null): boolean {
return isBoolean(value) ? value : def return isBoolean(value) ? value : def
} }
/**
* 注册组件工厂
* @param instanceRef 组件实例 Ref
* @param props 组件属性
* @param callback 回调函数
*/
export function registerFactory<T extends BasicWidgetInstance<P>, P>(
instanceRef: Ref<Nullable<T>>,
props: P,
callback?: (instance: T) => void,
): (instance: T) => void {
function register(instance: T) {
if (isProdMode()) {
if (instance === unref(instanceRef)) {
return
}
onUnmounted(() => {
instanceRef.value = null
})
}
instanceRef.value = instance
props && instance?.setProps(props)
callback && callback(instance)
}
return register
}
/**
* 获取组件实例
* @param instanceRef 组件实例 Ref
* @param name 组件名称
* @returns 组件实例
*/
export function getInstance<T extends BasicWidgetInstance>(instanceRef: Ref<Nullable<T>>, name?: string): T {
const instance = unref(instanceRef)
if (!instance) {
console.warn(`The ${name || 'widget'} instance has not been obtained`)
}
return instance as T
}
/**
* 获取基础组件实例函数
* @param instanceRef 组件实例 Ref
* @param name 组件名称
* @returns 组件实例函数
* @example
* ```ts
* const { get, setProps, toggleShow } = getBasicWidgetInstanceFunctions<BasicWidgetInstance, BasicWidgetProps>(instanceRef, 'basic widget')
* ```
*/
export function getBasicWidgetInstanceFunctions<T extends BasicWidgetInstance, P extends BasicWidgetProps>(
instanceRef: Ref<Nullable<T>>,
name?: string,
) {
const get = () => getInstance(instanceRef, name)
return {
get,
setProps: (props: Partial<P>) => get()?.setProps(props),
toggleShow: (show?: boolean) => get()?.toggleShow(getBooleanOrDefault(show)),
} as T & { get: () => T }
}
...@@ -11,7 +11,14 @@ ...@@ -11,7 +11,14 @@
useShare() useShare()
const config: MapboxConfig = { // 页面参数
// const param = reactive({
// query: {},
// filter: {},
// })
// 地图配置
const config: MapboxConfig = reactive({
// 说明: 地图数据来源标注展示 // 说明: 地图数据来源标注展示
attribution: { attribution: {
text: '湖南省气象台', text: '湖南省气象台',
...@@ -21,11 +28,13 @@ ...@@ -21,11 +28,13 @@
// 说明: 根据每个页面的 widget 布局情况,可能需要适当调整地图的中心位置,让界面显示效果更好 // 说明: 根据每个页面的 widget 布局情况,可能需要适当调整地图的中心位置,让界面显示效果更好
center: [111.6, 26.170844], center: [111.6, 26.170844],
}, },
} })
// 顶部时间轴小部件 // 顶部时间轴小部件
const [registerTimeBarWidget] = useTimeBarWidget({ const [registerTimeBarWidget, { getTime, setTime, getCheckedOption }] = useTimeBarWidget({
show: true, show: true,
align: 'left',
readonly: false,
label: { label: {
options: [ options: [
{ {
...@@ -62,12 +71,37 @@ ...@@ -62,12 +71,37 @@
) )
}, },
}, },
buttons: [
{
icon: 'order',
label: '列表',
onClick: (e, { option, value }) => {
console.log(
'[TimeBarWidget] Button Click',
e,
option,
value.map((item) => formatTime(item)),
)
},
},
],
}) })
// 前后切换小部件 // 前后切换小部件
const [registerSwitchControlWidget] = useSwitchControlWidget({ const [registerSwitchControlWidget] = useSwitchControlWidget({
show: true, show: true,
prev: () => Message.toast('prev'), prev: () => {
const option = getCheckedOption()
const time = getTime()
console.log(
'[SwitchControlWidget] prev',
option,
time.map((item) => formatTime(item)),
)
setTime(time.map((item) => item.subtract(1, 'hours')))
Message.toast('prev')
},
next: () => Message.toast('next'), next: () => Message.toast('next'),
}) })
...@@ -87,6 +121,10 @@ ...@@ -87,6 +121,10 @@
height: 150, height: 150,
maxHeight: 240, maxHeight: 240,
}) })
function testPackUp() {
toggleLegendWidgetExpand()
}
</script> </script>
<template> <template>
...@@ -108,7 +146,7 @@ ...@@ -108,7 +146,7 @@
<!-- 底部 Bar 小部件 --> <!-- 底部 Bar 小部件 -->
<BottomBarWidget @register="registerBottomBarWidget"> <BottomBarWidget @register="registerBottomBarWidget">
<!-- 内容 Slot --> <!-- 内容 Slot -->
<view class="c-coolGray" @tap="toggleLegendWidgetExpand">底部交互控件/展示内容</view> <view class="c-coolGray" @tap="testPackUp">底部交互控件/展示内容</view>
</BottomBarWidget> </BottomBarWidget>
</view> </view>
</view> </view>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论