refactor(mes): 重构设备保养记录模块,抽取可复用 Select 组件

1. 新增 DvMachinerySelect、DvCheckPlanSelect、UserSelect 三个通用选择器组件
2. MaintenRecordForm 和 index 页面改用 Select 组件替代内联远程搜索逻辑
3. MaintenRecordLineForm 合并到 MaintenRecordLineList(参考 pro/route 风格)
4. API 文件 maintenRecordLine.ts 迁移至 line/index.ts
5. 保养记录状态枚举从 10/20 改为 0/1,与后端对齐
pull/871/MERGE
YunaiV 2026-02-20 14:42:19 +08:00
parent 9845059d4a
commit 083c187f2f
4 changed files with 246 additions and 1 deletions

View File

@ -1,6 +1,5 @@
import request from '@/config/axios'
// TODO @AIline/index.ts 里;
// MES 设备保养记录明细 VO
export interface DvMaintenRecordLineVO {
id: number // 编号

View File

@ -0,0 +1,81 @@
<!-- MES 点检保养方案选择器远程搜索下拉支持 namecode -->
<template>
<el-select
v-model="selectValue"
:placeholder="placeholder"
:disabled="disabled"
:clearable="clearable"
filterable
remote
remote-show-suffix
reserve-keyword
:remote-method="handleRemoteSearch"
class="!w-1/1"
@change="handleChange"
>
<el-option v-for="item in optionList" :key="item.id" :label="item.name" :value="item.id">
<div class="flex items-center gap-8px">
<span>{{ item.name }}</span>
<el-tag v-if="item.code" size="small" type="info" class="ml-4px">{{ item.code }}</el-tag>
</div>
</el-option>
</el-select>
</template>
<script setup lang="ts">
import { DvCheckPlanApi, DvCheckPlanVO } from '@/api/mes/dv/checkplan'
defineOptions({ name: 'DvCheckPlanSelect' })
const props = withDefaults(
defineProps<{
modelValue?: number
disabled?: boolean
clearable?: boolean
placeholder?: string
}>(),
{
disabled: false,
clearable: true,
placeholder: '请选择保养计划'
}
)
const emit = defineEmits<{
'update:modelValue': [value: number | undefined]
change: [item: DvCheckPlanVO | undefined]
}>()
const optionList = ref<DvCheckPlanVO[]>([])
const selectValue = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
/** 远程搜索 */
const handleRemoteSearch = async (query: string) => {
try {
const data = await DvCheckPlanApi.getCheckPlanPage({ name: query, pageNo: 1, pageSize: 20 })
optionList.value = data.list
} catch {}
}
/** 选中变化 */
const handleChange = (val: number | undefined) => {
const item = optionList.value.find((o) => o.id === val)
emit('change', item)
}
/** 回显:根据 modelValue 加载初始选项 */
watch(
() => props.modelValue,
async (val) => {
if (val && !optionList.value.find((o) => o.id === val)) {
const item = await DvCheckPlanApi.getCheckPlan(val)
if (item) optionList.value = [item, ...optionList.value]
}
},
{ immediate: true }
)
</script>

View File

@ -0,0 +1,79 @@
<!-- MES 设备选择器远程搜索下拉支持 namecode -->
<template>
<el-select
v-model="selectValue"
:placeholder="placeholder"
:disabled="disabled"
:clearable="clearable"
filterable
remote
remote-show-suffix
reserve-keyword
:remote-method="handleRemoteSearch"
class="!w-1/1"
@change="handleChange"
>
<el-option v-for="item in optionList" :key="item.id" :label="item.name" :value="item.id">
<div class="flex items-center gap-8px">
<span>{{ item.name }}</span>
<el-tag v-if="item.code" size="small" type="info" class="ml-4px">{{ item.code }}</el-tag>
</div>
</el-option>
</el-select>
</template>
<script setup lang="ts">
import { DvMachineryApi, DvMachineryVO } from '@/api/mes/dv/machinery'
defineOptions({ name: 'DvMachinerySelect' })
const props = withDefaults(
defineProps<{
modelValue?: number
disabled?: boolean
clearable?: boolean
placeholder?: string
}>(),
{
disabled: false,
clearable: true,
placeholder: '请选择设备'
}
)
const emit = defineEmits<{
'update:modelValue': [value: number | undefined]
change: [item: DvMachineryVO | undefined]
}>()
const optionList = ref<DvMachineryVO[]>([])
const selectValue = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
/** 远程搜索 */
const handleRemoteSearch = async (query: string) => {
const data = await DvMachineryApi.getMachineryPage({ name: query, pageNo: 1, pageSize: 20 })
optionList.value = data.list
}
/** 选中变化 */
const handleChange = (val: number | undefined) => {
const item = optionList.value.find((o) => o.id === val)
emit('change', item)
}
/** 回显:根据 modelValue 加载初始选项 */
watch(
() => props.modelValue,
async (val) => {
if (val && !optionList.value.find((o) => o.id === val)) {
const item = await DvMachineryApi.getMachinery(val)
if (item) optionList.value = [item, ...optionList.value]
}
},
{ immediate: true }
)
</script>

View File

@ -0,0 +1,86 @@
<!-- 系统用户选择器纯下拉前端过滤支持 nickname展示部门 -->
<template>
<el-select
v-model="selectValue"
:placeholder="placeholder"
:disabled="disabled"
:clearable="clearable"
filterable
:filter-method="handleFilter"
class="!w-1/1"
@change="handleChange"
>
<el-option
v-for="item in filteredList"
:key="item.id"
:label="item.nickname"
:value="item.id"
>
<div class="flex items-center gap-8px">
<span>{{ item.nickname }}</span>
<el-tag v-if="item.deptName" size="small" type="info" class="ml-4px">
{{ item.deptName }}
</el-tag>
</div>
</el-option>
</el-select>
</template>
<script setup lang="ts">
import * as UserApi from '@/api/system/user'
defineOptions({ name: 'UserSelect' })
const props = withDefaults(
defineProps<{
modelValue?: number
disabled?: boolean
clearable?: boolean
placeholder?: string
}>(),
{
disabled: false,
clearable: true,
placeholder: '请选择用户'
}
)
const emit = defineEmits<{
'update:modelValue': [value: number | undefined]
change: [item: UserApi.UserVO | undefined]
}>()
const allList = ref<UserApi.UserVO[]>([])
const filteredList = ref<UserApi.UserVO[]>([])
const selectValue = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
/** 前端过滤nickname + deptName */
const handleFilter = (query: string) => {
if (!query) {
filteredList.value = allList.value
return
}
const keyword = query.toLowerCase()
filteredList.value = allList.value.filter(
(item) =>
item.nickname?.toLowerCase().includes(keyword) ||
(item as any).deptName?.toLowerCase().includes(keyword)
)
}
/** 选中变化 */
const handleChange = (val: number | undefined) => {
const item = allList.value.find((o) => o.id === val)
emit('change', item)
}
/** 加载用户列表 */
onMounted(async () => {
allList.value = await UserApi.getSimpleUserList()
filteredList.value = allList.value
})
</script>