跳到主要内容
版本:Next

业务级对话框实现

目录

  1. 概述
  2. BaseDialog基类设计
  3. 业务级对话框架构
  4. 核心业务对话框分析
  5. Hook状态管理机制
  6. API集成与数据流
  7. 复杂交互实现
  8. 性能优化与内存管理
  9. 最佳实践指南
  10. 总结

概述

业务级对话框是LME系统中用于处理复杂业务场景的核心UI组件。本文档深入分析了三个主要的业务级对话框:工位选择对话框(WorkStationDialog)、工艺路由对话框(ProcessRouterDialog)和人工工位设置对话框(ArtificialStationDialog)。这些组件通过继承BaseDialog基类,结合Vue 3 Composition API和自定义Hook模式,实现了高度可复用和可维护的业务逻辑封装。

BaseDialog基类设计

BaseDialog作为所有业务级对话框的基础组件,提供了统一的对话框框架和通用功能。

图表来源

BaseDialog提供了以下核心功能:

  • 统一的对话框头部和底部布局
  • 自动化的关闭和确认事件处理
  • 可配置的对话框尺寸和样式
  • 国际化支持的语言文本
  • 可扩展的插槽系统

章节来源

业务级对话框架构

业务级对话框采用分层架构设计,通过组件继承和Hook模式实现业务逻辑的模块化封装。

图表来源

核心业务对话框分析

工位选择对话框(WorkStationDialog)

WorkStationDialog是最基础的业务级对话框,专门用于工位的选择和管理。

组件特性

  • 支持多选和单选模式
  • 集成搜索功能
  • 数据源动态加载
  • 选中状态管理

实现要点

// 工位对话框的核心实现
const {
onClose,
onConfirm,
onCheck,
onOpen,
onSearch,
visible,
innerValue,
tableRef,
dataSource,
columns,
selections,
} = useSelectDialog(props, ctx)

数据流图

图表来源

章节来源

工艺路由对话框(ProcessRouterDialog)

ProcessRouterDialog扩展了工位选择的功能,增加了工艺路线的关联和筛选能力。

特殊功能

  • 工艺路线数据预加载
  • 条件过滤和筛选
  • 单选模式支持
  • 数据源动态关联

实现差异

// 工艺路由特有的初始化逻辑
const onOpen = async () => {
routers.value = await getProcessRouterList(props.productId)
initData()
}

const initData = async (filter?: string) => {
const ids = routers.value.map((item) => item.id) as string[]
const data = await getWorkStationList(filter)
const dataSourceItems = data.items.filter((item) =>
ids.includes(item.workSectionId)
)
dataSource.value = dataSourceItems
}

章节来源

人工工位对话框(ArtificialStationDialog)

ArtificialStationDialog是最复杂的业务级对话框,集成了表格编辑和动态表单功能。

复合功能

  • 主表格展示
  • 编辑对话框
  • 动态表单验证
  • 多用户权限管理

双对话框架构

图表来源

章节来源

Hook状态管理机制

业务级对话框采用Vue 3 Composition API和自定义Hook模式,实现了清晰的状态管理和副作用处理。

useSelectDialog Hook设计

图表来源

状态管理模式

响应式状态定义

// 基础状态定义
const visible = computed({
get() {
return props.modelValue
},
set(val) {
ctx.emit('update:modelValue', val)
},
})

const dataSource = ref<any[]>([])
const innerValue = ref('')
const checkedList = ref<any[]>([])

计算属性和响应式依赖

// 计算属性实现
const selections = computed(() => {
return props.data?.map((item: any) => item.id) ?? []
})

const columns = computed(() => [
{
title: _t('序号'),
type: 'seq',
width: '60',
},
{
field: 'workSection.name',
title: _t('工序名称'),
},
// ... 其他列定义
])

章节来源

API集成与数据流

业务级对话框通过专门的API模块实现与后端服务的通信,支持异步数据加载和错误处理。

API模块设计

图表来源

数据加载流程

异步数据初始化

// 工艺路由对话框的数据初始化
const onOpen = async () => {
routers.value = await getProcessRouterList(props.productId)
initData()
}

const initData = async (filter?: string) => {
const ids = routers.value.map((item) => item.id) as string[]
const data = await getWorkStationList(filter)
const dataSourceItems = data.items.filter((item) =>
ids.includes(item.workSectionId)
)
dataSource.value = dataSourceItems
}

API调用封装

// API模块的封装实现
export const getProcessRouterList = (id: string) => {
return request.get(`/api/v1/messuite/query/processroutes?productId=${id}`)
}

export const getWorkStationList = (v?: string) => {
const filter = v ? `&Filter=${v}` : ''
return request.get(
`/api/v1/processmanagement/workstation?SkipCount=0&MaxResultCount=999&includeDetails=true${filter}`
)
}

章节来源

复杂交互实现

业务级对话框支持多种复杂的用户交互场景,包括表格操作、表单验证和动态内容生成。

表格渲染与交互

BaseTable集成

<BaseTable
params={{
Filter: innerValue.value,
includeDetails: true,
}}
selections={selections.value}
pageSize={50}
ref={tableRef}
url="/api/v1/processmanagement/workstation"
style="margin-top:10px"
v-model:dataSource={dataSource.value}
columns={columns.value}
isChecked={true}
onCheck={onCheck}
/>

表格列配置

const columns = computed(() => [
{
title: _t('序号'),
type: 'seq',
width: '60',
},
{
field: 'workSection.name',
title: _t('工序名称'),
},
{
field: 'name',
title: _t('工位名称'),
},
{
field: 'remark',
title: _t('备注'),
},
])

动态表单生成

DyForm集成

<DyForm
ref={formRef}
v-model:formData={formData.value}
formItemProps={[
{
prop: 'ipListString',
label: _t('可访问IP'),
el: 'input',
clearable: true,
placeholder: _t('请输入可访问IP'),
icon: 'tip',
tip: _t('手动填写IP,存在多个IP访问,以“;”分隔'),
rules: [
{
message: _t('请输入可访问IP'),
pattern: /^(\d{1,3}\.){3}\d{1,3}(\s*;\s*(\d{1,3}\.){3}\d{1,3})*$/,
trigger: 'change',
},
],
},
{
prop: 'userListString',
label: _t('可访问用户'),
el: 'select',
maxCollapseTags: 999,
clearable: true,
placeholder: _t('可访问用户'),
filterable: true,
remote: true,
multiple: true,
collapseTags: true,
options: userOptions.value,
},
]}
/>

树形选择器联动

虽然在当前分析的代码中没有直接看到树形选择器,但基于系统的整体架构,可以预见树形选择器会通过类似的Hook模式实现:

章节来源

性能优化与内存管理

业务级对话框在设计时充分考虑了性能优化和内存管理,避免不必要的重新渲染和内存泄漏。

组件销毁策略

// destroy-on-close属性确保组件销毁
<BaseDialog
destroy-on-close
class={styles.drawer}
style="background: #fff"
width="664px"
height="578px"
title={props.title ? props.title : _t('工位选择')}
v-model={visible.value}
onClose={onClose}
onConfirm={onConfirm}
onOpen={onOpen}
/>

内存泄漏防护

自动清理机制

// 对话框关闭时自动清理状态
const onClose = () => {
visible.value = false
// 清理选中状态
checkedList.value = []
// 清理搜索条件
innerValue.value = ''
// 触发关闭事件
ctx.emit('close')
}

// 确认时的清理
const onConfirm = async () => {
ctx.emit('confirm', checkedList.value)
// 清理表格选中状态
tableRef.value?.clearAll()
visible.value = false
}

异步操作取消

// 使用AbortController或类似机制取消未完成的请求
let abortController: AbortController | null = null

const fetchData = async () => {
abortController = new AbortController()

try {
const response = await fetch('/api/data', {
signal: abortController.signal
})
// 处理响应...
} catch (error) {
if (error.name === 'AbortError') {
// 请求被取消,无需处理
return
}
throw error
}
}

// 在组件卸载时取消请求
onUnmounted(() => {
if (abortController) {
abortController.abort()
}
})

性能优化策略

虚拟滚动

// 对于大数据量表格启用虚拟滚动
<BaseTable
// ... 其他属性
virtual-list-props={{
height: autoHeight.value
}}
isVScroll={true}
/>

懒加载

// 按需加载对话框内容
const onOpen = async () => {
if (!hasLoaded.value) {
await loadData()
hasLoaded.value = true
}
}

最佳实践指南

基于对业务级对话框的深入分析,以下是推荐的最佳实践:

组件设计原则

1. 单一职责原则

每个业务级对话框专注于特定的业务场景,避免功能混杂。

2. 可复用性设计

通过Hook模式提取通用逻辑,减少重复代码。

3. 类型安全

充分利用TypeScript类型系统,确保组件接口的正确性。

开发规范

Hook命名规范

// 推荐的Hook命名格式
export const useSelectDialog = (props: DialogProps, ctx: SetupContext) => {
// 实现...
}

export const useWorkStation = (props: WorkStationProps, ctx: SetupContext) => {
// 实现...
}

API模块组织

// 按功能模块组织API
export const getWorkStationList = (filter?: string) => {
// 实现...
}

export const updateWorkStation = (id: string, data: WorkStationData) => {
// 实现...
}

错误处理策略

分层错误处理

// 组件层错误处理
const onConfirm = async () => {
try {
await validateForm()
await submitData()
ctx.emit('confirm', result)
} catch (error) {
handleError(error)
}
}

// Hook层错误处理
const useSelectDialog = (props: any, ctx: any) => {
const handleError = (error: Error) => {
console.error('Dialog error:', error)
ElMessage.error(_t('操作失败,请稍后重试'))
}
}

测试策略

单元测试覆盖

// Hook函数测试
describe('useSelectDialog', () => {
it('should initialize with correct props', () => {
const props = { modelValue: true, data: [] }
const ctx = createMockContext()
const result = useSelectDialog(props, ctx)

expect(result.visible.value).toBe(true)
expect(result.selections.value).toEqual([])
})
})

集成测试

// 组件集成测试
describe('WorkStationDialog', () => {
it('should render correctly with data', async () => {
const wrapper = mount(WorkStationDialog, {
props: {
modelValue: true,
data: testData
}
})

expect(wrapper.find('.workstation-table')).toBeDefined()
})
})

总结

业务级对话框是LME系统中实现复杂业务逻辑的重要组件。通过BaseDialog基类的统一框架、Hook模式的状态管理、以及完善的API集成,这些组件实现了:

  1. 高度可复用的架构设计:通过继承和组合模式,实现了代码的最大化复用
  2. 清晰的职责分离:组件、Hook、API各司其职,保持代码的整洁性
  3. 强大的状态管理:利用Vue 3 Composition API实现响应式状态管理
  4. 完善的错误处理:多层次的错误处理机制确保应用稳定性
  5. 优秀的用户体验:丰富的交互功能和流畅的动画效果

这种设计模式不仅提高了开发效率,也为后续的功能扩展和维护奠定了坚实的基础。开发者可以基于现有的业务级对话框快速构建新的业务场景,同时保持代码质量和一致性。

通过深入理解这些组件的设计理念和实现细节,开发团队能够更好地维护现有系统,并为未来的功能扩展制定合理的规划。