提交
This commit is contained in:
1 parent
038a60b09e
commit
3740a7dd80
45 files changed
+10945
-6192
No files matched your search
@@ -34,13 +34,41 @@
|
||||
scroll-to-error
|
||||
class="protocol-form"
|
||||
>
|
||||
<!-- Tab 1: 基本信息 -->
|
||||
<div id="form-section-basic" class="form-tab-pane">
|
||||
<!-- Tab 1: 基本信息(新增时左侧一键导入、右侧基本信息) -->
|
||||
<div
|
||||
id="form-section-basic"
|
||||
class="form-tab-pane"
|
||||
:class="{ 'form-tab-pane--import-basic': !isEdit }"
|
||||
>
|
||||
<div v-if="!isEdit" class="section-card section-card--import">
|
||||
<div class="section-title">
|
||||
<div class="section-title-left"><h3>一键导入</h3></div>
|
||||
</div>
|
||||
<el-form-item label="标准信息">
|
||||
<el-input
|
||||
v-model="standardImportText"
|
||||
type="textarea"
|
||||
:rows="12"
|
||||
placeholder="请粘贴标准格式信息,点击「一键导入」填充各 Tab 字段"
|
||||
/>
|
||||
</el-form-item>
|
||||
<div class="import-actions">
|
||||
<el-button
|
||||
class="btn-main"
|
||||
type="primary"
|
||||
:loading="standardImportLoading"
|
||||
@click="handleStandardImport"
|
||||
>
|
||||
<el-icon><Upload /></el-icon>
|
||||
一键导入
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section-card">
|
||||
<div class="section-title">
|
||||
<div class="section-title-left"><h3>基本信息</h3></div>
|
||||
</div>
|
||||
<div class="form-grid form-grid--col4">
|
||||
<div class="form-grid" :class="isEdit ? 'form-grid--col4' : 'form-grid--col2'">
|
||||
<el-form-item label="协议状态" prop="protocolStatus">
|
||||
<el-select
|
||||
v-model="formData.protocolStatus"
|
||||
@@ -673,13 +701,12 @@
|
||||
<div class="detail-body-inner">
|
||||
<div class="form-grid form-grid--col4">
|
||||
<el-form-item label="应缴费金额(元)">
|
||||
<el-input
|
||||
<AmountInput
|
||||
v-model="detail.dueAmount"
|
||||
type="number"
|
||||
step="any"
|
||||
:min="0"
|
||||
disabled
|
||||
style="width: 100%"
|
||||
:disabled="isPayDetailLocked(detail)"
|
||||
placeholder="请输入应缴费金额"
|
||||
@change="onPaymentDetailDueAmountChange(dIdx)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="转账方式">
|
||||
@@ -891,7 +918,8 @@
|
||||
Loading,
|
||||
Download,
|
||||
ArrowDown,
|
||||
ArrowRight
|
||||
ArrowRight,
|
||||
Upload
|
||||
} from '@element-plus/icons-vue'
|
||||
import {
|
||||
fetchCollectionProtocolDetail,
|
||||
@@ -906,6 +934,17 @@
|
||||
useIndexedAttachmentDropZone
|
||||
} from '@/composables/useAttachmentDropZone'
|
||||
import { formatDatetimeToMinute } from '@/utils/chinese-datetime-parse'
|
||||
import {
|
||||
matchExpressCompany,
|
||||
matchSampleTypeByExactName
|
||||
} from '@/utils/donation-standard-import-parse'
|
||||
import {
|
||||
parseProtocolStandardImportText,
|
||||
resolveTransferTypeCode,
|
||||
isBlankString,
|
||||
matchCellSampleType,
|
||||
type ProtocolStandardImportParsed
|
||||
} from '@/utils/protocol-standard-import-parse'
|
||||
import {
|
||||
fetchCustomerList,
|
||||
fetchUserList,
|
||||
@@ -914,6 +953,7 @@
|
||||
fetchItemUnitList,
|
||||
fetchCollectionRegionList,
|
||||
fetchHospitalList,
|
||||
fetchSearchCollectionHospitals,
|
||||
fetchSampleCodeList,
|
||||
fetchExpressCompanyList,
|
||||
fetchSiteList
|
||||
@@ -1165,6 +1205,8 @@
|
||||
const dialogFormLoading = ref(false)
|
||||
const dialogTitle = ref('新增协议单')
|
||||
const isEdit = ref(false)
|
||||
const standardImportText = ref('')
|
||||
const standardImportLoading = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
const editingId = ref<string | null>(null)
|
||||
const formRef = ref()
|
||||
@@ -1302,6 +1344,7 @@
|
||||
expressCompanyOptions.value = []
|
||||
activeFormTab.value = 'basic'
|
||||
lastConfirmedPayMode.value = 'dj'
|
||||
standardImportText.value = ''
|
||||
lastConfirmedFqParams.value = {
|
||||
installmentCount: null,
|
||||
installmentIntervalMonths: null,
|
||||
@@ -1862,7 +1905,6 @@
|
||||
submitLoading.value = true
|
||||
try {
|
||||
syncFqPaymentDetailRowCount(fqPaymentContext(), formData.paymentDetails)
|
||||
syncPaymentDueAmounts()
|
||||
const protocolAttachmentUrls = formData.attachments
|
||||
.map((a) => a.fileUrl)
|
||||
.filter(Boolean)
|
||||
@@ -2246,6 +2288,527 @@
|
||||
ensureSitesInOptions(formData.samples)
|
||||
}
|
||||
|
||||
function formatNowDatetime(): string {
|
||||
const now = new Date()
|
||||
const pad = (n: number) => String(n).padStart(2, '0')
|
||||
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`
|
||||
}
|
||||
|
||||
/** 一键导入前清空上次导入/手填的可覆盖字段(保留协议状态、登记日期、附件等) */
|
||||
function clearFormBeforeStandardImport() {
|
||||
customerId.value = null
|
||||
customerSnapshot.value = null
|
||||
customerOptions.value = []
|
||||
formData.customerId = ''
|
||||
formData.motherName = ''
|
||||
formData.motherPhone = ''
|
||||
formData.motherIdCard = ''
|
||||
formData.motherBirthYm = ''
|
||||
formData.motherEmail = ''
|
||||
formData.motherAddress = ''
|
||||
|
||||
formData.fatherName = ''
|
||||
formData.fatherPhone = ''
|
||||
formData.fatherIdCard = ''
|
||||
formData.newbornName = ''
|
||||
formData.newbornIdCard = ''
|
||||
formData.expectedDeliveryDate = ''
|
||||
|
||||
formData.newbornSex = ''
|
||||
formData.newbornWeightGram = null
|
||||
formData.apgar1min = null
|
||||
formData.apgar5min = null
|
||||
formData.newbornDeliveryTime = ''
|
||||
formData.deliveryMode = ''
|
||||
formData.birthOrder = null
|
||||
|
||||
formData.regionId = ''
|
||||
formData.hospitalId = ''
|
||||
formData.medicalStaff = ''
|
||||
formData.sampleCollectTime = ''
|
||||
formData.maternalBloodCollectTime = ''
|
||||
regionOptions.value = []
|
||||
hospitalOptions.value = []
|
||||
|
||||
collectorUserId.value = null
|
||||
collectorSnapshot.value = null
|
||||
collectorUserOptions.value = []
|
||||
formData.collectorUserId = ''
|
||||
|
||||
salesUserId.value = null
|
||||
salesSnapshot.value = null
|
||||
salesUserOptions.value = []
|
||||
formData.salesUserId = ''
|
||||
|
||||
formData.samples = []
|
||||
sampleCodeOptions.value = []
|
||||
siteOptions.value = []
|
||||
expressCompanyOptions.value = []
|
||||
|
||||
formData.payMode = 'dj'
|
||||
formData.contractAmount = null
|
||||
formData.lumpSumDeadline = ''
|
||||
formData.installmentCount = null
|
||||
formData.installmentIntervalMonths = null
|
||||
formData.installmentStartDate = ''
|
||||
formData.installmentAdvanceDays = DEFAULT_INSTALLMENT_ADVANCE_DAYS
|
||||
formData.installmentRatios = []
|
||||
formData.paymentDetails = []
|
||||
lastConfirmedPayMode.value = 'dj'
|
||||
lastConfirmedFqParams.value = {
|
||||
installmentCount: null,
|
||||
installmentIntervalMonths: null,
|
||||
installmentStartDate: '',
|
||||
installmentAdvanceDays: DEFAULT_INSTALLMENT_ADVANCE_DAYS,
|
||||
installmentRatios: [] as number[]
|
||||
}
|
||||
|
||||
formData.remark = ''
|
||||
}
|
||||
|
||||
async function applyMotherByName(name: string): Promise<'linked' | 'name-only' | 'skipped'> {
|
||||
const keyword = (name || '').trim()
|
||||
if (!keyword) return 'skipped'
|
||||
if (!isBlankString(formData.customerId)) return 'skipped'
|
||||
if (!isBlankString(formData.motherName)) return 'skipped'
|
||||
|
||||
try {
|
||||
const res = await fetchCustomerList({ page: 1, pageSize: 50, keyword })
|
||||
const list = res.list || []
|
||||
const match =
|
||||
list.find((c) => c.customerName === keyword) ||
|
||||
list.find((c) => (c.customerName || '').includes(keyword))
|
||||
if (match) {
|
||||
customerOptions.value = [match, ...list.filter((c) => c.id !== match.id)]
|
||||
onCustomerChange(match.id)
|
||||
return 'linked'
|
||||
}
|
||||
formData.motherName = keyword
|
||||
return 'name-only'
|
||||
} catch {
|
||||
formData.motherName = keyword
|
||||
return 'name-only'
|
||||
}
|
||||
}
|
||||
|
||||
async function applyHospitalByName(name: string): Promise<boolean> {
|
||||
const keyword = (name || '').trim()
|
||||
if (!keyword || !isBlankString(formData.hospitalId)) return false
|
||||
try {
|
||||
const res = await fetchSearchCollectionHospitals({ keyword, limit: 20 })
|
||||
const list = res.list || []
|
||||
const match =
|
||||
list.find((h) => h.hospitalName === keyword) ||
|
||||
list.find((h) => (h.hospitalName || '').includes(keyword)) ||
|
||||
list[0]
|
||||
if (!match) return false
|
||||
|
||||
const regionStub: Api.BizCollectionRegion.RegionItem = {
|
||||
id: match.regionId,
|
||||
regionName: match.regionName || match.regionId,
|
||||
hospitalNames: [],
|
||||
tenantNo: match.tenantNo || '',
|
||||
orderNum: 0,
|
||||
remark: '',
|
||||
createTime: '',
|
||||
updateTime: ''
|
||||
}
|
||||
if (!regionOptions.value.some((r) => r.id === match.regionId)) {
|
||||
regionOptions.value = [regionStub, ...regionOptions.value]
|
||||
}
|
||||
formData.regionId = match.regionId
|
||||
await loadHospitalsByRegion(match.regionId, keyword)
|
||||
if (!hospitalOptions.value.some((h) => h.id === match.id)) {
|
||||
hospitalOptions.value = [match, ...hospitalOptions.value]
|
||||
}
|
||||
formData.hospitalId = match.id
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async function applySalesUserByName(name: string): Promise<boolean> {
|
||||
const keyword = (name || '').trim()
|
||||
if (!keyword) return false
|
||||
try {
|
||||
const res = await fetchUserList({
|
||||
page: 1,
|
||||
pageSize: 50,
|
||||
keyword,
|
||||
status: '1'
|
||||
})
|
||||
const list = res.list || []
|
||||
const match =
|
||||
list.find((u) => u.nickName === keyword) ||
|
||||
list.find((u) => (u.nickName || '').includes(keyword))
|
||||
if (!match) return false
|
||||
applyUserToCollector(match)
|
||||
applyUserToSales(match)
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function applyUserToCollector(u: Api.User.UserItem) {
|
||||
collectorSnapshot.value = { ...u }
|
||||
collectorUserId.value = u.id
|
||||
formData.collectorUserId = u.id
|
||||
if (!collectorUserOptions.value.some((x) => x.id === u.id)) {
|
||||
collectorUserOptions.value = [u, ...collectorUserOptions.value]
|
||||
}
|
||||
}
|
||||
|
||||
function applyUserToSales(u: Api.User.UserItem) {
|
||||
salesSnapshot.value = { ...u }
|
||||
salesUserId.value = u.id
|
||||
formData.salesUserId = u.id
|
||||
if (!salesUserOptions.value.some((x) => x.id === u.id)) {
|
||||
salesUserOptions.value = [u, ...salesUserOptions.value]
|
||||
}
|
||||
}
|
||||
|
||||
async function resolveSampleCodeByCode(code: string) {
|
||||
const keyword = (code || '').trim()
|
||||
if (!keyword) return null
|
||||
const res = await fetchSampleCodeList({ page: 1, pageSize: 50, keyword })
|
||||
const list = (res.list || []) as Api.BizSampleCode.SampleCodeItem[]
|
||||
return (
|
||||
list.find((sc) => sc.sampleCode === keyword) ||
|
||||
list.find((sc) => String(sc.sampleCode || '').includes(keyword)) ||
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
function applyParsedTransportToSample(
|
||||
sample: Record<string, any>,
|
||||
parsed: ProtocolStandardImportParsed,
|
||||
warnings: string[],
|
||||
filledLabels: string[]
|
||||
) {
|
||||
if (!parsed.transportType) return
|
||||
|
||||
const transport = { ...(sample.transport || createEmptyTransport()) }
|
||||
let transportFilled = false
|
||||
|
||||
if (isBlankString(transport.transportType)) {
|
||||
transport.transportType = parsed.transportType
|
||||
transportFilled = true
|
||||
}
|
||||
if (isBlankString(transport.destSiteId) && siteOptions.value.length) {
|
||||
const site = siteOptions.value[0]
|
||||
transport.destSiteId = site.id
|
||||
transportFilled = true
|
||||
}
|
||||
if (parsed.etaTime && isBlankString(transport.etaTime)) {
|
||||
transport.etaTime = parsed.etaTime
|
||||
transportFilled = true
|
||||
} else if (isBlankString(transport.etaTime)) {
|
||||
transport.etaTime = formatNowDatetime()
|
||||
transportFilled = true
|
||||
}
|
||||
if (parsed.transportType === 'kdys' && isBlankString(transport.expressCompanyId)) {
|
||||
const ec = matchExpressCompany(
|
||||
parsed.transportModeText || '顺丰快递',
|
||||
expressCompanyOptions.value
|
||||
)
|
||||
if (ec) {
|
||||
transport.expressCompanyId = ec.id
|
||||
if (!expressCompanyOptions.value.some((x) => x.id === ec.id)) {
|
||||
expressCompanyOptions.value = [ec, ...expressCompanyOptions.value]
|
||||
}
|
||||
transportFilled = true
|
||||
} else {
|
||||
warnings.push(`未找到快递公司「${parsed.transportModeText || ''}」`)
|
||||
}
|
||||
}
|
||||
if (parsed.transportType === 'ryxd' && parsed.carrierName && isBlankString(transport.carrierName)) {
|
||||
transport.carrierName = parsed.carrierName
|
||||
transportFilled = true
|
||||
}
|
||||
sample.transport = transport
|
||||
if (transportFilled) filledLabels.push('运输信息')
|
||||
}
|
||||
|
||||
async function applySampleHintsFromImport(
|
||||
parsed: ProtocolStandardImportParsed,
|
||||
warnings: string[],
|
||||
filledLabels: string[]
|
||||
) {
|
||||
let hints = parsed.sampleHints
|
||||
if (!hints.length) {
|
||||
const matched = matchCellSampleType(parsed.sampleTypeHeader, sampleTypeOptions.value)
|
||||
if (matched) {
|
||||
hints = [{ typeKey: 'hsc', typeName: matched.typeName }]
|
||||
}
|
||||
}
|
||||
|
||||
for (const hint of hints) {
|
||||
const matchedType = matchSampleTypeByExactName(hint.typeName, sampleTypeOptions.value)
|
||||
const sample = normalizeSampleRow({ sampleTypeId: '', sampleStatus: 'ycj' }, formData.samples.length)
|
||||
formData.samples.push(sample)
|
||||
|
||||
if (matchedType) {
|
||||
sample.sampleTypeId = matchedType.id
|
||||
sample.storageYears = matchedType.storageYears ?? null
|
||||
sample.originalPrice = matchedType.storagePrice ?? null
|
||||
sample.price = matchedType.storagePrice ?? null
|
||||
if (!sampleTypeOptions.value.some((x) => x.id === matchedType.id)) {
|
||||
sampleTypeOptions.value = [matchedType, ...sampleTypeOptions.value]
|
||||
}
|
||||
filledLabels.push(hint.typeName)
|
||||
} else {
|
||||
warnings.push(`无法匹配样本类型「${hint.typeName}」`)
|
||||
}
|
||||
|
||||
if (hint.sampleCode) {
|
||||
const sc = await resolveSampleCodeByCode(hint.sampleCode)
|
||||
if (sc) {
|
||||
sample.sampleCodeId = sc.id
|
||||
sample.sampleCode = sc.sampleCode
|
||||
if (!sampleCodeOptions.value.some((x) => x.id === sc.id)) {
|
||||
sampleCodeOptions.value = [sc, ...sampleCodeOptions.value]
|
||||
}
|
||||
filledLabels.push('样本编码')
|
||||
} else {
|
||||
warnings.push(`未找到样本编码「${hint.sampleCode}」`)
|
||||
}
|
||||
}
|
||||
|
||||
applyParsedTransportToSample(sample, parsed, warnings, filledLabels)
|
||||
}
|
||||
}
|
||||
|
||||
function syncFormSamplesAfterImport() {
|
||||
formData.samples = formData.samples.map((s, i) =>
|
||||
normalizeSampleRow(
|
||||
{
|
||||
...s,
|
||||
transport: s.transport ? { ...s.transport } : undefined
|
||||
},
|
||||
i
|
||||
)
|
||||
)
|
||||
hydrateSampleLookupOptions()
|
||||
}
|
||||
|
||||
function applyPaymentFromImport(parsed: ProtocolStandardImportParsed, warnings: string[]) {
|
||||
formData.payMode = parsed.payMode || 'dj'
|
||||
lastConfirmedPayMode.value = formData.payMode as PayMode
|
||||
|
||||
if (parsed.payMode === 'fq') {
|
||||
applyFqPaymentDefaults()
|
||||
}
|
||||
|
||||
if (parsed.contractAmount != null) {
|
||||
formData.contractAmount = parsed.contractAmount
|
||||
}
|
||||
|
||||
const transferTypeCode = resolveTransferTypeCode(
|
||||
parsed.transferTypeLabel || '',
|
||||
transferTypeOptions.value
|
||||
)
|
||||
if (parsed.transferTypeLabel && !transferTypeCode) {
|
||||
warnings.push(`无法匹配转账方式「${parsed.transferTypeLabel}」`)
|
||||
}
|
||||
|
||||
const now = new Date()
|
||||
const pad = (n: number) => String(n).padStart(2, '0')
|
||||
const defaultTime = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`
|
||||
|
||||
formData.paymentDetails = []
|
||||
const transfers = parsed.paymentTransfers.filter((t) => t.transferAmount > 0)
|
||||
|
||||
if (transfers.length) {
|
||||
transfers.forEach((t, i) => {
|
||||
formData.paymentDetails.push({
|
||||
transferType: transferTypeCode,
|
||||
dueAmount: t.transferAmount,
|
||||
transferAmount: t.transferAmount,
|
||||
transferTime: t.transferTime || defaultTime,
|
||||
payStatus: 'dfj',
|
||||
installmentDueDate: formData.payMode === 'dj' ? formData.lumpSumDeadline : '',
|
||||
_expanded: i === 0,
|
||||
attachments: []
|
||||
})
|
||||
})
|
||||
} else if (formData.payMode === 'dj' && formData.contractAmount != null) {
|
||||
addPaymentDetail()
|
||||
const detail = formData.paymentDetails[0]
|
||||
if (detail) {
|
||||
detail.transferType = transferTypeCode
|
||||
detail.dueAmount = formData.contractAmount
|
||||
detail.transferAmount = formData.contractAmount
|
||||
}
|
||||
}
|
||||
|
||||
initPaymentDetailExpandFlags(formData.paymentDetails)
|
||||
markPayDetailLocks(formData.paymentDetails)
|
||||
if (!transfers.length && !(formData.payMode === 'dj' && formData.contractAmount != null)) {
|
||||
syncPaymentDueAmounts()
|
||||
}
|
||||
|
||||
if (parsed.contractAmount != null && transfers.length) {
|
||||
const sum = transfers.reduce((acc, t) => acc + Number(t.transferAmount || 0), 0)
|
||||
if (Math.abs(sum - Number(parsed.contractAmount)) > 0.01) {
|
||||
warnings.push(
|
||||
`转账合计 ${sum} 与合同金额 ${parsed.contractAmount} 不一致,请核对缴费明细`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function handleStandardImport() {
|
||||
const parsed = parseProtocolStandardImportText(standardImportText.value)
|
||||
if (!parsed) {
|
||||
ElMessage.warning('请粘贴有效的标准信息')
|
||||
return
|
||||
}
|
||||
|
||||
standardImportLoading.value = true
|
||||
const warnings: string[] = []
|
||||
const filledLabels: string[] = []
|
||||
|
||||
try {
|
||||
clearFormBeforeStandardImport()
|
||||
await ensureTransferTypeOptions()
|
||||
await remoteSearchSampleTypes('')
|
||||
|
||||
const tasks: Promise<void>[] = []
|
||||
|
||||
if (parsed.motherName) {
|
||||
tasks.push(
|
||||
applyMotherByName(parsed.motherName).then((result) => {
|
||||
if (result === 'linked') filledLabels.push('母亲信息(已关联客户)')
|
||||
else if (result === 'name-only') filledLabels.push('母亲姓名')
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
if (parsed.hospitalName) {
|
||||
tasks.push(
|
||||
applyHospitalByName(parsed.hospitalName).then((ok) => {
|
||||
if (ok) filledLabels.push('采集地区/采集医院')
|
||||
else if (isBlankString(formData.hospitalId)) {
|
||||
warnings.push(`未找到采集医院「${parsed.hospitalName}」`)
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
if (parsed.salesUserName) {
|
||||
tasks.push(
|
||||
applySalesUserByName(parsed.salesUserName).then((ok) => {
|
||||
if (ok) filledLabels.push('采集专员/销售人员')
|
||||
else warnings.push(`未找到销售人员「${parsed.salesUserName}」`)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const needsTransport = !!parsed.transportType
|
||||
if (needsTransport) {
|
||||
tasks.push(remoteSearchSites('').then(() => undefined))
|
||||
if (parsed.transportType === 'kdys') {
|
||||
tasks.push(
|
||||
remoteSearchExpressCompanies(
|
||||
(parsed.transportModeText || '').replace(/快递$/, '') || '顺丰'
|
||||
).then(() => undefined)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(tasks)
|
||||
|
||||
if (parsed.motherPhone) {
|
||||
formData.motherPhone = parsed.motherPhone
|
||||
filledLabels.push('孕妇电话')
|
||||
}
|
||||
if (parsed.newbornSex) {
|
||||
formData.newbornSex = parsed.newbornSex
|
||||
filledLabels.push('新生儿性别')
|
||||
}
|
||||
if (parsed.newbornWeightGram != null) {
|
||||
formData.newbornWeightGram = parsed.newbornWeightGram
|
||||
filledLabels.push('新生儿体重')
|
||||
}
|
||||
if (parsed.apgarScore != null) {
|
||||
formData.apgar1min = parsed.apgarScore
|
||||
filledLabels.push('新生儿评分')
|
||||
}
|
||||
if (parsed.newbornDeliveryTime) {
|
||||
formData.newbornDeliveryTime = parsed.newbornDeliveryTime
|
||||
filledLabels.push('新生儿分娩时间')
|
||||
}
|
||||
if (parsed.sampleCollectTime) {
|
||||
formData.sampleCollectTime = formatDatetimeToMinute(parsed.sampleCollectTime)
|
||||
filledLabels.push('样本采集时间')
|
||||
}
|
||||
if (parsed.maternalBloodExplicitEmpty) {
|
||||
formData.maternalBloodCollectTime = ''
|
||||
filledLabels.push('母血采集时间')
|
||||
} else if (parsed.maternalBloodCollectTime) {
|
||||
formData.maternalBloodCollectTime = formatDatetimeToMinute(parsed.maternalBloodCollectTime)
|
||||
filledLabels.push('母血采集时间')
|
||||
}
|
||||
if (parsed.deliveryMode) {
|
||||
formData.deliveryMode = parsed.deliveryMode
|
||||
filledLabels.push('分娩方式')
|
||||
}
|
||||
if (parsed.birthOrder != null) {
|
||||
formData.birthOrder = parsed.birthOrder
|
||||
filledLabels.push('胎次')
|
||||
}
|
||||
if (parsed.medicalStaff) {
|
||||
formData.medicalStaff = parsed.medicalStaff
|
||||
filledLabels.push('采集医护')
|
||||
}
|
||||
if (parsed.remark) {
|
||||
formData.remark = parsed.remark
|
||||
filledLabels.push('备注')
|
||||
}
|
||||
|
||||
await applySampleHintsFromImport(parsed, warnings, filledLabels)
|
||||
|
||||
if (formData.samples.length) {
|
||||
syncFormSamplesAfterImport()
|
||||
}
|
||||
|
||||
applyPaymentFromImport(parsed, warnings)
|
||||
|
||||
if (parsed.contractAmount != null) {
|
||||
filledLabels.push('合同金额')
|
||||
const sampleTotal = formData.samples.reduce(
|
||||
(sum, s) => sum + (Number(s.price) || 0),
|
||||
0
|
||||
)
|
||||
if (sampleTotal > 0 && Math.abs(sampleTotal - Number(parsed.contractAmount)) > 0.01) {
|
||||
warnings.push(
|
||||
`样本优惠价合计 ${sampleTotal} 与合同金额 ${parsed.contractAmount} 不一致,请核对样本价格`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (parsed.transportModeText && !parsed.transportType) {
|
||||
warnings.push(`无法识别运输方式「${parsed.transportModeText}」`)
|
||||
}
|
||||
|
||||
const uniqueFilled = [...new Set(filledLabels)]
|
||||
if (uniqueFilled.length) {
|
||||
ElMessage.success(`已填充:${uniqueFilled.join('、')}`)
|
||||
} else if (!warnings.length) {
|
||||
ElMessage.info('没有可填充的字段')
|
||||
}
|
||||
if (warnings.length) {
|
||||
ElMessage.warning(warnings.join(';'))
|
||||
}
|
||||
} catch {
|
||||
ElMessage.error('导入失败,请检查标准信息格式')
|
||||
} finally {
|
||||
standardImportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/* ====== 客户检索(母亲信息) ====== */
|
||||
function formatCustomerLabel(c: { customerName: string; phoneNo: string; idCardNo: string }) {
|
||||
const parts = [c.customerName || '']
|
||||
@@ -2554,6 +3117,20 @@
|
||||
handleFqParamsChange()
|
||||
}
|
||||
|
||||
/** 缴费明细应缴金额变更:分期模式下回写分期金额,保持与主表一致 */
|
||||
function onPaymentDetailDueAmountChange(dIdx: number) {
|
||||
if (formData.payMode !== 'fq') return
|
||||
const detail = formData.paymentDetails[dIdx]
|
||||
if (!detail || isPayDetailLocked(detail)) return
|
||||
const installmentNo = Number(detail.installmentNo)
|
||||
const ratioIdx = installmentNo >= 1 ? installmentNo - 1 : dIdx
|
||||
if (!formData.installmentRatios) formData.installmentRatios = []
|
||||
while (formData.installmentRatios.length <= ratioIdx) {
|
||||
formData.installmentRatios.push(0)
|
||||
}
|
||||
formData.installmentRatios[ratioIdx] = Number(detail.dueAmount) || 0
|
||||
}
|
||||
|
||||
const installmentAmountsError = computed(() => {
|
||||
const amounts = formData.installmentRatios || []
|
||||
if (!amounts.length || formData.contractAmount == null) return ''
|
||||
@@ -2867,6 +3444,29 @@
|
||||
&--green {
|
||||
background: #f0fdf4;
|
||||
}
|
||||
|
||||
&--import {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.import-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 0 0 8px;
|
||||
}
|
||||
|
||||
.form-tab-pane--import-basic {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
||||
gap: 16px;
|
||||
align-items: stretch;
|
||||
margin-bottom: 28px;
|
||||
|
||||
.section-card {
|
||||
margin-bottom: 0;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.section-title {
|
||||
@@ -3318,6 +3918,10 @@
|
||||
RESPONSIVE
|
||||
═══════════════════════════════════════════ */
|
||||
@media (max-width: 900px) {
|
||||
.form-tab-pane--import-basic {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.form-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
|
||||
|
||||
Reference in new issue
Block a user