<template>
|
<ElDialog
|
:title="dialogTitle"
|
:model-value="visible"
|
width="1120px"
|
align-center
|
destroy-on-close
|
@update:model-value="handleCancel"
|
@closed="handleClosed"
|
>
|
<ArtForm
|
ref="formRef"
|
v-model="form"
|
:items="formItems"
|
:rules="rules"
|
:span="12"
|
:gutter="20"
|
label-width="110px"
|
:show-reset="false"
|
:show-submit="false"
|
/>
|
|
<div class="deviceSite-init-row mt-4">
|
<div class="mb-3 flex items-center justify-between">
|
<div class="text-sm font-medium text-[var(--art-gray-900)]">路径行列表</div>
|
<ElButton size="small" @click="addRow">新增一行</ElButton>
|
</div>
|
<ElTable :data="form.rows" border>
|
<ElTableColumn label="设备站点" min-width="220">
|
<template #default="{ row }">
|
<ElSelect v-model="row.deviceSite" class="w-full" filterable clearable placeholder="请选择设备站点">
|
<ElOption v-for="item in stationOptions" :key="item.value" :label="item.label" :value="item.value" />
|
</ElSelect>
|
</template>
|
</ElTableColumn>
|
<ElTableColumn label="作业站点" min-width="220">
|
<template #default="{ row }">
|
<ElSelect v-model="row.site" class="w-full" filterable clearable placeholder="请选择作业站点">
|
<ElOption v-for="item in stationOptions" :key="item.value" :label="item.label" :value="item.value" />
|
</ElSelect>
|
</template>
|
</ElTableColumn>
|
<ElTableColumn label="目标站点" min-width="220">
|
<template #default="{ row }">
|
<ElInput v-model="row.target" clearable placeholder="请输入目标站点" />
|
</template>
|
</ElTableColumn>
|
<ElTableColumn label="操作" width="100" align="center">
|
<template #default="{ $index }">
|
<ElButton link type="danger" :disabled="form.rows.length <= 1" @click="removeRow($index)">删除</ElButton>
|
</template>
|
</ElTableColumn>
|
</ElTable>
|
<div class="mt-2 text-xs text-[var(--art-gray-500)]">
|
每行表示一组设备站点、作业站点、目标站点。
|
</div>
|
</div>
|
|
<template #footer>
|
<span class="dialog-footer">
|
<ElButton @click="handleCancel">取消</ElButton>
|
<ElButton type="primary" @click="handleSubmit">确定</ElButton>
|
</span>
|
</template>
|
</ElDialog>
|
</template>
|
|
<script setup>
|
import { computed, nextTick, reactive, ref, watch } from 'vue'
|
import { ElMessage } from 'element-plus'
|
import ArtForm from '@/components/core/forms/art-form/index.vue'
|
import { buildDeviceSiteInitModel, createDeviceSiteInitState } from '../deviceSitePage.helpers'
|
|
const props = defineProps({
|
visible: { type: Boolean, default: false },
|
initialData: { type: Object, default: () => ({}) },
|
typeOptions: { type: Array, default: () => [] },
|
deviceOptions: { type: Array, default: () => [] },
|
areaOptions: { type: Array, default: () => [] },
|
stationOptions: { type: Array, default: () => [] }
|
})
|
|
const emit = defineEmits(['update:visible', 'submit'])
|
const formRef = ref()
|
const form = reactive(createDeviceSiteInitState())
|
|
const dialogTitle = computed(() => '路径初始化')
|
|
const rules = computed(() => ({
|
typeIds: [{ type: 'array', required: true, message: '请选择作业类型', trigger: 'change' }],
|
deviceType: [{ required: true, message: '请选择设备类型', trigger: 'change' }],
|
channel: [{ required: true, message: '请输入巷道', trigger: 'blur' }],
|
areaIdStart: [{ required: true, message: '请选择源库区', trigger: 'change' }],
|
areaIdEnd: [{ required: true, message: '请选择目标库区', trigger: 'change' }]
|
}))
|
|
const formItems = computed(() => [
|
{ label: '是否初始化', key: 'flagInit', type: 'select', props: { clearable: false, options: [{ label: '否', value: 0 }, { label: '是', value: 1 }] } },
|
{ label: '设备类型', key: 'deviceType', type: 'select', props: { placeholder: '请选择设备类型', clearable: true, filterable: true, options: props.deviceOptions || [] } },
|
{ label: '作业类型', key: 'typeIds', type: 'select', span: 24, props: { placeholder: '请选择作业类型', clearable: true, multiple: true, collapseTags: true, filterable: true, options: props.typeOptions || [] } },
|
{ label: '巷道', key: 'channel', type: 'input', props: { placeholder: '请输入巷道,多个请用英文逗号分隔', clearable: true } },
|
{ label: '源库区', key: 'areaIdStart', type: 'select', props: { placeholder: '请选择源库区', clearable: true, filterable: true, options: props.areaOptions || [] } },
|
{ label: '目标库区', key: 'areaIdEnd', type: 'select', props: { placeholder: '请选择目标库区', clearable: true, filterable: true, options: props.areaOptions || [] } },
|
{ label: '名称', key: 'name', type: 'input', props: { placeholder: '请输入名称', clearable: true } },
|
{ label: '站点标签', key: 'label', type: 'input', props: { placeholder: '请输入站点标签', clearable: true } }
|
])
|
|
function resolveStationValue(rawValue) {
|
const text = String(rawValue ?? '').trim()
|
if (!text) {
|
return ''
|
}
|
const exact = props.stationOptions.find((item) => String(item.value) === text)
|
if (exact) {
|
return exact.value
|
}
|
const matched = props.stationOptions.find((item) => item.label === text)
|
return matched ? matched.value : text
|
}
|
|
function normalizeRows(rows = []) {
|
return Array.isArray(rows)
|
? rows
|
.map((row) => ({
|
deviceSite: resolveStationValue(row?.deviceSite || row?.deviceSiteName || ''),
|
site: resolveStationValue(row?.site || row?.siteName || ''),
|
target: String(row?.target || '').trim()
|
}))
|
.filter((row) => row.deviceSite || row.site || row.target)
|
: []
|
}
|
|
function loadFormData() {
|
const resolved = buildDeviceSiteInitModel(props.initialData)
|
Object.assign(form, {
|
...resolved,
|
rows: normalizeRows(resolved.rows.length ? resolved.rows : [{ deviceSite: '', site: '', target: '' }])
|
})
|
}
|
|
function resetForm() {
|
Object.assign(form, createDeviceSiteInitState())
|
form.rows = [{ deviceSite: '', site: '', target: '' }]
|
formRef.value?.clearValidate?.()
|
}
|
|
function addRow() {
|
form.rows.push({ deviceSite: '', site: '', target: '' })
|
}
|
|
function removeRow(index) {
|
if (form.rows.length <= 1) {
|
return
|
}
|
form.rows.splice(index, 1)
|
}
|
|
async function handleSubmit() {
|
if (!formRef.value) return
|
try {
|
await formRef.value.validate()
|
const validRows = normalizeRows(form.rows)
|
if (!validRows.length) {
|
ElMessage.error('请至少填写一行完整的路径行')
|
return
|
}
|
emit('submit', { ...form, rows: validRows })
|
} catch {
|
return
|
}
|
}
|
|
function handleCancel() {
|
emit('update:visible', false)
|
}
|
|
function handleClosed() {
|
resetForm()
|
}
|
|
watch(
|
() => props.visible,
|
async (visible) => {
|
if (visible) {
|
loadFormData()
|
await nextTick()
|
formRef.value?.clearValidate?.()
|
}
|
},
|
{ immediate: true }
|
)
|
|
watch(
|
() => props.initialData,
|
() => {
|
if (props.visible) {
|
loadFormData()
|
}
|
},
|
{ deep: true }
|
)
|
|
watch(
|
() => props.stationOptions,
|
() => {
|
if (props.visible) {
|
loadFormData()
|
}
|
},
|
{ deep: true }
|
)
|
</script>
|