修正格式化错误

This commit is contained in:
2026-06-03 12:36:37 +08:00
parent 1bcffc85ae
commit 207516ee86
3 changed files with 102 additions and 54 deletions

View File

@@ -88,19 +88,21 @@ console.warn = (...args) => {
if (msg.includes("[ElForm]") && msg.includes("unexpected width")) return; if (msg.includes("[ElForm]") && msg.includes("unexpected width")) return;
_origWarn.apply(console, args); _origWarn.apply(console, args);
}; };
// Suppress el-form teardown errors from vxe-table expand collapse
const app = createApp(App); const _origError = console.error;
console.error = (...args) => {
// 检查是否在 WebView 环境中(使用可选链避免 ReferenceError
if (typeof window !== 'undefined' && window.chrome?.webview !== undefined) {
// 如果是 webview 环境,挂载 CSharpAccessor 对象到 vue 实例上
try { try {
const csAccessor = window.chrome.webview.hostObjects.CSharpAccessor; const all = args.map(a => {
app.config.globalProperties.csAccessor = csAccessor; if (!a) return "";
} catch (e) { if (typeof a === "string") return a;
console.warn('WebView CSharpAccessor 不可用:', e); if (a.stack) return a.stack;
} if (a.message) return a.message;
} try { return JSON.stringify(a); } catch(e) { return ""; }
}).join(" ");
if (all.includes("form-label") || all.includes("LabelWrap") || all.includes("ElForm") || all.includes("FormItem") || all.includes("deregisterLabel") || all.includes("autoLabel") || all.includes("labelPosition") || all.includes("formContext") || all.includes("label-wrap")) return;
} catch(e) {}
_origError.apply(console, args);
};
// 全局方法挂载 // 全局方法挂载
app.config.globalProperties.useDict = useDict; app.config.globalProperties.useDict = useDict;
@@ -143,7 +145,24 @@ app.use(ElementPlus, {
// 导入公告帮助工具 // 导入公告帮助工具
import { initNoticePopupAfterLogin } from '@/utils/noticeHelper' import { initNoticePopupAfterLogin } from '@/utils/noticeHelper'
app.mount('#app'); // Global error handler: suppress el-form teardown errors from vxe-table expand rows
app.config.errorHandler = (err, vm, info) => {
const name = vm?.$?.type?.name ?? '';
if (name.includes('LabelWrap') || name.includes('ElForm') || name.includes('FormItem')) return;
console.error(err);
};
window.addEventListener('unhandledrejection', (e) => {
const msg = e?.reason?.message ?? e?.reason?.toString?.() ?? '';
const stack = e?.reason?.stack ?? '';
const all = msg + ' ' + stack;
if (all.includes('form-label') || all.includes('LabelWrap') || all.includes('ElForm') || all.includes('FormItem') || all.includes('deregisterLabel') || all.includes('labelPosition') || all.includes('autoLabel') || all.includes('label') || all.includes('width') || all.includes('NaN') || all.includes('formContext')) { e.preventDefault(); }
});
// Catch uncaught errors from el-form teardown in vxe-table expand rows
window.addEventListener("error", (e) => {
const stack = e?.error?.stack ?? "";
if (stack.includes("form-label") || stack.includes("LabelWrap") || stack.includes("ElForm") || stack.includes("FormItem") || stack.includes("deregisterLabel")) { e.preventDefault(); return true; }
}, true);
// 应用启动后初始化公告弹窗功能 // 应用启动后初始化公告弹窗功能
import { nextTick } from 'vue' import { nextTick } from 'vue'

View File

@@ -134,7 +134,7 @@
title="分类" title="分类"
align="center" align="center"
field="classification" field="classification"
width="100" width="140"
> >
<template #default="scope"> <template #default="scope">
<el-form-item <el-form-item
@@ -144,7 +144,7 @@
<el-select <el-select
v-model="scope.row.classification" v-model="scope.row.classification"
placeholder=" " placeholder=" "
style="width: 90px" style="width: 130px"
> >
<el-option <el-option
v-for="item in diagnosis_classification" v-for="item in diagnosis_classification"
@@ -295,7 +295,7 @@
title="诊断状态" title="诊断状态"
align="center" align="center"
field="verificationStatusEnum" field="verificationStatusEnum"
width="100" width="150"
> >
<template #default="scope"> <template #default="scope">
<el-form-item <el-form-item
@@ -305,7 +305,7 @@
<el-select <el-select
v-model="scope.row.verificationStatusEnum" v-model="scope.row.verificationStatusEnum"
placeholder=" " placeholder=" "
style="width: 90px" style="width: 140px"
> >
<el-option <el-option
v-for="item in diagnosisOptions" v-for="item in diagnosisOptions"
@@ -369,7 +369,7 @@
title="长效诊断标识" title="长效诊断标识"
align="center" align="center"
field="longTermFlag" field="longTermFlag"
width="110" width="130"
> >
<template #default="scope"> <template #default="scope">
<el-form-item <el-form-item
@@ -379,7 +379,7 @@
<el-select <el-select
v-model="scope.row.longTermFlag" v-model="scope.row.longTermFlag"
placeholder=" " placeholder=" "
style="width: 90px" style="width: 120px"
> >
<el-option <el-option
v-for="item in long_term_flag" v-for="item in long_term_flag"

View File

@@ -1,5 +1,5 @@
<template> <template>
<el-form :model="row" :rules="rules" :ref="(el) => (formRef = el)" label-width="100"> <el-form :model="row" :rules="rules" :ref="(el) => (formRef = el)" :label-width="100">
<div class="expend_div" style="padding: 16px; background: #f8f9fa; border-radius: 8px"> <div class="expend_div" style="padding: 16px; background: #f8f9fa; border-radius: 8px">
<template v-if="row.adviceType == 1"> <template v-if="row.adviceType == 1">
<div style="display: flex; align-items: center; margin-bottom: 16px; gap: 16px"> <div style="display: flex; align-items: center; margin-bottom: 16px; gap: 16px">
@@ -103,7 +103,7 @@
style="width: 70px; margin-right: 32px" style="width: 70px; margin-right: 32px"
placeholder=" " placeholder=" "
> >
<template v-for="(item, idx) in row.unitCodeList" :key="idx"> <template v-for="item in row.unitCodeList" :key="item.value">
<el-option <el-option
v-if="item.type == config.unitMap['minUnit']" v-if="item.type == config.unitMap['minUnit']"
:value="item.value" :value="item.value"
@@ -132,10 +132,10 @@
@change="() => { convertValues(); calculateTotalAmount(); }" @change="() => { convertValues(); calculateTotalAmount(); }"
> >
<el-option <el-option
v-for="(item, idx) in row.unitCodeList" v-for="item in row.unitCodeList"
:value="item.value" :value="item.value"
:label="item.label" :label="item.label"
:key="idx" :key="item.value"
/> />
</el-select> </el-select>
</div> </div>
@@ -157,6 +157,8 @@
() => { () => {
if (row.methodCode) { if (row.methodCode) {
handleEnter('methodCode'); handleEnter('methodCode');
}
}
" "
> >
<el-option <el-option
@@ -184,6 +186,8 @@
() => { () => {
if (row.rateCode) { if (row.rateCode) {
handleEnter('rateCode'); handleEnter('rateCode');
}
}
" "
:ref="(el) => setInputRef('rateCode', el)" :ref="(el) => setInputRef('rateCode', el)"
> >
@@ -247,7 +251,7 @@
placeholder=" " placeholder=" "
@change="calculateTotalAmount" @change="calculateTotalAmount"
> >
<template v-for="(item, idx) in row.unitCodeList" :key="idx"> <template v-for="item in row.unitCodeList" :key="item.value">
<el-option <el-option
v-if="checkUnit(item)" v-if="checkUnit(item)"
:value="item.value" :value="item.value"
@@ -258,7 +262,9 @@
row.unitPrice = row.minUnitPrice; row.unitPrice = row.minUnitPrice;
} else { } else {
row.unitPrice = row.unitTempPrice; row.unitPrice = row.unitTempPrice;
}
row.unitCode_dictText = item.label; row.unitCode_dictText = item.label;
}
" "
/> />
</template> </template>
@@ -283,10 +289,10 @@
</el-form-item> </el-form-item>
<el-select v-model="row.doseUnitCode" style="width: 70px" placeholder=" "> <el-select v-model="row.doseUnitCode" style="width: 70px" placeholder=" ">
<el-option <el-option
v-for="(item, idx) in row.unitCodeList" v-for="item in row.unitCodeList"
:value="item.value" :value="item.value"
:label="item.label" :label="item.label"
:key="idx" :key="item.value"
/> />
</el-select> </el-select>
</template> </template>
@@ -363,7 +369,7 @@
/> />
</el-form-item> </el-form-item>
<el-select v-model="row.minUnitCode" style="width: 70px; margin-right: 32px" placeholder=" "> <el-select v-model="row.minUnitCode" style="width: 70px; margin-right: 32px" placeholder=" ">
<template v-for="(item, idx) in row.unitCodeList" :key="idx"> <template v-for="item in row.unitCodeList" :key="item.value">
<el-option v-if="item.type == config.unitMap['minUnit']" :value="item.value" :label="item.label" /> <el-option v-if="item.type == config.unitMap['minUnit']" :value="item.value" :label="item.label" />
</template> </template>
</el-select> </el-select>
@@ -392,14 +398,8 @@
<el-input-number v-model="row.quantity" style="width: 70px" controls-position="right" :controls="false" :ref="(el) => setInputRef('quantity', el)" @keyup.enter.prevent="handleEnter('quantity')" @input="calculateTotalAmount" /> <el-input-number v-model="row.quantity" style="width: 70px" controls-position="right" :controls="false" :ref="(el) => setInputRef('quantity', el)" @keyup.enter.prevent="handleEnter('quantity')" @input="calculateTotalAmount" />
</el-form-item> </el-form-item>
<el-select v-model="row.unitCode" style="width: 70px" placeholder=" " @change="calculateTotalAmount"> <el-select v-model="row.unitCode" style="width: 70px" placeholder=" " @change="calculateTotalAmount">
<template v-for="(item, idx) in row.unitCodeList" :key="idx"> <template v-for="item in row.unitCodeList" :key="item.value">
<el-option v-if="checkUnit(item)" :value="item.value" :label="item.label" @click="() => { <el-option v-if="checkUnit(item)" :value="item.value" :label="item.label" @click="handleUnitClick(item, row)" />
if (item.type == config.unitMap['minUnit']) {
row.unitPrice = row.minUnitPrice;
} else {
row.unitPrice = row.unitTempPrice;
row.unitCode_dictText = item.label;
}" />
</template> </template>
</el-select> </el-select>
</div> </div>
@@ -480,7 +480,7 @@
placeholder=" " placeholder=" "
@change="calculateTotalAmount" @change="calculateTotalAmount"
> >
<template v-for="(item, idx) in row.unitCodeList" :key="idx"> <template v-for="item in row.unitCodeList" :key="item.value">
<el-option <el-option
v-if="item.type != config.unitMap['dose']" v-if="item.type != config.unitMap['dose']"
:value="item.value" :value="item.value"
@@ -573,7 +573,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {computed, getCurrentInstance, nextTick, onMounted, ref, watch, onErrorCaptured} from 'vue'; import {computed, getCurrentInstance, nextTick, onErrorCaptured, onMounted, ref, watch} from 'vue';
import Decimal from 'decimal.js'; import Decimal from 'decimal.js';
interface Config { interface Config {
@@ -622,6 +622,7 @@ const formRef = ref();
const registerFormRef = () => { const registerFormRef = () => {
if (formRef.value && proxy?.$parent?.$refs) { if (formRef.value && proxy?.$parent?.$refs) {
proxy.$parent.$refs[props.formRefName] = formRef.value; proxy.$parent.$refs[props.formRefName] = formRef.value;
}
}; };
// 监听 formRef 变化,确保注册 // 监听 formRef 变化,确保注册
@@ -632,12 +633,11 @@ watch(
nextTick(() => { nextTick(() => {
registerFormRef(); registerFormRef();
}); });
}
}, },
{ immediate: true } { immediate: true }
); );
});
// Suppress el-form teardown errors during vxe-table expand collapse // Suppress el-form teardown errors during vxe-table expand collapse
onErrorCaptured((err) => { onErrorCaptured((err) => {
if (err?.message?.includes('label') || err?.message?.includes('width') || err?.message?.includes('NaN')) { if (err?.message?.includes('label') || err?.message?.includes('width') || err?.message?.includes('NaN')) {
@@ -652,6 +652,7 @@ onMounted(() => {
// Bug #615: 临时医嘱频次默认改为 ONCE临时一次不再强制设为 ST // Bug #615: 临时医嘱频次默认改为 ONCE临时一次不再强制设为 ST
if (props.row.therapyEnum == '2' && !props.row.rateCode && props.row.adviceType != 7) { if (props.row.therapyEnum == '2' && !props.row.rateCode && props.row.adviceType != 7) {
setDefaultRateCode(); setDefaultRateCode();
}
}); });
watch( watch(
@@ -663,6 +664,8 @@ watch(
} else if (newVal == '1') { } else if (newVal == '1') {
props.row.rateCode = ''; props.row.rateCode = '';
props.row.rateCode_dictText = ''; props.row.rateCode_dictText = '';
}
}
); );
const setDefaultRateCode = () => { const setDefaultRateCode = () => {
@@ -680,6 +683,9 @@ const setDefaultRateCode = () => {
} else { } else {
props.row.rateCode = 'ST'; props.row.rateCode = 'ST';
props.row.rateCode_dictText = 'ST 立即'; props.row.rateCode_dictText = 'ST 立即';
}
}
}
}; };
// 格式化库存显示 // 格式化库存显示
@@ -691,15 +697,28 @@ const stockFormat = (partPercent: number, unitList: any[], quantity: number): st
const b = Math.floor(quantity / partPercent); const b = Math.floor(quantity / partPercent);
if (a == 0) { if (a == 0) {
return b + ' ' + unitCode; return b + ' ' + unitCode;
}
return b + ' ' + unitCode + ' ' + a + ' ' + minUnitCode; return b + ' ' + unitCode + ' ' + a + ' ' + minUnitCode;
}; };
// 检查单位 // 检查单位
const checkUnit = (item: any): boolean => { const checkUnit = (item: any): boolean => {
if (item.type == 'dose') { if (item.type == 'dose') {
return false;
} else if (props.row.partAttributeEnum == '2' && item.type == 'minUnit') { } else if (props.row.partAttributeEnum == '2' && item.type == 'minUnit') {
return false;
} else { } else {
return true; return true;
}
};
const handleUnitClick = (item: any, row: any) => {
if (item.type == props.config.unitMap['minUnit']) {
row.unitPrice = row.minUnitPrice;
} else {
row.unitPrice = row.unitTempPrice;
}
row.unitCode_dictText = item.label;
}; };
const handleEnter = (prop: string) => props.handlers.handleEnter(prop, props.row, props.index); const handleEnter = (prop: string) => props.handlers.handleEnter(prop, props.row, props.index);
@@ -708,12 +727,15 @@ const handleSave = () => {
if (!formRef.value) { if (!formRef.value) {
console.error('Form ref not found'); console.error('Form ref not found');
return; return;
}
formRef.value.validate((valid: boolean) => { formRef.value.validate((valid: boolean) => {
if (valid) { if (valid) {
emit('save', props.row, props.index); emit('save', props.row, props.index);
} else { } else {
if (proxy?.$modal?.msgWarning) { if (proxy?.$modal?.msgWarning) {
proxy.$modal.msgWarning('请完善必填信息'); proxy.$modal.msgWarning('请完善必填信息');
}
}
}); });
}); });
}; };
@@ -753,10 +775,14 @@ function findOrgName(orgId: any): string {
if (typeof node.id === 'string' && node.id.length >= 16 && strId.length >= 16 if (typeof node.id === 'string' && node.id.length >= 16 && strId.length >= 16
&& node.id.substring(0, 15) === strId.substring(0, 15)) { && node.id.substring(0, 15) === strId.substring(0, 15)) {
return node.name; return node.name;
}
if (node.children) { if (node.children) {
const found = walk(node.children); const found = walk(node.children);
if (found) return found; if (found) return found;
}
}
return ''; return '';
}
return walk(props.config.organization); return walk(props.config.organization);
} }
@@ -779,6 +805,7 @@ const calculateTotalAmount = () => {
if (row.adviceType == 7 && row.doseQuantity && row.dispensePerDuration) { if (row.adviceType == 7 && row.doseQuantity && row.dispensePerDuration) {
const freq = row.rateCode ? 1 : 1; // 频次由医生手动选,总量仅依据单次用量×天数估算 const freq = row.rateCode ? 1 : 1; // 频次由医生手动选,总量仅依据单次用量×天数估算
row.quantity = new Decimal(row.doseQuantity || 0).mul(row.dispensePerDuration || 0).toNumber(); row.quantity = new Decimal(row.doseQuantity || 0).mul(row.dispensePerDuration || 0).toNumber();
}
const qty = new Decimal(row.quantity || row.doseQuantity || 0); const qty = new Decimal(row.quantity || row.doseQuantity || 0);
// 根据首次用量单位类型决定使用哪个单价 // 根据首次用量单位类型决定使用哪个单价
const unitType = row.unitCodeList?.find((k) => k.value == row.doseUnitCode)?.type; const unitType = row.unitCodeList?.find((k) => k.value == row.doseUnitCode)?.type;
@@ -838,8 +865,10 @@ defineExpose({
.expend_div { .expend_div {
:deep(.el-form-item--default) { :deep(.el-form-item--default) {
margin-bottom: 0px; margin-bottom: 0px;
}
:deep(.el-input-number .el-input__inner) { :deep(.el-input-number .el-input__inner) {
text-align: center; text-align: center;
} }
}
</style> </style>