提交 147866b0 作者: 方治民

feat: 实现 ToolBoxWidget 小部件的核心功能,优化其他小部件的样式

上级 b229c6c4
......@@ -67,12 +67,12 @@
<template>
<view class="wrap bottom-bar" :class="{ expand: data.expand }" v-show="data.show">
<view class="action" @tap="toggleExpand()" v-show="data.showExpandButton">
<view class="action flex-center" @tap="toggleExpand()" v-show="data.showExpandButton">
<Icon icon="solar-double-alt-arrow-up-line-duotone" size="60" class="icon" />
</view>
<!-- 自定义内容 -->
<view class="content">
<view class="content flex-center">
<slot></slot>
</view>
......@@ -114,9 +114,6 @@
.action {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
.icon {
@include animate();
......@@ -129,9 +126,6 @@
}
.content {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: calc(100% - 60rpx - 20rpx);
overflow: hidden;
......
......@@ -70,15 +70,15 @@
</script>
<template>
<view class="wrap legend" @click="data.expand = !data.expand">
<view class="wrap legend flex-center" @click="data.expand = !data.expand">
<!-- 展开/收起 -->
<view class="expand-action" v-show="!data.expand">
<view class="expand-action flex-center" v-show="!data.expand">
<view class="text">图例</view>
<Icon icon="ic-round-keyboard-arrow-up" color="#1890ff" size="42" />
</view>
<!-- 内容 -->
<view class="expand-content" v-show="data.expand">
<view class="expand-content flex-center" v-show="data.expand">
<!-- 标题 -->
<view v-if="data.title" class="title">{{ data.title }}</view>
......@@ -86,7 +86,7 @@
<DefineTemplate v-slot="{ item, sub }">
<view class="item">
<!-- 图标 -->
<view v-if="item.icon" class="icon">
<view v-if="item.icon" class="icon flex-center">
<CacheImage :src="item.icon" width="34" height="34" />
</view>
......@@ -146,19 +146,13 @@
}
.legend {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 12rpx 20rpx;
background-color: #fff;
border-radius: 10rpx;
box-shadow: 0 0 15rpx rgba(0, 0, 0, 0.3);
.expand-action {
display: flex;
justify-content: center;
align-items: center;
font-size: 26rpx;
font-weight: bold;
color: #1890ff;
......@@ -169,9 +163,6 @@
}
.expand-content {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
font-size: 24rpx;
color: #555;
......@@ -195,9 +186,6 @@
justify-content: flex-start;
.icon {
display: flex;
justify-content: center;
align-items: center;
margin-right: 8rpx;
padding: 4rpx;
}
......
......@@ -7,12 +7,19 @@
type: Boolean,
default: true,
},
// 底部距离 rpx
bottom: {
type: String,
default: '1rpx',
},
})
const emits = defineEmits(['register', 'prev', 'next'])
const height = computed(() => `calc(50% - 60rpx - ${Number(data.bottom.replace('rpx', '')) / 2}rpx)`)
const data = reactive({
show: props.show,
bottom: props.bottom,
// 往前
prev: () => {},
// 往后
......@@ -47,10 +54,10 @@
<template>
<view class="wrap switch-control">
<view class="prev" @tap="onPrev">
<view class="flex-center prev" @tap="onPrev">
<Icon class="icon" icon="ic-baseline-arrow-back-ios" size="50" color="white" />
</view>
<view class="next" @tap="onNext">
<view class="flex-center next" @tap="onNext">
<Icon class="icon" icon="ic-baseline-arrow-forward-ios" size="50" color="white" />
</view>
</view>
......@@ -61,15 +68,14 @@
.switch-control {
> * {
@include animate();
width: 60rpx;
height: 120rpx;
background-color: rgba(0, 0, 0, 0.3);
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: calc(50% - 100rpx);
top: v-bind(height);
z-index: 99;
}
......
import type { BasicWidgetInstance, BasicWidgetProps } from '../../utils'
export interface SwitchControlProps extends BasicWidgetProps {
// 底部距离 rpx
bottom?: string
// 上一个
prev?: () => void
// 下一个
......
......@@ -124,6 +124,7 @@
// ================== TimePicker 选择相关开始 ===================
const showTimePicker = ref(false)
const zIndex = computed(() => (showTimePicker.value ? 200 : 110))
function changeTime(e: Recordable) {
if (e.startDate) {
data.time.value = [dayjs(e.startDate.result), dayjs(e.endDate.result)]
......@@ -140,7 +141,6 @@
watch(
() => data.time.value,
() => data.time.onChange?.(getTimeBarValue()),
{ deep: true },
)
// ================== TimePicker 选择相关结束 ===================
......@@ -174,7 +174,7 @@
@close="showDropdownMenu = false"
ref="dropdownMenu"
>
<view class="fui-filter__item" @tap="openDropdownMenu">
<view class="fui-filter__item flex-center" @tap="openDropdownMenu">
<text>{{ checkedLabelOption.text }}</text>
<view class="fui-filter__icon" :class="{ 'fui-icon__ani': showDropdownMenu }">
<fui-icon name="turningdown" :size="32" />
......@@ -187,7 +187,7 @@
</template>
</view>
<view class="flex flex-auto justify-between items-center">
<view class="flex flex-auto justify-between items-center h-55rpx">
<view class="time-wrap" :class="{ left: data.buttons?.length }" @tap="openTimePicker">
<view class="time" :class="{ readonly: data.readonly }">{{ timeText }}</view>
<Icon icon="ic-baseline-keyboard-arrow-right" size="40" color="#666" />
......@@ -198,8 +198,8 @@
<fui-button
bold
:size="24"
width="140rpx"
height="60rpx"
width="130rpx"
height="55rpx"
radius="8rpx"
color="#1890FF"
background="#E7F3FF"
......@@ -244,7 +244,7 @@
top: 0;
left: 0;
// 层级需要比其他 widget 高,否则 picker 会被遮挡
z-index: 100;
z-index: v-bind(zIndex);
background-color: white;
}
......@@ -268,11 +268,11 @@
color: #333;
.icon {
margin-right: 10rpx;
margin-right: 6rpx;
}
.text {
margin-right: 5rpx;
margin-right: 2rpx;
&.after::after {
content: ':';
......@@ -280,14 +280,11 @@
}
.fui-filter__item {
display: flex;
align-items: center;
justify-content: center;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
background-color: #fff;
margin-right: 10rpx;
margin-right: 6rpx;
}
.fui-filter__icon {
......@@ -312,9 +309,16 @@
&.left {
justify-content: flex-start;
flex: none;
.time {
max-width: 350rpx;
}
}
.time {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #1890ff;
&.readonly {
......
export type * from './src/types'
export * from './src/hook'
export { default as ToolBoxWidget } from './src/ToolBox.vue'
import { getBasicWidgetInstanceFunctions, getBooleanOrDefault, registerFactory } from '../../utils'
import type { ToolBoxInstance, ToolBoxProps } from './types'
// 组件名称
export const name = 'ToolBoxWidget'
/**
* 左侧工具盒子组件响应式 Hook
* @param props 组件参数
* @returns 组件响应式数据
*/
export function useToolBoxWidget<T extends ToolBoxInstance, P extends ToolBoxProps>(
props: P,
): [(instance: T) => void, ToolBoxInstance] {
const instanceRef = ref<T>()
const register = registerFactory(instanceRef, props)
const { get, setProps, toggleShow } = getBasicWidgetInstanceFunctions(instanceRef, name)
return [
register,
{
setProps,
toggleShow,
toggleExpand: (expand?: boolean) => get()?.toggleExpand(getBooleanOrDefault(expand)),
},
]
}
import type { BasicWidgetInstance, BasicWidgetProps } from '../../utils'
export interface ToolBoxButtonHandleEvent {
// 事件类型
type: 'click' | 'change'
// 事件名称
name: string
// 事件值
value?: string | string[] | { text: string; value: string } | { text: string; value: string }[]
}
export interface ToolBoxButton {
// 按钮类型
type: 'select' | 'button' | 'filter'
// 按钮名称
name: string
// 按钮图标
icon?: string
// 按钮是否禁用
disabled?: boolean
// select 类型按钮选项
options?: {
id?: string
// 选项名称
text: string
// 选项值
value: string
// 是否选中
checked?: boolean
// 是否禁用
disabled?: boolean
}[]
// select 类型下是否支持多选
multiple?: boolean
// 按钮事件
handle?: (e: ToolBoxButtonHandleEvent) => void
// 按钮值
value?: string | string[]
// filter 类型的结果
result?: string | string[]
}
export interface ToolBoxButtonGroup {
// 标识
key: string
// 对齐方向
align?: 'top' | 'bottom'
// 按钮列表
buttons: ToolBoxButton[]
}
export interface ToolBoxProps extends BasicWidgetProps {
// 是否展开
expand?: boolean
// 是否显示是否展开按钮
showExpandButton?: boolean
// 底部距离 rpx
bottom?: string
// 底部内边距 rpx
bottomPadding?: string
// 工具集
tools?: ToolBoxButtonGroup[]
}
export interface ToolBoxInstance extends BasicWidgetInstance<ToolBoxProps> {
toggleExpand: (expand?: boolean) => void
}
......@@ -6,6 +6,7 @@
import type { MapboxConfig } from '@/components/Map/Mapbox'
import { LegendWidget, useLegendWidget } from '@/components/Map/Widgets/Legend'
import { TimeBarWidget, formatTime, useTimeBarWidget } from '@/components/Map/Widgets/TimeBarWidget'
import { ToolBoxWidget, useToolBoxWidget } from '@/components/Map/Widgets/ToolBoxWidget'
import { BottomBarWidget, useBottomBarWidget } from '@/components/Map/Widgets/BottomBar'
import { SwitchControlWidget, useSwitchControlWidget } from '@/components/Map/Widgets/SwitchControl'
......@@ -87,8 +88,116 @@
],
})
// 左侧工具栏小部件
const [registerToolBoxWidget, { setProps: setToolBoxProps }] = useToolBoxWidget({
show: true,
expand: true,
showExpandButton: true,
// 说明: 如果底部使用 bottom-left attribution 则需要加上 65rpx,默认显示在右侧,不会冲突
bottomPadding: '65rpx',
tools: [
{
key: 'filter',
align: 'top',
buttons: [
{
name: '过滤',
icon: '/static/icons/toolbox/filter.png',
type: 'filter',
handle: () => {},
},
{
name: '图层',
icon: '/static/icons/toolbox/menu.png',
type: 'select',
multiple: true,
options: [
{
text: '色斑',
value: 'contour',
checked: true,
},
{
text: '数值',
value: 'text',
},
],
handle: () => {},
},
{
name: '区域',
icon: '/static/icons/toolbox/location.png',
type: 'select',
multiple: false,
options: [
{
text: '湖南省',
value: '430000',
checked: true,
},
{
text: '长沙市',
value: '430100',
},
{
text: '湘潭市',
value: '430300',
},
],
handle: () => {},
},
{
name: '站点',
icon: '/static/icons/toolbox/station.png',
type: 'select',
multiple: false,
handle: () => {},
},
],
},
{
key: 'action',
align: 'bottom',
buttons: [
{
name: '要素',
icon: '/static/icons/toolbox/element.png',
type: 'select',
multiple: true,
handle: () => {},
},
{
name: '排名',
icon: '/static/icons/toolbox/rank.png',
type: 'button',
handle: () => {},
},
{
name: '累加',
icon: '/static/icons/toolbox/cumulative.png',
type: 'button',
disabled: true,
handle: () => {},
},
],
},
{
key: 'desc',
align: 'bottom',
buttons: [
{
name: '综述',
icon: '/static/icons/toolbox/describe.png',
type: 'button',
handle: () => {},
},
],
},
],
})
// 前后切换小部件
const [registerSwitchControlWidget] = useSwitchControlWidget({
const [registerSwitchControlWidget, { setProps: setSwitchControlProps }] = useSwitchControlWidget({
show: true,
prev: () => {
const { option, value } = getTimeBarValue()
......@@ -124,6 +233,16 @@
function testPackUp() {
toggleLegendWidgetExpand()
}
watch(
() => height.value,
(value) => {
console.log('[useBottomBarWidget] height', value)
setToolBoxProps({ bottom: value })
setSwitchControlProps({ bottom: value })
},
)
</script>
<template>
......@@ -133,9 +252,12 @@
<!-- 地图上方所有小部件 -->
<view class="widgets">
<!-- -->
<!-- 时间栏小部件 -->
<TimeBarWidget @register="registerTimeBarWidget" />
<!-- 左侧工具栏小部件 -->
<ToolBoxWidget @register="registerToolBoxWidget" />
<!-- 前后切换小部件 -->
<SwitchControlWidget @register="registerSwitchControlWidget" />
......
......@@ -147,6 +147,7 @@ declare module 'vue' {
SwitchControl: typeof import('./../src/components/Map/Widgets/SwitchControl/src/SwitchControl.vue')['default']
ThumbnailPreview: typeof import('./../src/components/ThumbnailPreview/index.vue')['default']
TimeBar: typeof import('./../src/components/Map/Widgets/TimeBarWidget/src/TimeBar.vue')['default']
ToolBox: typeof import('./../src/components/Map/Widgets/ToolBoxWidget/src/ToolBox.vue')['default']
TopBar: typeof import('./../src/components/Map/Mapbox/widgets/TopBarWidget/src/TopBar.vue')['default']
TopBarWidget: typeof import('./../src/components/Map/Mapbox/widgets/TopBarWidget/TopBarWidget.vue')['default']
View: typeof import('./../src/components/Layout/View.vue')['default']
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论