2025-05-20 16:34:38 +08:00
|
|
|
|
<template>
|
2025-09-26 17:26:06 +08:00
|
|
|
|
<div class="result-container">
|
|
|
|
|
|
<div class="flex-between mb10">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<el-button class="btn_green" @click="handleCheck(1)">初审</el-button>
|
|
|
|
|
|
<el-button class="btn_green" v-if="labPat.jgbz != 2" @click="handleCheck(2)">审核</el-button>
|
|
|
|
|
|
<el-button class="btn_green" v-if="labPat.jgbz == 2" @click="handleCheck(3)">取消审核</el-button>
|
2025-09-29 17:30:02 +08:00
|
|
|
|
<el-button type="primary" plain :disabled="labPat.jgbz != null && labPat.jgbz != 0"
|
|
|
|
|
|
@click="openItemDictDialog">新增</el-button>
|
|
|
|
|
|
<el-button type="primary" :disabled="labPat.jgbz != null && labPat.jgbz != 0" plain
|
|
|
|
|
|
@click="handleBatchDelete">删除</el-button>
|
2025-09-26 17:26:06 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<el-button type="primary" plain icon="Files" @click="printHandle">打印</el-button>
|
|
|
|
|
|
<el-button type="primary" plain icon="View" @click="previewHandle">预览</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<el-table :data="tableData" border ref="tableRef" highlight-current-row class="custom-table-container" height="100%"
|
|
|
|
|
|
@row-click="handleRowClick">
|
|
|
|
|
|
<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>
|
2025-05-20 16:34:38 +08:00
|
|
|
|
</el-table-column>
|
2025-09-26 17:26:06 +08:00
|
|
|
|
<el-table-column prop="xmmc" label="名称" show-overflow-tooltip>
|
2025-05-20 16:34:38 +08:00
|
|
|
|
</el-table-column>
|
2025-09-26 17:26:06 +08:00
|
|
|
|
<el-table-column prop="csjg" label="结果">
|
2025-05-20 16:34:38 +08:00
|
|
|
|
<template #default="scope">
|
2025-09-29 17:30:02 +08:00
|
|
|
|
<el-input v-if="labPat.jgbz == 0 || labPat.jgbz == null" v-model="scope.row.csjg" size="small"
|
|
|
|
|
|
class="full-width-input" :disabled="readonly" @blur="handleCsjgEnter(scope.row)"
|
|
|
|
|
|
@keyup.enter="handleCsjgEnter(scope.row)"></el-input>
|
|
|
|
|
|
<span v-else>{{ scope.row.csjg }}</span>
|
2025-05-20 16:34:38 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
2025-09-26 17:26:06 +08:00
|
|
|
|
<el-table-column prop="refs" label="参考值" show-overflow-tooltip>
|
2025-05-20 16:34:38 +08:00
|
|
|
|
</el-table-column>
|
2025-09-26 17:26:06 +08:00
|
|
|
|
<el-table-column prop="dw" label="单位" show-overflow-tooltip>
|
2025-05-20 16:34:38 +08:00
|
|
|
|
</el-table-column>
|
|
|
|
|
|
</el-table>
|
2025-09-26 17:26:06 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- <div class="flex-between mt10">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<el-button class="btn_green" @click=" ">初报</el-button>
|
|
|
|
|
|
<el-button class="btn_green" @click=" ">二报</el-button>
|
|
|
|
|
|
<el-button class="btn_green" @click=" ">锁定</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div> -->
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 新增明细 -->
|
|
|
|
|
|
<ItemInput ref="itemDictRef" v-model="selectedItemValue" :label-value.sync="selectedItemLabel"
|
|
|
|
|
|
:dict-type="'LAB_ITEM'" :fetch-dict="fetchLabItemDict" :dialog-title="'选择检验项目'" :disabled="false"
|
|
|
|
|
|
:load-on-mount="false" :table-data.sync="labResuts" class="hidden-dict-input" @select="handleItemSelect" />
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 校验用户 -->
|
|
|
|
|
|
<el-dialog v-model="checkShow" title="用户身份验证" width="500" :close-on-click-modal="false" :draggable="true"
|
|
|
|
|
|
@close="resetForm">
|
|
|
|
|
|
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto">
|
|
|
|
|
|
<el-form-item label="用户工号:" prop="yhdh">
|
|
|
|
|
|
<el-input v-model.trim="ruleForm.yhdh" placeholder="请输入用户工号" maxlength="20" @keyup.enter="submitForm" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="密码:" prop="mm">
|
|
|
|
|
|
<el-input v-model.trim="ruleForm.mm" placeholder="请输入密码" type="mm" maxlength="20" show-password
|
|
|
|
|
|
@keyup.enter="submitForm" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item>
|
|
|
|
|
|
<div style="text-align: center; width: 100%;">
|
|
|
|
|
|
<el-button type="primary" @click="submitForm()"> 确认 </el-button>
|
|
|
|
|
|
<el-button @click="resetForm">取消</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 危急值结果上报 -->
|
|
|
|
|
|
<el-dialog v-model="showuploadwarning" title="危急值结果上报" width="500" :close-on-click-modal="false" :draggable="true"
|
|
|
|
|
|
@close="warningResetForm">
|
|
|
|
|
|
<div class="red-static-text">{{ warningMsgdata }}</div>
|
|
|
|
|
|
<el-form ref="warningFormRef" style="max-width: 600px" :model="warningForm" :rules="wrules" label-width="auto">
|
|
|
|
|
|
<el-form-item label="上报方式:" prop="uploadTp">
|
|
|
|
|
|
<el-radio-group v-model="warningForm.uploadTp" size="default">
|
|
|
|
|
|
<el-radio value="1">系统通知</el-radio>
|
|
|
|
|
|
<el-radio value="2">电话通知</el-radio>
|
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<template v-if="warningForm.uploadTp == 2">
|
|
|
|
|
|
<el-form-item label="电话通知人:" prop="userId">
|
|
|
|
|
|
<el-input v-model.trim="warningForm.userId" class="form-input" placeholder="请输入医生工号" @keyup.enter=" " />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="联系电话:" prop="phone">
|
|
|
|
|
|
<el-input v-model="warningForm.phone" class="form-input" placeholder="请输入联系电话" @keyup.enter=" " />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item>
|
|
|
|
|
|
<div style="text-align: center; width: 100%;">
|
|
|
|
|
|
<el-button type="primary" @click="handleWarningSuccess()"> 确认 </el-button>
|
|
|
|
|
|
<el-button @click="warningResetForm">取消</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 操作原因 -->
|
|
|
|
|
|
<el-dialog v-model="unCheckshow" title="操作原因" width="500" :close-on-click-modal="false" :draggable="true"
|
|
|
|
|
|
@close="unconfirmlogCancel">
|
|
|
|
|
|
<div class="dialog-body mb10">
|
|
|
|
|
|
<p class="reason-text mb5">{{ reasonText }}</p>
|
|
|
|
|
|
<el-form ref="uncheckFormRef" style="max-width: 600px" :model="uncheckForm" :rules="rules" label-width="auto">
|
|
|
|
|
|
<template v-if="tableKey.problemId == 4">
|
|
|
|
|
|
<el-input type="textarea" v-model="uncheckForm.reason" class="reason-input" placeholder="请输入操作原因..."
|
|
|
|
|
|
:rows="4"></el-input>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-if="tableKey.problemId == 6">
|
|
|
|
|
|
<el-form-item label="用户工号:" prop="yhdh">
|
|
|
|
|
|
<el-input v-model.trim="uncheckForm.yhdh" placeholder="请输入用户工号" maxlength="20"
|
|
|
|
|
|
@keyup.enter="submitForm" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="密码:" prop="mm">
|
|
|
|
|
|
<el-input v-model.trim="uncheckForm.mm" placeholder="请输入密码" type="mm" maxlength="20" show-password
|
|
|
|
|
|
@keyup.enter="submitForm" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div style="text-align: center; width: 100%;">
|
|
|
|
|
|
<el-button type="primary" @click="unconfirmlogConfirm()"> 确认 </el-button>
|
|
|
|
|
|
<el-button @click="unconfirmlogCancel">取消</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
2025-05-20 16:34:38 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
2025-09-17 10:19:20 +08:00
|
|
|
|
import { ref, toRefs, watch, nextTick, onMounted } from "vue";
|
2025-09-29 17:30:02 +08:00
|
|
|
|
import { check1, check2, uncheck2, unconfirmlog, checkuser, reglimit, queryXmInfo, deleteresult, changeresult, newresult, printsample, printListwork } from "@/api/liswork/work/LisWork";
|
2025-09-17 10:19:20 +08:00
|
|
|
|
import { ElMessageBox, ElMessage } from "element-plus";
|
2025-09-26 17:26:06 +08:00
|
|
|
|
import ItemInput from "@/views/liswork/work/components/ItemInput.vue";
|
2025-09-29 17:30:02 +08:00
|
|
|
|
import { classCom } from '@/utils/classCom'
|
2025-09-17 10:19:20 +08:00
|
|
|
|
// 组件属性定义
|
2025-05-20 16:34:38 +08:00
|
|
|
|
const props = defineProps({
|
2025-09-17 10:19:20 +08:00
|
|
|
|
tableData: { type: Array, default: () => [] },
|
2025-09-26 17:26:06 +08:00
|
|
|
|
tableKey: { type: Object, default: () => { } },
|
2025-09-17 10:19:20 +08:00
|
|
|
|
readonly: { type: Boolean, default: false },
|
2025-09-26 17:26:06 +08:00
|
|
|
|
hasChanges: { type: Boolean, default: false },
|
|
|
|
|
|
labPat: { type: Object, required: true },
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
watch(() => props.tableData, (newVal) => {
|
|
|
|
|
|
selectedRows.value = [];
|
2025-05-20 16:34:38 +08:00
|
|
|
|
});
|
2025-09-17 10:19:20 +08:00
|
|
|
|
|
2025-09-26 17:26:06 +08:00
|
|
|
|
const warningForm = ref({
|
|
|
|
|
|
userId: '',
|
|
|
|
|
|
phone: '',
|
|
|
|
|
|
uploadTp: '1'
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const uncheckForm = ref({
|
|
|
|
|
|
reason: '',
|
|
|
|
|
|
yhdh: '',
|
|
|
|
|
|
mm: '',
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const wrules = ref({
|
|
|
|
|
|
userId: [{ required: true, message: "请输入用户工号", trigger: "blur" },
|
|
|
|
|
|
{ min: 3, max: 20, message: "长度在 3 到 20 个字符", trigger: "blur" }
|
|
|
|
|
|
],
|
|
|
|
|
|
phone: [{ required: true, message: "请输入联系电话", trigger: "blur" },
|
|
|
|
|
|
{ min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" }
|
|
|
|
|
|
]
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const unCheckshow = ref(false);
|
|
|
|
|
|
const inputValue = ref('');
|
|
|
|
|
|
const reasonText = ref('');
|
|
|
|
|
|
const warningMsgdata = ref('');
|
|
|
|
|
|
const showuploadwarning = ref(false);
|
|
|
|
|
|
const checkuserid = ref()
|
|
|
|
|
|
const checkShow = ref(false);
|
|
|
|
|
|
const ruleForm = ref({
|
|
|
|
|
|
yhdh: '',
|
|
|
|
|
|
mm: ''
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const rules = ref(
|
|
|
|
|
|
{
|
|
|
|
|
|
yhdh: [{ required: true, message: "请输入用户工号", trigger: "blur" },
|
|
|
|
|
|
{ min: 3, max: 20, message: "长度在 3 到 20 个字符", trigger: "blur" }
|
|
|
|
|
|
],
|
|
|
|
|
|
mm: [{ required: true, message: "请输入密码", trigger: "blur" },
|
|
|
|
|
|
{ min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" }
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const itemDictRef = ref(); // DictInput组件引用
|
|
|
|
|
|
const selectedItemValue = ref(""); // 选择的项目编码xmdh
|
|
|
|
|
|
const selectedItemLabel = ref(""); // 选择的项目名称xmmc
|
|
|
|
|
|
const labResuts = ref([])
|
|
|
|
|
|
const tableRef = ref();
|
|
|
|
|
|
const fetchLabItemDict = async (dictType) => {
|
|
|
|
|
|
// 日志1:确认方法被调用
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 1. 验证必要参数(如当前仪器yq)
|
|
|
|
|
|
if (!tableKey.value.yq) {
|
|
|
|
|
|
console.error("[fetchLabItemDict] 缺少必要参数:yq(仪器)");
|
|
|
|
|
|
ElMessage.error("请先选择仪器");
|
|
|
|
|
|
return [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 日志2:打印请求参数
|
|
|
|
|
|
const requestParams = {
|
|
|
|
|
|
pageNum: 1,
|
|
|
|
|
|
pageSize: 1000, // 加载足够多的项目
|
|
|
|
|
|
yq: tableKey.value.yq, // 当前选中的仪器
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 调用API(确保queryXmInfo是正确的API方法)
|
|
|
|
|
|
const response = await queryXmInfo(requestParams);
|
|
|
|
|
|
|
|
|
|
|
|
// 日志3:打印原始响应
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 验证响应格式
|
|
|
|
|
|
if (!response) {
|
|
|
|
|
|
throw new Error("API返回为空");
|
|
|
|
|
|
}
|
|
|
|
|
|
if (response.code !== "0") { // 假设0为成功状态码
|
|
|
|
|
|
throw new Error(`API返回错误:${response.msg || "未知错误"}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!Array.isArray(response.data)) {
|
|
|
|
|
|
throw new Error(`API返回data不是数组,实际为:${typeof response.data}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 格式化数据(适配DictInput的{value, label}结构)
|
|
|
|
|
|
const formattedData = response.data.map((item, index) => {
|
|
|
|
|
|
// 验证项目数据完整性
|
|
|
|
|
|
if (!item.xmdh) {
|
|
|
|
|
|
console.warn(`[fetchLabItemDict] 第${index}条数据缺少xmdh(项目编码):`, item);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!item.xmmc) {
|
|
|
|
|
|
console.warn(`[fetchLabItemDict] 第${index}条数据缺少xmmc(项目名称):`, item);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
value: item.xmdh || `未知编码_${index}`, // 确保value存在
|
|
|
|
|
|
label: item.xmmc || `未知名称_${index}`, // 确保label存在
|
|
|
|
|
|
dw: item.dw || "", // 单位(可选)
|
|
|
|
|
|
refs: item.refs || "", // 参考值(可选)
|
|
|
|
|
|
};
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 日志4:打印格式化后的数据量
|
|
|
|
|
|
return formattedData;
|
|
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
// 日志5:捕获并显示错误
|
|
|
|
|
|
console.error(`[fetchLabItemDict] 加载失败:`, error.message);
|
|
|
|
|
|
ElMessage.error(`项目字典加载失败:${error.message}`);
|
|
|
|
|
|
return []; // 失败时返回空数组,避免弹窗报错
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleCheck = (checkType) => {
|
|
|
|
|
|
// yhdh = checkuserid.value
|
|
|
|
|
|
switch (checkType) {
|
|
|
|
|
|
case 1: // 初审
|
|
|
|
|
|
check1({ ...tableKey.value, yhdh: 'admin' }).then(res => {
|
|
|
|
|
|
emits("changeStatus", props.labPat);
|
|
|
|
|
|
})
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2: // 审核
|
|
|
|
|
|
tableKey.value.problemId = 0
|
|
|
|
|
|
shHandleCheck()
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 3: // 取消审核
|
|
|
|
|
|
tableKey.value.problemId = 0
|
|
|
|
|
|
unShHandle()
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const shHandleCheck = () => {
|
|
|
|
|
|
check2({ ...props.tableKey, yhdh: 'admin' }).then(res => {
|
|
|
|
|
|
emits("changeStatus", props.labPat);
|
|
|
|
|
|
if (res.code == "4" && res.problemId === 4) {
|
|
|
|
|
|
tableKey.value.problemId = res.problemId;
|
|
|
|
|
|
warningMsgdata.value = res.msg;
|
|
|
|
|
|
showuploadwarning.value = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const warningFormRef = ref(null);
|
|
|
|
|
|
|
|
|
|
|
|
const warningResetForm = () => {
|
|
|
|
|
|
warningForm.value.userId = '';
|
|
|
|
|
|
warningForm.value.phone = '';
|
|
|
|
|
|
warningForm.value.uploadTp = '1';
|
|
|
|
|
|
warningFormRef.value.resetFields();
|
|
|
|
|
|
showuploadwarning.value = false;
|
|
|
|
|
|
};
|
|
|
|
|
|
// 处理危急值登记
|
|
|
|
|
|
const handleWarningSuccess = async () => {
|
|
|
|
|
|
if (warningForm.value.uploadTp == 2) {
|
|
|
|
|
|
const valid = await warningFormRef.value.validate().catch(() => { });
|
|
|
|
|
|
if (!valid) return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
reglimit({ ...tableKey.value, qrr: warningForm.value.userId, tzfs: warningForm.value.uploadTp, phone: warningForm.value.phone }).then(response => {
|
|
|
|
|
|
showuploadwarning.value = false;
|
|
|
|
|
|
if (response.code == 0) {
|
|
|
|
|
|
shHandleCheck();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (response.code == 4) {
|
|
|
|
|
|
ElMessageBox.confirm(response.msg, '系统提示', { confirmButtonText: '是', cancelButtonText: '否', type: 'warning' }).then(() => {
|
|
|
|
|
|
tableKey.value.problemId = tableKey.value.problemId + 1;
|
|
|
|
|
|
handleWarningSuccess();
|
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
shHandleCheck();
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const unShHandle = () => {
|
|
|
|
|
|
uncheck2({ ...tableKey.value, yhdh: 'admin' }).then(res => {
|
|
|
|
|
|
if (res.code == "4") {
|
|
|
|
|
|
tableKey.value.problemId = res.problemId;
|
|
|
|
|
|
reasonText.value = res.msg;
|
|
|
|
|
|
unCheckshow.value = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
emits("changeStatus", props.labPat);
|
|
|
|
|
|
})
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const uncheckFormRef = ref();
|
|
|
|
|
|
// 取消审核原因
|
|
|
|
|
|
const unconfirmlogConfirm = async () => {
|
|
|
|
|
|
if (tableKey.value.problemId == 4) {
|
|
|
|
|
|
if (!uncheckForm.value.inputValue) return ElMessage.warning("请输入操作原因")
|
|
|
|
|
|
} else if (tableKey.value.problemId == 6) {
|
|
|
|
|
|
const valid = await uncheckFormRef.value.validate().catch(() => { });
|
|
|
|
|
|
if (!valid) return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tableKey.value.problemId = 0
|
|
|
|
|
|
|
|
|
|
|
|
unconfirmlog({ ...tableKey.value, ...uncheckForm.value }).then(response => {
|
|
|
|
|
|
if (response.code == "0") {
|
|
|
|
|
|
unCheckshow.value = false;
|
|
|
|
|
|
unShHandle();
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const unconfirmlogCancel = () => {
|
|
|
|
|
|
unCheckshow.value = false;
|
|
|
|
|
|
uncheckForm.value.reason = '';
|
|
|
|
|
|
uncheckForm.value.yhdh = '';
|
|
|
|
|
|
uncheckForm.value.mm = '';
|
|
|
|
|
|
uncheckFormRef.value.resetFields();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const ruleFormRef = ref(null);
|
|
|
|
|
|
|
|
|
|
|
|
const submitForm = () => {
|
|
|
|
|
|
ruleFormRef.value.validate((valid) => {
|
|
|
|
|
|
if (valid) {
|
|
|
|
|
|
checkuser(ruleForm.value).then(res => {
|
|
|
|
|
|
if (res.code == 0) {
|
|
|
|
|
|
checkuserid.value = ruleForm.value.yhdh
|
|
|
|
|
|
checkShow.value = false;
|
|
|
|
|
|
ElMessage.success("验证成功");
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const resetForm = () => {
|
|
|
|
|
|
checkShow.value = false;
|
|
|
|
|
|
ruleForm.value.userId = '';
|
|
|
|
|
|
ruleForm.value.mm = '';
|
|
|
|
|
|
ruleFormRef.value.resetFields();
|
|
|
|
|
|
};
|
|
|
|
|
|
// 2. 打开项目选择弹窗
|
|
|
|
|
|
const openItemDictDialog = () => {
|
|
|
|
|
|
if (itemDictRef.value && typeof itemDictRef.value.openDictSelector === 'function') {
|
|
|
|
|
|
itemDictRef.value.openDictSelector(); // 确保方法存在再调用
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.warn("DictInput组件未加载完成或方法未暴露");
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 处理项目选择结果:传递给labresult子组件新增行
|
|
|
|
|
|
const handleItemSelect = async (selectedItem) => {
|
|
|
|
|
|
// 1. 构造新增行数据
|
|
|
|
|
|
const newRow = {
|
|
|
|
|
|
id: `temp_${Date.now()}_${Math.random().toString(36).substr(2, 8)}`,
|
|
|
|
|
|
xmdh: selectedItem.value,
|
|
|
|
|
|
xmmc: selectedItem.label,
|
|
|
|
|
|
dw: selectedItem.dw || "",
|
|
|
|
|
|
refs: selectedItem.refs || "",
|
|
|
|
|
|
jyrq: tableKey.value.jyrq,
|
|
|
|
|
|
yq: tableKey.value.yq,
|
|
|
|
|
|
ybh: tableKey.value.ybh,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
addRowFromDict(newRow);
|
|
|
|
|
|
// ElMessage.success(`已新增项目:${newRow.xmmc}`);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-17 10:19:20 +08:00
|
|
|
|
// 事件定义
|
2025-05-20 16:34:38 +08:00
|
|
|
|
const emits = defineEmits([
|
2025-09-17 10:19:20 +08:00
|
|
|
|
'fetchLabResults',
|
2025-09-26 17:26:06 +08:00
|
|
|
|
'changeStatus',
|
2025-09-29 17:30:02 +08:00
|
|
|
|
'previewHandle'
|
2025-05-20 16:34:38 +08:00
|
|
|
|
]);
|
2025-09-17 10:19:20 +08:00
|
|
|
|
|
|
|
|
|
|
// 解构props
|
|
|
|
|
|
const { tableData, tableKey, readonly, hasChanges } = toRefs(props);
|
2025-05-20 16:34:38 +08:00
|
|
|
|
const selectedRows = ref([]);
|
|
|
|
|
|
const filteredList = ref([]);
|
|
|
|
|
|
const originalData = ref(JSON.parse(JSON.stringify(props.tableData)));
|
2025-09-17 10:19:20 +08:00
|
|
|
|
const isEnterHandled = ref(false);
|
|
|
|
|
|
const originalCsjgMap = ref({});
|
2025-05-20 16:34:38 +08:00
|
|
|
|
|
2025-09-17 10:19:20 +08:00
|
|
|
|
// 组件挂载时初始化缓存
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
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 getRowUniqueKey = (row) => {
|
2025-10-10 17:35:28 +08:00
|
|
|
|
return row.xmdh;
|
2025-09-17 10:19:20 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-26 17:26:06 +08:00
|
|
|
|
|
2025-09-17 10:19:20 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* csjg输入框回车触发保存
|
|
|
|
|
|
*/
|
2025-10-10 17:35:28 +08:00
|
|
|
|
|
2025-09-17 10:19:20 +08:00
|
|
|
|
const handleCsjgEnter = async (row) => {
|
2025-10-10 17:35:28 +08:00
|
|
|
|
// 获取当前输入值
|
|
|
|
|
|
const currentCsjg = row.csjg ? String(row.csjg).trim() : "";
|
|
|
|
|
|
// 获取原始缓存值
|
|
|
|
|
|
const uniqueKey = getRowUniqueKey(row);
|
|
|
|
|
|
|
|
|
|
|
|
const originalCsjg = originalCsjgMap.value[uniqueKey] || "";
|
|
|
|
|
|
|
|
|
|
|
|
// 判断值是否改变
|
|
|
|
|
|
if (currentCsjg === originalCsjg) return;
|
|
|
|
|
|
// 值已改变,执行保存逻辑
|
2025-09-17 10:19:20 +08:00
|
|
|
|
await saveCsjgChange(row);
|
2025-09-29 17:30:02 +08:00
|
|
|
|
nextTick(() => {
|
|
|
|
|
|
const input = document.activeElement;
|
|
|
|
|
|
if (input.tagName === "INPUT") input.blur();
|
|
|
|
|
|
});
|
2025-09-17 10:19:20 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-26 17:26:06 +08:00
|
|
|
|
|
2025-10-10 17:35:28 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 核心:保存csjg修改(调用API + 失败回滚)
|
|
|
|
|
|
*/
|
|
|
|
|
|
const saveCsjgChange = async (row) => {
|
|
|
|
|
|
const requestParams = {
|
|
|
|
|
|
...row,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (row.id) {
|
|
|
|
|
|
newresult(requestParams).then(response => {
|
|
|
|
|
|
ElMessage.success("结果保存成功");
|
|
|
|
|
|
emits('fetchLabResults');
|
|
|
|
|
|
}).catch(error => {
|
|
|
|
|
|
emits('fetchLabResults');
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
changeresult(requestParams).then(response => {
|
|
|
|
|
|
ElMessage.success("结果保存成功");
|
|
|
|
|
|
emits('fetchLabResults');
|
|
|
|
|
|
}).catch(error => {
|
|
|
|
|
|
emits('fetchLabResults');
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-17 10:19:20 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 处理选择变化
|
|
|
|
|
|
*/
|
2025-09-26 17:26:06 +08:00
|
|
|
|
const handleRowClick = (row) => {
|
|
|
|
|
|
selectedRows.value = [row];
|
2025-05-20 16:34:38 +08:00
|
|
|
|
};
|
2025-09-17 10:19:20 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 新增行
|
|
|
|
|
|
*/
|
2025-05-20 16:34:38 +08:00
|
|
|
|
const handleAdd = () => {
|
|
|
|
|
|
const newRow = {
|
2025-09-17 10:19:20 +08:00
|
|
|
|
// 生成临时ID确保唯一性
|
|
|
|
|
|
id: `temp_${Date.now()}`,
|
|
|
|
|
|
jyrq: tableKey.value?.jyrq,
|
|
|
|
|
|
yq: tableKey.value?.yq,
|
|
|
|
|
|
ybh: tableKey.value?.ybh,
|
|
|
|
|
|
csjg: ""
|
2025-05-20 16:34:38 +08:00
|
|
|
|
};
|
2025-09-17 10:19:20 +08:00
|
|
|
|
|
2025-05-20 16:34:38 +08:00
|
|
|
|
tableData.value.push(newRow);
|
2025-09-17 10:19:20 +08:00
|
|
|
|
|
2025-05-20 16:34:38 +08:00
|
|
|
|
nextTick(() => {
|
2025-09-17 10:19:20 +08:00
|
|
|
|
const tableBody = document.querySelector('.el-table__body-wrapper');
|
|
|
|
|
|
if (tableBody) {
|
|
|
|
|
|
tableBody.scrollTop = tableBody.scrollHeight;
|
2025-05-20 16:34:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-17 10:19:20 +08:00
|
|
|
|
// 聚焦到新行的输入框
|
|
|
|
|
|
const inputs = document.querySelectorAll('.full-width-input .el-input__inner');
|
2025-05-20 16:34:38 +08:00
|
|
|
|
if (inputs.length > 0) {
|
2025-09-17 10:19:20 +08:00
|
|
|
|
inputs[inputs.length - 1].focus();
|
2025-05-20 16:34:38 +08:00
|
|
|
|
}
|
2025-09-17 10:19:20 +08:00
|
|
|
|
|
|
|
|
|
|
updateOriginalCsjgMap();
|
|
|
|
|
|
});
|
2025-05-20 16:34:38 +08:00
|
|
|
|
};
|
2025-09-17 10:19:20 +08:00
|
|
|
|
// 新增行核心方法:接收父组件传递的项目数据
|
|
|
|
|
|
const addRowFromDict = async (rowData) => {
|
|
|
|
|
|
if (!rowData?.xmdh) {
|
|
|
|
|
|
ElMessage.error("项目编码不能为空");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 1. 校验输入数据有效性
|
|
|
|
|
|
if (!rowData || !rowData.xmdh) {
|
|
|
|
|
|
ElMessage.error("新增失败:项目编码不能为空");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 检查是否重复添加同一项目(根据xmdh判断)
|
|
|
|
|
|
const isDuplicate = tableData.value.some(item => item.xmdh === rowData.xmdh);
|
|
|
|
|
|
if (isDuplicate) {
|
|
|
|
|
|
ElMessage.warning(`项目【${rowData.xmmc}】已存在`);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 补全新增行的必要字段(如无则初始化)
|
|
|
|
|
|
const newRow = { ...rowData, csjg: "" };
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 添加到表格数据
|
2025-09-26 17:26:06 +08:00
|
|
|
|
tableData.value.unshift(newRow);
|
2025-09-17 10:19:20 +08:00
|
|
|
|
console.log("子组件新增行:", newRow);
|
|
|
|
|
|
|
2025-09-26 17:26:06 +08:00
|
|
|
|
|
2025-09-17 10:19:20 +08:00
|
|
|
|
// 4. 同步缓存
|
|
|
|
|
|
await nextTick();
|
|
|
|
|
|
updateOriginalCsjgMap();
|
2025-05-20 16:34:38 +08:00
|
|
|
|
|
2025-09-17 10:19:20 +08:00
|
|
|
|
|
|
|
|
|
|
// 5. 自动聚焦
|
|
|
|
|
|
nextTick(() => {
|
2025-09-26 17:26:06 +08:00
|
|
|
|
selectedRows.value = [newRow];
|
|
|
|
|
|
tableRef.value.setCurrentRow(newRow);
|
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
|
tableRef.value.setScrollTop(30 * tableRef.value.length)
|
|
|
|
|
|
})
|
|
|
|
|
|
// const lastInput = document.querySelector(`.el-table__row:last-child .csjg-input .el-input__inner`);
|
|
|
|
|
|
// if (lastInput) lastInput.focus();
|
2025-09-17 10:19:20 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
};
|
2025-09-26 17:26:06 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-09-17 10:19:20 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 保存数据
|
|
|
|
|
|
*/
|
2025-05-20 16:34:38 +08:00
|
|
|
|
const handleSave = () => {
|
|
|
|
|
|
if (hasChanges.value) {
|
|
|
|
|
|
emits('save', props.tableData);
|
2025-09-17 10:19:20 +08:00
|
|
|
|
updateOriginalCsjgMap();
|
|
|
|
|
|
emits("update:hasChanges", false);
|
2025-05-20 16:34:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-26 17:26:06 +08:00
|
|
|
|
|
2025-05-20 16:34:38 +08:00
|
|
|
|
|
2025-09-17 10:19:20 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 批量删除
|
|
|
|
|
|
*/
|
2025-09-26 17:26:06 +08:00
|
|
|
|
const handleBatchDelete = () => {
|
|
|
|
|
|
if (selectedRows.value.length === 0) return ElMessage.warning("请先选择要删除的记录");
|
|
|
|
|
|
const arr = selectedRows.value.filter(row => !row.id);
|
|
|
|
|
|
|
|
|
|
|
|
ElMessageBox.confirm(
|
|
|
|
|
|
`确定要删除选中的 ${selectedRows.value.length} 条记录吗?`,
|
|
|
|
|
|
'提示',
|
|
|
|
|
|
{
|
|
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
|
type: 'warning'
|
|
|
|
|
|
}
|
|
|
|
|
|
).then(() => {
|
|
|
|
|
|
if (arr.length == 0) {
|
|
|
|
|
|
const index = tableData.value.findIndex(item => item.xmdh === selectedRows.value[0].xmdh);
|
|
|
|
|
|
if (index > -1) tableData.value.splice(index, 1);
|
|
|
|
|
|
selectedRows.value = [];
|
|
|
|
|
|
} else {
|
|
|
|
|
|
deleteresult(arr).then(res => {
|
|
|
|
|
|
if (res.code == 0) {
|
|
|
|
|
|
ElMessage.success('删除成功');
|
|
|
|
|
|
emits('fetchLabResults');
|
2025-09-17 10:19:20 +08:00
|
|
|
|
}
|
2025-09-26 17:26:06 +08:00
|
|
|
|
})
|
2025-09-17 10:19:20 +08:00
|
|
|
|
}
|
2025-09-26 17:26:06 +08:00
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
});
|
2025-09-17 10:19:20 +08:00
|
|
|
|
};
|
2025-05-20 16:34:38 +08:00
|
|
|
|
|
2025-09-26 17:26:06 +08:00
|
|
|
|
const printHandle = () => {
|
2025-09-29 17:30:02 +08:00
|
|
|
|
const data = {
|
|
|
|
|
|
jyrq: tableKey.value.jyrq,
|
|
|
|
|
|
yq: tableKey.value.yq,
|
|
|
|
|
|
ybh: tableKey.value.ybh,
|
|
|
|
|
|
sqh: tableKey.value.sqh
|
|
|
|
|
|
}
|
|
|
|
|
|
printListwork(data).then(res => {
|
2025-09-26 17:26:06 +08:00
|
|
|
|
if (res.code == 0) {
|
2025-09-29 17:30:02 +08:00
|
|
|
|
classCom.printBase64PDF(res.data)
|
2025-09-26 17:26:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
2025-05-20 16:34:38 +08:00
|
|
|
|
};
|
2025-09-26 17:26:06 +08:00
|
|
|
|
const previewHandle = () => {
|
2025-09-29 17:30:02 +08:00
|
|
|
|
const data = {
|
|
|
|
|
|
jyrq: tableKey.value.jyrq,
|
|
|
|
|
|
yq: tableKey.value.yq,
|
|
|
|
|
|
ybh: tableKey.value.ybh,
|
|
|
|
|
|
sqh: tableKey.value.sqh
|
|
|
|
|
|
}
|
|
|
|
|
|
printListwork(data).then(res => {
|
|
|
|
|
|
if (res.code == 0) {
|
|
|
|
|
|
emits('previewHandle', res.data);
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
2025-09-17 10:19:20 +08:00
|
|
|
|
};
|
2025-05-20 16:34:38 +08:00
|
|
|
|
|
2025-09-26 17:26:06 +08:00
|
|
|
|
|
2025-09-17 10:19:20 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取行号
|
|
|
|
|
|
*/
|
2025-05-20 16:34:38 +08:00
|
|
|
|
const getRowIndex = (index) => {
|
|
|
|
|
|
return index + 1;
|
|
|
|
|
|
};
|
2025-10-10 17:35:28 +08:00
|
|
|
|
|
2025-09-17 10:19:20 +08:00
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
if (props.tableData.length > 0) {
|
|
|
|
|
|
updateOriginalCsjgMap();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-10-10 17:35:28 +08:00
|
|
|
|
|
2025-09-17 10:19:20 +08:00
|
|
|
|
watch(
|
2025-10-10 17:35:28 +08:00
|
|
|
|
() => props.tableData,
|
|
|
|
|
|
() => {
|
|
|
|
|
|
updateOriginalCsjgMap();
|
2025-09-26 17:26:06 +08:00
|
|
|
|
}
|
2025-09-17 10:19:20 +08:00
|
|
|
|
);
|
2025-05-20 16:34:38 +08:00
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
2025-09-26 17:26:06 +08:00
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
|
.result-container {
|
|
|
|
|
|
height: calc(90vh - 95px);
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
overflow: hidden;
|
2025-05-20 16:34:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 17:26:06 +08:00
|
|
|
|
.flex-between {
|
|
|
|
|
|
height: 32px;
|
2025-05-20 16:34:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 17:26:06 +08:00
|
|
|
|
.custom-table-container {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-table__cell) {
|
|
|
|
|
|
padding: 0 !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.full-width-input .el-input__inner {
|
2025-05-20 16:34:38 +08:00
|
|
|
|
width: 100%;
|
2025-09-17 10:19:20 +08:00
|
|
|
|
height: calc(var(--table-row-height) - 2px);
|
2025-09-26 17:26:06 +08:00
|
|
|
|
padding: 0 8px;
|
|
|
|
|
|
/* 增加内边距提升输入体验 */
|
2025-05-20 16:34:38 +08:00
|
|
|
|
border: 0px solid #dcdfe6;
|
|
|
|
|
|
border-radius: 0;
|
|
|
|
|
|
box-sizing: border-box;
|
2025-09-17 10:19:20 +08:00
|
|
|
|
background-color: transparent;
|
2025-05-20 16:34:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 17:26:06 +08:00
|
|
|
|
.full-width-input .el-input__inner:focus {
|
2025-05-20 16:34:38 +08:00
|
|
|
|
border-color: #409eff;
|
2025-09-17 10:19:20 +08:00
|
|
|
|
box-shadow: 0 0 0 1px rgba(64, 158, 255, 0.2);
|
2025-05-20 16:34:38 +08:00
|
|
|
|
outline: none;
|
|
|
|
|
|
}
|
2025-09-17 10:19:20 +08:00
|
|
|
|
</style>
|