This commit is contained in:
zlwu committed 2026-05-22 12:40:22 +08:00
1 parent 320f7e75f0
commit 53d3b21f57
41 files changed
+10854 -7752

No files matched your search

@@ -39,7 +39,7 @@
<div class="section-title">
<div class="section-title-left"><h3>基本信息</h3></div>
</div>
<div class="form-grid">
<div class="form-grid form-grid--col4">
<el-form-item label="协议号" prop="protocolNo">
<el-select
v-model="formData.protocolNoId"
@@ -110,89 +110,89 @@
</el-form-item>
</div>
<!-- 协议附件 -->
<el-form-item label="协议附件" style="margin-top: 18px">
<div class="attachment-upload">
<div class="attachment-list">
<el-upload
ref="attachmentUploadRef"
:auto-upload="false"
:show-file-list="false"
:multiple="true"
accept="image/*,video/*,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.zip,.rar"
@change="handleAttachmentChange"
>
<div class="upload-card">
<el-icon :size="28" color="#10b981"><Plus /></el-icon>
<span class="upload-card-text">上传附件</span>
</div>
</el-upload>
<div
v-for="(file, index) in formData.attachments"
:key="file.id || index"
class="attachment-item"
:class="{ 'is-uploading': file._uploading }"
>
<div
class="attachment-preview"
@click="
isImageFile(file) && file.fileUrl
? handlePreviewAttachment(file)
: undefined
"
<div class="form-grid form-grid--col2 basic-remark-attach-row">
<el-form-item label="备注">
<el-input
v-model="formData.remark"
type="textarea"
:rows="3"
placeholder="可选"
/>
</el-form-item>
<el-form-item label="协议附件">
<div class="attachment-upload">
<div class="attachment-list">
<el-upload
ref="attachmentUploadRef"
:auto-upload="false"
:show-file-list="false"
:multiple="true"
accept="image/*,video/*,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.zip,.rar"
@change="handleAttachmentChange"
>
<template v-if="isImageFile(file) && file.fileUrl">
<img :src="fullFileUrl(file.fileUrl)" :alt="file.fileName" />
</template>
<template v-else-if="isImageFile(file) && !file.fileUrl">
<el-icon :size="24" color="#94a3b8"><Loading /></el-icon>
</template>
<template v-else-if="isVideoFile(file)">
<div class="attachment-preview__icon attachment-preview__icon--video">
<el-icon :size="28"><VideoPlay /></el-icon>
<div class="upload-card">
<el-icon :size="28" color="#10b981"><Plus /></el-icon>
<span class="upload-card-text">上传附件</span>
</div>
</el-upload>
<div
v-for="(file, index) in formData.attachments"
:key="file.id || index"
class="attachment-item"
:class="{ 'is-uploading': file._uploading }"
>
<div
class="attachment-preview"
@click="
isImageFile(file) && file.fileUrl
? handlePreviewAttachment(file)
: undefined
"
>
<template v-if="isImageFile(file) && file.fileUrl">
<img :src="fullFileUrl(file.fileUrl)" :alt="file.fileName" />
</template>
<template v-else-if="isImageFile(file) && !file.fileUrl">
<el-icon :size="24" color="#94a3b8"><Loading /></el-icon>
</template>
<template v-else-if="isVideoFile(file)">
<div class="attachment-preview__icon attachment-preview__icon--video">
<el-icon :size="28"><VideoPlay /></el-icon>
</div>
</template>
<template v-else>
<div class="attachment-preview__icon attachment-preview__icon--doc">
<el-icon :size="28"><Document /></el-icon>
</div>
</template>
</div>
<div class="attachment-footer">
<span class="attachment-name" :title="file.fileName">{{
file.fileName
}}</span>
<div class="attachment-actions">
<el-icon
class="action-btn"
title="下载"
@click="handleDownloadAttachment(file)"
><Download
/></el-icon>
<el-icon
class="action-btn action-btn--danger"
title="删除"
@click="removeAttachment(index)"
><Delete
/></el-icon>
</div>
</template>
<template v-else>
<div class="attachment-preview__icon attachment-preview__icon--doc">
<el-icon :size="28"><Document /></el-icon>
</div>
</template>
</div>
<div class="attachment-footer">
<span class="attachment-name" :title="file.fileName">{{
file.fileName
}}</span>
<div class="attachment-actions">
<el-icon
class="action-btn"
title="下载"
@click="handleDownloadAttachment(file)"
><Download
/></el-icon>
<el-icon
class="action-btn action-btn--danger"
title="删除"
@click="removeAttachment(index)"
><Delete
/></el-icon>
</div>
</div>
</div>
<span class="upload-hint"
>支持图片、视频、PDF、Word、Excel等文件,单文件不超过 20MB</span
>
</div>
<span class="upload-hint"
>支持图片、视频、PDF、Word、Excel等文件,单文件不超过 20MB</span
>
</div>
</el-form-item>
<el-form-item label="备注">
<el-input
v-model="formData.remark"
type="textarea"
:rows="3"
placeholder="可选"
/>
</el-form-item>
</el-form-item>
</div>
</div>
</div>
@@ -527,7 +527,7 @@
</el-button>
</div>
</div>
<div class="form-grid">
<div class="form-grid form-grid--col4">
<el-form-item label="样本类型">
<el-select
v-model="row.sampleTypeId"
@@ -749,7 +749,7 @@
<!-- 缴费主表 -->
<div class="payment-main-card">
<div class="section-subtitle">缴费主表</div>
<div class="form-grid">
<div class="form-grid form-grid--col5">
<el-form-item label="缴费模式">
<el-radio-group v-model="formData.payMode" @change="onPayModeChange">
<el-radio label="dj">趸交</el-radio>
@@ -872,7 +872,7 @@
</div>
<div v-show="detail._expanded" class="detail-body">
<div class="detail-body-inner">
<div class="form-grid">
<div class="form-grid form-grid--col4">
<el-form-item label="应缴费金额(元)">
<el-input
v-model="detail.dueAmount"
@@ -3008,6 +3008,22 @@
&--col2 {
grid-template-columns: repeat(2, 1fr);
}
&--col4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
&--col5 {
grid-template-columns: repeat(5, minmax(0, 1fr));
}
:deep(.el-form-item) {
margin-bottom: 0;
}
}
.basic-remark-attach-row {
margin-top: 16px;
}
.form-col-span-2 {
@@ -3516,6 +3532,18 @@
&--col2 {
grid-template-columns: 1fr;
}
&--col4 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
&--col5 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
&--col2.basic-remark-attach-row {
grid-template-columns: 1fr;
}
}
.client-sub-cards {
@@ -1877,6 +1877,8 @@
/* 储存证:储存证附件 / 制作状态 / 制作日期同一行(在协议附件行下方) */
.storage-cert-info-row {
margin-top: 14px;
padding-top: 14px;
border-top: 1px dashed #e2e8f0;
}
.storage-cert-attachments-item {
@@ -249,7 +249,7 @@
<el-dialog
v-model="dialogVisible"
:title="dialogTitle"
width="960px"
width="1080px"
class="dialog-form-layout"
align-center
destroy-on-close
@@ -264,7 +264,7 @@
scroll-to-error
:scroll-into-view-options="{ behavior: 'smooth', block: 'center' }"
>
<div class="form-grid-3">
<div class="form-grid-4">
<el-form-item label="产品编码" prop="productCode">
<el-input
v-model="formData.productCode"
@@ -334,7 +334,7 @@
</div>
<div class="route-config-right-body">
<el-form label-position="top" class="route-config-step-form">
<div class="form-grid-2">
<div class="form-grid-4">
<el-form-item label="工序名称">
<el-input v-model="selectedStep.processName" @change="saveStepBasic" />
</el-form-item>
@@ -353,7 +353,13 @@
/>
</el-select>
</el-form-item>
<el-form-item label="描述" class="form-col-span-2">
<el-form-item label="设备名称">
<el-input v-model="selectedStep.equipmentName" @change="saveStepBasic" />
</el-form-item>
<el-form-item label="预计时长(min)">
<el-input v-model="selectedStep.estimatedDuration" placeholder="如 2h" @change="saveStepBasic" />
</el-form-item>
<el-form-item label="描述" class="step-form-col-half">
<el-input
v-model="selectedStep.description"
type="textarea"
@@ -362,13 +368,7 @@
@change="saveStepBasic"
/>
</el-form-item>
<el-form-item label="设备名称">
<el-input v-model="selectedStep.equipmentName" @change="saveStepBasic" />
</el-form-item>
<el-form-item label="预计时长(min)">
<el-input v-model="selectedStep.estimatedDuration" placeholder="如 2h" @change="saveStepBasic" />
</el-form-item>
<el-form-item label="关联SOP" class="form-col-span-2">
<el-form-item label="关联SOP" class="step-form-col-half">
<el-select
v-model="sopIdsArr"
multiple
@@ -384,6 +384,16 @@
/>
</el-select>
</el-form-item>
<div
v-if="sopIdsArr.length"
class="step-sop-attachment-row step-form-col-full"
>
<ProtocolAttachmentReadonly
:files="linkedSopAttachmentFiles"
@preview="handleSopAttachmentPreview"
@download="handleSopAttachmentDownload"
/>
</div>
</div>
</el-form>
@@ -715,7 +725,10 @@
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Plus, Delete, Rank, Close, Check, CopyDocument, RefreshLeft, Search } from '@element-plus/icons-vue'
import ProtocolAttachmentReadonly from '@/views/cell-storage/protocol/ProtocolAttachmentReadonly.vue'
import { downloadAttachmentFile } from '@/utils/download-attachment'
import { VueDraggable as draggable } from 'vue-draggable-plus'
import {
fetchProcessRouteList,
@@ -1275,6 +1288,63 @@
saveStepBasic()
}
const minioBaseUrl = (import.meta.env.VITE_MINIO_BASE_URL || '').replace(/\/$/, '')
function sopAttachmentFullUrl(url: string) {
const u = String(url || '').trim()
if (!u) return ''
if (/^https?:\/\//i.test(u)) return u
return minioBaseUrl ? `${minioBaseUrl}/${u.replace(/^\//, '')}` : u
}
function attachmentsFromUrls(urls: string, sopId: string): Array<Record<string, unknown>> {
return urls
.split(',')
.map((u) => u.trim())
.filter(Boolean)
.map((url, i) => ({
id: `${sopId}_url_${i}`,
fileName: decodeURIComponent(url.split('/').pop() || `附件${i + 1}`),
fileUrl: url,
fileType: ''
}))
}
const linkedSopAttachmentFiles = computed(() => {
const ids = sopIdsArr.value
if (!ids?.length) return []
const idSet = new Set(ids)
const files: Array<Record<string, unknown>> = []
for (const sop of sopOptions.value) {
if (!idSet.has(sop.id)) continue
if (sop.attachmentFiles?.length) {
for (const f of sop.attachmentFiles) {
if (!f?.fileUrl) continue
files.push({
id: f.id || `${sop.id}_${f.fileUrl}`,
fileName:
f.fileName ||
decodeURIComponent(String(f.fileUrl).split('/').pop() || '文档'),
fileUrl: f.fileUrl,
fileType: f.fileType || ''
})
}
} else if (sop.sopAttachments) {
files.push(...attachmentsFromUrls(sop.sopAttachments, sop.id))
}
}
return files
})
function handleSopAttachmentPreview(file: Record<string, unknown>) {
const url = sopAttachmentFullUrl(String(file.fileUrl || ''))
if (url) window.open(url, '_blank')
}
function handleSopAttachmentDownload(file: Record<string, unknown>) {
downloadAttachmentFile(file, { fullFileUrl: sopAttachmentFullUrl })
}
// 按分类分组的工艺库(支持搜索过滤)
const filteredProcessLibrary = computed(() => {
const keyword = processSearchKeyword.value?.trim().toLowerCase() || ''
@@ -1835,7 +1905,7 @@
/* 中间面板:步骤列表 */
.route-config-center {
width: 640px;
width: 480px;
flex-shrink: 0;
display: flex;
flex-direction: column;
@@ -2054,4 +2124,57 @@
padding: 16px;
}
}
.form-grid-4 .step-form-col-half {
grid-column: span 2;
}
.step-form-col-full {
grid-column: 1 / -1;
}
.step-sop-attachment-row {
margin-top: -4px;
:deep(.attachment-list) {
gap: 8px;
}
:deep(.attachment-item) {
width: 100px;
}
:deep(.attachment-preview) {
height: 68px;
}
:deep(.attachment-preview__icon) {
width: 36px;
height: 36px;
.el-icon {
font-size: 22px !important;
}
}
:deep(.attachment-footer) {
padding: 4px 6px;
}
:deep(.attachment-name) {
font-size: 10px;
min-height: calc(10px * 1.4 * 2);
}
:deep(.attachment-actions) {
margin-top: 2px;
gap: 6px;
}
:deep(.action-btn) {
width: 20px;
height: 20px;
font-size: 11px;
}
}
</style>
@@ -228,7 +228,7 @@
/>
</el-select>
</el-form-item>
<el-form-item label="描述" class="form-col-span-2">
<el-form-item label="描述">
<el-input
v-model="formData.description"
type="textarea"
@@ -236,8 +236,8 @@
placeholder="请输入描述"
/>
</el-form-item>
<el-form-item label="备注" class="form-col-span-2">
<el-input v-model="formData.remark" placeholder="可选" />
<el-form-item label="备注">
<el-input v-model="formData.remark" type="textarea" :rows="2" placeholder="可选" />
</el-form-item>
</div>
</div>
@@ -240,5 +240,9 @@
overflow: hidden;
padding: 16px;
}
.route-config-center {
width: 480px;
}
}
</style>
@@ -40,7 +40,7 @@
</div>
<div class="route-config-right-body">
<el-form label-position="top" class="route-config-step-form">
<div class="form-grid-2">
<div class="form-grid-4">
<el-form-item label="工序名称">
<el-input v-model="editor.selectedStep.value.processName" />
</el-form-item>
@@ -50,23 +50,33 @@
:label="cat.categoryName || cat.name" :value="cat.id" />
</el-select>
</el-form-item>
<el-form-item label="描述" class="form-col-span-2">
<el-input v-model="editor.selectedStep.value.description" type="textarea" :rows="2"
placeholder="工序描述" />
</el-form-item>
<el-form-item label="设备名称">
<el-input v-model="editor.selectedStep.value.equipmentName" />
</el-form-item>
<el-form-item label="预计时长(min)">
<el-input v-model="editor.selectedStep.value.estimatedDuration" placeholder="如 2h" />
</el-form-item>
<el-form-item label="关联SOP" class="form-col-span-2">
<el-form-item label="描述" class="step-form-col-half">
<el-input v-model="editor.selectedStep.value.description" type="textarea" :rows="2"
placeholder="工序描述" />
</el-form-item>
<el-form-item label="关联SOP" class="step-form-col-half">
<el-select v-model="editor.sopIdsArr.value" multiple placeholder="选择SOP文档" filterable
@change="editor.onSopIdsChange">
<el-option v-for="sop in editor.sopOptions.value" :key="sop.id"
:label="sop.sopName || sop.name" :value="sop.id" />
</el-select>
</el-form-item>
<div
v-if="editor.sopIdsArr.value.length"
class="step-sop-attachment-row step-form-col-full"
>
<ProtocolAttachmentReadonly
:files="linkedSopAttachmentFiles"
@preview="handleSopAttachmentPreview"
@download="handleSopAttachmentDownload"
/>
</div>
</div>
</el-form>
@@ -308,13 +318,73 @@
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Check, Plus, Rank, VideoPlay } from '@element-plus/icons-vue'
import ProtocolAttachmentReadonly from '@/views/cell-storage/protocol/ProtocolAttachmentReadonly.vue'
import { downloadAttachmentFile } from '@/utils/download-attachment'
import { useTaskStepEditor } from './useTaskStepEditor'
defineProps<{
const props = defineProps<{
editor: ReturnType<typeof useTaskStepEditor>
readonly?: boolean
}>()
const minioBaseUrl = (import.meta.env.VITE_MINIO_BASE_URL || '').replace(/\/$/, '')
function sopAttachmentFullUrl(url: string) {
const u = String(url || '').trim()
if (!u) return ''
if (/^https?:\/\//i.test(u)) return u
return minioBaseUrl ? `${minioBaseUrl}/${u.replace(/^\//, '')}` : u
}
function attachmentsFromUrls(urls: string, sopId: string): Array<Record<string, unknown>> {
return urls
.split(',')
.map((u) => u.trim())
.filter(Boolean)
.map((url, i) => ({
id: `${sopId}_url_${i}`,
fileName: decodeURIComponent(url.split('/').pop() || `附件${i + 1}`),
fileUrl: url,
fileType: ''
}))
}
const linkedSopAttachmentFiles = computed(() => {
const ids = props.editor.sopIdsArr.value
if (!ids?.length) return []
const idSet = new Set(ids)
const files: Array<Record<string, unknown>> = []
for (const sop of props.editor.sopOptions.value) {
if (!idSet.has(sop.id)) continue
if (sop.attachmentFiles?.length) {
for (const f of sop.attachmentFiles) {
if (!f?.fileUrl) continue
files.push({
id: f.id || `${sop.id}_${f.fileUrl}`,
fileName:
f.fileName ||
decodeURIComponent(String(f.fileUrl).split('/').pop() || '文档'),
fileUrl: f.fileUrl,
fileType: f.fileType || ''
})
}
} else if (sop.sopAttachments) {
files.push(...attachmentsFromUrls(sop.sopAttachments, sop.id))
}
}
return files
})
function handleSopAttachmentPreview(file: Record<string, unknown>) {
const url = sopAttachmentFullUrl(String(file.fileUrl || ''))
if (url) window.open(url, '_blank')
}
function handleSopAttachmentDownload(file: Record<string, unknown>) {
downloadAttachmentFile(file, { fullFileUrl: sopAttachmentFullUrl })
}
</script>
<style scoped lang="scss">
@@ -326,4 +396,58 @@
gap: 8px;
margin-left: 12px;
}
/* 4 列栅格下各占半行(2/4 列) */
.form-grid-4 .step-form-col-half {
grid-column: span 2;
}
.step-form-col-full {
grid-column: 1 / -1;
}
.step-sop-attachment-row {
margin-top: -4px;
:deep(.attachment-list) {
gap: 8px;
}
:deep(.attachment-item) {
width: 100px;
}
:deep(.attachment-preview) {
height: 68px;
}
:deep(.attachment-preview__icon) {
width: 36px;
height: 36px;
.el-icon {
font-size: 22px !important;
}
}
:deep(.attachment-footer) {
padding: 4px 6px;
}
:deep(.attachment-name) {
font-size: 10px;
min-height: calc(10px * 1.4 * 2);
}
:deep(.attachment-actions) {
margin-top: 2px;
gap: 6px;
}
:deep(.action-btn) {
width: 20px;
height: 20px;
font-size: 11px;
}
}
</style>
@@ -84,7 +84,7 @@
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="840px" class="dialog-form-layout" align-center destroy-on-close :close-on-click-modal="false">
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" class="biz-dialog-form">
<div class="form-grid-2">
<div class="form-grid-3">
<el-form-item label="项目编码" prop="itemCode">
<el-input v-model="formData.itemCode" :disabled="isEdit" />
</el-form-item>
@@ -97,10 +97,12 @@
<el-radio value="0">停用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="描述" class="form-col-span-2">
</div>
<div class="form-grid-2">
<el-form-item label="描述">
<el-input v-model="formData.description" type="textarea" :rows="2" />
</el-form-item>
<el-form-item label="备注" class="form-col-span-2">
<el-form-item label="备注">
<el-input v-model="formData.remark" type="textarea" :rows="2" />
</el-form-item>
</div>
@@ -371,6 +373,10 @@
</script>
<style scoped lang="scss">
.biz-dialog-form .form-grid-3 + .form-grid-2 {
margin-top: 12px;
}
.form-section {
background: #fafafa;
border-radius: 8px;
@@ -220,19 +220,19 @@
>
<div v-if="currentRow" class="sample-reception-readonly">
<h4 class="detail-section-title">样本信息</h4>
<div class="readonly-grid form-grid-2">
<div class="readonly-grid form-grid-3">
<div class="readonly-item"><span class="label">协议号</span>{{ currentRow.protocolNo || '-' }}</div>
<div class="readonly-item"><span class="label">样本编码</span>{{ currentRow.sampleCode || '-' }}</div>
<div class="readonly-item"><span class="label">样本类型</span>{{ currentRow.sampleTypeName || '-' }}</div>
<div class="readonly-item"><span class="label">预计到达</span>{{ currentRow.etaTime || '-' }}</div>
<div class="readonly-item form-col-span-2">
<div class="readonly-item readonly-col-span-2">
<span class="label">客户</span>{{ currentRow.motherName || '-' }} / {{ currentRow.newbornName || '-' }}
</div>
</div>
</div>
<div v-if="currentRow" class="form-section-divider" />
<h4 class="detail-section-title">运输信息</h4>
<div class="readonly-grid form-grid-2">
<div class="readonly-grid form-grid-3">
<div class="readonly-item">
<span class="label">运输方式</span>{{ transportTypeLabel(String(currentRow?.transportType || '')) }}
</div>
@@ -255,7 +255,7 @@
label-position="top"
class="biz-dialog-form"
>
<div class="form-grid-2">
<div class="form-grid-3">
<el-form-item label="样本接收时间" prop="receptionTime">
<el-date-picker
v-model="receiveForm.receptionTime"
@@ -453,7 +453,7 @@
<div class="readonly-item"><span class="label">运输方式</span>{{ entry.transportType === 'kdys' ? '快递运输' : entry.transportType === 'ryxd' ? '人员携带' : '-' }}</div>
</div>
<el-form label-position="top" class="biz-dialog-form">
<div class="form-grid-2">
<div class="form-grid-3">
<el-form-item label="样本接收时间" required>
<el-date-picker
v-model="entry.receptionTime"
@@ -1224,6 +1224,10 @@
}
}
.readonly-grid.form-grid-3 .readonly-item.readonly-col-span-2 {
grid-column: span 2;
}
.check-list {
display: flex;
flex-wrap: wrap;
@@ -101,60 +101,60 @@
<el-dialog
v-model="companyDialogVisible"
:title="companyDialogTitle"
width="720px"
width="920px"
class="dialog-form-layout"
align-center
destroy-on-close
:close-on-click-modal="false"
>
<el-form ref="companyFormRef" :model="companyForm" :rules="companyFormRules" label-position="top" class="biz-dialog-form">
<div class="form-grid-2">
<el-form-item label="公司编码" prop="companyCode">
<el-input v-model="companyForm.companyCode" :disabled="companyIsEdit" placeholder="租户内唯一" />
<div class="form-grid-3">
<el-form-item label="公司编码" prop="companyCode">
<el-input v-model="companyForm.companyCode" :disabled="companyIsEdit" placeholder="租户内唯一" />
</el-form-item>
<el-form-item label="公司名称" prop="companyName">
<el-input v-model="companyForm.companyName" />
</el-form-item>
<el-form-item label="联系人">
<el-input v-model="companyForm.contactName" />
</el-form-item>
<el-form-item label="联系电话">
<el-input v-model="companyForm.contactPhone" />
</el-form-item>
<el-form-item label="地址" class="form-col-span-2-in-grid3">
<el-input v-model="companyForm.address" />
</el-form-item>
</div>
<div class="form-section">
<div class="section-title section-title--static">
<div class="section-title-left"><h3>开票信息</h3></div>
</div>
<div class="form-grid-3">
<el-form-item label="发票抬头">
<el-input v-model="companyForm.invoiceTitle" placeholder="与营业执照一致" />
</el-form-item>
<el-form-item label="公司名称" prop="companyName">
<el-input v-model="companyForm.companyName" />
<el-form-item label="纳税人识别号">
<el-input v-model="companyForm.taxId" placeholder="统一社会信用代码" />
</el-form-item>
<el-form-item label="联系人">
<el-input v-model="companyForm.contactName" />
<el-form-item label="开户银行">
<el-input v-model="companyForm.bankName" placeholder="收款银行全称" />
</el-form-item>
<el-form-item label="联系电话">
<el-input v-model="companyForm.contactPhone" />
</el-form-item>
<el-form-item label="地址" class="form-col-span-2">
<el-input v-model="companyForm.address" />
</el-form-item>
</div>
<div class="form-section">
<div class="section-title section-title--static">
<div class="section-title-left"><h3>开票信息</h3></div>
</div>
<div class="form-grid-2">
<el-form-item label="发票抬头">
<el-input v-model="companyForm.invoiceTitle" placeholder="与营业执照一致" />
</el-form-item>
<el-form-item label="纳税人识别号">
<el-input v-model="companyForm.taxId" placeholder="统一社会信用代码" />
</el-form-item>
<el-form-item label="开户银行">
<el-input v-model="companyForm.bankName" placeholder="收款银行全称" />
</el-form-item>
<el-form-item label="银行账号">
<el-input v-model="companyForm.bankAccount" placeholder="收款账号" />
</el-form-item>
</div>
</div>
<div class="form-grid-2">
<el-form-item label="状态" prop="status">
<el-radio-group v-model="companyForm.status">
<el-radio value="1">启用</el-radio>
<el-radio value="0">停用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" class="form-col-span-2">
<el-input v-model="companyForm.remark" type="textarea" :rows="2" />
<el-form-item label="银行账号">
<el-input v-model="companyForm.bankAccount" placeholder="收款账号" />
</el-form-item>
</div>
</div>
<div class="form-grid-3">
<el-form-item label="状态" prop="status">
<el-radio-group v-model="companyForm.status">
<el-radio value="1">启用</el-radio>
<el-radio value="0">停用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" class="form-col-span-2">
<el-input v-model="companyForm.remark" type="textarea" :rows="2" />
</el-form-item>
</div>
</el-form>
<template #footer>
<el-button class="btn-ghost" @click="companyDialogVisible = false">
@@ -876,6 +876,10 @@
width: 100%;
}
}
.form-grid-3 .form-col-span-2-in-grid3 {
grid-column: span 2;
}
</style>
<!-- 检测项目配置弹窗 teleport 到 body,尺寸类名需非 scoped -->
@@ -39,7 +39,7 @@
<div class="section-title">
<div class="section-title-left"><h3>基本信息</h3></div>
</div>
<div class="form-grid">
<div class="form-grid form-grid--col4">
<el-form-item label="捐赠协议号" prop="donationNoId">
<el-select
v-model="formData.donationNoId"
@@ -444,7 +444,7 @@
</el-button>
</div>
</div>
<div class="form-grid">
<div class="form-grid form-grid--col4">
<el-form-item label="样本类型">
<el-select
v-model="row.sampleTypeId"
@@ -2413,6 +2413,14 @@
&--col2 {
grid-template-columns: repeat(2, 1fr);
}
&--col4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
:deep(.el-form-item) {
margin-bottom: 0;
}
}
.form-col-span-2 {
@@ -2804,6 +2812,10 @@
&--col2 {
grid-template-columns: 1fr;
}
&--col4 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
.client-sub-cards {