240 lines
6.8 KiB
Vue
240 lines
6.8 KiB
Vue
|
|
<template>
|
|||
|
|
<div class="compact-form">
|
|||
|
|
<el-table
|
|||
|
|
:data="tableData"
|
|||
|
|
border
|
|||
|
|
stripe
|
|||
|
|
highlight-current-row
|
|||
|
|
@selection-change="handleSelectionChange"
|
|||
|
|
class="custom-table-container"
|
|||
|
|
height="640px"
|
|||
|
|
style="width: 100%; --table-row-height: 32px;"
|
|||
|
|
:header-cell-style="{ backgroundColor: '#f5f7fa' }"
|
|||
|
|
>
|
|||
|
|
<el-table-column
|
|||
|
|
type="index" prop="id" label="" width="45" :index="getRowIndex" >
|
|||
|
|
</el-table-column>
|
|||
|
|
<el-table-column type="selection" width="30"></el-table-column>
|
|||
|
|
<el-table-column prop="jyrq" label="检验日期" v-if="false"></el-table-column>
|
|||
|
|
<el-table-column prop="yq" label="仪器" v-if="false"></el-table-column>
|
|||
|
|
<el-table-column prop="ybh" label="样本号" v-if="false"></el-table-column>
|
|||
|
|
|
|||
|
|
<el-table-column prop="xmdh" label="项目" width="60" show-overflow-tooltip>
|
|||
|
|
</el-table-column>
|
|||
|
|
<el-table-column prop="xmmc" label="名称" width="100" show-overflow-tooltip>
|
|||
|
|
</el-table-column>
|
|||
|
|
<el-table-column prop="csjg" label="结果" width="100" >
|
|||
|
|
<template #default="scope">
|
|||
|
|
<el-input v-model="scope.row.csjg" size="small" class="full-width-input"></el-input>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
<el-table-column prop="od" label="OD" width="60" v-if="false">
|
|||
|
|
<template #default="scope">
|
|||
|
|
<el-input v-model="scope.row.od" size="small" class="full-width-input"></el-input>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
<el-table-column prop="cutoff" label="SCO" width="60" v-if="false">
|
|||
|
|
<template #default="scope">
|
|||
|
|
<el-input v-model="scope.row.od" size="small" class="full-width-input"></el-input>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
<el-table-column prop="refs" label="参考值" width="100" show-overflow-tooltip>
|
|||
|
|
</el-table-column>
|
|||
|
|
<el-table-column prop="dw" label="单位" width="100" show-overflow-tooltip >
|
|||
|
|
</el-table-column>
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
</el-table>
|
|||
|
|
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
//import {ref, reactive, watch, toRefs, nextTick} from 'vue';
|
|||
|
|
import {deleteresult, queryLabResults} from "@/api/liswork/work/LisWork.js";
|
|||
|
|
import {delType} from "@/api/system/dict/type.js";
|
|||
|
|
import {ElMessageBox} from "element-plus";
|
|||
|
|
const { proxy } = getCurrentInstance();
|
|||
|
|
const props = defineProps({
|
|||
|
|
// 表格数据
|
|||
|
|
tableData: {type: Array,default: () => []},
|
|||
|
|
//主键
|
|||
|
|
tableKey:{type: Array, default: () => []},
|
|||
|
|
// 部门选项
|
|||
|
|
// departments: {
|
|||
|
|
// type: Array,
|
|||
|
|
// default: () => []
|
|||
|
|
// },
|
|||
|
|
// 是否只读
|
|||
|
|
readonly: {type: Boolean, default: false}
|
|||
|
|
});
|
|||
|
|
const { tableData, tableKey, readonly,undeleteflag,hasChanges } = toRefs(props);
|
|||
|
|
const emits = defineEmits([
|
|||
|
|
'add', // 新增行
|
|||
|
|
'save', // 保存数据
|
|||
|
|
'delete', // 删除行
|
|||
|
|
'batch-delete', // 批量删除
|
|||
|
|
'fetchLabResults' //刷新数据
|
|||
|
|
]);
|
|||
|
|
// 选中的行
|
|||
|
|
const selectedRows = ref([]);
|
|||
|
|
const filteredList = ref([]);
|
|||
|
|
// 原始数据副本,用于检测变化
|
|||
|
|
const originalData = ref(JSON.parse(JSON.stringify(props.tableData)));
|
|||
|
|
// 处理选择变化
|
|||
|
|
|
|||
|
|
const handleSelectionChange = (val) => {
|
|||
|
|
selectedRows.value = val;
|
|||
|
|
if (val.length === 0) {
|
|||
|
|
emits('delfalg', true);
|
|||
|
|
}else{
|
|||
|
|
emits('delfalg', false);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
// 新增行
|
|||
|
|
const handleAdd = () => {
|
|||
|
|
// emits('add');
|
|||
|
|
// 创建新行数据
|
|||
|
|
const newRow = {
|
|||
|
|
jyrq: tableKey.jyrq,
|
|||
|
|
yq: tableKey.yq,
|
|||
|
|
ybh: tableKey.ybh
|
|||
|
|
};
|
|||
|
|
// 添加到表格数据
|
|||
|
|
tableData.value.push(newRow);
|
|||
|
|
// 动画结束后移除标记
|
|||
|
|
// 可选:滚动到表格底部并聚焦到第一个输入框
|
|||
|
|
nextTick(() => {
|
|||
|
|
const tableData = document.querySelector('.el-table__body-wrapper');
|
|||
|
|
if (tableData) {
|
|||
|
|
tableData.scrollTop = tableData.scrollHeight;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 聚焦到新行的第一个输入框
|
|||
|
|
const inputs = document.querySelectorAll('.el-input__inner');
|
|||
|
|
if (inputs.length > 0) {
|
|||
|
|
inputs[4].focus(); // 通常最后一个是操作列的按钮,所以取倒数第二个
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 保存数据
|
|||
|
|
const handleSave = () => {
|
|||
|
|
if (hasChanges.value) {
|
|||
|
|
emits('save', props.tableData);
|
|||
|
|
// 保存后更新原始数据
|
|||
|
|
// originalData.value = JSON.parse(JSON.stringify(props.tableData));
|
|||
|
|
hasChanges.value = false;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 删除行
|
|||
|
|
const handleDelete = (row) => {
|
|||
|
|
emits('delete', row);
|
|||
|
|
tableData.value = tableData.value.filter(item => item.id !== row.id);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 批量删除(调用API)
|
|||
|
|
const handleBatchDelete = async () => {
|
|||
|
|
try {
|
|||
|
|
if (selectedRows.length === 0) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
// 确认删除
|
|||
|
|
await ElMessageBox.confirm(
|
|||
|
|
`确定要删除选中的 ${selectedRows.value.length} 条记录吗?`,
|
|||
|
|
'提示',
|
|||
|
|
{
|
|||
|
|
confirmButtonText: '确定',
|
|||
|
|
cancelButtonText: '取消',
|
|||
|
|
type: 'warning'
|
|||
|
|
}
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
await deleteresult(selectedRows.value);
|
|||
|
|
fetchLabResults();
|
|||
|
|
} catch (error) {
|
|||
|
|
// 错误已经在拦截器中处理,这里可以不做处理或添加额外逻辑
|
|||
|
|
console.error('删除失败:', error);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
// 重置表格的修改状态
|
|||
|
|
const resetChange = () => {
|
|||
|
|
// 原始数据副本,用于检测变化
|
|||
|
|
originalData.value = JSON.parse(JSON.stringify(props.tableData));
|
|||
|
|
hasChanges.value = false;
|
|||
|
|
};
|
|||
|
|
const fetchLabResults = () => {
|
|||
|
|
emits('fetchLabResults');
|
|||
|
|
}
|
|||
|
|
// 监听数据变化
|
|||
|
|
watch(() => props.tableData, (newVal, oldVal) => {
|
|||
|
|
// 简单比较数据是否有变化
|
|||
|
|
//hasChanges.value = JSON.stringify(newVal) !== JSON.stringify(originalData.value);
|
|||
|
|
}, { deep: true });
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 获取行号(支持分页时显示正确行号)
|
|||
|
|
const getRowIndex = (index) => {
|
|||
|
|
// 如果有分页,可以根据当前页码计算真实行号
|
|||
|
|
// return (currentPage - 1) * pageSize + index + 1;
|
|||
|
|
// 无分页时直接返回索引+1
|
|||
|
|
return index + 1;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 暴露方法给父组件
|
|||
|
|
defineExpose({
|
|||
|
|
handleAdd,
|
|||
|
|
handleDelete,
|
|||
|
|
handleSave,
|
|||
|
|
handleBatchDelete
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped>
|
|||
|
|
/* 移除单元格内边距 */
|
|||
|
|
.custom-table-container /deep/ .el-table__cell {
|
|||
|
|
padding: 0 !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 表格行高 */
|
|||
|
|
.custom-table-container /deep/ .el-table__row {
|
|||
|
|
height: var(--table-row-height) !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 输入框占满单元格 */
|
|||
|
|
.full-width-input /deep/ .el-input__inner {
|
|||
|
|
width: 100%;
|
|||
|
|
height: calc(var(--table-row-height) - 2px); /* 减去上下边框 */
|
|||
|
|
padding: 0 0px; /* 减小内边距 */
|
|||
|
|
border: 0px solid #dcdfe6;
|
|||
|
|
border-radius: 0;
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
background-color: transparent; /* 可选:透明背景 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 输入框聚焦效果 */
|
|||
|
|
.full-width-input /deep/ .el-input__inner:focus {
|
|||
|
|
border-color: #409eff;
|
|||
|
|
box-shadow: 0 0 0 0px rgba(64, 158, 255, 0.2);
|
|||
|
|
outline: none;
|
|||
|
|
}
|
|||
|
|
/* 新增行动画 */
|
|||
|
|
.el-table__body-wrapper {
|
|||
|
|
overflow: visible !important; /* 确保动画不被裁剪 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.new-row-enter-active {
|
|||
|
|
animation: fadeIn 0.5s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@keyframes fadeIn {
|
|||
|
|
from { opacity: 0; transform: translateY(10px); }
|
|||
|
|
to { opacity: 1; transform: translateY(0); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
</style>
|