2026-07-15 18:24:05 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<a-modal
|
|
|
|
|
|
:title="isEdit ? '编辑飞行路径' : '新增飞行路径'"
|
|
|
|
|
|
v-model:open="modalVisible"
|
|
|
|
|
|
:confirm-loading="localLoading"
|
|
|
|
|
|
width="1536px"
|
|
|
|
|
|
:destroy-on-close="true"
|
|
|
|
|
|
ok-text="保存"
|
|
|
|
|
|
@cancel="handleCancel"
|
|
|
|
|
|
@ok="handleOk"
|
|
|
|
|
|
>
|
|
|
|
|
|
<a-form
|
|
|
|
|
|
ref="formRef"
|
|
|
|
|
|
:model="formData"
|
|
|
|
|
|
:rules="rules"
|
|
|
|
|
|
name="edit_form"
|
|
|
|
|
|
:labelCol="{ span: 5 }"
|
|
|
|
|
|
>
|
|
|
|
|
|
<a-row>
|
|
|
|
|
|
<a-col :span="12">
|
|
|
|
|
|
<a-form-item label="飞行路径名称" name="name">
|
|
|
|
|
|
<a-input
|
|
|
|
|
|
v-model:value="formData.name"
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
placeholder="请输入飞行路径名称"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
</a-col>
|
|
|
|
|
|
<a-col :span="12">
|
|
|
|
|
|
<a-form-item label="飞行路径Code" name="code">
|
|
|
|
|
|
<a-input
|
|
|
|
|
|
v-model:value="formData.code"
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
placeholder="请输入飞行路径Code"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
</a-col>
|
|
|
|
|
|
</a-row>
|
|
|
|
|
|
<a-row>
|
|
|
|
|
|
<a-col :span="12">
|
|
|
|
|
|
<a-form-item label="备注" name="remark">
|
|
|
|
|
|
<a-textarea
|
|
|
|
|
|
v-model:value="formData.remark"
|
|
|
|
|
|
:rows="4"
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
placeholder="请输入备注"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
</a-col>
|
|
|
|
|
|
<a-col :span="12">
|
|
|
|
|
|
<a-form-item label="水电基地" name="baseId">
|
|
|
|
|
|
<a-select
|
|
|
|
|
|
v-model:value="formData.baseId"
|
|
|
|
|
|
show-search
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
placeholder="请选择水电基地"
|
|
|
|
|
|
:options="ennmOptions"
|
|
|
|
|
|
:filter-option="filterOption"
|
|
|
|
|
|
:disabled="isEdit"
|
|
|
|
|
|
@change="getdianzha"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
</a-col>
|
|
|
|
|
|
</a-row>
|
|
|
|
|
|
|
|
|
|
|
|
<a-divider />
|
|
|
|
|
|
<div class="flex justify-between items-center mb-2">
|
|
|
|
|
|
<a-button type="primary" @click="handleAddRow"> 新增行</a-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div ref="tableWrapperRef">
|
|
|
|
|
|
<a-table
|
|
|
|
|
|
:data-source="currentPageData"
|
|
|
|
|
|
:columns="columns"
|
|
|
|
|
|
:pagination="false"
|
|
|
|
|
|
row-key="id"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
:scroll="{ x: 950 }"
|
|
|
|
|
|
:custom-row="customRow"
|
|
|
|
|
|
>
|
|
|
|
|
|
<template #bodyCell="{ column, record, index }">
|
|
|
|
|
|
<template v-if="column.key === 'drag'">
|
|
|
|
|
|
<UnorderedListOutlined
|
|
|
|
|
|
v-if="editingRowId !== record.id"
|
|
|
|
|
|
class="drag-handle cursor-move text-gray-400"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-else-if="column.key === 'index'">
|
|
|
|
|
|
{{ (currentPage - 1) * pageSize + index + 1 }}
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-else-if="column.key === 'time'">
|
|
|
|
|
|
<template v-if="editingRowId === record.id">
|
|
|
|
|
|
<a-input-number
|
|
|
|
|
|
v-model:value="record.time"
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
placeholder="时间(s)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-else>
|
|
|
|
|
|
{{ record.time ?? '-' }}
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-else-if="column.key === 'lgtd'">
|
|
|
|
|
|
<template v-if="editingRowId === record.id">
|
|
|
|
|
|
<a-input-number
|
|
|
|
|
|
v-model:value="record.lgtd"
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
placeholder="经度"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-else>
|
|
|
|
|
|
{{ record.lgtd ?? '-' }}
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-else-if="column.key === 'lttd'">
|
|
|
|
|
|
<template v-if="editingRowId === record.id">
|
|
|
|
|
|
<a-input-number
|
|
|
|
|
|
v-model:value="record.lttd"
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
placeholder="纬度"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-else>
|
|
|
|
|
|
{{ record.lttd ?? '-' }}
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-else-if="column.key === 'dtmel'">
|
|
|
|
|
|
<template v-if="editingRowId === record.id">
|
|
|
|
|
|
<a-input-number
|
|
|
|
|
|
v-model:value="record.dtmel"
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
placeholder="高程(m)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-else>
|
|
|
|
|
|
{{ record.dtmel ?? '-' }}
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-else-if="column.key === 'stnm'">
|
|
|
|
|
|
<template v-if="editingRowId === record.id">
|
|
|
|
|
|
<a-select
|
|
|
|
|
|
v-model:value="record.stcd"
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
placeholder="请选择电站"
|
|
|
|
|
|
:options="stationOptions"
|
|
|
|
|
|
allow-clear
|
|
|
|
|
|
@change="(val) => handleStnmChange(record, val)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-else>
|
|
|
|
|
|
{{ getStationLabel(record.stcd) || '-' }}
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-else-if="column.key === 'action'">
|
|
|
|
|
|
<template v-if="editingRowId === record.id">
|
|
|
|
|
|
<a-button
|
|
|
|
|
|
type="link"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
@click="handleSaveRow(record)"
|
|
|
|
|
|
>保存</a-button
|
|
|
|
|
|
>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-else>
|
|
|
|
|
|
<a-button
|
|
|
|
|
|
type="link"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
@click="handleStartEdit(record)"
|
|
|
|
|
|
>编辑</a-button
|
|
|
|
|
|
>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<a-popconfirm
|
|
|
|
|
|
title="确定删除该航点?"
|
|
|
|
|
|
@confirm="handleDeleteRow(record)"
|
|
|
|
|
|
>
|
|
|
|
|
|
<a-button type="link" danger size="small">删除</a-button>
|
|
|
|
|
|
</a-popconfirm>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</a-table>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div v-if="formData.list.length > pageSize" class="flex justify-end mt-2">
|
|
|
|
|
|
<a-pagination
|
|
|
|
|
|
v-model:current="currentPage"
|
|
|
|
|
|
:total="formData.list.length"
|
|
|
|
|
|
:page-size="pageSize"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
show-size-changer
|
|
|
|
|
|
:page-size-options="['5', '10', '20', '50']"
|
|
|
|
|
|
show-total
|
|
|
|
|
|
@change="handlePageChange"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</a-form>
|
|
|
|
|
|
</a-modal>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
|
|
|
import { ref, reactive, computed, watch, nextTick, onBeforeUnmount } from 'vue';
|
|
|
|
|
|
import { message } from 'ant-design-vue';
|
|
|
|
|
|
import type { Rule } from 'ant-design-vue/es/form';
|
|
|
|
|
|
import { UnorderedListOutlined } from '@ant-design/icons-vue';
|
|
|
|
|
|
import Sortable from 'sortablejs';
|
|
|
|
|
|
import dayjs from 'dayjs';
|
|
|
|
|
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
|
|
|
|
|
import { getEngInfoDropdown } from '@/api/select';
|
|
|
|
|
|
import { useDraggable } from '@/utils/drag';
|
|
|
|
|
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
|
|
|
|
|
|
|
|
|
|
|
// 电站名称下拉(假数据)
|
|
|
|
|
|
const stationOptions = ref([]);
|
|
|
|
|
|
|
|
|
|
|
|
// 表格列配置
|
|
|
|
|
|
const columns = [
|
|
|
|
|
|
{ title: '排序', key: 'drag', width: 60, align: 'center' as const },
|
|
|
|
|
|
{ title: '序号', key: 'index', width: 60, align: 'center' as const },
|
|
|
|
|
|
{ title: '时间(s)', key: 'time', width: 130 },
|
|
|
|
|
|
{ title: '经度°', key: 'lgtd', width: 150 },
|
|
|
|
|
|
{ title: '纬度°', key: 'lttd', width: 150 },
|
|
|
|
|
|
{ title: '高程(m)', key: 'dtmel', width: 120 },
|
|
|
|
|
|
{ title: '电站名称', key: 'stnm', width: 160 },
|
|
|
|
|
|
{ title: '操作', key: 'action', width: 120, align: 'center' as const }
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
interface Props {
|
|
|
|
|
|
visible: boolean;
|
|
|
|
|
|
initialValues?: any | null;
|
|
|
|
|
|
loading?: boolean;
|
|
|
|
|
|
}
|
|
|
|
|
|
const localLoading = ref(false);
|
|
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
|
|
|
|
visible: false,
|
|
|
|
|
|
initialValues: null,
|
|
|
|
|
|
loading: false
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const modalVisible = computed({
|
|
|
|
|
|
get: () => props.visible,
|
|
|
|
|
|
set: val => emit('update:visible', val)
|
|
|
|
|
|
});
|
|
|
|
|
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
|
|
|
|
|
const emit = defineEmits<{
|
|
|
|
|
|
(e: 'update:visible', value: boolean): void;
|
|
|
|
|
|
(e: 'cancel'): void;
|
|
|
|
|
|
(e: 'ok', values: any): void;
|
|
|
|
|
|
}>();
|
|
|
|
|
|
|
|
|
|
|
|
const formRef = ref();
|
|
|
|
|
|
const tableWrapperRef = ref<HTMLElement | null>(null);
|
|
|
|
|
|
let sortableInstance: Sortable | null = null;
|
|
|
|
|
|
|
|
|
|
|
|
// 当前正在编辑的行 ID(同一时间只允许编辑一行)
|
|
|
|
|
|
const editingRowId = ref<string | null>(null);
|
|
|
|
|
|
|
|
|
|
|
|
// 给每行添加 data-row-key 属性,供拖拽时识别行身份
|
|
|
|
|
|
const customRow = (record: any) => {
|
|
|
|
|
|
return {
|
|
|
|
|
|
attrs: {
|
|
|
|
|
|
'data-row-key': record?.id
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 分页
|
|
|
|
|
|
const currentPage = ref(1);
|
|
|
|
|
|
const pageSize = ref(5);
|
|
|
|
|
|
const currentPageData = computed(() => {
|
|
|
|
|
|
const start = (currentPage.value - 1) * pageSize.value;
|
|
|
|
|
|
return formData.list.slice(start, start + pageSize.value);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const defaultFormData = reactive({
|
|
|
|
|
|
id: undefined,
|
|
|
|
|
|
name: undefined,
|
|
|
|
|
|
baseId: undefined,
|
|
|
|
|
|
code: undefined,
|
|
|
|
|
|
remark: undefined,
|
|
|
|
|
|
list: [] as any[]
|
|
|
|
|
|
});
|
|
|
|
|
|
const formData: any = reactive({ ...defaultFormData });
|
|
|
|
|
|
|
|
|
|
|
|
const rules: Record<string, Rule[]> = {
|
|
|
|
|
|
name: [{ required: true, message: '请输入飞行路径名称', trigger: 'blur' }],
|
|
|
|
|
|
code: [{ required: true, message: '请输入飞行路径Code', trigger: 'blur' }]
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const isEdit = computed(() => !!props.initialValues);
|
|
|
|
|
|
|
|
|
|
|
|
// 生成唯一ID
|
|
|
|
|
|
const generateId = () => {
|
|
|
|
|
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
|
|
|
|
|
const r = (Math.random() * 16) | 0;
|
|
|
|
|
|
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16).toUpperCase();
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 开始编辑行
|
|
|
|
|
|
const handleStartEdit = (record: any) => {
|
|
|
|
|
|
editingRowId.value = record.id;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 保存行(退出编辑模式,保留当前输入值)
|
|
|
|
|
|
const handleSaveRow = (record: any) => {
|
|
|
|
|
|
editingRowId.value = null;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 新增航点
|
|
|
|
|
|
const handleAddRow = () => {
|
|
|
|
|
|
if(!formData.baseId){
|
|
|
|
|
|
message.warning('请先选择水电基地');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 有行正在编辑时禁止新增
|
|
|
|
|
|
if (editingRowId.value) {
|
|
|
|
|
|
message.warning('请先保存当前编辑的行');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const newRow = {
|
|
|
|
|
|
id: generateId(),
|
|
|
|
|
|
recordUser: null,
|
|
|
|
|
|
recordTime: null,
|
|
|
|
|
|
modifyTime: null,
|
|
|
|
|
|
displayRecordUser: null,
|
|
|
|
|
|
roamId: null,
|
|
|
|
|
|
code: formData.code || null,
|
|
|
|
|
|
name: formData.name || null,
|
|
|
|
|
|
lgtd: undefined,
|
|
|
|
|
|
lttd: undefined,
|
|
|
|
|
|
dtmel: undefined,
|
|
|
|
|
|
time: undefined,
|
|
|
|
|
|
orderIndex: formData.list.length,
|
|
|
|
|
|
stcd: null,
|
|
|
|
|
|
stnm: undefined,
|
|
|
|
|
|
departmentId: null,
|
|
|
|
|
|
displayDepartment: null
|
|
|
|
|
|
};
|
|
|
|
|
|
formData.list.push(newRow);
|
|
|
|
|
|
// 新增行自动进入编辑模式
|
|
|
|
|
|
editingRowId.value = newRow.id;
|
|
|
|
|
|
// 翻到最后一页
|
|
|
|
|
|
const lastPage = Math.ceil(formData.list.length / pageSize.value);
|
|
|
|
|
|
currentPage.value = lastPage;
|
|
|
|
|
|
nextTick(() => initSortable());
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 删除航点
|
|
|
|
|
|
const handleDeleteRow = (record: any) => {
|
|
|
|
|
|
// 如果正编辑的行被删了,退出编辑
|
|
|
|
|
|
if (editingRowId.value === record.id) {
|
|
|
|
|
|
editingRowId.value = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
const idx = formData.list.findIndex((item: any) => item.id === record.id);
|
|
|
|
|
|
if (idx !== -1) {
|
|
|
|
|
|
formData.list.splice(idx, 1);
|
|
|
|
|
|
// 如果当前页没数据了,往前翻一页
|
|
|
|
|
|
if (currentPageData.value.length === 0 && currentPage.value > 1) {
|
|
|
|
|
|
currentPage.value--;
|
|
|
|
|
|
}
|
|
|
|
|
|
nextTick(() => initSortable());
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 页码变化
|
|
|
|
|
|
const handlePageChange = () => {
|
|
|
|
|
|
editingRowId.value = null; // 切换页时退出编辑
|
|
|
|
|
|
nextTick(() => initSortable());
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Sortable 拖拽 — 基于 DOM data-row-key 排序,不依赖 oldIndex/newIndex
|
|
|
|
|
|
const initSortable = () => {
|
|
|
|
|
|
destroySortable();
|
|
|
|
|
|
if (!tableWrapperRef.value) return;
|
|
|
|
|
|
const tbody = tableWrapperRef.value.querySelector('.ant-table-tbody');
|
|
|
|
|
|
if (!tbody) return;
|
|
|
|
|
|
sortableInstance = new Sortable(tbody as HTMLElement, {
|
|
|
|
|
|
handle: '.drag-handle',
|
|
|
|
|
|
animation: 150,
|
|
|
|
|
|
onEnd: evt => {
|
|
|
|
|
|
if (!tbody) return;
|
|
|
|
|
|
// 读取拖拽后 DOM 中的行顺序(只读当前页)
|
|
|
|
|
|
const rows = tbody.querySelectorAll<HTMLElement>('tr.ant-table-row');
|
|
|
|
|
|
const domIds: (string | null)[] = [];
|
|
|
|
|
|
rows.forEach(row => {
|
|
|
|
|
|
const id = row.getAttribute('data-row-key');
|
|
|
|
|
|
if (id) domIds.push(id);
|
|
|
|
|
|
});
|
|
|
|
|
|
if (domIds.length === 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
const page = currentPage.value;
|
|
|
|
|
|
const size = pageSize.value;
|
|
|
|
|
|
const start = (page - 1) * size;
|
|
|
|
|
|
const end = start + size;
|
|
|
|
|
|
|
|
|
|
|
|
// 按 DOM 顺序重排当前页数据
|
|
|
|
|
|
const pageItems = domIds
|
|
|
|
|
|
.map(id => formData.list.find((item: any) => item.id === id))
|
|
|
|
|
|
.filter(Boolean);
|
|
|
|
|
|
|
|
|
|
|
|
if (pageItems.length === 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
// 重建完整数组:前面 + 当前页(新顺序)+ 后面
|
|
|
|
|
|
const before = formData.list.slice(0, start);
|
|
|
|
|
|
const after = formData.list.slice(end);
|
|
|
|
|
|
formData.list.splice(
|
|
|
|
|
|
0,
|
|
|
|
|
|
formData.list.length,
|
|
|
|
|
|
...before,
|
|
|
|
|
|
...pageItems,
|
|
|
|
|
|
...after
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const destroySortable = () => {
|
|
|
|
|
|
if (sortableInstance) {
|
|
|
|
|
|
sortableInstance.destroy();
|
|
|
|
|
|
sortableInstance = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 表单提交
|
|
|
|
|
|
const handleOk = async () => {
|
|
|
|
|
|
// 有行正在编辑时禁止保存
|
|
|
|
|
|
if (editingRowId.value) {
|
|
|
|
|
|
message.warning('请先保存当前编辑的行');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
|
|
|
await formRef.value.validate();
|
|
|
|
|
|
// 转换数据:baseId → rvcd,更新 orderIndex
|
|
|
|
|
|
const submitValues = {
|
|
|
|
|
|
name: formData.name,
|
|
|
|
|
|
code: formData.code,
|
|
|
|
|
|
remark: formData.remark || null,
|
|
|
|
|
|
baseId: formData.baseId,
|
|
|
|
|
|
id: formData.id || undefined,
|
|
|
|
|
|
list: formData.list.map((item: any, index: number) => ({
|
|
|
|
|
|
...item,
|
|
|
|
|
|
orderIndex: index,
|
|
|
|
|
|
time: item.time ?? null,
|
|
|
|
|
|
lgtd: item.lgtd ?? null,
|
|
|
|
|
|
lttd: item.lttd ?? null,
|
|
|
|
|
|
dtmel: item.dtmel ?? null
|
|
|
|
|
|
}))
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
emit('ok', submitValues);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('Validate Failed:', error);
|
|
|
|
|
|
message.error('请检查表单填写是否正确');
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化表单
|
|
|
|
|
|
const initForm = () => {
|
|
|
|
|
|
currentPage.value = 1;
|
|
|
|
|
|
editingRowId.value = null;
|
|
|
|
|
|
if (props.initialValues) {
|
|
|
|
|
|
const values = props.initialValues;
|
|
|
|
|
|
// 先将匹配的字段复制到 formData
|
|
|
|
|
|
Object.keys(formData).forEach(key => {
|
|
|
|
|
|
if (key === 'list') return; // list 单独处理
|
|
|
|
|
|
if (values.hasOwnProperty(key)) {
|
|
|
|
|
|
if (key === 'captureDate' && values[key]) {
|
|
|
|
|
|
formData[key] = dayjs(values[key]);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
formData[key] = values[key];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
// rvcd → baseId 映射
|
|
|
|
|
|
if (values.baseId) {
|
|
|
|
|
|
formData.baseId = values.baseId;
|
2026-07-16 17:33:08 +08:00
|
|
|
|
getdianzha(values.baseId);
|
2026-07-15 18:24:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
// list 数据
|
|
|
|
|
|
formData.list = values.list
|
|
|
|
|
|
? values.list.map((item: any) => ({ ...item }))
|
|
|
|
|
|
: [];
|
|
|
|
|
|
} else {
|
|
|
|
|
|
resetForm();
|
|
|
|
|
|
}
|
|
|
|
|
|
nextTick(() => initSortable());
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const resetForm = () => {
|
|
|
|
|
|
if (formRef.value) {
|
|
|
|
|
|
formRef.value.resetFields();
|
|
|
|
|
|
}
|
|
|
|
|
|
Object.assign(formData, defaultFormData);
|
|
|
|
|
|
formData.list = [];
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleCancel = () => {
|
|
|
|
|
|
emit('update:visible', false);
|
|
|
|
|
|
emit('cancel');
|
|
|
|
|
|
resetForm();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 搜索过滤
|
|
|
|
|
|
const filterOption = (inputValue: string, option: any) => {
|
|
|
|
|
|
const label = option.label || option.name || '';
|
|
|
|
|
|
const reachcdName = option.reachcdName || '';
|
|
|
|
|
|
const keyword = inputValue || '';
|
|
|
|
|
|
return label.indexOf(keyword) !== -1 || reachcdName.indexOf(keyword) !== -1;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const ennmOptions = computed(() => {
|
|
|
|
|
|
return JidiSelectEventStore.jidiData.map((item: any) => ({
|
|
|
|
|
|
label: item.wbsName,
|
|
|
|
|
|
value: item.wbsCode
|
|
|
|
|
|
}));
|
|
|
|
|
|
});
|
|
|
|
|
|
const getdianzha = async (data: any) => {
|
|
|
|
|
|
// 切换水电基地时,清空已新增的航点(仅在新增模式下)
|
|
|
|
|
|
if (!isEdit.value && formData.list.length > 0) {
|
|
|
|
|
|
formData.list = [];
|
|
|
|
|
|
currentPage.value = 1;
|
|
|
|
|
|
editingRowId.value = null;
|
|
|
|
|
|
nextTick(() => initSortable());
|
|
|
|
|
|
}
|
|
|
|
|
|
const res = await getEngInfoDropdown({ baseId: data });
|
|
|
|
|
|
stationOptions.value = res.data.map((item: any) => ({
|
|
|
|
|
|
label: item.ennm,
|
|
|
|
|
|
value: item.stcd
|
|
|
|
|
|
}));
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// select 选中 stcd 后同步填充 stnm,供展示时使用
|
|
|
|
|
|
const handleStnmChange = (record: any, stcd: string | undefined) => {
|
|
|
|
|
|
const option = stationOptions.value.find((opt: any) => opt.value === stcd);
|
|
|
|
|
|
record.stnm = option ? option.label : null;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 根据 stcd 查找电站名称 label 用于展示
|
|
|
|
|
|
const getStationLabel = (stcd: string | undefined) => {
|
|
|
|
|
|
const option = stationOptions.value.find((opt: any) => opt.value === stcd);
|
|
|
|
|
|
return option ? option.label : stcd;
|
|
|
|
|
|
};
|
|
|
|
|
|
watch(
|
|
|
|
|
|
() => props.visible,
|
|
|
|
|
|
newVisible => {
|
|
|
|
|
|
if (newVisible) {
|
|
|
|
|
|
initForm();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
destroySortable();
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{ immediate: false }
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
|
|
|
destroySortable();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
defineExpose({
|
|
|
|
|
|
localLoading
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
|
.drag-handle {
|
|
|
|
|
|
cursor: grab;
|
|
|
|
|
|
&:active {
|
|
|
|
|
|
cursor: grabbing;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|