diff --git a/src/api/liswork/work/LisWork.ts b/src/api/liswork/work/LisWork.ts index 5acc965..7b74aa1 100644 --- a/src/api/liswork/work/LisWork.ts +++ b/src/api/liswork/work/LisWork.ts @@ -330,5 +330,29 @@ export function clinicInfo(query?: Object) { params: query }) } +// 指定为某样本复查结果 +export function setredoSample(query?: Object) { + return request({ + url: '/lisworkoper/setredosample', + method: 'get', + params: query + }) +} +// 锁定报告 +export function lockSample(query?: Object) { + return request({ + url: '/lisworkoper/locksample', + method: 'get', + params: query + }) +} +// 解锁报告 +export function unLockSample(query?: Object) { + return request({ + url: '/lisworkoper/unlocksample', + method: 'get', + params: query + }) +} diff --git a/src/components/SelectTable/YQSelectTable/index.vue b/src/components/SelectTable/YQSelectTable/index.vue index f283575..c1489ab 100644 --- a/src/components/SelectTable/YQSelectTable/index.vue +++ b/src/components/SelectTable/YQSelectTable/index.vue @@ -57,6 +57,10 @@ const getDataValue = (val: any) => { emits('getDataValue', val); }; +watch(() => props.data, (val) => { + modelValue.value = val; +}); + onMounted(() => { // 初始化时同步一次父级值(如果有)到内部 modelValue if (props.data !== undefined && props.data !== null) { diff --git a/src/components/contextMenu/index.vue b/src/components/contextMenu/index.vue index 71fd89d..ebf3478 100644 --- a/src/components/contextMenu/index.vue +++ b/src/components/contextMenu/index.vue @@ -31,9 +31,9 @@ import emitter from '@/utils/mitt'; // 组件Props const props = withDefaults(defineProps<{ - items: ContextMenuItem[]; - autoClose?: boolean; - menuWidth?: number | string; + items: ContextMenuItem[]; // 菜单项 + autoClose?: boolean; // 是否自动关闭菜单 + menuWidth?: number | string; // 菜单宽度 }>(), { autoClose: true, menuWidth: 180, @@ -51,14 +51,29 @@ const visible = ref(false); const top = ref(0); const left = ref(0); -const handleContextMenu = (e: MouseEvent) => { - // 打开当前菜单关闭其他菜单 + +const handleContextMenu = async (e: MouseEvent) => { emitter.emit('closeAllContextMenus'); - top.value = Math.min(e.clientY, window.innerHeight - 200); - left.value = Math.min(e.clientX, window.innerWidth - 200); + // 先计算初始位置 + left.value = Math.min(e.clientX, window.innerWidth - (typeof props.menuWidth === 'number' ? props.menuWidth : 180)); + top.value = e.clientY; visible.value = true; emit('open'); + + // 等待菜单渲染完成后获取实际高度 + await nextTick(); + const menuEl = document.querySelector('.hospital-menu') as HTMLElement; + if (menuEl) { + const menuHeight = menuEl.offsetHeight; + const maxTop = window.innerHeight - menuHeight; + // 确保菜单不会超出底部可视区域 + if (top.value > maxTop) { + top.value = maxTop; + // 如果向上调整后仍超出顶部,则取最小0值 + if (top.value < 0) top.value = 0; + } + } }; // 处理菜单项点击 @@ -74,10 +89,8 @@ const handleItemClick = (item: ContextMenuItem) => { // 隐藏菜单 const hideMenu = () => { - if (visible.value) { - visible.value = false; - emit('close'); - } + visible.value = false; + emit('close'); }; // 点击外部区域关闭菜单 @@ -87,12 +100,15 @@ const handleClickOutside = (e: MouseEvent) => { // 键盘事件处理 const handleKeyDown = (e: KeyboardEvent) => { - // console.log('e==>', e); + if (!visible.value) return; if (e.key === 'Escape') { hideMenu(); } - if (e.key === 'e' && visible.value) { - console.log('e==>', e); + // 统一转换小写 + const row: ContextMenuItem | undefined = props.items.find(item => item.shortcut?.toLowerCase() === e.key?.toLowerCase()); + + if (row && !row.disabled) { + handleItemClick(row) } }; diff --git a/src/components/elTable/index.vue b/src/components/elTable/index.vue index a88887f..cdffaa4 100644 --- a/src/components/elTable/index.vue +++ b/src/components/elTable/index.vue @@ -331,6 +331,10 @@ const setCurrentRow = (row: Object) => { tableRef.value?.setCurrentRow(row); }; +const setScrollTo = (top: number) => { + tableRef.value?.scrollTo(top); +}; + const clearSort = () => { tableRef.value?.clearSort(); }; @@ -349,6 +353,7 @@ defineExpose({ toggleRowSelection, toggleAllSelection, setCurrentRow, + setScrollTo, clearSort, doLayout, sort, diff --git a/src/views/liswork/work/components/ItemInput.vue b/src/components/projectDetails/index.vue similarity index 63% rename from src/views/liswork/work/components/ItemInput.vue rename to src/components/projectDetails/index.vue index cd64448..d668f64 100644 --- a/src/views/liswork/work/components/ItemInput.vue +++ b/src/components/projectDetails/index.vue @@ -1,19 +1,5 @@ @@ -31,7 +29,7 @@ import { ref, watch, toRefs, onMounted, nextTick } from 'vue' import { redoResult, queryXmInfo, saveRedo, swapRedo, delRedo } from "@/api/liswork/work/LisWork"; import { ElMessage } from 'element-plus' // @ts-ignore -import ItemInput from '../components/ItemInput.vue' +import ProjectDetails from '@/components/projectDetails/index.vue' const props = defineProps({ // 主键 @@ -39,6 +37,10 @@ const props = defineProps({ type: Object, default: {} }, + tablekey: { + type: Object, + default: () => { } + } }) // 解构 props @@ -58,51 +60,16 @@ watch(() => queryParams.value, () => { const tableRef = ref(); const itemDictRef = ref(); // DictInput组件引用 -const selectedItemValue = ref(""); // 选择的项目编码xmdh -const labResuts = ref([]) -const selectedItemLabel = ref(""); // 选择的项目名称xmmc + // 事件定义 const emits = defineEmits(['fetchResults',]); const openItemDictDialog = () => { - if (itemDictRef.value && typeof itemDictRef.value.openDictSelector === 'function') { - itemDictRef.value.openDictSelector(); // 确保方法存在再调用 - } else { - console.warn("DictInput组件未加载完成或方法未暴露"); - } + itemDictRef.value.openDictSelector(); // 确保方法存在再调用 }; -const fetchLabItemDict = async (dictType: string) => { - try { - // 1. 验证必要参数(如当前仪器yq) - if (!queryParams.value.yq) { - ElMessage.error("请先选择仪器"); - return []; - } - - const requestParams = { - pageNum: 1, - pageSize: 1000, // 加载足够多的项目 - yq: queryParams.value.yq, // 当前选中的仪器 - }; - const response = await queryXmInfo(requestParams); - - const formattedData = response.data.map((item: any, index: number) => { - return { - value: item.xmdh || `未知编码_${index}`, // 确保value存在 - label: item.xmmc || `未知名称_${index}`, // 确保label存在 - dw: item.dw || "", - refs: item.refs || "", - }; - }); - return formattedData; - } catch (error: any) { - console.error(`[fetchLabItemDict] 加载失败:`, error.message); - return []; // 失败时返回空数组,避免弹窗报错 - } -}; const handleItemSelect = async (selectedItem: any) => { // 1. 构造新增行数据 @@ -123,50 +90,24 @@ const handleItemSelect = async (selectedItem: any) => { }; const addRowFromDict = async (rowData: any) => { - if (!rowData?.xmdh) { - ElMessage.error("项目编码不能为空"); - return; - } - // 1. 校验输入数据有效性 - if (!rowData || !rowData.xmdh) { - ElMessage.error("新增失败:项目编码不能为空"); - return false; - } + if (!rowData.xmdh) return ElMessage.error("新增失败:项目编码不能为空"); - // 2. 检查是否重复添加同一项目(根据xmdh判断) const isDuplicate = tableData.value.some((item: any) => item.xmdh === rowData.xmdh); - if (isDuplicate) { - ElMessage.warning(`项目【${rowData.xmmc}】已存在`); - return; - } + if (isDuplicate) return ElMessage.warning(`项目【${rowData.xmmc}】已存在`); - // 3. 补全新增行的必要字段(如无则初始化) const newRow = { ...rowData, csjg: "" }; - - // 4. 添加到表格数据 tableData.value.push(newRow); // 5. 自动聚焦 nextTick(() => { tableRef.value.setCurrentRow(newRow); - nextTick(() => { - tableRef.value.setScrollTop(23 * tableRef.value.length) - }) - nextTick(() => { - const tableBody = document.querySelector('.el-table__body-wrapper'); - if (tableBody) { - tableBody.scrollTop = tableBody.scrollHeight; - } - - // 聚焦到新行的输入框 - const inputs = document.querySelectorAll('.full-width-input .el-input__inner') as NodeListOf; - if (inputs.length > 0) { - inputs[inputs.length - 1]?.focus(); - } - }); + tableRef.value.setScrollTo(tableData.value.length - 1) + // 聚焦到新行的输入框 + const inputs = document.querySelectorAll('.full-width-input .el-input__inner') as NodeListOf; + if (inputs.length > 0) { + inputs[inputs.length - 1]?.focus(); + } }); - - return true; }; const handleCsjgEnter = (row: any) => {