feat: copy pre-transit sample views under production.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-08-17 11:53:29 +08:00
1 parent b8a89a81f9
commit dcf4f83ed0
2 files changed
+1706

No files matched your search

File diff suppressed because it is too large. Load diff
@@ -0,0 +1,284 @@
<!-- 生产管理 — 预产及在途样本 -->
<!-- eslint-disable vue/no-v-model-argument -->
<template>
<div class="page-container">
<section class="panel">
<div class="panel-top">
<h2>预产及在途样本</h2>
</div>
<div class="filter-block">
<el-form :model="searchForm" class="filter-form" @submit.prevent>
<div class="filter-grid">
<el-form-item label="关键词">
<el-input
v-model="searchForm.keyword"
placeholder="姓名/身份证号/电话"
clearable
/>
</el-form-item>
<el-form-item label="来源类型">
<el-select
v-model="searchForm.sourceType"
placeholder="全部"
clearable
style="width: 100%"
>
<el-option label="细胞存储" value="cell_storage" />
<el-option label="科研捐赠" value="research_donation" />
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="createTimeRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="样本采集时间">
<el-date-picker
v-model="sampleCollectTimeRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD"
clearable
style="width: 100%"
/>
</el-form-item>
</div>
<div class="filter-actions-row">
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset">
<el-icon><RefreshLeft /></el-icon>重置
</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch">
<el-icon><Search /></el-icon>搜索
</el-button>
</div>
</div>
</el-form>
</div>
<div class="pre-transit-section">
<div class="panel-top pre-transit-section-head">
<h2 class="title-bar-heading">在途样本</h2>
</div>
<PreTransitProtocolCardList
mode="in_transit"
:rows="inTransitData"
:loading="inTransitLoading"
:pagination="inTransitPagination"
empty-description="暂无在途样本"
@view="handleView"
@page-size-change="onInTransitPageSizeChange"
@page-change="onInTransitPageChange"
/>
</div>
<div class="pre-transit-section">
<div class="panel-top pre-transit-section-head">
<h2 class="title-bar-heading">预产样本</h2>
</div>
<PreTransitProtocolCardList
mode="pre_delivery"
:rows="preDeliveryData"
:loading="preDeliveryLoading"
:pagination="preDeliveryPagination"
empty-description="暂无预产样本"
@view="handleView"
@page-size-change="onPreDeliveryPageSizeChange"
@page-change="onPreDeliveryPageChange"
/>
</div>
</section>
<ProtocolViewDialog
v-model="protocolViewVisible"
:protocol-id="viewProtocolId"
:list-row="protocolViewRow"
/>
<DonationViewDialog
v-model="donationViewVisible"
:donation-id="viewDonationId"
:list-row="donationViewRow"
/>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { Search, RefreshLeft } from '@element-plus/icons-vue'
import PreTransitProtocolCardList from './PreTransitProtocolCardList.vue'
import ProtocolViewDialog from '@/views/cell-storage/protocol/ProtocolViewDialog.vue'
import DonationViewDialog from '@/views/research-donation/list/DonationViewDialog.vue'
import {
fetchPreTransitInTransitList,
fetchPreTransitPreDeliveryList,
type PreTransitProtocolRow
} from '@/api/pre-transit-sample'
import type { CollectionProtocolRow } from '@/api/collection-protocol'
import type { ResearchDonationRow } from '@/api/research-donation'
defineOptions({ name: 'ProductionPreTransitSample' })
const searchForm = reactive({ keyword: '', sourceType: '' })
const createTimeRange = ref<[string, string] | null>(null)
const sampleCollectTimeRange = ref<[string, string] | null>(null)
const inTransitData = ref<PreTransitProtocolRow[]>([])
const preDeliveryData = ref<PreTransitProtocolRow[]>([])
const inTransitLoading = ref(false)
const preDeliveryLoading = ref(false)
const inTransitPagination = reactive({ page: 1, pageSize: 10, total: 0 })
const preDeliveryPagination = reactive({ page: 1, pageSize: 10, total: 0 })
const protocolViewVisible = ref(false)
const donationViewVisible = ref(false)
const viewProtocolId = ref<string | null>(null)
const viewDonationId = ref<string | null>(null)
const protocolViewRow = ref<CollectionProtocolRow | null>(null)
const donationViewRow = ref<ResearchDonationRow | null>(null)
function listParams(page: number, pageSize: number) {
return {
page,
pageSize,
keyword: searchForm.keyword || undefined,
sourceType: searchForm.sourceType || undefined,
createTimeStart: createTimeRange.value?.[0] || undefined,
createTimeEnd: createTimeRange.value?.[1] || undefined,
sampleCollectTimeStart: sampleCollectTimeRange.value?.[0] || undefined,
sampleCollectTimeEnd: sampleCollectTimeRange.value?.[1] || undefined
}
}
async function loadInTransit() {
inTransitLoading.value = true
try {
const result = await fetchPreTransitInTransitList(
listParams(inTransitPagination.page, inTransitPagination.pageSize)
)
const res = (result as Record<string, unknown>) || {}
inTransitData.value = (res.list as PreTransitProtocolRow[]) || []
inTransitPagination.total = Number(res.total) || 0
} finally {
inTransitLoading.value = false
}
}
async function loadPreDelivery() {
preDeliveryLoading.value = true
try {
const result = await fetchPreTransitPreDeliveryList(
listParams(preDeliveryPagination.page, preDeliveryPagination.pageSize)
)
const res = (result as Record<string, unknown>) || {}
preDeliveryData.value = (res.list as PreTransitProtocolRow[]) || []
preDeliveryPagination.total = Number(res.total) || 0
} finally {
preDeliveryLoading.value = false
}
}
async function loadAll() {
await Promise.all([loadInTransit(), loadPreDelivery()])
}
function handleSearch() {
inTransitPagination.page = 1
preDeliveryPagination.page = 1
loadAll()
}
function handleReset() {
Object.assign(searchForm, { keyword: '', sourceType: '' })
createTimeRange.value = null
sampleCollectTimeRange.value = null
handleSearch()
}
function onInTransitPageSizeChange(val: number) {
inTransitPagination.page = 1
inTransitPagination.pageSize = val
loadInTransit()
}
function onInTransitPageChange(val: number) {
inTransitPagination.page = val
loadInTransit()
}
function onPreDeliveryPageSizeChange(val: number) {
preDeliveryPagination.page = 1
preDeliveryPagination.pageSize = val
loadPreDelivery()
}
function onPreDeliveryPageChange(val: number) {
preDeliveryPagination.page = val
loadPreDelivery()
}
function handleView(row: PreTransitProtocolRow) {
const source = String(row.sourceType || 'cell_storage')
if (source === 'research_donation') {
const did = String(row.researchDonationId || '')
if (!did) {
ElMessage.warning('缺少关联捐赠协议单,无法查看')
return
}
viewDonationId.value = did
donationViewRow.value = {
id: did,
motherName: row.motherName,
newbornName: row.newbornName
} as ResearchDonationRow
donationViewVisible.value = true
return
}
const pid = String(row.collectionProtocolId || row.id || '')
if (!pid) {
ElMessage.warning('缺少关联协议单,无法查看')
return
}
viewProtocolId.value = pid
protocolViewRow.value = {
id: pid,
motherName: row.motherName,
newbornName: row.newbornName
} as CollectionProtocolRow
protocolViewVisible.value = true
}
watchDebounced(
[searchForm, createTimeRange, sampleCollectTimeRange],
() => {
inTransitPagination.page = 1
preDeliveryPagination.page = 1
loadAll()
},
{ debounce: 300, deep: true }
)
onMounted(() => {
loadAll()
})
</script>
<style scoped lang="scss">
.pre-transit-section-head {
margin-top: 0;
}
.pre-transit-section + .pre-transit-section {
margin-top: 24px;
padding-top: 8px;
}
</style>