Hooks
@erp/common 提供的 Vue 组合式函数,用于在组件中复用逻辑。
功能概览
- popupManager - 弹出层 z-index 管理
- usePopupManager - 弹出层管理 Hook
- useDraggable - 元素拖拽功能
- useFormItem - 表单项上下文
- useLocale / useI18n - 国际化支持
引入方式
typescript
import {
popupManager,
useDraggable
} from '@erp/common'popupManager
弹出层层级管理器,用于管理弹窗、下拉框等弹出层的 z-index。
基础用法
typescript
import { popupManager } from '@erp/common'
// 获取下一个 z-index
const zIndex = popupManager.getNextZIndex('popup')
// 添加弹出层并获取 z-index
const zIndex = popupManager.add('popup')
// 移除弹出层
popupManager.delete(zIndex, 'popup')
// 获取当前最高 z-index
const current = popupManager.getCurrentZIndex('popup')弹出层类型
typescript
type PopupType = 'popup' | 'dialog' | 'message' | 'table'| 类型 | 说明 | 基础 z-index |
|---|---|---|
popup | 普通弹出层(下拉框、提示等) | 3000 |
dialog | 对话框、抽屉 | 3000 |
message | 消息提示 | 5000 |
table | 表格相关弹出层 | 3000 |
API
typescript
class PopupManager {
/** 获取下一个可用的 z-index */
getNextZIndex(type: PopupType): number
/** 获取当前最高的 z-index */
getCurrentZIndex(type: PopupType): number
/** 添加弹出层,返回分配的 z-index */
add(type: PopupType): number
/** 移除弹出层 */
delete(zIndex: number, type: PopupType): void
/** 判断是否为最后一个对话框 */
isLastDialog(zIndex: number): boolean
}在组件中使用
typescript
import { popupManager } from '@erp/common'
import { ref, onMounted, onBeforeUnmount } from 'vue'
const zIndex = ref(0)
onMounted(() => {
zIndex.value = popupManager.add('popup')
})
onBeforeUnmount(() => {
popupManager.delete(zIndex.value, 'popup')
})usePopupManager
弹出层管理 Hook,自动处理 z-index 的分配和回收。
基础用法
typescript
import usePopupManager from '@erp/common'
// 基础用法
const { zIndex, open, close, isLastDialog } = usePopupManager('dialog')
// 响应式 visible
const visible = ref(false)
const { zIndex } = usePopupManager('dialog', { visible })
// 挂载时自动打开
const { zIndex } = usePopupManager('popup', { runOnMounted: true })参数说明
typescript
function usePopupManager(
type: PopupType,
options?: {
/** 响应式的可见状态,变化时自动管理 z-index */
visible?: Ref<boolean>
/** 是否在挂载时自动打开 */
runOnMounted?: boolean
}
): {
/** 当前 z-index(只读) */
zIndex: Readonly<Ref<number>>
/** 打开弹出层 */
open: () => void
/** 关闭弹出层 */
close: () => void
/** 是否为最后一个对话框 */
isLastDialog: () => boolean
}使用示例
vue
<template>
<div class="modal" :style="{ zIndex }">
<slot />
</div>
</template>
<script setup>
import usePopupManager from '@erp/common'
const props = defineProps({
visible: Boolean
})
const { zIndex } = usePopupManager('dialog', {
visible: toRef(props, 'visible')
})
</script>useDraggable
拖拽功能 Hook,用于实现元素拖拽。
基础用法
typescript
import { useDraggable } from '@erp/common'
import { ref } from 'vue'
const modalRef = ref<HTMLElement>()
const headerRef = ref<HTMLElement>()
const { position, isDragging } = useDraggable(modalRef, {
handle: headerRef
})参数说明
typescript
function useDraggable(
target: Ref<HTMLElement | undefined>,
options?: {
/** 拖拽手柄元素 */
handle?: Ref<HTMLElement | undefined>
/** 初始位置 */
initialValue?: { x: number; y: number }
/** 是否阻止默认事件 */
preventDefault?: boolean
/** 是否阻止冒泡 */
stopPropagation?: boolean
/** 拖拽开始回调 */
onStart?: (position: Position, event: PointerEvent) => void
/** 拖拽中回调 */
onMove?: (position: Position, event: PointerEvent) => void
/** 拖拽结束回调 */
onEnd?: (position: Position, event: PointerEvent) => void
}
): {
/** 当前位置 */
position: Ref<{ x: number; y: number }>
/** 是否正在拖拽 */
isDragging: Ref<boolean>
/** 样式对象 */
style: ComputedRef<CSSProperties>
}使用示例
可拖拽弹窗
vue
<template>
<div ref="modalRef" class="modal" :style="style">
<div ref="headerRef" class="modal-header">
拖拽这里移动
</div>
<div class="modal-body">
<slot />
</div>
</div>
</template>
<script setup>
import { useDraggable } from '@erp/common'
import { ref } from 'vue'
const modalRef = ref()
const headerRef = ref()
const { style, isDragging } = useDraggable(modalRef, {
handle: headerRef,
onEnd: (pos) => {
console.log('拖拽结束,位置:', pos)
}
})
</script>
<style scoped>
.modal-header {
cursor: move;
}
</style>限制拖拽范围
typescript
const { position } = useDraggable(elementRef, {
onMove: (pos) => {
// 限制在视口内
pos.x = Math.max(0, Math.min(pos.x, window.innerWidth - 200))
pos.y = Math.max(0, Math.min(pos.y, window.innerHeight - 100))
}
})useFormItem
表单项 Hook,用于在自定义表单组件中获取表单上下文。
基础用法
typescript
import { useFormItem } from '@erp/common'
const {
formItemCtx,
mergedDisabled,
mergedSize,
eventHandlers
} = useFormItem({
size: props.size,
disabled: props.disabled
})返回值
typescript
interface UseFormItemReturn {
/** 表单项上下文 */
formItemCtx: FormItemContext | undefined
/** 合并后的禁用状态(组件 > 表单项 > 表单) */
mergedDisabled: ComputedRef<boolean>
/** 合并后的尺寸(组件 > 表单项 > 表单) */
mergedSize: ComputedRef<Size>
/** 事件处理器 */
eventHandlers: {
onChange: () => void
onBlur: () => void
}
}使用示例
vue
<template>
<input
:disabled="mergedDisabled"
:class="[`input-${mergedSize}`]"
@change="eventHandlers.onChange"
@blur="eventHandlers.onBlur"
/>
</template>
<script setup>
import { useFormItem } from '@erp/common'
const props = defineProps({
size: String,
disabled: Boolean
})
const { mergedDisabled, mergedSize, eventHandlers } = useFormItem({
size: props.size,
disabled: props.disabled
})
</script>useLocale / useI18n
国际化 Hook。
基础用法
typescript
import { useLocale, useI18n } from '@erp/common'
// 获取当前语言
const { locale, setLocale } = useLocale()
// 获取翻译函数
const { t } = useI18n()
// 使用翻译
const message = t('common.confirm') // 确认API
typescript
// useLocale
function useLocale(): {
locale: Ref<string>
setLocale: (locale: string) => void
}
// useI18n
function useI18n(): {
t: (key: string, ...args: any[]) => string
locale: Ref<string>
}使用示例
vue
<template>
<button>{{ t('common.submit') }}</button>
<span>当前语言: {{ locale }}</span>
</template>
<script setup>
import { useI18n } from '@erp/common'
const { t, locale } = useI18n()
</script>