| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505 |
- <template>
- <Dialog v-model="dialogVisible" title="新增" width="80%" @close="handleClosed" scroll>
- <div class="daily-fee-form">
- <el-form
- ref="formRef"
- :model="dataForm"
- :rules="dataRule"
- label-width="100px"
- >
- <el-row>
- <el-col :span="12" :xs="24">
- <el-form-item label="长者姓名" prop="elderId">
- <selectElder v-model="dataForm.elderId" @elder="handleUpdateElder" :tId="dataForm.tenantId" inStatus=""/>
- </el-form-item>
- </el-col>
- <el-col :span="12" :xs="24">
- <el-form-item label="证件号码" prop="idCard">
- <TgInput v-model="dataForm.idCard" disabled />
- </el-form-item>
- </el-col>
- <el-col :span="12" :xs="24">
- <el-form-item label="社会保障卡号" prop="socialSecurityCardNumber">
- <TgInput v-model="dataForm.socialSecurityCardNumber" disabled />
- </el-form-item>
- </el-col>
- <el-col :span="12" :xs="24">
- <el-form-item label="床位号" prop="bedName">
- <TgInput v-model="dataForm.bedName" disabled />
- </el-form-item>
- </el-col>
- <el-col :span="12" :xs="24">
- <el-form-item label="护理等级" prop="nursingLevel">
- <el-select
- v-model="dataForm.nursingLevel"
- placeholder="请选择护理等级"
- disabled
- >
- <el-option
- v-for="(n, i) in nurseLevelList"
- :key="i"
- :label="n.nurseLevelName"
- :value="n.id"
- />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12" :xs="24">
- <el-form-item label="归属账单月" prop="billingMonth">
- <el-date-picker
- v-model="dataForm.billingMonth"
- type="month"
- value-format="YYYY-MM"
- placeholder="请选择日期"
- :style="{ width: '100%' }"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-button type="primary" @click="handleAdd" link class="mb5" :disabled="!dataForm.billingMonth">
- <Icon icon="ep:zoom-in" class="mr-5px" />添加明细
- </el-button>
- <el-table :data="dataForm.medicineRecordList">
- <el-table-column width="55" >
- <template #default="scope">
- <Icon
- class="mt1"
- :size="26"
- color="#f09d31"
- icon="ep:remove"
- @click="handleDelete(scope.$index)"
- />
- </template>
- </el-table-column>
- <el-table-column prop="date" label="序号" width="55">
- <template #default="scope">
- {{ scope.$index + 1 }}
- </template>
- </el-table-column>
- <el-table-column label="药品名称" :width="180">
- <template #default="scope">
- <el-select
- v-model="scope.row.id"
- @change="handleChangeDrug(scope.row)"
- placeholder="请选择药品"
- filterable
- >
- <el-option
- v-for="(n, i) in treeList"
- :key="i"
- :label="n.drugName"
- :value="n.id"
- />
- </el-select>
- </template>
- </el-table-column>
- <el-table-column label="药品批次" :width="200">
- <template #default="scope">
- <el-select
- v-model="scope.row.itemId"
- @change="handleChangeItemName(scope.row)"
- filterable
- >
- <el-option
- v-for="(n, i) in bathList"
- :key="i"
- :label="n.name"
- :value="n.id"
- />
- </el-select>
- </template>
- </el-table-column>
- <el-table-column prop="specification" label="规格" width="100">
- <template #default="scope">
- {{ scope.row.specification }}
- </template>
- </el-table-column>
- <el-table-column prop="productionDate" label="生产日期" width="100">
- <template #default="scope">
- {{ scope.row.productionDate }}
- </template>
- </el-table-column>
- <el-table-column prop="expiryDate" label="有效日期" width="100">
- <template #default="scope">
- {{ scope.row.expiryDate }}
- </template>
- </el-table-column>
- <el-table-column prop="price" label="单价(元)" width="100">
- <template #default="scope">
- <TgInputNumber v-model="scope.row.price" @change="handleChangeNum(scope.row)" disabled />
- </template>
- </el-table-column>
- <el-table-column prop="count" label="数量" width="100">
- <template #default="scope">
- <TgInputNumber
- v-model="scope.row.count"
- :controls="false"
- @change="handleChangeNum(scope.row)"
- />
- </template>
- </el-table-column>
- <el-table-column prop="amount" label="费用(元)" :width="120">
- <template #default="scope">
- {{ formatNum(scope.row.amount) }}
- </template>
- </el-table-column>
- <el-table-column prop="startDate" label="开始日期" width="160">
- <template #default="scope">
- <TgDatePicker v-model="scope.row.startDate" type="date" :clearable="false" :editable="false"/>
- </template>
- </el-table-column>
- <el-table-column prop="endDate" label="结束日期" width="160">
- <template #default="scope">
- <TgDatePicker v-model="scope.row.endDate" type="date" :clearable="false" :editable="false"/>
- </template>
- </el-table-column>
- <el-table-column prop="accountDate" label="记账时间" width="180">
- <template #default="scope">
- {{ formatDate(scope.row.accountDate) }}
- </template>
- </el-table-column>
- <el-table-column prop="remarks" label="备注" :width="180">
- <template #default="scope">
- <TgTextarea v-model="scope.row.remarks" />
- </template>
- </el-table-column>
- </el-table>
- </el-form>
- </div>
- <template #footer>
- <el-button @click="handleClosed">取消</el-button>
- <el-button v-loading="formLoading" type="primary" @click="submitForm" >确定</el-button>
- </template>
- </Dialog>
- </template>
- <script setup lang="ts">
- import {
- getMedicineListByTenant,
- useMedicine
- } from '@/api/elderly/fee/daily-fee'
- import { formatDate } from '@/utils/formatTime'
- import { getNursingLevelPage } from '@/api/elderly/nursing'
- import { useSettingStore } from '@/store/modules/setting'
- import { formatNum } from '@/utils/formatter'
- const message = useMessage() // 消息弹窗
- const { t } = useI18n() // 国际化
- const dialogVisible = ref(false)
- const settingStore = useSettingStore()
- const formLoading = ref(false)
- const formRef = ref()
- const bathList = ref([] as any)
- const treeList = ref([] as any)
- const originalMedicineData = ref([]) // 存储原始数据
- // 护理等级列表
- const nurseLevelList = ref<{ nurseLevelName: string; id: string }[]>([])
- interface DrugFormType {
- elderId: number | undefined
- billingMonth: string
- tenantId: number
- idCard: string
- socialSecurityCardNumber: string
- bedName: string
- nursingLevel: string
- medicineRecordList: DrugTableFormType[]
- }
- interface DrugTableFormType {
- id: number | undefined
- itemId: number | undefined
- yetId:number | undefined
- count: number
- price: number
- amount: number
- startDate: string
- endDate: string
- accountDate: number
- billingMonth: string
- remarks: string
- specification: string
- productionDate: string
- expiryDate: string
- }
- const state = reactive({
- dataForm: {
- elderId: undefined,
- idCard: '',
- socialSecurityCardNumber: '',
- bedName: '',
- nursingLevel: '',
- billingMonth: '',
- medicineRecordList: [],
- tenantId: 0
- } as DrugFormType,
- dataRule: {
- elderId: [
- {
- required: true,
- message: '姓名不能为空',
- trigger: 'blur'
- }
- ],
- billingMonth: [
- {
- required: true,
- message: '归属账单月不能为空',
- trigger: 'blur'
- }
- ],
- }
- })
- defineOptions({ name: 'MedicineForm' })
- const { dataForm, dataRule } = toRefs(state)
- // 获取药品/耗材数据
- const getMedicineList = async () => {
- try {
- const data = await getMedicineListByTenant(dataForm.value.tenantId)
- originalMedicineData.value = data
- // 转换数据格式
- const result = [] as any[]
- // 处理耗材类型数据(数组)
- if (Array.isArray(data[0])) {
- data[0].forEach(item => {
- result.push({
- type: 2,
- drugName: item.drugName,
- expiryDate: item.expiryDate,
- id: item.id,
- originalData: item
- })
- })
- }
- // 处理药品类型数据(对象)
- if (typeof data[1] === 'object' && data[1] !== null) {
- Object.keys(data[1]).forEach(key => {
- if (Array.isArray(data[1][key]) && data[1][key].length > 0) {
- result.push({
- type: 1,
- drugName: key,
- id: data[1][key][0].id, // 使用第一个批次的id作为药品id
- batchData: data[1][key] // 存储所有批次数据
- })
- }
- })
- }
- treeList.value = result
- } catch (error) {
- console.error('获取药品列表失败:', error)
- }
- }
- // 获取护理等级
- const getNurseLevelList = async () => {
- try {
- const data = await getNursingLevelPage({
- pageNum: 1,
- pageSize: 100
- })
- nurseLevelList.value = data.list
- } finally {
- }
- }
- /** 打开弹窗 */
- const open = async (tenantId) => {
- dataForm.value.tenantId = tenantId
- dataForm.value.billingMonth = formatDate(new Date(), 'YYYY-MM')
- getNurseLevelList()
- getMedicineList()
- dialogVisible.value = true
- }
- // 关闭
- const handleClosed = () => {
- dataForm.value = {
- elderId: undefined,
- idCard: '',
- socialSecurityCardNumber: '',
- bedName: '',
- nursingLevel: '',
- billingMonth: '',
- medicineRecordList: [],
- tenantId: 0
- }
- dialogVisible.value = false
- }
- // 添加明细
- const handleAdd = () => {
- // 获取当前日期
- const now = new Date()
- // 获取本月第一天
- const startDate = formatDate(new Date(now.getFullYear(), now.getMonth(), 1), 'YYYY-MM-DD')
- // 获取本月最后一天
- const endDate = formatDate(new Date(now.getFullYear(), now.getMonth() + 1, 0), 'YYYY-MM-DD')
- dataForm.value.medicineRecordList.push({
- id: undefined,
- itemId: undefined,
- yetId: undefined,
- specification: '',
- productionDate: '',
- count: 1,
- amount: 0,
- accountDate: Date.now(),
- remarks: '',
- startDate: startDate,
- endDate: endDate,
- expiryDate: '',
- price: 0,
- billingMonth: dataForm.value.billingMonth,
- })
- }
- // 删除明细
- const handleDelete = (index) => {
- dataForm.value.medicineRecordList.splice(index, 1)
- }
- // 药品选择
- const handleChangeDrug = (row) => {
- // 先清空所有数据
- row.itemId = undefined
- row.yetId = undefined
- row.specification = ''
- row.productionDate = ''
- row.count = 1
- row.amount = 0
- row.accountDate = Date.now()
- row.expiryDate = ''
- row.price = 0
- // 获取选中的药品
- const selectedMedicine = treeList.value.find(item => item.id === row.id)
- if (!selectedMedicine) return
- // 更新药品名称
- if (selectedMedicine.type == 2) {
- // 耗材类型 - 直接填充数据
- const item = selectedMedicine.originalData
- row.price = item.unitPrice
- row.specification = item.specification
- row.productionDate = item.productionDate
- row.expiryDate = item.expiryDate
- row.yetId = item.id // 直接设置itemId
- // 计算金额
- handleChangeNum(row)
- // 清空批次列表
- bathList.value = []
- } else if (selectedMedicine.type === 1) {
- // 药品类型 - 设置批次数据
- bathList.value = selectedMedicine.batchData.map(batch => ({
- ...batch,
- name: `${batch.drugName}(${batch.batchNumber})`,
- id: batch.id
- }))
- // 清空itemId,等待选择批次
- row.itemId = ''
- }
- }
- // 计算金额
- const handleChangeNum = (row) => {
- row.amount = Number(row.count || 0) * Number(row.price || 0)
- }
- // 药品批次选择
- const handleChangeItemName = (row) => {
- let item = bathList.value.find((item) => item.id == row.itemId)
- if (!item) return
- row.yetId = item.id
- row.price = item.unitPrice || item.price
- row.specification = item.specification
- row.productionDate = item.productionDate
- row.expiryDate = item.expiryDate
- handleChangeNum(row)
- }
- // 老人选择
- const handleUpdateElder = async (item) => {
- dataForm.value.elderId = item.id.toString()
- dataForm.value.idCard = item.idCard
- dataForm.value.socialSecurityCardNumber = item.socialSecurityCardNumber
- dataForm.value.bedName = item.bedName
- dataForm.value.nursingLevel = item.nurseLevelId
- }
- /** 提交表单 */
- const submitForm = async () => {
- if(formLoading.value){
- return
- }
- formLoading.value = true
- // 提交请求
- try {
- if(!dataForm.value.medicineRecordList.length){
- message.error('至少添加一条数据')
- return
- }
- // 验证所有行数据
- for (let i = 0; i < dataForm.value.medicineRecordList.length; i++) {
- const row = dataForm.value.medicineRecordList[i]
- if (!row.yetId) {
- message.error(`第 ${i + 1} 行:请选择有效的药品`)
- return
- }
- }
-
- // 校验表单
- if (!formRef.value) return
- const valid = await formRef.value.validate()
- if (!valid) return
-
- let params = { ...JSON.parse(JSON.stringify(dataForm.value)) }
- params = {
- elderId: Number(params.elderId),
- medicineRecordList:params.medicineRecordList
- }
- params.medicineRecordList = params.medicineRecordList.map(item => {
- return {
- id: item.yetId,
- count: Number(item.count),
- price: Number(item.price),
- amount: Number(item.amount),
- startDate: item.startDate,
- endDate: item.endDate,
- accountDate: formatDate(item.accountDate),
- remarks: item.remarks,
- billingMonth: dataForm.value.billingMonth,
- }
- })
- const res = await useMedicine(params)
- if (res) {
- message.success(`操作成功!`)
- handleClosed()
- }
- }catch (e){
- setTimeout(()=>{
- formLoading.value = false
- },500)
- } finally {
- setTimeout(()=>{
- formLoading.value = false
- },500)
- }
- }
- defineExpose({ open }) // 提供 open 方法,用于打开弹窗
- </script>
- <style lang="scss" scoped>
- .w80 {
- width: 250px !important;
- }
- .underline{
- margin-left: 0.5rem;
- padding: 5px;
- background-color: #f2f2f2;
- color: #d5d5d5;
- text-decoration: line-through;
- }
- </style>
|