detect-embeded/src/views/data/task/drawer.vue
2025-05-26 17:00:24 +08:00

442 lines
13 KiB
Vue

<template>
<BasicDrawer v-bind="$attrs" @register="registerDrawer" showFooter :title="getTitle" width="960px" @ok="handleSubmit">
<BasicForm @register="registerForm" @field-value-change="handleValuesChanged" />
<BasicTable @register="registerTable">
<template #toolbar>
<div style="margin-right: 20px; color: #ffffff; font-size: 14px;">共 {{ paramData.length }} 件</div>
<div>
<div style="margin-bottom: 10px">
<a-button type="primary" style="margin-left: 10px" :icon="h(PlusOutlined)" @click="handleCreate">新 增</a-button>
<a-button type="primary" style="margin-left: 10px" :icon="h(EyeOutlined)" :disabled="importDisabled" @click="handleOpenFileDialog">OCR识别</a-button>
<a-button type="primary" style="margin-left: 10px" :icon="h(FileExcelOutlined)" :disabled="importDisabled" @click="handleImport">导入Excel</a-button>
<Popconfirm
title="确定要清空预埋件列表吗?"
ok-text="确定"
cancel-text="取消"
@confirm="handleDeleteAll"
>
<a-button type="primary" style="margin-left: 10px" :icon="h(MinusOutlined)">清空列表</a-button>
</Popconfirm>
</div>
<div>
<span v-if="numberList.length !== 0" style="font-family: 'Noto Sans SC', serif; font-size: 14px; color: #ffffff; padding-right: 10px">{{ valueLabel }}</span>
<CheckboxGroup v-if="numberList.length !== 0" v-model:value="numberCheckedList" :options="numberList" />
<a-button type="primary" style="margin-left: 10px" :icon="h(FileSyncOutlined)" :disabled="importDisabled" @click="handleParamData">整理OCR数据</a-button>
</div>
</div>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'x'">
<span v-if="markField('x', record)" style="color: red">{{ record.x }}</span>
<span v-else style="color: white">{{ record.x }}</span>
</template>
<template v-if="column.dataIndex === 'center'">
<span v-if="markField('center', record)" style="color: red">{{ record.center }}</span>
<span v-else style="color: white">{{ record.center }}</span>
</template>
<template v-if="column.dataIndex === 'w'">
<span v-if="record.w !== record.h" style="color: red">{{ record.w }}</span>
<span v-else style="color: white">{{ record.w }}</span>
</template>
<template v-if="column.dataIndex === 'h'">
<span v-if="record.w !== record.h" style="color: red">{{ record.h }}</span>
<span v-else style="color: white">{{ record.h }}</span>
</template>
<template v-if="column.dataIndex === 'action'">
<TableAction
:actions="[
{
label: '编辑',
icon: 'clarity:note-edit-line',
onClick: handleEdit.bind(null, record),
divider: true,
},
{
label: '删除',
icon: 'ant-design:delete-outlined',
color: 'error',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
placement: 'topRight',
},
divider: true,
},
]"
/>
</template>
</template>
</BasicTable>
<Modal @register="register" @success="updateParamData" />
</BasicDrawer>
</template>
<script lang="ts" setup>
import { defineEmits, ref, computed, unref, h } from 'vue';
import { BasicForm, useForm } from '@/components/Form/index';
import { formSchema } from './schema';
import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
import * as TaskApi from '@/api/data/taskApi';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { EyeOutlined, PlusOutlined, MinusOutlined, FileSyncOutlined, FileExcelOutlined } from "@ant-design/icons-vue";
import { Popconfirm, CheckboxGroup } from 'ant-design-vue';
import Modal from "@/views/data/task/modal.vue";
import { useModal } from '/@/components/Modal';
const [register, { openModal }] = useModal();
const columns = [
{
title: '序号',
dataIndex: 'sn',
key: 'sn',
width: '50px',
},
{
title: '预埋件编号',
dataIndex: 'code',
key: 'code',
},
{
title: '类型',
dataIndex: 'type',
key: 'type',
},
{
title: 'X(mm)',
dataIndex: 'x',
key: 'x',
width: '72px',
},
{
title: 'Y(mm)',
dataIndex: 'y',
key: 'y',
width: '72px',
},
{
title: 'w(mm)',
dataIndex: 'w',
key: 'w',
width: '72px',
},
{
title: 'h(mm)',
dataIndex: 'h',
key: 'h',
width: '72px',
},
{
title: '中心点(m)',
dataIndex: 'center',
key: 'center',
width: '80px',
},
];
const valueLabel = ref<string>("");
const numberList = ref<any>([]);
const numberCheckedList = ref<any>([]);
const paramRawData = ref<any>([]);
const paramData = ref<any>([]);
const emit = defineEmits(['success', 'register', 'ocrClick']);
const isUpdate = ref(true);
const importDisabled = ref(true);
const entity = ref();
const [registerForm, { resetFields, setFieldsValue, validate, getFieldsValue, updateSchema }] = useForm({
labelWidth: 120,
schemas: formSchema,
showActionButtonGroup: false,
});
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
await resetFields();
setDrawerProps({confirmLoading: false});
isUpdate.value = !!data?.isUpdate;
entity.value = data?.record;
valueLabel.value = "";
numberList.value = [];
numberCheckedList.value = [];
paramRawData.value = [];
paramData.value = [];
const items = entity.value && entity.value.paramJson ? JSON.parse(entity.value.paramJson) : [];
items.forEach((d: any, index: number) => {
if (Object.keys(d).includes('sn')) {
paramData.value.push({...d});
} else {
paramData.value.push({sn: (index + 1) + '', ...d});
}
});
await setFieldsValue({
...data.record,
});
await updateSchema([
{
field: 'wallType',
componentProps: {
disabled: unref(isUpdate)
}
},
{
field: 'direction',
componentProps: {
disabled: unref(isUpdate)
}
}]);
handleValuesChanged();
});
const [registerTable] = useTable({
title: '预埋件列表',
columns,
dataSource: paramData,
useSearchForm: false,
showTableSetting: false,
bordered: true,
showIndexColumn: false,
canResize: false,
pagination: false,
rowKey: (record: any) => record.code,
actionColumn: {
width: 140,
title: '操作',
dataIndex: 'action',
fixed: undefined,
},
});
const getTitle = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
async function handleSubmit() {
const values = await validate();
setDrawerProps({confirmLoading: true});
const {
...rest
} = values;
const action = !unref(isUpdate) ? TaskApi.add : TaskApi.update;
const data = !unref(isUpdate)
? {
...rest,
}
: Object.assign({},
{
...unref(entity),
...rest,
},
);
let p: any = [];
paramData.value.forEach((d: any) => {
// 添加 墙体类型 方向(正面、背面) 堆芯坐标
d.wallType = data.wallType;
d.direction = data.direction;
d.coreA = data.coreA;
d.coreB = data.coreB;
p.push({ ...d });
});
data.paramJson = JSON.stringify(p);
await action(data);
closeDrawer();
emit('success');
setDrawerProps({confirmLoading: false});
}
const handleCreate = () => {
openModal(true, { isUpdate: false });
};
const handleEdit = (record: Recordable) => {
openModal(true, { record, isUpdate: true });
};
const handleDelete = (record: Recordable) => {
paramData.value = paramData.value.filter((d: any) => d.code !== record.code);
};
const handleOpenFileDialog = () => {
const rest = getFieldsValue();
const data = !unref(isUpdate)
? {
...rest,
}
: Object.assign({},
{
...unref(entity),
...rest,
},
);
emit("ocrClick", data);
};
// 导入EXCEL
const handleImport = () => {
WebViewService.importExcel().then((res: any) => {
const data = getFieldsValue();
if (res === "") {
WebViewService.setMessage('没有预埋件数据!', 'information').then(() => {});
return;
}
const items = JSON.parse(res);
if (items.length === 0) {
WebViewService.setMessage('没有预埋件数据!', 'information').then(() => {});
return;
}
if (!paramData.value) {
paramData.value = [];
}
items.forEach((d: any) => {
if (d.wallType.toUpperCase() === data.wallType && d.direction === data.direction) {
const items = paramData.value.filter((p: any) => p.code === d.code);
if (items.length === 0) {
paramData.value.push({...d});
} else {
items[0] = {...d};
}
}
});
WebViewService.setMessage('数据导入成功!', "success").then(() => {});
})
}
const handleDeleteAll = (e: MouseEvent) => {
paramData.value = [];
};
const updateParamData = async (data: any) => {
paramData.value.forEach((d: any, index: number) => {
if (d["code"] === data["code"]) {
paramData.value[index] = { ...data };
}
});
}
const markField = computed(() => {
return (field: any, record: any) => {
let c = 0
paramData.value.forEach((d: any) => {
if (Number(d[field]) < 0) {
c += 1;
}
});
if (paramData.value.length - c < c) {
return Number(record[field]) > 0
} else {
return Number(record[field]) < 0
}
};
});
const handleValuesChanged = () => {
const data = getFieldsValue();
importDisabled.value = data.wallType === undefined || data.direction === undefined;
};
// OCR识别
const setParamData = (data: any) => {
data.forEach((d: any) => {
const items = paramData.value.filter((p: any) => p.code === d.code);
if (items.length === 0) {
paramData.value.push({...d});
}
else {
items[0] = {...d};
}
});
numberList.value = [];
numberCheckedList.value = [];
const wallType = getFieldsValue().wallType;
// x去重
const uniqueListX = Array.from(new Map(paramData.value.map((item: any) => [item.x, item])).values());
// y去重
const uniqueListY = Array.from(new Map(paramData.value.map((item: any) => [item.y, item])).values());
if (wallType === "B类" && uniqueListX.length <= 3 && uniqueListY.length > 3) {
valueLabel.value = "选择X值:";
uniqueListX.forEach((item: any) => { numberList.value.push(item.x); });
}
if (wallType === "A类" && uniqueListY.length <= 3 && uniqueListX.length > 3) {
valueLabel.value = "选择Y值:";
uniqueListY.forEach((item: any) => { numberList.value.push(item.y); });
}
};
// OCR识别数据整理
const handleParamData = () => {
if (valueLabel.value === "") return;
if (numberCheckedList.value.length === 0) {
WebViewService.setMessage('没有' + valueLabel.value, 'information').then(() => {});
return;
}
if (paramRawData.value.length === 0) {
paramData.value.forEach((d: any) => {
paramRawData.value.push({ ...d });
})
}
paramData.value = paramRawData.value.filter((d: any) => {
return (valueLabel.value.includes("X") && numberCheckedList.value.join(",").includes(d.x)) ||
(valueLabel.value.includes("Y") && numberCheckedList.value.join(",").includes(d.y))
});
// const data = getFieldsValue();
// const wallType = data.wallType;
// const direction = data.direction;
// x去重
// const uniqueListX = Array.from(new Map(paramData.value.map((item: any) => [item.x, item])).values());
// // y去重
// const uniqueListY = Array.from(new Map(paramData.value.map((item: any) => [item.y, item])).values());
// // 墙体类型为 B
// paramData.value.forEach((d: any) => {
// if (wallType === "B类" && uniqueListX.length <= 4 && uniqueListY.length > 3) {
// const nX: any = d["y"];
// const nY: any = d["x"];
// d.nX = nX;
// d.nY = nY;
// } else {
// const nX: any = d["x"];
// const nY: any = d["y"];
// d.nX = nX;
// d.nY = nY;
// }
// });
// // 判断正面、背面
// const uniqueY = Array.from(new Map(paramData.value.map((item: any) => [item.nY, item])).values());
// const maxY = Math.max(...uniqueY.map((item: any) => Math.abs(Number(item.nY))));
// const minY = Math.min(...uniqueY.map((item: any) => Math.abs(Number(item.nY))));
// paramData.value.forEach((d: any) => {
// if (Math.abs(Number(d.nY)) === minY) {
// d.zm = 1;
// } else if (Math.abs(Number(d.nY)) === maxY) {
// d.zm = 0;
// } else if (maxY - Math.abs(Number(d.nY)) < Math.abs(Number(d.nY)) - minY) {
// d.zm = 0;
// } else {
// d.zm = 1;
// }
// });
// paramData.value = direction === "正面" ? paramData.value.filter((d: any) => {
// return d.zm === 1
// }).map((d: any) => ({...d})) : paramData.value.filter((d: any) => {
// return d.zm === 0
// }).map((d: any) => ({...d}));
// paramData.value.forEach((d: any) => {
// if (d.hasOwnProperty("zm")) {
// delete d.zm;
// }
// if (d.hasOwnProperty("nX")) {
// delete d.nX;
// }
// if (d.hasOwnProperty("nY")) {
// delete d.nY;
// }
// });
WebViewService.setMessage('数据整理完成!', "success").then(() => {});
}
defineExpose({
setParamData
});
</script>
<style lang="scss" scoped>
@use '@/assets/custom.scss';
</style>