优化
This commit is contained in:
parent
2f56182ca9
commit
a5639b87ad
@ -181,6 +181,7 @@
|
|||||||
|
|
||||||
.vxe-table {
|
.vxe-table {
|
||||||
border: 1px solid #96B8D9 !important;
|
border: 1px solid #96B8D9 !important;
|
||||||
|
border-top: none !important;
|
||||||
/* 蓝色外边框 */
|
/* 蓝色外边框 */
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
/* 可选:添加边框圆角 */
|
/* 可选:添加边框圆角 */
|
||||||
|
|||||||
330
src/components/DoubleClickInputTable/index.vue
Normal file
330
src/components/DoubleClickInputTable/index.vue
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
<template>
|
||||||
|
<div class="double-click-input-table" ref="componentRef">
|
||||||
|
<!-- 输入框 -->
|
||||||
|
<el-input ref="inputRef" v-model="inputValue" class="full-width-input" :placeholder="placeholder"
|
||||||
|
:disabled="disabled" @dblclick="handleDoubleClick" @change="handleInputBlur" />
|
||||||
|
|
||||||
|
<!-- 下拉表格面板 -->
|
||||||
|
<el-popover ref="popoverRef" v-model:visible="isPopoverVisible" :width="popoverWidth" trigger="click"
|
||||||
|
placement="bottom-start" :teleported="false" @hide="handlePopoverHide">
|
||||||
|
<!-- 搜索框 -->
|
||||||
|
<el-input ref="searchInputRef" v-model="searchKeyword" placeholder="搜索..." size="small" class="search-input"
|
||||||
|
@input="handleSearch" @keydown="handleSearchKeydown" />
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<el-table ref="tableRef" :data="filteredData" :height="tableHeight" highlight-current-row
|
||||||
|
:current-row-key="currentRowKey" @row-dblclick="handleRowDblClick" class="select-table">
|
||||||
|
<!-- 动态渲染列 -->
|
||||||
|
<el-table-column v-for="column in columns" :key="column.prop" :prop="column.prop" :label="column.label"
|
||||||
|
:width="column.width" :align="column.align || 'left'" />
|
||||||
|
</el-table>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch, nextTick, onMounted, defineProps, defineEmits, toRefs } from 'vue';
|
||||||
|
import { ElInput, ElPopover, ElTable, ElTableColumn } from 'element-plus';
|
||||||
|
|
||||||
|
// 定义列的类型
|
||||||
|
interface TableColumn {
|
||||||
|
prop: string;
|
||||||
|
label: string;
|
||||||
|
width?: number | string;
|
||||||
|
align?: 'left' | 'center' | 'right';
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DataItem {
|
||||||
|
[key: string]: any; // 或者更严格的字段定义
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue: string | number | DataItem;
|
||||||
|
data: DataItem[];
|
||||||
|
columns: TableColumn[];
|
||||||
|
labelField: string;
|
||||||
|
valueField: string;
|
||||||
|
placeholder?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
popoverWidth?: number | string;
|
||||||
|
tableHeight?: number | string;
|
||||||
|
searchable?: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 定义事件
|
||||||
|
const emits = defineEmits(['update:modelValue', 'change', 'select', 'visible-change']);
|
||||||
|
|
||||||
|
// 解构 props
|
||||||
|
const { modelValue, data, columns, labelField, valueField, searchable } = toRefs(props);
|
||||||
|
|
||||||
|
// 组件内部状态
|
||||||
|
const inputValue = ref('');
|
||||||
|
const isPopoverVisible = ref(false);
|
||||||
|
const searchKeyword = ref('');
|
||||||
|
const filteredData = ref<any[]>([]);
|
||||||
|
const currentRowKey = ref('');
|
||||||
|
const currentIndex = ref(-1);
|
||||||
|
const isInputFocused = ref(false);
|
||||||
|
|
||||||
|
// 引用
|
||||||
|
const inputRef = ref<InstanceType<typeof ElInput>>();
|
||||||
|
const popoverRef = ref<InstanceType<typeof ElPopover>>();
|
||||||
|
const tableRef = ref<InstanceType<typeof ElTable>>();
|
||||||
|
const searchInputRef = ref<InstanceType<typeof ElInput>>();
|
||||||
|
const componentRef = ref<HTMLElement | null>(null);
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
filteredData.value = [...data.value];
|
||||||
|
syncInputValue();
|
||||||
|
|
||||||
|
// 监听数据变化
|
||||||
|
watch(data, (newVal) => {
|
||||||
|
filteredData.value = [...newVal];
|
||||||
|
handleSearch();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听选中值变化
|
||||||
|
watch(modelValue, () => {
|
||||||
|
syncInputValue();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 同步输入框值
|
||||||
|
const syncInputValue = () => {
|
||||||
|
if (modelValue.value && typeof modelValue.value === 'object') {
|
||||||
|
inputValue.value = modelValue.value[labelField.value] || '';
|
||||||
|
setCurrentRow(modelValue.value);
|
||||||
|
} else if (modelValue.value) {
|
||||||
|
// 当值不是对象时,查找对应的数据
|
||||||
|
const found = data.value.find((item: any) => item[valueField.value] === modelValue.value);
|
||||||
|
inputValue.value = found ? found[labelField.value] : '';
|
||||||
|
setCurrentRow(found);
|
||||||
|
} else {
|
||||||
|
inputValue.value = '';
|
||||||
|
currentRowKey.value = '';
|
||||||
|
currentIndex.value = -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 设置当前选中行
|
||||||
|
const setCurrentRow = (row: any) => {
|
||||||
|
if (!row) return;
|
||||||
|
|
||||||
|
currentRowKey.value = row[valueField.value];
|
||||||
|
const index = filteredData.value.findIndex(item => item[valueField.value] === row[valueField.value]);
|
||||||
|
if (index !== -1) {
|
||||||
|
currentIndex.value = index;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 双击输入框显示下拉面板
|
||||||
|
const handleDoubleClick = () => {
|
||||||
|
if (props.disabled) return;
|
||||||
|
|
||||||
|
isPopoverVisible.value = true;
|
||||||
|
emits('visible-change', true);
|
||||||
|
|
||||||
|
// 延迟聚焦搜索框,确保弹窗已渲染
|
||||||
|
nextTick(() => {
|
||||||
|
if (searchable.value && searchInputRef.value) {
|
||||||
|
searchInputRef.value.focus();
|
||||||
|
} else if (tableRef.value) {
|
||||||
|
// 如果不可搜索,聚焦表格
|
||||||
|
const tableEl = tableRef.value.$el.querySelector('.el-table__body-wrapper');
|
||||||
|
tableEl?.focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理搜索
|
||||||
|
const handleSearch = () => {
|
||||||
|
const keyword = searchKeyword.value.toLowerCase().trim();
|
||||||
|
|
||||||
|
if (!keyword) {
|
||||||
|
filteredData.value = [...data.value];
|
||||||
|
currentIndex.value = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过滤数据,在所有列中搜索
|
||||||
|
filteredData.value = data.value.filter((item: any) => {
|
||||||
|
return columns.value.some(column => {
|
||||||
|
const value = item[column.prop];
|
||||||
|
return value !== null && value !== undefined &&
|
||||||
|
String(value).toLowerCase().includes(keyword);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 重置当前索引
|
||||||
|
currentIndex.value = filteredData.value.length > 0 ? 0 : -1;
|
||||||
|
if (currentIndex.value !== -1) {
|
||||||
|
currentRowKey.value = filteredData.value[0][valueField.value];
|
||||||
|
scrollToCurrentRow();
|
||||||
|
} else {
|
||||||
|
currentRowKey.value = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格行点击
|
||||||
|
const handleRowClick = (row: any) => {
|
||||||
|
currentRowKey.value = row[valueField.value];
|
||||||
|
currentIndex.value = filteredData.value.findIndex(item => item[valueField.value] === row[valueField.value]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格行双击
|
||||||
|
const handleRowDblClick = (row: any) => {
|
||||||
|
selectRow(row);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择行
|
||||||
|
const selectRow = (row: any) => {
|
||||||
|
if (!row) return;
|
||||||
|
|
||||||
|
inputValue.value = row[labelField.value];
|
||||||
|
emits('update:modelValue', row[valueField.value]);
|
||||||
|
emits('change', row[valueField.value]);
|
||||||
|
emits('select', row);
|
||||||
|
|
||||||
|
isPopoverVisible.value = false;
|
||||||
|
emits('visible-change',);
|
||||||
|
|
||||||
|
// 聚焦输入框
|
||||||
|
nextTick(() => {
|
||||||
|
inputRef.value?.focus();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 处理输入框失焦
|
||||||
|
const handleInputBlur = () => {
|
||||||
|
emits('visible-change');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理输入框键盘事件
|
||||||
|
const handleInputKeydown = (e: any) => {
|
||||||
|
// 按向下箭头显示下拉面板
|
||||||
|
if (e.key === 'ArrowDown' && isInputFocused.value) {
|
||||||
|
e.preventDefault();
|
||||||
|
handleDoubleClick();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理搜索框键盘事件
|
||||||
|
const handleSearchKeydown = (e: any) => {
|
||||||
|
// 上下箭头控制表格选择
|
||||||
|
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
|
||||||
|
e.preventDefault();
|
||||||
|
handleArrowKey(e.key);
|
||||||
|
}
|
||||||
|
// 回车键选择
|
||||||
|
else if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
if (currentIndex.value !== -1 && filteredData.value[currentIndex.value]) {
|
||||||
|
selectRow(filteredData.value[currentIndex.value]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ESC键关闭
|
||||||
|
else if (e.key === 'Escape') {
|
||||||
|
isPopoverVisible.value = false;
|
||||||
|
emits('visible-change', false);
|
||||||
|
inputRef.value?.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理箭头键
|
||||||
|
const handleArrowKey = (direction: 'ArrowUp' | 'ArrowDown') => {
|
||||||
|
if (filteredData.value.length === 0) return;
|
||||||
|
|
||||||
|
if (direction === 'ArrowUp') {
|
||||||
|
currentIndex.value = Math.max(0, currentIndex.value - 1);
|
||||||
|
} else {
|
||||||
|
currentIndex.value = Math.min(filteredData.value.length - 1, currentIndex.value + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentRow = filteredData.value[currentIndex.value];
|
||||||
|
currentRowKey.value = currentRow[valueField.value];
|
||||||
|
scrollToCurrentRow();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 滚动到当前行
|
||||||
|
const scrollToCurrentRow = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
const table = tableRef.value;
|
||||||
|
if (!table) return;
|
||||||
|
|
||||||
|
const rowEl = table.$el.querySelector(`.el-table__row[current-row-key="${currentRowKey.value}"]`);
|
||||||
|
const scrollContainer = table.$el.querySelector('.el-table__body-wrapper');
|
||||||
|
|
||||||
|
if (rowEl && scrollContainer) {
|
||||||
|
// 计算滚动位置,使当前行居中
|
||||||
|
const containerHeight = scrollContainer.clientHeight;
|
||||||
|
const rowHeight = rowEl.offsetHeight;
|
||||||
|
const rowTop = rowEl.offsetTop;
|
||||||
|
const scrollTop = rowTop - containerHeight / 2 + rowHeight / 2;
|
||||||
|
|
||||||
|
scrollContainer.scrollTo({
|
||||||
|
top: scrollTop,
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理弹窗隐藏
|
||||||
|
const handlePopoverHide = () => {
|
||||||
|
searchKeyword.value = '';
|
||||||
|
handleSearch(); // 重置搜索
|
||||||
|
emits('visible-change', false);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.full-width-input .el-input__inner {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
background: transparent !important;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.full-width-input {
|
||||||
|
:deep(.el-input__wrapper) {
|
||||||
|
// box-shadow: 0 0 0 1px rgba(64, 158, 255, 0.2);
|
||||||
|
box-shadow: none;
|
||||||
|
background: transparent !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.double-click-input-table {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-table__body-wrapper {
|
||||||
|
tabindex: 0;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-table__row.current-row {
|
||||||
|
background-color: #e6f7ff !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -10,31 +10,32 @@
|
|||||||
* tableData[Required]: 表格数据对象
|
* tableData[Required]: 表格数据对象
|
||||||
* value: 双向绑定数据的值(为空时data属性为表格当前行数据对象)
|
* value: 双向绑定数据的值(为空时data属性为表格当前行数据对象)
|
||||||
* label: 选择框显示的文本内容(为空时分别查看value和objKey是否为空,若value和objKey都有值,则value优先级大于objKey)
|
* label: 选择框显示的文本内容(为空时分别查看value和objKey是否为空,若value和objKey都有值,则value优先级大于objKey)
|
||||||
* objKey: 对象key(绑定值的唯一标识,绑定值为对象时必填)
|
* objKey: 对象key(绑定值的唯一标识,绑定值为对象时必填) 数据回显对应值
|
||||||
* placeholder: 选择框占位文本
|
* placeholder: 选择框占位文本
|
||||||
* size: 组件大小
|
* size: 组件大小
|
||||||
* border: 表格是否带有边框
|
* border: 表格是否带有边框
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="select-table-container">
|
||||||
<el-select ref="selectTable" v-model="selectShowValue" :placeholder="props.placeholder" :size="props.size"
|
<el-select ref="selectTable" v-model="selectShowValue" :placeholder="props.placeholder" :size="props.size"
|
||||||
:style="{ width: props.width }" @visible-change="visibleChange" @clear="clearHandle" clearable>
|
:style="{ width: props.width }" @visible-change="visibleChange" @clear="clearHandle" clearable>
|
||||||
<template #empty>
|
<template #empty>
|
||||||
<div class="select-table-dropdown">
|
<div class="select-table-dropdown">
|
||||||
<div style="text-align: left;">
|
<div style="text-align: left;">
|
||||||
<el-input v-model="searchKey" ref="searchInput" size="small" placeholder="快速搜索(支持简拼)" class="mb10" clearable
|
<el-input v-model="searchKey" ref="searchInput" size="small" placeholder="快速搜索(支持简拼)" class="mb10" clearable
|
||||||
@clear="filterDataHandle" @input="filterDataHandle" />
|
@clear="filterDataHandle" @input="filterDataHandle" @keydown="handleInputKeydown" />
|
||||||
</div>
|
</div>
|
||||||
<!-- 数据为空时显示空状态提示 -->
|
<!-- 数据为空时显示空状态提示 -->
|
||||||
<el-empty v-if="filterData.length === 0" description="没有匹配的数据" :image-size="100" />
|
<el-empty v-if="filterData.length === 0" description="没有匹配的数据" :image-size="100" />
|
||||||
|
<div @keydown="handleKeydown" v-else tabindex="0" style="outline: none;">
|
||||||
<!-- 数据存在时显示表格 -->
|
<!-- 数据存在时显示表格 -->
|
||||||
<el-table ref="tableRef" v-else :data="filterData" :highlight-current-row="props.isHighlight"
|
<el-table ref="tableRef" :data="filterData" :highlight-current-row="props.isHighlight" style="width: 100%"
|
||||||
style="width: 100%" :border="props.border" @row-click="handleRowChange" max-height="350px">
|
:border="props.border" @row-click="handleRowChange" max-height="350px" :row-style="{ height: '25px' }">
|
||||||
<el-table-column v-for="field in props.fields" :prop="field.prop" :label="field.label" :width="field.width"
|
<el-table-column v-for="field in props.fields" :prop="field.prop" :label="field.label"
|
||||||
:show-overflow-tooltip="field.showTooltip" align="center" />
|
:width="field.width" show-overflow-tooltip align="center" />
|
||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
@ -49,8 +50,7 @@ import { ElEmpty } from 'element-plus';
|
|||||||
interface Field {
|
interface Field {
|
||||||
prop: string;
|
prop: string;
|
||||||
label: string;
|
label: string;
|
||||||
width: number;
|
width?: number;
|
||||||
showTooltip?: boolean;
|
|
||||||
enablePinyinSearch?: boolean; //是否参与拼音搜索
|
enablePinyinSearch?: boolean; //是否参与拼音搜索
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ const searchInput = ref();
|
|||||||
const filterData = ref<{ [key: string]: any; pinyinMap: Record<string, string> }[]>([]);
|
const filterData = ref<{ [key: string]: any; pinyinMap: Record<string, string> }[]>([]);
|
||||||
// 存储预处理后的带拼音数据
|
// 存储预处理后的带拼音数据
|
||||||
const processedTableData = ref<{ [key: string]: any; pinyinMap: Record<string, string> }[]>([]);
|
const processedTableData = ref<{ [key: string]: any; pinyinMap: Record<string, string> }[]>([]);
|
||||||
|
const currentIndex = ref(-1);
|
||||||
// 预处理数据:生成拼音信息
|
// 预处理数据:生成拼音信息
|
||||||
const processTableData = (data: object[]) => {
|
const processTableData = (data: object[]) => {
|
||||||
return data.map((item: any) => {
|
return data.map((item: any) => {
|
||||||
@ -117,8 +117,15 @@ const processTableData = (data: object[]) => {
|
|||||||
const visibleChange = (val: any) => {
|
const visibleChange = (val: any) => {
|
||||||
searchKey.value = '';
|
searchKey.value = '';
|
||||||
if (val) {
|
if (val) {
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
searchInput.value.focus();
|
searchInput.value.focus();
|
||||||
|
|
||||||
|
currentIndex.value = filterData.value.findIndex(item => item[props.value!] === props.data);
|
||||||
|
if (currentIndex.value >= 0) {
|
||||||
|
tableRef.value.setCurrentRow(filterData.value[currentIndex.value]);
|
||||||
|
tableRef.value.setScrollTop(currentIndex.value * 25);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
filterDataHandle()
|
filterDataHandle()
|
||||||
@ -137,15 +144,84 @@ watch(() => props.tableData, (newVal) => {
|
|||||||
handleDataEcho();
|
handleDataEcho();
|
||||||
}, { deep: true });
|
}, { deep: true });
|
||||||
|
|
||||||
// 数据回显处理
|
|
||||||
const handleDataEcho = () => {
|
// 监听绑定值数据变化,重新处理
|
||||||
if (props.data === null || props.data === undefined) return;
|
watch(() => props.data, (newVal) => {
|
||||||
// 查找匹配的行数据
|
// 数据回显
|
||||||
const row: any = props.tableData.find((item: any) => props.objKey && item[props.objKey] === props.data)
|
handleDataEcho();
|
||||||
selectShowValue.value = row ? (props.label ? row[props.label] : (props.value ? row[props.value] : '')) : '';
|
}, { deep: true });
|
||||||
|
|
||||||
|
// 输入框键盘事件处理(专门处理上下键)
|
||||||
|
const handleInputKeydown = (e: KeyboardEvent) => {
|
||||||
|
// 仅处理上下方向键
|
||||||
|
if (e.key !== "ArrowUp" && e.key !== "ArrowDown") return;
|
||||||
|
|
||||||
|
// 阻止事件冒泡到输入框父元素
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
// 如果有筛选数据,转移焦点到表格容器
|
||||||
|
if (filterData.value.length > 0) {
|
||||||
|
// 筛选后让表格容器获得焦点
|
||||||
|
nextTick(() => {
|
||||||
|
// 通过组件内部的 DOM 结构关系查找当前实例的表格容器 避免找不到table焦点
|
||||||
|
const dropdown = searchInput.value.$el.closest('.select-table-dropdown');
|
||||||
|
const tableContainer = dropdown?.querySelector('div[tabindex="0"]') as HTMLElement;
|
||||||
|
if (tableContainer) {
|
||||||
|
tableContainer.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 手动触发一次表格容器的键盘事件
|
||||||
|
const event = new KeyboardEvent('keydown', { key: e.key });
|
||||||
|
tableContainer?.dispatchEvent(event);
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// 监听table键盘事件(核心)
|
||||||
|
const handleKeydown = (e: any) => {
|
||||||
|
// console.log('e==>', e);
|
||||||
|
// 仅处理方向键和回车键
|
||||||
|
if (!['ArrowUp', 'ArrowDown', 'Enter'].includes(e.key)) return;
|
||||||
|
// 阻止默认行为(如页面滚动)
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
// 根据方向键更新“当前选中行索引”
|
||||||
|
const maxIndex = filterData.value.length - 1; // 末行索引
|
||||||
|
if (e.key === "ArrowUp") {
|
||||||
|
// 按↑:索引减1,最小为0(首行)
|
||||||
|
currentIndex.value = Math.max(0, currentIndex.value - 1);
|
||||||
|
} else if (e.key === "ArrowDown") {
|
||||||
|
// 按↓:索引加1,最大为 maxIndex(末行)
|
||||||
|
currentIndex.value = Math.min(maxIndex, currentIndex.value + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
tableRef.value.setCurrentRow(filterData.value[currentIndex.value]);
|
||||||
|
|
||||||
|
// 滚动到当前行
|
||||||
|
tableRef.value.setScrollTop(currentIndex.value * 25);
|
||||||
|
|
||||||
|
// 回车确认
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
const currentRow = filterData.value[currentIndex.value];
|
||||||
|
handleRowChange(currentRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据回显处理
|
||||||
|
const handleDataEcho = () => {
|
||||||
|
if (props.data === null || props.data === undefined) {
|
||||||
|
selectShowValue.value = '';
|
||||||
|
emits('update:data', null);
|
||||||
|
// emits('getDataValue', null);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// 查找匹配的行数据
|
||||||
|
const row: any = props.tableData.find((item: any) => props.objKey && item[props.objKey] === props.data)
|
||||||
|
selectShowValue.value = row ? (props.label ? row[props.label] : (props.value ? row[props.value] : '')) : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
// 搜索过滤逻辑
|
// 搜索过滤逻辑
|
||||||
const filterDataHandle = () => {
|
const filterDataHandle = () => {
|
||||||
@ -155,6 +231,8 @@ const filterDataHandle = () => {
|
|||||||
// 空搜索时显示全部预处理数据
|
// 空搜索时显示全部预处理数据
|
||||||
filterData.value = [...processedTableData.value];
|
filterData.value = [...processedTableData.value];
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
currentIndex.value = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
filterData.value = processedTableData.value.filter((item: any) => {
|
filterData.value = processedTableData.value.filter((item: any) => {
|
||||||
@ -180,11 +258,16 @@ const filterDataHandle = () => {
|
|||||||
|
|
||||||
return matchLabel || matchValue || matchLabelPinyin || matchValuePinyin || matchOtherField;
|
return matchLabel || matchValue || matchLabelPinyin || matchValuePinyin || matchOtherField;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (filterData.value.length > 0) {
|
||||||
|
tableRef.value.setScrollTop(0)
|
||||||
|
tableRef.value.setCurrentRow(filterData.value[0]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRowChange = (val: any) => {
|
const handleRowChange = (val: any) => {
|
||||||
setLabel(val);
|
|
||||||
emits("update:data", props.value ? val[props.value] : val);
|
emits("update:data", props.value ? val[props.value] : val);
|
||||||
|
setLabel(val);
|
||||||
};
|
};
|
||||||
|
|
||||||
const setLabel = (val: any) => {
|
const setLabel = (val: any) => {
|
||||||
@ -194,7 +277,8 @@ const setLabel = (val: any) => {
|
|||||||
selectShowValue.value = val[props.value];
|
selectShowValue.value = val[props.value];
|
||||||
}
|
}
|
||||||
if (props.objKey) {
|
if (props.objKey) {
|
||||||
emits('getDataValue', val[props.objKey]);
|
// 返回值objKey对应的对象数据
|
||||||
|
emits('getDataValue', val);
|
||||||
}
|
}
|
||||||
selectTable.value.blur();
|
selectTable.value.blur();
|
||||||
};
|
};
|
||||||
@ -207,9 +291,12 @@ const clearHandle = () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.select-table-container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.select-table-dropdown {
|
.select-table-dropdown {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-table .el-table__cell) {
|
:deep(.el-table .el-table__cell) {
|
||||||
|
|||||||
101
src/components/projectsjg/index.vue
Normal file
101
src/components/projectsjg/index.vue
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-dialog :title="dialogTitle" v-model="csjgVisible" width="300px" :close-on-click-modal="false" :draggable="true">
|
||||||
|
<el-input v-model="searchKey" :placeholder="placeholder" size="small" class="mb10" clearable
|
||||||
|
@clear="filterDictData" @input="filterDictData" />
|
||||||
|
|
||||||
|
<el-table :data="filterData" max-height="300px" border @row-dblclick="selectItem" highlight-current-row
|
||||||
|
:row-style="{ helght: '25px' }">
|
||||||
|
<el-table-column prop="qz" label="取值" align="center" />
|
||||||
|
<el-table-column prop="pinyin" label="简拼" align="center" />
|
||||||
|
</el-table>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, ref, watch, computed, reactive, toRaw } from 'vue';
|
||||||
|
// @ts-ignore
|
||||||
|
import { getFirstLetter } from '@/api/pinyin.js';
|
||||||
|
interface Props {
|
||||||
|
tableData: object[];
|
||||||
|
label?: string;
|
||||||
|
dialogTitle?: string;
|
||||||
|
placeholder?: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
label: undefined,
|
||||||
|
dialogTitle: '选择数据',
|
||||||
|
placeholder: '支持简拼搜索'
|
||||||
|
});
|
||||||
|
const csjgVisible = ref(false)
|
||||||
|
const searchKey = ref('')
|
||||||
|
const filterData = ref<{ [key: string]: any; pinyinMap: Record<string, string> }[]>([]);
|
||||||
|
const filterDictData = () => {
|
||||||
|
const key = searchKey.value.trim().toLowerCase();
|
||||||
|
|
||||||
|
if (!key) {
|
||||||
|
// 空搜索时显示全部预处理数据
|
||||||
|
filterData.value = [...processedTableData.value];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filterData.value = processedTableData.value.filter((item: any) => {
|
||||||
|
// 1. 原文本匹配
|
||||||
|
const matchLabel = props.label && item[props.label]?.toString().toLowerCase().includes(key);
|
||||||
|
return matchLabel;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: "selectItem", val: any): void;
|
||||||
|
}
|
||||||
|
const emits = defineEmits<Emits>();
|
||||||
|
const selectItem = (row: any) => {
|
||||||
|
emits('selectItem', row);
|
||||||
|
csjgVisible.value = false;
|
||||||
|
}
|
||||||
|
// 存储预处理后的带拼音数据
|
||||||
|
const processedTableData = ref<{ [key: string]: any; pinyinMap: Record<string, string> }[]>([]);
|
||||||
|
// 初始化数据
|
||||||
|
onMounted(() => {
|
||||||
|
processedTableData.value = processTableData(props.tableData);
|
||||||
|
|
||||||
|
filterData.value = [...processedTableData.value];
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听表格数据变化,重新处理
|
||||||
|
watch(() => props.tableData, (newVal) => {
|
||||||
|
processedTableData.value = processTableData(newVal);
|
||||||
|
filterData.value = [...processedTableData.value];
|
||||||
|
// 数据回显
|
||||||
|
}, { deep: true });
|
||||||
|
// 预处理数据:生成拼音信息
|
||||||
|
const processTableData = (data: object[]) => {
|
||||||
|
return data.map((item: any) => {
|
||||||
|
const pinyinMap: Record<string, string> = {};
|
||||||
|
// 处理label字段拼音
|
||||||
|
if (props.label) {
|
||||||
|
pinyinMap['pinyin'] = getFirstLetter(item[props.label]).toLowerCase();
|
||||||
|
return { ...item, ...pinyinMap };
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const open = () => {
|
||||||
|
csjgVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open,
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
:deep(.el-table .el-table__cell) {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -80,7 +80,7 @@ const props = defineProps({
|
|||||||
// 纵向滚动配置
|
// 纵向滚动配置
|
||||||
scrollYConfig: {
|
scrollYConfig: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({ enabled: true, rSize: 50, adaptive: true })
|
default: () => ({ enabled: true, rSize: 30, adaptive: true })
|
||||||
},
|
},
|
||||||
// 表格尺寸
|
// 表格尺寸
|
||||||
size: {
|
size: {
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="5">
|
<el-col :span="5">
|
||||||
<el-form-item label="打印状态:" prop="dybz">
|
<el-form-item label="打印状态:" prop="dybz">
|
||||||
<el-select v-model="queryParams.dybz" placeholder="请选择" clearable>
|
<el-select v-model="queryParams.dybz" placeholder="请选择" clearable @change="handleQuery">
|
||||||
<el-option label="已打印" value="1" />
|
<el-option label="已打印" value="1" />
|
||||||
<el-option label="未打印" value="0" />
|
<el-option label="未打印" value="0" />
|
||||||
</el-select>
|
</el-select>
|
||||||
@ -20,16 +20,16 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="5">
|
<el-col :span="5">
|
||||||
<el-form-item label="科室:" prop="ksdh">
|
<el-form-item label="科室:" prop="ksdh">
|
||||||
<el-select v-model="queryParams.ksdh" placeholder="请选择" filterable clearable>
|
<SelectTable v-model:data="queryParams.ksdh" :fields="ksdhFields" :tableData="dictData.DP || []"
|
||||||
<el-option v-for="item in dictData.DP" :key="item.value" :label="item.label" :value="item.value" />
|
label="label" value="value" objKey="value" :border="true" placeholder="请选择科室"
|
||||||
</el-select>
|
@getDataValue="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="5">
|
<el-col :span="5">
|
||||||
<el-form-item label="病人类型:" prop="brlyname">
|
<el-form-item label="病人类型:" prop="brlyname">
|
||||||
<el-select v-model="queryParams.brlyname" placeholder="请选择" clearable>
|
<SelectTable v-model:data="queryParams.brlyname" :fields="brlxFields" :tableData="dictData.PT || []"
|
||||||
<el-option v-for="item in dictData.PT" :key="item.value" :label="item.label" :value="item.label" />
|
label="label" value="label" objKey="label" :border="true" placeholder="请选择科室"
|
||||||
</el-select>
|
@getDataValue="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
@ -68,7 +68,6 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
@ -112,8 +111,8 @@
|
|||||||
<!-- <el-button type="primary">知识库</el-button> -->
|
<!-- <el-button type="primary">知识库</el-button> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CustomTable :data="rightTableData" :columns="rightColumns" :config="rightTableConfig" :loading="loading"
|
<CustomTable :data="rightTableData" :columns="rightColumns" :config="rightTableConfig" @row-click="xmrowHandle"
|
||||||
@row-click="xmrowHandle" ref="rightTableRef">
|
ref="rightTableRef">
|
||||||
<template #jgbz="{ row }">
|
<template #jgbz="{ row }">
|
||||||
{{ formatJgbz(row.jgbz) }}
|
{{ formatJgbz(row.jgbz) }}
|
||||||
</template>
|
</template>
|
||||||
@ -121,7 +120,7 @@
|
|||||||
|
|
||||||
<div class="mt10" v-if="bottomTableData.length > 0"></div>
|
<div class="mt10" v-if="bottomTableData.length > 0"></div>
|
||||||
<CustomTable v-if="bottomTableData.length > 0" :data="bottomTableData" :columns="bottomColumns"
|
<CustomTable v-if="bottomTableData.length > 0" :data="bottomTableData" :columns="bottomColumns"
|
||||||
:config="bottomTableConfig" :loading="loading">
|
:config="bottomTableConfig">
|
||||||
</CustomTable>
|
</CustomTable>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -152,6 +151,7 @@ import CustomTable from '@/components/elTable/index.vue'
|
|||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { reportList, reportPrintPdf, reportResult, reportMedList, reportFsresult } from '@/api/checkCode/index'
|
import { reportList, reportPrintPdf, reportResult, reportMedList, reportFsresult } from '@/api/checkCode/index'
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import SelectTable from '@/components/SelectTable/index.vue';
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { classCom } from '@/utils/classCom'
|
import { classCom } from '@/utils/classCom'
|
||||||
import { HiprintPrinter } from '@/utils/hiprintPrinter';
|
import { HiprintPrinter } from '@/utils/hiprintPrinter';
|
||||||
@ -215,7 +215,6 @@ queryParams.ksdh = (route.query.deptcode as string) || '';
|
|||||||
queryParams.userid = (route.query.userid as string) || '';
|
queryParams.userid = (route.query.userid as string) || '';
|
||||||
queryParams.brdh = (route.query.brdh as string) || '';
|
queryParams.brdh = (route.query.brdh as string) || '';
|
||||||
|
|
||||||
console.log('queryParams==>', queryParams);
|
|
||||||
|
|
||||||
const single = ref(true);
|
const single = ref(true);
|
||||||
const multiple = ref(true);
|
const multiple = ref(true);
|
||||||
@ -248,7 +247,7 @@ const resetQuery = () => {
|
|||||||
getList()
|
getList()
|
||||||
}
|
}
|
||||||
|
|
||||||
const loading = false;
|
const loading = ref(false);
|
||||||
// 勾选框数据
|
// 勾选框数据
|
||||||
const rows = ref<any[]>([])
|
const rows = ref<any[]>([])
|
||||||
// 数据源
|
// 数据源
|
||||||
@ -363,7 +362,7 @@ const alarmHandle = (val: boolean) => {
|
|||||||
} else {
|
} else {
|
||||||
alarmflag.value = null
|
alarmflag.value = null
|
||||||
}
|
}
|
||||||
|
getList()
|
||||||
}
|
}
|
||||||
const jzbzHandle = (val: boolean) => {
|
const jzbzHandle = (val: boolean) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
@ -373,6 +372,7 @@ const jzbzHandle = (val: boolean) => {
|
|||||||
} else {
|
} else {
|
||||||
jzbz.value = null
|
jzbz.value = null
|
||||||
}
|
}
|
||||||
|
getList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -392,6 +392,17 @@ const updateColumns = (arr: any[]) => {
|
|||||||
columns.value = arr
|
columns.value = arr
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ksdhFields = ref([
|
||||||
|
{ prop: 'value', label: '代号', width: 80, enablePinyinSearch: true },
|
||||||
|
{ prop: 'label', label: '名称', enablePinyinSearch: true },
|
||||||
|
])
|
||||||
|
|
||||||
|
const brlxFields = ref([
|
||||||
|
{ prop: 'value', label: '代号', width: 80, enablePinyinSearch: true },
|
||||||
|
{ prop: 'label', label: '名称', enablePinyinSearch: true },
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 右侧数据源
|
// 右侧数据源
|
||||||
const rightTableData = ref([])
|
const rightTableData = ref([])
|
||||||
@ -781,11 +792,18 @@ const getList = () => {
|
|||||||
} else {
|
} else {
|
||||||
return ElMessage.error('日期时间段不能为空');
|
return ElMessage.error('日期时间段不能为空');
|
||||||
}
|
}
|
||||||
|
loading.value = true
|
||||||
reportList(data).then((res: any) => {
|
reportList(data).then((res: any) => {
|
||||||
if (res.code == 0) {
|
if (res.code == 0) {
|
||||||
|
loading.value = false
|
||||||
tableData.value = res.data
|
tableData.value = res.data
|
||||||
|
if (res.data.length > 0) {
|
||||||
tableRefs.value.setCurrentRow(res.data[0])
|
tableRefs.value.setCurrentRow(res.data[0])
|
||||||
rowHandle(res.data[0])
|
rowHandle(res.data[0])
|
||||||
|
} else {
|
||||||
|
rightTableData.value = []
|
||||||
|
bottomTableData.value = []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,37 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<!-- <SelectTable v-model:data="query" :fields="fields" :tableData="tableData" label="name" objKey="id" :border="true"
|
|
||||||
:width="'300px'" placeholder="请选择指定项" @getDataValue="getDataValue" /> -->
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useFingerprint } from '@/utils/useFingerprint';
|
import { useFingerprint } from '@/utils/useFingerprint';
|
||||||
import SelectTable from '@/components/SelectTable/index.vue';
|
|
||||||
|
|
||||||
|
|
||||||
const query = ref(6);
|
|
||||||
const fields = [
|
|
||||||
{ prop: 'name', label: '名称', width: 150, enablePinyinSearch: true },
|
|
||||||
{ prop: 'value', label: '值', width: 150, enablePinyinSearch: true },
|
|
||||||
{ prop: 'description', label: '描述', width: 300, showTooltip: true }
|
|
||||||
];
|
|
||||||
const tableData = [
|
|
||||||
{ id: 1, name: '指纹', value: 'fingerprint', description: '唯一标识用户的指纹信息' },
|
|
||||||
{ id: 2, name: '浏览器', value: 'browser', description: '用户使用的浏览器信息' },
|
|
||||||
{ id: 3, name: '操作系统', value: 'os', description: '用户使用的操作系统信息' },
|
|
||||||
{ id: 4, name: 'IP地址', value: 'ip', description: '用户的IP地址信息' },
|
|
||||||
{ id: 5, name: '设备信息', value: 'device', description: '用户使用的设备信息' },
|
|
||||||
{ id: 6, name: '地理位置', value: 'location', description: '用户使用的地理位置信息' },
|
|
||||||
{ id: 7, name: '浏览器语言', value: 'language', description: '用户使用的浏览器语言' },
|
|
||||||
{ id: 8, name: '屏幕分辨率', value: 'screen', description: '用户使用的屏幕分辨率信息' },
|
|
||||||
{ id: 9, name: '时区', value: 'timezone', description: '用户使用的时区信息' },
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
const getDataValue = (key) => {
|
|
||||||
console.log('SelectTable组件绑定对应值:', key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用自定义hook获取指纹信息
|
// 使用自定义hook获取指纹信息
|
||||||
const {
|
const {
|
||||||
|
|||||||
@ -15,11 +15,12 @@
|
|||||||
</el-input> -->
|
</el-input> -->
|
||||||
|
|
||||||
<!-- 字典选择弹窗 -->
|
<!-- 字典选择弹窗 -->
|
||||||
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="30vw" @close="handleDialogClose">
|
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="30vw" :close-on-click-modal="false" :draggable="true"
|
||||||
|
@close="handleDialogClose">
|
||||||
<el-input v-model="searchKey" placeholder="搜索(支持名称、编码、简拼)..." class="mb10" clearable @clear="filterDictData"
|
<el-input v-model="searchKey" placeholder="搜索(支持名称、编码、简拼)..." class="mb10" clearable @clear="filterDictData"
|
||||||
@input="filterDictData" />
|
@input="filterDictData" />
|
||||||
|
|
||||||
<el-table :data="filteredDictData" height="300px" border @row-click="selectItem">
|
<el-table :data="filteredDictData" height="300px" border @row-dblclick="selectItem" highlight-current-row>
|
||||||
<el-table-column prop="value" label="编码" align="center" width="150" />
|
<el-table-column prop="value" label="编码" align="center" width="150" />
|
||||||
<el-table-column prop="label" label="名称" align="center" show-overflow-tooltip />
|
<el-table-column prop="label" label="名称" align="center" show-overflow-tooltip />
|
||||||
<el-table-column prop="pinyin" label="简拼" align="center" width="100" /> <!-- 显示简拼便于调试 -->
|
<el-table-column prop="pinyin" label="简拼" align="center" width="100" /> <!-- 显示简拼便于调试 -->
|
||||||
|
|||||||
@ -11,10 +11,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<el-form-item label="病人来源">
|
<el-form-item label="病人来源">
|
||||||
<el-col :span="14">
|
<el-col :span="14">
|
||||||
<el-select v-model="labPat.brly" placeholder="请选择" style="width: 100%;" filterable size="small"
|
<SelectTable v-model:data="labPat.brly" :fields="brlyFields" :tableData="dictData.PT || []" label="label"
|
||||||
@change="handleFieldChange">
|
value="value" objKey="value" :border="true" placeholder="请选择" size="small"
|
||||||
<el-option v-for="item in dictData.PT" :key="item.value" :label="item.label" :value="item.value" />
|
@getDataValue="handleFieldChange" />
|
||||||
</el-select>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
<el-col :span="10">
|
||||||
<el-switch v-model="labPat.jzbz" active-text="急诊" active-color="#FD0101" active-value="1" inactive-value="0"
|
<el-switch v-model="labPat.jzbz" active-text="急诊" active-color="#FD0101" active-value="1" inactive-value="0"
|
||||||
@ -50,20 +49,28 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="送检科室">
|
<el-form-item label="送检科室">
|
||||||
<el-select v-model="labPat.ksdh" placeholder="请选择" style="width: 100%;" filterable @change="handleFieldChange"
|
<!-- <el-select v-model="labPat.ksdh" placeholder="请选择" style="width: 100%;" filterable @change="handleFieldChange"
|
||||||
size="small">
|
size="small">
|
||||||
<el-option v-for="item in dictData.DP" :key="item.value" :label="item.label" :value="item.value" />
|
<el-option v-for="item in dictData.DP" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
</el-select>
|
</el-select> -->
|
||||||
|
|
||||||
|
<SelectTable v-model:data="labPat.ksdh" :fields="ksdhFields" :tableData="dictData.DP || []" label="label"
|
||||||
|
value="value" objKey="value" :border="true" placeholder="请选择" size="small"
|
||||||
|
@getDataValue="handleFieldChange" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="床 号">
|
<el-form-item label="床 号">
|
||||||
<el-input v-model="labPat.ch" placeholder="请输入床号" @blur="handleFieldChange" @keyup.enter="handleFieldChange"
|
<el-input v-model="labPat.ch" placeholder="请输入床号" @blur="handleFieldChange" @keyup.enter="handleFieldChange"
|
||||||
size="small" />
|
size="small" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="样本类型">
|
<el-form-item label="样本类型">
|
||||||
<el-select v-model="labPat.yblx" placeholder="请选择" style="width: 100%;" @change="handleFieldChange" filterable
|
<!-- <el-select v-model="labPat.yblx" placeholder="请选择" style="width: 100%;" @change="handleFieldChange" filterable
|
||||||
size="small">
|
size="small">
|
||||||
<el-option v-for="item in dictData.BT" :key="item.value" :label="item.label" :value="item.value" />
|
<el-option v-for="item in dictData.BT" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
</el-select>
|
</el-select> -->
|
||||||
|
|
||||||
|
<SelectTable v-model:data="labPat.ksdh" :fields="ksdhFields" :tableData="dictData.DP || []" label="label"
|
||||||
|
value="value" objKey="value" :border="true" placeholder="请选择" size="small"
|
||||||
|
@getDataValue="handleFieldChange" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="申请医生">
|
<el-form-item label="申请医生">
|
||||||
<el-select v-model="labPat.sjys" placeholder="请选择" style="width: 100%;" @change="handleFieldChange" filterable
|
<el-select v-model="labPat.sjys" placeholder="请选择" style="width: 100%;" @change="handleFieldChange" filterable
|
||||||
@ -127,9 +134,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, watch, toRaw, computed, onMounted } from 'vue';
|
import { ref, reactive, watch, toRaw, computed, onMounted } from 'vue';
|
||||||
import { changepatcolumn, updateLabPat } from "@/api/liswork/work/LisWork";
|
import { changepatcolumn, updateLabPat } from "@/api/liswork/work/LisWork";
|
||||||
//@ts-ignore
|
import SelectTable from '@/components/SelectTable/index.vue';
|
||||||
import { comDict } from '@/utils/dict'
|
|
||||||
const loading = ref(true);
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
labPat: {
|
labPat: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -153,6 +159,16 @@ watch(() => props.labPat, (newVal) => {
|
|||||||
|
|
||||||
const emit = defineEmits(['update:labPat']);
|
const emit = defineEmits(['update:labPat']);
|
||||||
const lastValue = ref('');
|
const lastValue = ref('');
|
||||||
|
|
||||||
|
const brlyFields = ref([
|
||||||
|
{ prop: 'value', label: '代号', width: 80, enablePinyinSearch: true },
|
||||||
|
{ prop: 'label', label: '名称', width: 120, enablePinyinSearch: true },
|
||||||
|
])
|
||||||
|
|
||||||
|
const ksdhFields = ref([
|
||||||
|
{ prop: 'value', label: '代号', width: 80, enablePinyinSearch: true },
|
||||||
|
{ prop: 'label', label: '名称', width: 150, enablePinyinSearch: true },
|
||||||
|
])
|
||||||
/**
|
/**
|
||||||
* 通用字段变化处理(失焦、回车触发)
|
* 通用字段变化处理(失焦、回车触发)
|
||||||
*/
|
*/
|
||||||
@ -269,32 +285,6 @@ const resetMain = () => {
|
|||||||
lastValue.value = JSON.stringify(resetData);
|
lastValue.value = JSON.stringify(resetData);
|
||||||
};
|
};
|
||||||
|
|
||||||
// interface DictData {
|
|
||||||
// PT?: Array<any>;
|
|
||||||
// AU?: Array<any>;
|
|
||||||
// SX?: Array<any>;
|
|
||||||
// DP?: Array<any>;
|
|
||||||
// BT?: Array<any>;
|
|
||||||
// SRD?: Array<any>;
|
|
||||||
// [key: string]: any[] | undefined; // 添加索引签名以支持动态访问
|
|
||||||
// }
|
|
||||||
// // 字典数据存储
|
|
||||||
// const dictData = ref<DictData>({});
|
|
||||||
|
|
||||||
// onMounted(async () => {
|
|
||||||
// // 加载病人来源字典
|
|
||||||
// const dictRefs = await comDict('PT', 'AU', 'SX', 'DP', 'BT', 'SRD');
|
|
||||||
|
|
||||||
// // 从 ref 中获取实际数据
|
|
||||||
// dictData.value = {
|
|
||||||
// PT: toRaw(dictRefs.PT.value) || [],
|
|
||||||
// AU: toRaw(dictRefs.AU.value) || [],
|
|
||||||
// SX: toRaw(dictRefs.SX.value) || [],
|
|
||||||
// DP: toRaw(dictRefs.DP.value) || [],
|
|
||||||
// BT: toRaw(dictRefs.BT.value) || [],
|
|
||||||
// SRD: toRaw(dictRefs.SRD.value) || [],
|
|
||||||
// };
|
|
||||||
// });
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@ -23,6 +23,9 @@
|
|||||||
<template #nldw="{ row }">
|
<template #nldw="{ row }">
|
||||||
{{ formatDict(row.nldw, 'AU') }}
|
{{ formatDict(row.nldw, 'AU') }}
|
||||||
</template>
|
</template>
|
||||||
|
<template #ksdh="{ row }">
|
||||||
|
{{ formatDict(row.ksdh, 'DP') }}
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #autojgbz="{ row }">
|
<template #autojgbz="{ row }">
|
||||||
<el-checkbox :model-value="row.autojgbz === '1'" disabled />
|
<el-checkbox :model-value="row.autojgbz === '1'" disabled />
|
||||||
@ -66,26 +69,26 @@ const emits = defineEmits(['select'])
|
|||||||
|
|
||||||
// 表格列配置
|
// 表格列配置
|
||||||
const tableColumns = ref([
|
const tableColumns = ref([
|
||||||
{ field: 'finish', title: '完成', width: 60, align: 'center', slotName: 'finish' },
|
{ field: 'finish', title: '完成', width: 50, align: 'center', slotName: 'finish' },
|
||||||
{ field: 'jgbz', title: '审核', width: 60, align: 'center', slotName: 'jgbz' },
|
{ field: 'jgbz', title: '审核', width: 50, align: 'center', slotName: 'jgbz' },
|
||||||
{ field: 'alarmflag', title: '报警', width: 60, align: 'center', slotName: 'alarmflag' },
|
{ field: 'alarmflag', title: '报警', width: 50, align: 'center', slotName: 'alarmflag' },
|
||||||
{ field: 'brly', title: '类型', width: 60, align: 'center', slotName: 'brly' },
|
{ field: 'brly', title: '类型', width: 50, align: 'center', slotName: 'brly' },
|
||||||
{ field: 'autojgbz', title: '自审', width: 60, align: 'center', slotName: 'autojgbz' },
|
{ field: 'autojgbz', title: '自审', width: 50, align: 'center', slotName: 'autojgbz' },
|
||||||
{ field: 'ybh', title: '样本号', width: 100, align: 'center' },
|
{ field: 'ybh', title: '样本号', width: 80, align: 'center' },
|
||||||
{ field: 'brxm', title: '病人姓名', width: 100, align: 'center' },
|
{ field: 'brxm', title: '病人姓名', width: 80, align: 'center' },
|
||||||
{ field: 'brdh', title: '病历号', width: 120, align: 'center' },
|
{ field: 'brdh', title: '病历号', width: 120, align: 'center' },
|
||||||
{ field: 'ch', title: '床号', width: 60, align: 'center' },
|
{ field: 'ch', title: '床号', width: 50, align: 'center' },
|
||||||
{ field: 'brxb', title: '病人性别', width: 100, align: 'center', slotName: 'brxb' },
|
{ field: 'brxb', title: '病人性别', width: 80, align: 'center', slotName: 'brxb' },
|
||||||
{ field: 'nl', title: '年', width: 60, align: 'center' },
|
{ field: 'nl', title: '年', width: 50, align: 'center' },
|
||||||
{ field: 'nldw', title: '龄', width: 60, align: 'center', slotName: 'nldw' },
|
{ field: 'nldw', title: '龄', width: 50, align: 'center', slotName: 'nldw' },
|
||||||
{ field: 'ksdh', title: '科室', width: 60, align: 'center' },
|
{ field: 'ksdh', title: '科室', width: 100, align: 'center', slotName: 'ksdh' },
|
||||||
{ field: 'yblx', title: '标本', width: 60, align: 'center' },
|
{ field: 'yblx', title: '标本', width: 50, align: 'center' },
|
||||||
{ field: 'dybz', title: '打印', width: 60, align: 'center', slotName: 'dybz' },
|
{ field: 'dybz', title: '打印', width: 50, align: 'center', slotName: 'dybz' },
|
||||||
{ field: 'fslx', title: '发送', width: 60, align: 'center', slotName: 'fslx' },
|
{ field: 'fslx', title: '发送', width: 50, align: 'center', slotName: 'fslx' },
|
||||||
{ field: 'shcs', title: '次数', width: 60, align: 'center' },
|
{ field: 'shcs', title: '次数', width: 50, align: 'center' },
|
||||||
{ field: 'sqh', title: '申请号/条码', width: 150, align: 'center' },
|
{ field: 'sqh', title: '申请号/条码', width: 150, align: 'center' },
|
||||||
{ field: 'jymd', title: '检验目的', width: 120, align: 'center' },
|
{ field: 'jymd', title: '检验目的', width: 120, align: 'center' },
|
||||||
{ field: 'yhdh', title: '检验医生', width: 120, align: 'center', },
|
{ field: 'yhdh', title: '检验医生', width: 80, align: 'center', },
|
||||||
{ field: 'yljg', title: '送检医院', width: 120, align: 'center', slotName: 'yljg' }
|
{ field: 'yljg', title: '送检医院', width: 120, align: 'center', slotName: 'yljg' }
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|||||||
@ -16,24 +16,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="tableData" border ref="tableRef" highlight-current-row class="custom-table-container" height="100%"
|
<el-table :data="tableData" border ref="tableRef" highlight-current-row class="custom-table-container" height="100%"
|
||||||
@row-click="handleRowClick">
|
@row-click="handleRowClick" :cell-style="cellStyle">
|
||||||
<el-table-column type="index" prop="id" label="" width="45" :index="getRowIndex"></el-table-column>
|
<el-table-column type="index" prop="id" label="" width="45" :index="getRowIndex"></el-table-column>
|
||||||
<!-- <el-table-column type="selection" width="40" align="center"></el-table-column> -->
|
|
||||||
<el-table-column prop="xmdh" label="项目" show-overflow-tooltip>
|
<el-table-column prop="xmdh" label="项目" show-overflow-tooltip>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="xmmc" label="名称" show-overflow-tooltip>
|
<el-table-column prop="xmmc" label="名称" align="center" show-overflow-tooltip>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="csjg" label="结果">
|
<el-table-column prop="csjg" label="结果" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-input v-if="labPat.jgbz == 0 || labPat.jgbz == null" v-model="scope.row.csjg" size="small"
|
<el-input v-model="scope.row.csjg" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small"
|
||||||
class="full-width-input" :disabled="readonly" @blur="handleCsjgEnter(scope.row)"
|
class="full-width-input" @change="handleCsjgEnter(scope.row)" @dblclick="handleInputFocus(scope.row)" />
|
||||||
@keyup.enter="handleCsjgEnter(scope.row)"></el-input>
|
|
||||||
<span v-else>{{ scope.row.csjg }}</span>
|
<span v-else>{{ scope.row.csjg }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="refs" label="参考值" show-overflow-tooltip>
|
<el-table-column prop="refs" label="参考值" align="center" show-overflow-tooltip>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="dw" label="单位" show-overflow-tooltip>
|
<el-table-column prop="dw" label="单位" align="center" show-overflow-tooltip>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
@ -46,6 +44,9 @@
|
|||||||
<div>
|
<div>
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
</div> -->
|
||||||
|
<!-- csjg弹窗 -->
|
||||||
|
<projectsJg ref="csjgRef" :tableData='csjgTableData' :dialog-title="'项目常用结果选择'" @selectItem="selectItem"
|
||||||
|
label="qz" />
|
||||||
|
|
||||||
<!-- 新增明细 -->
|
<!-- 新增明细 -->
|
||||||
<ItemInput ref="itemDictRef" v-model="selectedItemValue" :label-value.sync="selectedItemLabel"
|
<ItemInput ref="itemDictRef" v-model="selectedItemValue" :label-value.sync="selectedItemLabel"
|
||||||
@ -105,7 +106,7 @@
|
|||||||
<el-dialog v-model="unCheckshow" title="操作原因" width="500" :close-on-click-modal="false" :draggable="true"
|
<el-dialog v-model="unCheckshow" title="操作原因" width="500" :close-on-click-modal="false" :draggable="true"
|
||||||
@close="unconfirmlogCancel">
|
@close="unconfirmlogCancel">
|
||||||
<div class="dialog-body mb10">
|
<div class="dialog-body mb10">
|
||||||
<p class="reason-text mb5">{{ reasonText }}</p>
|
<p class="reason-text mb5">{{ reasonText }} </p>
|
||||||
<el-form ref="uncheckFormRef" style="max-width: 600px" :model="uncheckForm" :rules="rules" label-width="auto">
|
<el-form ref="uncheckFormRef" style="max-width: 600px" :model="uncheckForm" :rules="rules" label-width="auto">
|
||||||
<template v-if="tableKey.problemId == 4">
|
<template v-if="tableKey.problemId == 4">
|
||||||
<el-input type="textarea" v-model="uncheckForm.reason" class="reason-input" placeholder="请输入操作原因..."
|
<el-input type="textarea" v-model="uncheckForm.reason" class="reason-input" placeholder="请输入操作原因..."
|
||||||
@ -135,19 +136,23 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, toRefs, watch, nextTick, onMounted } from "vue";
|
import { ref, toRefs, watch, nextTick, onMounted } from "vue";
|
||||||
import { check1, check2, uncheck2, unconfirmlog, checkuser, reglimit, queryXmInfo, deleteresult, changeresult, newresult, printsample, printListwork } from "@/api/liswork/work/LisWork";
|
import { check1, check2, uncheck2, unconfirmlog, checkuser, reglimit, queryXmInfo, deleteresult, changeresult, newresult, queryXmVal, printListwork } from "@/api/liswork/work/LisWork";
|
||||||
import { ElMessageBox, ElMessage } from "element-plus";
|
import { ElMessageBox, ElMessage } from "element-plus";
|
||||||
import ItemInput from "@/views/liswork/work/components/ItemInput.vue";
|
import ItemInput from "@/views/liswork/work/components/ItemInput.vue";
|
||||||
|
import projectsJg from "@/components/projectsjg/index.vue"
|
||||||
import { classCom } from '@/utils/classCom'
|
import { classCom } from '@/utils/classCom'
|
||||||
// 组件属性定义
|
// 组件属性定义
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
tableData: { type: Array, default: () => [] },
|
tableData: { type: Array, default: () => [] },
|
||||||
tableKey: { type: Object, default: () => { } },
|
tableKey: {
|
||||||
readonly: { type: Boolean, default: false },
|
type: Object, default: () => { }
|
||||||
hasChanges: { type: Boolean, default: false },
|
},
|
||||||
labPat: { type: Object, required: true },
|
labPat: { type: Object, required: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 解构props
|
||||||
|
const { tableData, tableKey, } = toRefs(props);
|
||||||
|
const selectedRows = ref([]);
|
||||||
|
|
||||||
watch(() => props.tableData, (newVal) => {
|
watch(() => props.tableData, (newVal) => {
|
||||||
selectedRows.value = [];
|
selectedRows.value = [];
|
||||||
@ -198,7 +203,7 @@ const rules = ref(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const csjgRef = ref();
|
||||||
|
|
||||||
const itemDictRef = ref(); // DictInput组件引用
|
const itemDictRef = ref(); // DictInput组件引用
|
||||||
const selectedItemValue = ref(""); // 选择的项目编码xmdh
|
const selectedItemValue = ref(""); // 选择的项目编码xmdh
|
||||||
@ -289,6 +294,25 @@ const handleCheck = (checkType) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const cellStyle = ({ row, column, rowIndex, columnIndex }) => {
|
||||||
|
if (column.label == "结果" && (row.alarm_flag ?? "").trim().length > 0) {
|
||||||
|
return { background: '#f00 !important', color: '#FFF' };
|
||||||
|
}
|
||||||
|
if (column.label == "结果" && row.jgbz == "H") {
|
||||||
|
return { background: '#ffc0c0 !important', color: '#606266' };
|
||||||
|
}
|
||||||
|
if (column.label == "结果" && row.jgbz == "L") {
|
||||||
|
return { background: '#8080ff !important', color: '#fff' };
|
||||||
|
}
|
||||||
|
if (column.label == "结果" && row.jgbz == "P") {
|
||||||
|
return { background: '#ffc0c0 !important', color: '#606266' };
|
||||||
|
}
|
||||||
|
if (column.label == "结果" && row.jgbz == "Q") {
|
||||||
|
return { background: '#ffff80 !important', color: '#606266' };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const shHandleCheck = () => {
|
const shHandleCheck = () => {
|
||||||
check2({ ...props.tableKey, yhdh: 'admin' }).then(res => {
|
check2({ ...props.tableKey, yhdh: 'admin' }).then(res => {
|
||||||
emits("changeStatus", props.labPat);
|
emits("changeStatus", props.labPat);
|
||||||
@ -352,8 +376,6 @@ const unconfirmlogConfirm = async () => {
|
|||||||
if (!valid) return false;
|
if (!valid) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
tableKey.value.problemId = 0
|
|
||||||
|
|
||||||
unconfirmlog({ ...tableKey.value, ...uncheckForm.value }).then(response => {
|
unconfirmlog({ ...tableKey.value, ...uncheckForm.value }).then(response => {
|
||||||
if (response.code == "0") {
|
if (response.code == "0") {
|
||||||
unCheckshow.value = false;
|
unCheckshow.value = false;
|
||||||
@ -431,82 +453,41 @@ const emits = defineEmits([
|
|||||||
'previewHandle'
|
'previewHandle'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 解构props
|
const csjgTableData = ref([]);
|
||||||
const { tableData, tableKey, readonly, hasChanges } = toRefs(props);
|
// const dbRow = ref({});
|
||||||
const selectedRows = ref([]);
|
const handleInputFocus = (row) => {
|
||||||
const filteredList = ref([]);
|
// dbRow.value = row
|
||||||
const originalData = ref(JSON.parse(JSON.stringify(props.tableData)));
|
queryXmVal({ yq: tableKey.value.yq, xmdh: row.xmdh }).then(res => {
|
||||||
const isEnterHandled = ref(false);
|
if (res.code == 0) {
|
||||||
const originalCsjgMap = ref({});
|
csjgTableData.value = res.data
|
||||||
|
}
|
||||||
// 组件挂载时初始化缓存
|
nextTick(() => {
|
||||||
onMounted(() => {
|
csjgRef.value.open()
|
||||||
updateOriginalCsjgMap();
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新csjg原始值缓存
|
|
||||||
*/
|
|
||||||
const updateOriginalCsjgMap = () => {
|
|
||||||
const newMap = {};
|
|
||||||
props.tableData.forEach((row) => {
|
|
||||||
const uniqueKey = getRowUniqueKey(row);
|
|
||||||
let originalCsjg = row.csjg;
|
|
||||||
originalCsjg = originalCsjg == null ? "" : String(originalCsjg).trim();
|
|
||||||
newMap[uniqueKey] = originalCsjg;
|
|
||||||
});
|
|
||||||
originalCsjgMap.value = newMap;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
const selectItem = (row) => {
|
||||||
* 获取行的唯一标识
|
// 查找修改行
|
||||||
*/
|
const index = tableData.value.findIndex(item => item.xmdh == row.xmdh)
|
||||||
const getRowUniqueKey = (row) => {
|
tableData.value[index].csjg = row.qz
|
||||||
return row.xmdh;
|
handleCsjgEnter(tableData.value[index])
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* csjg输入框回车触发保存
|
* csjg输入框回车触发保存
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const handleCsjgEnter = async (row) => {
|
const handleCsjgEnter = async (row) => {
|
||||||
// 获取当前输入值
|
|
||||||
const currentCsjg = row.csjg ? String(row.csjg).trim() : "";
|
|
||||||
// 获取原始缓存值
|
|
||||||
const uniqueKey = getRowUniqueKey(row);
|
|
||||||
|
|
||||||
const originalCsjg = originalCsjgMap.value[uniqueKey] || "";
|
|
||||||
|
|
||||||
// 判断值是否改变
|
|
||||||
if (currentCsjg === originalCsjg) return;
|
|
||||||
// 值已改变,执行保存逻辑
|
|
||||||
await saveCsjgChange(row);
|
|
||||||
nextTick(() => {
|
|
||||||
const input = document.activeElement;
|
|
||||||
if (input.tagName === "INPUT") input.blur();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 核心:保存csjg修改(调用API + 失败回滚)
|
|
||||||
*/
|
|
||||||
const saveCsjgChange = async (row) => {
|
|
||||||
const requestParams = {
|
|
||||||
...row,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (row.id) {
|
if (row.id) {
|
||||||
newresult(requestParams).then(response => {
|
newresult(row).then(response => {
|
||||||
ElMessage.success("结果保存成功");
|
ElMessage.success("结果保存成功");
|
||||||
emits('fetchLabResults');
|
emits('fetchLabResults');
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
emits('fetchLabResults');
|
emits('fetchLabResults');
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
changeresult(requestParams).then(response => {
|
changeresult(row).then(response => {
|
||||||
ElMessage.success("结果保存成功");
|
ElMessage.success("结果保存成功");
|
||||||
emits('fetchLabResults');
|
emits('fetchLabResults');
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
@ -514,6 +495,10 @@ const saveCsjgChange = async (row) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
const input = document.activeElement;
|
||||||
|
if (input.tagName === "INPUT") input.blur();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -549,8 +534,6 @@ const handleAdd = () => {
|
|||||||
if (inputs.length > 0) {
|
if (inputs.length > 0) {
|
||||||
inputs[inputs.length - 1].focus();
|
inputs[inputs.length - 1].focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateOriginalCsjgMap();
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
// 新增行核心方法:接收父组件传递的项目数据
|
// 新增行核心方法:接收父组件传递的项目数据
|
||||||
@ -576,13 +559,13 @@ const addRowFromDict = async (rowData) => {
|
|||||||
const newRow = { ...rowData, csjg: "" };
|
const newRow = { ...rowData, csjg: "" };
|
||||||
|
|
||||||
// 4. 添加到表格数据
|
// 4. 添加到表格数据
|
||||||
tableData.value.unshift(newRow);
|
tableData.value.push(newRow);
|
||||||
console.log("子组件新增行:", newRow);
|
console.log("子组件新增行:", newRow);
|
||||||
|
|
||||||
|
|
||||||
// 4. 同步缓存
|
// // 4. 同步缓存
|
||||||
await nextTick();
|
// await nextTick();
|
||||||
updateOriginalCsjgMap();
|
// updateOriginalCsjgMap();
|
||||||
|
|
||||||
|
|
||||||
// 5. 自动聚焦
|
// 5. 自动聚焦
|
||||||
@ -590,10 +573,21 @@ const addRowFromDict = async (rowData) => {
|
|||||||
selectedRows.value = [newRow];
|
selectedRows.value = [newRow];
|
||||||
tableRef.value.setCurrentRow(newRow);
|
tableRef.value.setCurrentRow(newRow);
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
tableRef.value.setScrollTop(30 * tableRef.value.length)
|
tableRef.value.setScrollTop(23 * tableRef.value.length)
|
||||||
})
|
})
|
||||||
// const lastInput = document.querySelector(`.el-table__row:last-child .csjg-input .el-input__inner`);
|
nextTick(() => {
|
||||||
// if (lastInput) lastInput.focus();
|
const tableBody = document.querySelector('.el-table__body-wrapper');
|
||||||
|
if (tableBody) {
|
||||||
|
tableBody.scrollTop = tableBody.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 聚焦到新行的输入框
|
||||||
|
const inputs = document.querySelectorAll('.full-width-input .el-input__inner');
|
||||||
|
if (inputs.length > 0) {
|
||||||
|
inputs[inputs.length - 1].focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -601,16 +595,7 @@ const addRowFromDict = async (rowData) => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存数据
|
|
||||||
*/
|
|
||||||
const handleSave = () => {
|
|
||||||
if (hasChanges.value) {
|
|
||||||
emits('save', props.tableData);
|
|
||||||
updateOriginalCsjgMap();
|
|
||||||
emits("update:hasChanges", false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -683,14 +668,14 @@ const getRowIndex = (index) => {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.tableData.length > 0) {
|
if (props.tableData.length > 0) {
|
||||||
updateOriginalCsjgMap();
|
// updateOriginalCsjgMap();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.tableData,
|
() => props.tableData,
|
||||||
() => {
|
() => {
|
||||||
updateOriginalCsjgMap();
|
// updateOriginalCsjgMap();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -720,18 +705,23 @@ watch(
|
|||||||
|
|
||||||
.full-width-input .el-input__inner {
|
.full-width-input .el-input__inner {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(var(--table-row-height) - 2px);
|
height: 100%;
|
||||||
padding: 0 8px;
|
|
||||||
/* 增加内边距提升输入体验 */
|
background: transparent !important;
|
||||||
border: 0px solid #dcdfe6;
|
border: none !important;
|
||||||
border-radius: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.full-width-input .el-input__inner:focus {
|
.full-width-input {
|
||||||
border-color: #409eff;
|
:deep(.el-input__wrapper) {
|
||||||
box-shadow: 0 0 0 1px rgba(64, 158, 255, 0.2);
|
// box-shadow: 0 0 0 1px rgba(64, 158, 255, 0.2);
|
||||||
|
box-shadow: none;
|
||||||
|
background: transparent !important;
|
||||||
|
padding: 0 !important;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -14,23 +14,14 @@
|
|||||||
style="width:140px"></el-date-picker>
|
style="width:140px"></el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="部门:" prop="instrGroup">
|
<el-form-item label="部门:" prop="instrGroup">
|
||||||
<!-- <el-select v-model="queryParams.instrGroup" placeholder="请选择" style="width:140px" filterable
|
|
||||||
@change="handleinstrGroupChange">
|
|
||||||
<el-option v-for="item in instrGroupOptions" :key="item.zddh" :label="item.zdmc" :value="item.zddh" />
|
|
||||||
</el-select> -->
|
|
||||||
|
|
||||||
<SelectTable v-model:data="queryParams.instrGroup" :fields="instrGroupFields"
|
<SelectTable v-model:data="queryParams.instrGroup" :fields="instrGroupFields"
|
||||||
:tableData="instrGroupOptions" label="zdmc" objKey="zddh" :border="true" width="140px"
|
:tableData="instrGroupOptions" label="zdmc" value="zddh" objKey="zddh" :border="true" width="140px"
|
||||||
placeholder="请选择部门" @getDataValue="handleinstrGroupChange" />
|
placeholder="请选择部门" @getDataValue="handleinstrGroupChange" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="仪器:" prop="yq">
|
<el-form-item label="仪器:" prop="yq">
|
||||||
<!-- <el-select v-model="queryParams.yq" placeholder="请选择" style="width:140px" @change="yqHandleChange"
|
|
||||||
filterable>
|
|
||||||
<el-option v-for="item in instrOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
||||||
</el-select> -->
|
|
||||||
|
|
||||||
<SelectTable v-model:data="queryParams.yq" :fields="yqFields" :tableData="instrOptions" label="yqmc"
|
<SelectTable v-model:data="queryParams.yq" :fields="yqFields" :tableData="instrOptions" label="yqmc"
|
||||||
objKey="yq" :border="true" width="140px" placeholder="请选择仪器" @getDataValue="yqHandleChange" />
|
value="yq" objKey="yq" :border="true" width="140px" placeholder="请选择仪器"
|
||||||
|
@getDataValue="yqHandleChange" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-icon color="#3c80d9" size="20" style="margin-right: 10px;" class="cp">
|
<el-icon color="#3c80d9" size="20" style="margin-right: 10px;" class="cp">
|
||||||
@ -43,10 +34,10 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
<el-row :gutter="5">
|
<el-row :gutter="5">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<LabPat ref="labPatRef" v-model:labPat="labPat" :labPatKey="labPat" :dictData="dictData" />
|
<LabPat ref="labPatRef" v-model:labPat="labPat" :labPatKey="queryParams" :dictData="dictData" />
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="16">
|
<el-col :span="16">
|
||||||
<LabResult ref="labResultRef" v-model:labPat="labPat" :tableData="labResuts" :tableKey="labPat"
|
<LabResult ref="labResultRef" v-model:labPat="labPat" :tableData="labResuts" :tableKey="queryParams"
|
||||||
@fetchLabResults="fetchLabResults" @changeStatus="changeStatus" @previewHandle="previewHandle" />
|
@fetchLabResults="fetchLabResults" @changeStatus="changeStatus" @previewHandle="previewHandle" />
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -187,7 +178,7 @@ const labPat = ref<any>(
|
|||||||
yhdh: '',
|
yhdh: '',
|
||||||
hdys: '',
|
hdys: '',
|
||||||
jgbz: '0',
|
jgbz: '0',
|
||||||
yblx: ''
|
yblx: '',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
const labPatList = ref<Array<{ ybh: string; jgbz: string }>>([]);
|
const labPatList = ref<Array<{ ybh: string; jgbz: string }>>([]);
|
||||||
@ -204,17 +195,14 @@ const previewHandle = (url: string) => {
|
|||||||
pdfUrl.value = `data:application/pdf;base64,${url}`
|
pdfUrl.value = `data:application/pdf;base64,${url}`
|
||||||
previewShow.value = true
|
previewShow.value = true
|
||||||
}
|
}
|
||||||
const handleinstrGroupChange = (val: string) => {
|
const handleinstrGroupChange = (val: any) => {
|
||||||
queryParams.value.instrGroup = val
|
|
||||||
queryParams.value.yq = ''
|
queryParams.value.yq = ''
|
||||||
labResuts.value = []
|
// labResuts.value = []
|
||||||
labPat.value = {}
|
// labPat.value = {}
|
||||||
getYqConfig()
|
getYqConfig()
|
||||||
// fetchlabPatList()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const yqHandleChange = (val: string) => {
|
const yqHandleChange = (val: any) => {
|
||||||
queryParams.value.yq = val
|
|
||||||
labResuts.value = []
|
labResuts.value = []
|
||||||
labPat.value = {}
|
labPat.value = {}
|
||||||
fetchlabPatList()
|
fetchlabPatList()
|
||||||
@ -268,7 +256,6 @@ const labResuts = ref([])
|
|||||||
//载入样本结果表单(中间labresult.vue组件)
|
//载入样本结果表单(中间labresult.vue组件)
|
||||||
const fetchLabResults = async () => {
|
const fetchLabResults = async () => {
|
||||||
queryLabResults({ jyrq: queryParams.value.jyrq, yq: queryParams.value.yq, ybh: queryParams.value.ybh }).then((response: any) => {
|
queryLabResults({ jyrq: queryParams.value.jyrq, yq: queryParams.value.yq, ybh: queryParams.value.ybh }).then((response: any) => {
|
||||||
// console.log('RESULT:', response);
|
|
||||||
labResuts.value = response.data;
|
labResuts.value = response.data;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user