This commit is contained in:
zlwu committed 2026-05-20 09:28:36 +08:00
1 parent e6072457fd
commit be4fab78e1
578 files changed
+174415 -214

No files matched your search

@@ -9,7 +9,7 @@
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">细胞样本类型列表</h2>
<h2>细胞样本类型列表</h2>
</div>
<div class="filter-block">
@@ -34,12 +34,11 @@
<div class="list-toolbar-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
<el-button v-if="hasAuth('add')" class="btn-main" type="primary" @click="handleAdd">
<el-button class="btn-main" type="primary" @click="handleAdd">
<el-icon><Plus /></el-icon>
新增类型
</el-button>
<el-button
v-if="hasAuth('delete')"
class="btn-ghost"
type="danger"
:disabled="selectedRows.length === 0"
@@ -117,8 +116,8 @@
>
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleView(row)"><el-icon><View /></el-icon>查看</el-button>
<el-button v-if="hasAuth('edit')" class="btn-op-item primary" @click="handleEdit(row)">编辑</el-button>
<el-button v-if="hasAuth('delete')" class="btn-op-item" @click="handleDelete(row)">删除</el-button>
<el-button class="btn-op-item primary" @click="handleEdit(row)">编辑</el-button>
<el-button class="btn-op-item" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@@ -219,8 +218,6 @@
fetchDeleteCellSampleType
} from '@/api/admin'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import { useAuth } from '@/hooks/core/useAuth'
const { hasAuth } = useAuth()
defineOptions({ name: 'BizCellSampleType' })
@@ -9,7 +9,7 @@
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集协议号列表</h2>
<h2>采集协议号列表</h2>
</div>
<div class="filter-block">
@@ -34,11 +34,11 @@
<div class="list-toolbar-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
<el-button v-if="hasAuth('add')" class="btn-main" type="primary" @click="handleAdd">
<el-button class="btn-main" type="primary" @click="handleAdd">
<el-icon><Plus /></el-icon>
新增协议号
</el-button>
<el-button v-if="hasAuth('add')" class="btn-ghost" @click="openBatchGenerate">
<el-button class="btn-ghost" @click="openBatchGenerate">
批量生成
</el-button>
<el-button
@@ -56,7 +56,6 @@
批量收回
</el-button>
<el-button
v-if="hasAuth('delete')"
class="btn-ghost"
type="danger"
:disabled="selectedRows.length === 0"
@@ -138,8 +137,8 @@
>
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleView(row)"><el-icon><View /></el-icon>查看</el-button>
<el-button v-if="hasAuth('edit')" class="btn-op-item primary" @click="handleEdit(row)">编辑</el-button>
<el-button v-if="hasAuth('delete')" class="btn-op-item" @click="handleDelete(row)">删除</el-button>
<el-button class="btn-op-item primary" @click="handleEdit(row)">编辑</el-button>
<el-button class="btn-op-item" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@@ -377,8 +376,6 @@
fetchBatchIssueProtocolNos,
fetchBatchRevokeProtocolNos
} from '@/api/admin'
import { useAuth } from '@/hooks/core/useAuth'
const { hasAuth } = useAuth()
defineOptions({ name: 'BizCollectionProtocolNo' })
@@ -9,7 +9,7 @@
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集地区列表</h2>
<h2>采集地区列表</h2>
</div>
<div class="filter-block">
@@ -34,12 +34,11 @@
<div class="list-toolbar-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
<el-button v-if="hasAuth('add')" class="btn-main" type="primary" @click="handleAdd">
<el-button class="btn-main" type="primary" @click="handleAdd">
<el-icon><Plus /></el-icon>
新增地区
</el-button>
<el-button
v-if="hasAuth('delete')"
class="btn-ghost"
type="danger"
:disabled="selectedRows.length === 0"
@@ -114,8 +113,8 @@
<el-button class="btn-op-item primary" @click="openHospitalDialog(row)"
>地区医院配置</el-button
>
<el-button v-if="hasAuth('edit')" class="btn-op-item" @click="handleEdit(row)">编辑</el-button>
<el-button v-if="hasAuth('delete')" class="btn-op-item" @click="handleDelete(row)">删除</el-button>
<el-button class="btn-op-item" @click="handleEdit(row)">编辑</el-button>
<el-button class="btn-op-item" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@@ -346,8 +345,6 @@
fetchUpdateHospital,
fetchDeleteHospital
} from '@/api/admin'
import { useAuth } from '@/hooks/core/useAuth'
const { hasAuth } = useAuth()
defineOptions({ name: 'BizCollectionRegion' })
@@ -9,7 +9,7 @@
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">客户列表</h2>
<h2>客户列表</h2>
</div>
<div class="filter-block">
@@ -38,12 +38,11 @@
<div class="list-toolbar-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
<el-button v-if="hasAuth('add')" class="btn-main" type="primary" @click="handleAdd">
<el-button class="btn-main" type="primary" @click="handleAdd">
<el-icon><Plus /></el-icon>
新增客户
</el-button>
<el-button
v-if="hasAuth('delete')"
class="btn-ghost"
type="danger"
:disabled="selectedRows.length === 0"
@@ -126,8 +125,8 @@
>
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleView(row)"><el-icon><View /></el-icon>查看</el-button>
<el-button v-if="hasAuth('edit')" class="btn-op-item primary" @click="handleEdit(row)">编辑</el-button>
<el-button v-if="hasAuth('delete')" class="btn-op-item" @click="handleDelete(row)">删除</el-button>
<el-button class="btn-op-item primary" @click="handleEdit(row)">编辑</el-button>
<el-button class="btn-op-item" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@@ -236,9 +235,7 @@
fetchDeleteCustomer
} from '@/api/admin'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import { useAuth } from '@/hooks/core/useAuth'
import { sexLabel } from '@/utils/status-tag-registry'
const { hasAuth } = useAuth()
defineOptions({ name: 'BizCustomer' })
@@ -0,0 +1,735 @@
<!-- 保险公司 — 项目价格配置 -->
<!-- eslint-disable vue/no-v-model-argument -->
<template>
<div class="page-container">
<header class="page-head">
<h1>保险公司及项目价格</h1>
<p class="page-desc">维护保险公司基础信息、开票信息及项目价格管理。</p>
</header>
<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.tag" placeholder="全部" clearable style="width: 100%">
<el-option label="正常" value="1" />
<el-option label="停用" value="0" />
</el-select>
</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="list-toolbar">
<div class="list-toolbar-row">
<div class="list-toolbar-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
<el-button class="btn-main" type="primary" @click="handleAdd">
<el-icon><Plus /></el-icon>新增保险公司
</el-button>
</div>
</div>
<div class="list-body list-wrap">
<el-table
class="list-table"
:data="tableData"
v-loading="loading"
stripe
row-key="id"
@selection-change="handleSelectionChange"
@row-dblclick="handleView"
>
<el-table-column type="selection" width="55" align="center" header-align="center" />
<el-table-column
type="index"
label="序号"
width="68"
align="center"
header-align="center"
:index="(i) => (pagination.page - 1) * pagination.pageSize + i + 1"
/>
<el-table-column prop="companyName" label="保险公司名称" min-width="160" align="center" header-align="center" />
<el-table-column prop="companyAddress" label="地址" min-width="180" align="center" header-align="center" />
<el-table-column prop="contactName" label="联系人" min-width="100" align="center" header-align="center" />
<el-table-column prop="contactPhone" label="联系电话" min-width="120" align="center" header-align="center" />
<el-table-column prop="tag" label="状态" width="90" align="center" header-align="center">
<template #default="{ row }">
<el-tag :type="row.status == '1' ? 'success' : 'info'" size="small">{{ row.status == '1' ? '正常' : '停用' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="400" fixed="right" align="center" header-align="center">
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleView(row)"><el-icon><View /></el-icon>查看</el-button>
<el-button class="btn-op-item primary" @click="openItemDialog(row)"><el-icon><Setting /></el-icon>项目价格配置</el-button>
<el-button class="btn-op-item" @click="handleEdit(row)"><el-icon><Edit /></el-icon>编辑</el-button>
<el-button class="btn-op-item" @click="handleDelete(row)"><el-icon><Delete /></el-icon>删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination list-pager-bar">
<el-pagination
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
layout="total, sizes, prev, pager, next"
@size-change="(v) => ((pagination.page = 1), (pagination.pageSize = v), loadData())"
@current-change="(v) => ((pagination.page = v), loadData())"
/>
</div>
</div>
<!-- 新增/编辑保险公司弹窗 -->
<el-dialog
v-model="companyDialogVisible"
:title="companyDialogTitle"
width="720px"
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="companyName">
<el-input v-model="companyForm.companyName" placeholder="请输入保险公司名称" />
</el-form-item>
<el-form-item label="公司地址">
<el-input v-model="companyForm.companyAddress" placeholder="请输入公司地址" />
</el-form-item>
<el-form-item label="联系人">
<el-input v-model="companyForm.contactName" placeholder="请输入联系人" />
</el-form-item>
<el-form-item label="联系电话">
<el-input v-model="companyForm.contactPhone" placeholder="请输入联系电话" />
</el-form-item>
<el-form-item label="状态" prop="tag">
<el-radio-group v-model="companyForm.tag">
<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>
<div class="form-section">
<div class="section-title">开票信息</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.taxNo" 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>
</el-form>
<template #footer>
<el-button class="btn-ghost" @click="companyDialogVisible = false">
<el-icon><Close /></el-icon>取消
</el-button>
<el-button class="btn-main" type="primary" :loading="companySubmitLoading" @click="submitCompany">
<el-icon><Check /></el-icon>确定
</el-button>
</template>
</el-dialog>
<!-- 项目价格配置弹窗 -->
<el-dialog
v-model="itemDialogVisible"
:title="itemDialogTitle"
width="960px"
class="dialog-form-layout insurance-item-config-dialog"
align-center
destroy-on-close
:close-on-click-modal="false"
@closed="onItemDialogClosed"
>
<div class="item-dialog-head">
<span class="muted">当前公司:{{ currentCompanyName }}</span>
</div>
<div class="list-toolbar item-toolbar">
<div class="list-toolbar-row">
<div class="list-toolbar-selected">
已选 <span class="sel-num">{{ itemSelected.length }}</span> 项
</div>
<el-button class="btn-main" type="primary" @click="handleAddItem">
<el-icon><Plus /></el-icon>新增项目
</el-button>
</div>
</div>
<div class="list-body list-wrap item-table-wrap">
<el-table
class="list-table"
:data="itemTable"
v-loading="itemLoading"
stripe
row-key="id"
max-height="460"
@selection-change="onItemSelectionChange"
>
<el-table-column type="selection" width="55" align="center" header-align="center" />
<el-table-column type="index" label="序号" width="68" align="center" header-align="center" />
<el-table-column prop="projectName" label="项目名称" min-width="160" align="center" header-align="center" />
<el-table-column prop="projectFee" label="项目费用(元)" width="120" align="center" header-align="center">
<template #default="{ row }">{{ row.projectFee != null ? `¥${row.projectFee}` : '—' }}</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="90" align="center" header-align="center">
<template #default="{ row }">
<el-tag :type="row.status == '1' ? 'success' : 'info'" size="small">{{ row.status == '1' ? '正常' : '停用' }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="140" align="center" header-align="center" show-overflow-tooltip />
<el-table-column label="操作" width="260" fixed="right" align="center" header-align="center">
<template #default="{ row }">
<el-button class="btn-op-item primary" @click="handleEditItem(row)"><el-icon><Edit /></el-icon>编辑</el-button>
<el-button class="btn-op-item" @click="handleDeleteItem(row)"><el-icon><Delete /></el-icon>删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination list-pager-bar">
<el-pagination
:current-page="itemPagination.page"
:page-size="itemPagination.pageSize"
:total="itemPagination.total"
:page-sizes="[10, 20, 50]"
layout="total, sizes, prev, pager, next"
@size-change="(v) => ((itemPagination.page = 1), (itemPagination.pageSize = v), loadItems())"
@current-change="(v) => ((itemPagination.page = v), loadItems())"
/>
</div>
</div>
<!-- 新增/编辑项目嵌套弹窗 -->
<el-dialog
v-model="itemFormVisible"
:title="itemFormTitle"
width="640px"
class="dialog-form-layout"
align-center
append-to-body
destroy-on-close
:close-on-click-modal="false"
>
<el-form ref="itemFormRef" :model="itemForm" :rules="itemFormRules" label-position="top" class="biz-dialog-form">
<div class="form-grid-2">
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="itemForm.projectName" />
</el-form-item>
<el-form-item label="项目费用(元)" prop="projectFee">
<el-input-number v-model="itemForm.projectFee" :min="0" :precision="2" style="width: 100%" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="itemForm.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="itemForm.remark" type="textarea" :rows="2" />
</el-form-item>
</div>
</el-form>
<template #footer>
<el-button class="btn-ghost" @click="itemFormVisible = false">
<el-icon><Close /></el-icon>取消
</el-button>
<el-button class="btn-main" type="primary" :loading="itemSubmitLoading" @click="submitItem">
<el-icon><Check /></el-icon>确定
</el-button>
</template>
</el-dialog>
<template #footer>
<el-button class="btn-ghost" @click="itemDialogVisible = false">
<el-icon><Close /></el-icon>关闭
</el-button>
</template>
</el-dialog>
<!-- 查看弹窗 -->
<SystemViewDialog
v-model:visible="viewVisible"
title="查看保险公司"
:icon="OfficeBuilding"
:meta="viewCompanyName"
:sections="viewSections"
/>
</section>
</div>
</template>
<script setup lang="ts">
import { Plus, Close, Check, Search, RefreshLeft, View, Setting, Edit, Delete, OfficeBuilding } from '@element-plus/icons-vue'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import type { ViewSection } from '@/components/business/system-view-dialog/index.vue'
import {
fetchInsuranceCompanyList,
fetchCreateInsuranceCompany,
fetchUpdateInsuranceCompany,
fetchDeleteInsuranceCompany,
fetchInsuranceCompanyInvoices,
fetchCreateInsuranceCompanyInvoice,
fetchUpdateInsuranceCompanyInvoice,
fetchDeleteInsuranceCompanyInvoice,
fetchInsuranceProjectPrices,
fetchCreateInsuranceProjectPrice,
fetchUpdateInsuranceProjectPrice,
fetchDeleteInsuranceProjectPrice
} from '@/api/admin'
import { withFullscreenLoading, fullscreenLoadingText } from '@/utils/fullscreen-loading'
defineOptions({ name: 'BasicInfoInsuranceCompany' })
// ---------------------------------------------------------------------------
// 搜索 & 主表
// ---------------------------------------------------------------------------
const searchForm = reactive({ keyword: '', tag: '' })
const tableData = ref<any[]>([])
const selectedRows = ref<any[]>([])
const loading = ref(false)
const pagination = reactive({ page: 1, pageSize: 10, total: 0 })
// ---------------------------------------------------------------------------
// 保险公司弹窗
// ---------------------------------------------------------------------------
const companyDialogVisible = ref(false)
const companyDialogTitle = ref('新增保险公司')
const companyIsEdit = ref(false)
const companySubmitLoading = ref(false)
const companyFormRef = ref()
const editingId = ref<string | null>(null)
const companyForm = reactive({
companyName: '',
companyAddress: '',
contactName: '',
contactPhone: '',
invoiceTitle: '',
taxNo: '',
bankName: '',
bankAccount: '',
tag: 1 as number,
remark: ''
})
const companyFormRules = {
companyName: [{ required: true, message: '请输入保险公司名称', trigger: 'blur' }],
tag: [{ required: true, message: '请选择状态', trigger: 'change' }]
}
// ---------------------------------------------------------------------------
// 项目价格配置弹窗
// ---------------------------------------------------------------------------
const itemDialogVisible = ref(false)
const itemDialogTitle = ref('项目价格配置')
const currentCompanyId = ref('')
const currentCompanyName = ref('')
const itemTable = ref<any[]>([])
const itemSelected = ref<any[]>([])
const itemLoading = ref(false)
const itemPagination = reactive({ page: 1, pageSize: 10, total: 0 })
const itemFormVisible = ref(false)
const itemFormTitle = ref('新增项目')
const itemIsEdit = ref(false)
const itemSubmitLoading = ref(false)
const itemFormRef = ref()
const editingItemId = ref<string | null>(null)
const itemForm = reactive({
projectName: '',
projectFee: 0 as number | null,
status: '1',
remark: ''
})
const itemFormRules = {
projectName: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
status: [{ required: true, message: '请选择状态', trigger: 'change' }]
}
// ---------------------------------------------------------------------------
// 查看弹窗
// ---------------------------------------------------------------------------
const viewVisible = ref(false)
const viewCompanyName = ref('')
const viewSections = ref<ViewSection[]>([])
// ---------------------------------------------------------------------------
// 主表数据加载
// ---------------------------------------------------------------------------
async function loadData() {
loading.value = true
try {
const res = await fetchInsuranceCompanyList({
page: pagination.page,
pageSize: pagination.pageSize,
keyword: searchForm.keyword || undefined,
})
tableData.value = (res as any)?.list || []
pagination.total = (res as any)?.total ?? 0
} finally {
loading.value = false
}
}
function handleSearch() {
pagination.page = 1
loadData()
}
function handleReset() {
searchForm.keyword = ''
searchForm.tag = ''
pagination.page = 1
loadData()
}
function handleSelectionChange(rows: any[]) {
selectedRows.value = rows
}
// ---------------------------------------------------------------------------
// 保险公司弹窗操作
// ---------------------------------------------------------------------------
function resetCompanyForm() {
companyForm.companyName = ''
companyForm.companyAddress = ''
companyForm.contactName = ''
companyForm.contactPhone = ''
companyForm.invoiceTitle = ''
companyForm.taxNo = ''
companyForm.bankName = ''
companyForm.bankAccount = ''
companyForm.tag = 1
companyForm.remark = ''
editingId.value = null
}
function handleAdd() {
companyIsEdit.value = false
companyDialogTitle.value = '新增保险公司'
resetCompanyForm()
companyDialogVisible.value = true
}
async function handleEdit(row: any) {
companyIsEdit.value = true
companyDialogTitle.value = '编辑保险公司'
editingId.value = row.id
companyForm.companyName = row.companyName || ''
companyForm.companyAddress = row.companyAddress || ''
companyForm.contactName = row.contactName || ''
companyForm.contactPhone = row.contactPhone || ''
companyForm.tag = row.status != null ? Number(row.status) : 1
companyForm.remark = row.remark || ''
// 加载开票信息
try {
const invRes = await fetchInsuranceCompanyInvoices(row.id)
const invoices = (invRes as any)?.list || (invRes as any) || []
if (invoices.length > 0) {
const inv = invoices[0]
companyForm.invoiceTitle = inv.invoiceTitle || inv.companyName || ''
companyForm.taxNo = inv.taxNo || ''
companyForm.bankName = inv.bankName || ''
companyForm.bankAccount = inv.bankAccount || ''
} else {
companyForm.invoiceTitle = ''
companyForm.taxNo = ''
companyForm.bankName = ''
companyForm.bankAccount = ''
}
} catch {
companyForm.invoiceTitle = ''
companyForm.taxNo = ''
companyForm.bankName = ''
companyForm.bankAccount = ''
}
companyDialogVisible.value = true
}
async function submitCompany() {
const valid = await companyFormRef.value?.validate?.().catch(() => false)
if (!valid) return
companySubmitLoading.value = true
try {
const payload = {
companyName: companyForm.companyName.trim(),
companyAddress: companyForm.companyAddress?.trim() || undefined,
contactName: companyForm.contactName?.trim() || undefined,
contactPhone: companyForm.contactPhone?.trim() || undefined,
status: String(companyForm.tag),
remark: companyForm.remark?.trim() || undefined
}
if (companyIsEdit.value && editingId.value) {
await fetchUpdateInsuranceCompany(editingId.value, payload)
// 同步开票信息
const invRes = await fetchInsuranceCompanyInvoices(editingId.value)
const invoices = (invRes as any)?.list || (invRes as any) || []
const invoicePayload = {
companyName: companyForm.invoiceTitle?.trim() || undefined,
invoiceTitle: companyForm.invoiceTitle?.trim() || undefined,
taxNo: companyForm.taxNo?.trim() || undefined,
bankName: companyForm.bankName?.trim() || undefined,
bankAccount: companyForm.bankAccount?.trim() || undefined
}
if (invoices.length > 0) {
await fetchUpdateInsuranceCompanyInvoice(invoices[0].id, invoicePayload)
} else if (companyForm.invoiceTitle) {
await fetchCreateInsuranceCompanyInvoice(editingId.value, invoicePayload)
}
ElMessage.success('已保存')
} else {
const newInst = await fetchCreateInsuranceCompany(payload)
// 新增时同步创建开票信息
if ((newInst as any)?.id && companyForm.invoiceTitle?.trim()) {
const invoicePayload = {
companyName: companyForm.invoiceTitle?.trim() || undefined,
invoiceTitle: companyForm.invoiceTitle?.trim() || undefined,
taxNo: companyForm.taxNo?.trim() || undefined,
bankName: companyForm.bankName?.trim() || undefined,
bankAccount: companyForm.bankAccount?.trim() || undefined,
}
await fetchCreateInsuranceCompanyInvoice((newInst as any).id, invoicePayload)
}
ElMessage.success('已新增')
}
companyDialogVisible.value = false
loadData()
} finally {
companySubmitLoading.value = false
}
}
async function handleDelete(row: any) {
try {
await ElMessageBox.confirm(`确定删除「${row.companyName}」?其下属项目价格将一并删除。`, '提示', {
type: 'warning'
})
} catch {
return
}
await withFullscreenLoading(async () => {
await fetchDeleteInsuranceCompany(row.id)
ElMessage.success('已删除')
await loadData()
}, fullscreenLoadingText.delete)
}
// ---------------------------------------------------------------------------
// 查看弹窗
// ---------------------------------------------------------------------------
async function handleView(row: any) {
viewCompanyName.value = row.companyName || ''
const sections: ViewSection[] = [
{
title: '基本信息',
fields: [
{ label: '保险公司名称', value: row.companyName },
{ label: '公司地址', value: row.companyAddress, span: true },
{ label: '联系人', value: row.contactName },
{ label: '联系电话', value: row.contactPhone },
{ label: '状态', value: row.status == '1' ? '正常' : '停用', tagType: row.status == '1' ? 'success' : 'info' },
{ label: '备注', value: row.remark, span: true }
]
}
]
// 加载开票信息
try {
const invRes = await fetchInsuranceCompanyInvoices(row.id)
const invoices = (invRes as any)?.list || (invRes as any) || []
if (invoices.length > 0) {
const inv = invoices[0]
sections.push({
title: '开票信息',
fields: [
{ label: '发票抬头', value: inv.invoiceTitle || inv.companyName },
{ label: '纳税人识别号', value: inv.taxNo },
{ label: '开户银行', value: inv.bankName },
{ label: '银行账号', value: inv.bankAccount }
]
})
}
} catch {
// ignore
}
viewSections.value = sections
viewVisible.value = true
}
// ---------------------------------------------------------------------------
// 项目价格配置弹窗
// ---------------------------------------------------------------------------
function openItemDialog(row: any) {
currentCompanyId.value = row.id
currentCompanyName.value = row.companyName || ''
itemPagination.page = 1
itemSelected.value = []
itemDialogTitle.value = `项目价格配置 — ${row.companyName}`
itemDialogVisible.value = true
loadItems()
}
async function loadItems() {
if (!currentCompanyId.value) return
itemLoading.value = true
try {
const res = await fetchInsuranceProjectPrices(currentCompanyId.value)
const list = Array.isArray(res) ? res : (res as any)?.list || []
itemTable.value = list
itemPagination.total = Array.isArray(res) ? list.length : ((res as any)?.total ?? list.length)
} finally {
itemLoading.value = false
}
}
function onItemDialogClosed() {
currentCompanyId.value = ''
currentCompanyName.value = ''
itemTable.value = []
}
function onItemSelectionChange(rows: any[]) {
itemSelected.value = rows
}
function resetItemForm() {
itemForm.projectName = ''
itemForm.projectFee = 0
itemForm.status = '1'
itemForm.remark = ''
editingItemId.value = null
}
function handleAddItem() {
itemIsEdit.value = false
itemFormTitle.value = '新增项目'
resetItemForm()
itemFormVisible.value = true
}
function handleEditItem(row: any) {
itemIsEdit.value = true
itemFormTitle.value = '编辑项目'
editingItemId.value = row.id
itemForm.projectName = row.projectName || ''
itemForm.projectFee = row.projectFee ?? 0
itemForm.status = row.status != null ? String(row.status) : '1'
itemForm.remark = row.remark || ''
itemFormVisible.value = true
}
async function submitItem() {
const valid = await itemFormRef.value?.validate?.().catch(() => false)
if (!valid) return
itemSubmitLoading.value = true
try {
const payload = {
projectName: itemForm.projectName.trim(),
projectFee: itemForm.projectFee,
status: itemForm.status,
remark: itemForm.remark?.trim() || undefined
}
if (itemIsEdit.value && editingItemId.value) {
await fetchUpdateInsuranceProjectPrice(editingItemId.value, payload)
ElMessage.success('已保存')
} else {
await fetchCreateInsuranceProjectPrice(currentCompanyId.value, payload)
ElMessage.success('已新增')
}
itemFormVisible.value = false
loadItems()
} finally {
itemSubmitLoading.value = false
}
}
async function handleDeleteItem(row: any) {
try {
await ElMessageBox.confirm(`确定删除「${row.projectName}」?`, '提示', { type: 'warning' })
} catch {
return
}
await withFullscreenLoading(async () => {
await fetchDeleteInsuranceProjectPrice(row.id)
ElMessage.success('已删除')
await loadItems()
}, fullscreenLoadingText.delete)
}
onMounted(() => loadData())
</script>
<style scoped lang="scss">
.biz-dialog-form {
:deep(.el-form-item) {
margin-bottom: 0;
}
}
.item-dialog-head {
margin-bottom: 12px;
}
.item-dialog-head .muted {
font-size: 13px;
color: var(--mint-text-muted);
}
.item-toolbar {
margin-bottom: 0;
}
.item-table-wrap {
padding-top: 0;
}
.form-section {
background: #fafafa;
border-radius: 8px;
padding: 20px;
margin: 4px 0;
}
.form-section .section-title {
font-size: 15px;
font-weight: 500;
color: #303133;
margin-bottom: 16px;
padding-bottom: 12px;
padding-left: 10px;
border-bottom: 1px solid #ebeef5;
border-left: 3px solid #10b981;
}
</style>
<!-- 弹窗 teleport 到 body,高度类名需非 scoped -->
<style lang="scss">
.el-dialog.insurance-item-config-dialog.dialog-form-layout {
min-height: min(640px, calc(100vh - 80px));
}
</style>
@@ -9,7 +9,7 @@
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">样本编码列表</h2>
<h2>样本编码列表</h2>
</div>
<div class="filter-block">
@@ -34,11 +34,11 @@
<div class="list-toolbar-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
<el-button v-if="hasAuth('add')" class="btn-main" type="primary" @click="handleAdd">
<el-button class="btn-main" type="primary" @click="handleAdd">
<el-icon><Plus /></el-icon>
新增样本编码
</el-button>
<el-button v-if="hasAuth('add')" class="btn-ghost" @click="openBatchGenerate">
<el-button class="btn-ghost" @click="openBatchGenerate">
批量生成
</el-button>
<el-button
@@ -56,7 +56,6 @@
批量收回
</el-button>
<el-button
v-if="hasAuth('delete')"
class="btn-ghost"
type="danger"
:disabled="selectedRows.length === 0"
@@ -147,8 +146,8 @@
>
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleView(row)"><el-icon><View /></el-icon>查看</el-button>
<el-button v-if="hasAuth('edit')" class="btn-op-item primary" @click="handleEdit(row)">编辑</el-button>
<el-button v-if="hasAuth('delete')" class="btn-op-item" @click="handleDelete(row)">删除</el-button>
<el-button class="btn-op-item primary" @click="handleEdit(row)">编辑</el-button>
<el-button class="btn-op-item" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@@ -392,9 +391,7 @@
fetchBatchIssueSampleCodes,
fetchBatchRevokeSampleCodes
} from '@/api/admin'
import { useAuth } from '@/hooks/core/useAuth'
import { sampleCodeTypeLabel } from '@/utils/status-tag-registry'
const { hasAuth } = useAuth()
defineOptions({ name: 'BizSampleCode' })