Selaa lähdekoodia

修改月度活动

unknown 2 kuukautta sitten
vanhempi
commit
864dbb232c

+ 2 - 0
src/components/ToggleForm/src/TgSelect.vue

@@ -6,6 +6,7 @@
       :disabled="props.disabled"
       :placeholder="placeholder"
       @change="onHandleSelectChange"
+      :clearable="clearable"
       :multiple="props.multiple"
       :filterable="props.filterable"
       :filter-method="props.filterMethod"
@@ -35,6 +36,7 @@ const props = defineProps({
   dictValue: propTypes.string.def('value'),
   multiple: propTypes.bool.def(false),
   filterable: propTypes.bool.def(true),
+  clearable: propTypes.bool.def(true),
   filterMethod: propTypes.Function
 })
 

+ 181 - 9
src/views/elderly/activity/management/index.vue

@@ -104,16 +104,17 @@
 import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
 import {
   getMonthlyActivityPage,
-  exportMonthlyActivity,
-  deleteMonthlyActivity
+  deleteMonthlyActivity,
+  getActivityExecutionRecordById
 } from '@/api/elderly/activity'
 import { ManagementColumns } from '../column'
 import Form from './Form.vue'
 import Detail from './Detail.vue'
-import download from '@/utils/download'
 import MonthActivity from '../monthly-activities/Form.vue'
-import { dayjs } from 'element-plus'
 import { useUserStore } from '@/store/modules/user'
+import { getAccessToken } from '@/utils/auth'
+import { saveAs } from 'file-saver'
+import ExcelJS from 'exceljs'
 
 defineOptions({ name: 'News' })
 const userStore = useUserStore()
@@ -172,12 +173,183 @@ const openDetail = (row: any = {}) => {
 }
 
 const handleExport = async () => {
-  const res = await exportMonthlyActivity({
-    ...queryParams,
-    pageNo: undefined,
-    pageSize: undefined
+  try {
+    loading.value = true
+
+
+    const listData = await getMonthlyActivityPage({
+      ...queryParams,
+      pageNo: undefined,
+      pageSize: undefined
+    })
+    const exportList = listData.list || []
+
+    const detailPromises = exportList.map((item: any) =>
+      getActivityExecutionRecordById(item.activityId).catch(() => null)
+    )
+    const detailResults = await Promise.all(detailPromises)
+
+    const exportData = exportList.map((item: any, index: number) => {
+      const detail = detailResults[index]
+      return {
+        ...item,
+        activityExecutionRecordDO: detail?.activityExecutionRecordDO || {}
+      }
+    })
+
+    await exportActivityRecordsToExcel(exportData)
+    loading.value=false
+  } catch (error) {
+    console.log(error)
+    loading.value=false
+    message.error('导出失败')
+  } finally {
+    loading.value = false
+  }
+}
+
+const exportActivityRecordsToExcel = async (data: any[]) => {
+  const workbook = new ExcelJS.Workbook()
+  const worksheet = workbook.addWorksheet('活动管理')
+
+  worksheet.columns = [
+    { header: '活动主题', key: 'activityTitle', width: 50 },
+    { header: '活动类型', key: 'activityTypeText', width: 15 },
+    { header: '活动日期', key: 'activityDate', width: 20 },
+    { header: '活动开始时间', key: 'activityStartTime', width: 20 },
+    { header: '活动结束时间', key: 'activityEndTime', width: 20 },
+    { header: '活动地点', key: 'activityAddress', width: 30 },
+    { header: '参与人数', key: 'number', width: 15 },
+    { header: '报名开始时间', key: 'registrationStartTime', width: 20 },
+    { header: '报名结束时间', key: 'registrationEndTime', width: 20 },
+    { header: '状态', key: 'statusText', width: 15 },
+    { header: '负责人', key: 'supervisorName', width: 15 },
+    { header: '创建人', key: 'createdBy', width: 15 },
+    { header: '活动执行记录', key: 'activityRecord', width: 40 },
+    { header: '照片1', key: 'photo1', width: 30 },
+    { header: '照片2', key: 'photo2', width: 30 },
+    { header: '照片3', key: 'photo3', width: 30 },
+    { header: '照片4', key: 'photo4', width: 30 },
+    { header: '照片5', key: 'photo5', width: 30 }
+  ]
+
+  const headerRow = worksheet.getRow(1)
+  headerRow.font = { bold: true, size: 12 }
+  headerRow.fill = {
+    type: 'pattern',
+    pattern: 'solid',
+    fgColor: { argb: 'FFE0E0E0' }
+  }
+  headerRow.alignment = { horizontal: 'center', vertical: 'middle' }
+
+  const activityTypeMap: Record<string, string> = {
+    '1': '节日庆典',
+    '2': '健康讲座',
+    '3': '文艺活动',
+    '4': '体育健身',
+    '5': '志愿服务',
+    '6': '其他'
+  }
+  const statusMap: Record<number, string> = {
+    0: '未开始',
+    1: '进行中',
+    2: '已结束'
+  }
+  console.log("AAAA",data)
+  for (let rowIndex = 0; rowIndex < data.length; rowIndex++) {
+    const item = data[rowIndex]
+
+    const activityDateStr = (item.activityDate && item.activityDate.length==3) ? item.activityDate.join('-') : (item.activityDate??'--')
+
+    const row = worksheet.addRow({
+      activityTitle: item.activityTitle,
+      activityTypeText: activityTypeMap[item.activityType] || item.activityType,
+      activityDate: activityDateStr,
+      activityStartTime: item.activityStartTime,
+      activityEndTime: item.activityEndTime,
+      activityAddress: item.activityAddress,
+      number: item.number,
+      registrationStartTime: item.registrationStartTime,
+      registrationEndTime: item.registrationEndTime,
+      statusText: statusMap[item.status] || item.status,
+      supervisorName: item.supervisorName,
+      createdBy: item.createdBy,
+      activityRecord: item.activityExecutionRecordDO?.activityRecord || ''
+    })
+
+    row.height = 120
+
+    const photosStr = item.activityExecutionRecordDO?.activityImages || '[]'
+    let photos: any[] = []
+    try {
+      photos = JSON.parse(photosStr)
+    } catch (e) {
+      photos = []
+    }
+
+    if (photos.length > 0) {
+      for (let photoIndex = 0; photoIndex < Math.min(photos.length, 5); photoIndex++) {
+        const photo = photos[photoIndex]
+        const photoUrl = photo.fileUrl || ''
+
+        if (photoUrl) {
+          try {
+            const imageBuffer = await fetchImageAsBuffer(photoUrl)
+            if (imageBuffer) {
+              const imageId = workbook.addImage({
+                buffer: imageBuffer,
+                extension: getImageExtension(photoUrl)
+              })
+
+              await worksheet.addImage(imageId, {
+                tl: { col: 13 + photoIndex, row: rowIndex + 1 },
+                ext: { width: 100, height: 100 }
+              })
+            }
+          } catch (e) {
+            console.error('加载图片失败:', photoUrl, e)
+            row.getCell(13 + photoIndex).value = '图片加载失败'
+          }
+        }
+      }
+    }
+
+    row.alignment = { vertical: 'top', wrapText: true }
+  }
+
+  const buffer = await workbook.xlsx.writeBuffer()
+  const blob = new Blob([buffer], {
+    type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
   })
-  download.excel(res, `活动管理${dayjs(new Date()).format('YYYY-MM-DD')}`)
+  saveAs(blob, `活动管理_${new Date().getTime()}.xlsx`)
+}
+
+const fetchImageAsBuffer = async (url: string): Promise<ArrayBuffer | null> => {
+  try {
+    const fullUrl = url.startsWith('http') ? url : `${import.meta.env.VITE_BASE_URL}${url}`
+
+    const response = await fetch(fullUrl, {
+      headers: {
+        Authorization: 'Bearer ' + getAccessToken()
+      }
+    })
+
+    if (!response.ok) {
+      throw new Error(`HTTP error! status: ${response.status}`)
+    }
+
+    return await response.arrayBuffer()
+  } catch (e) {
+    console.error('获取图片失败:', url, e)
+    return null
+  }
+}
+
+const getImageExtension = (url: string): 'png' | 'jpeg' | 'jpg' => {
+  const ext = url.split('.').pop()?.toLowerCase()
+  if (ext === 'png') return 'png'
+  if (ext === 'jpg' || ext === 'jpeg') return 'jpeg'
+  return 'jpeg'
 }
 
 const activityFormRef = ref()

+ 99 - 0
src/views/elderly/activity/monthly-activities/index.vue

@@ -20,7 +20,13 @@
         <TenantSelect v-model="queryParams.tenantIds" placeholder="请选择机构名称" prop="tenantIds" @change="changeMonth" />
         <el-form-item label="活动月份" class="!w-240px">
           <TgDatePicker type="month" v-model="queryParams.month" @change="changeMonth" />
+
+        </el-form-item>
+        <el-form-item label="" class="!w-240px">
+          <el-button type="warning" @click="exportPort">导 出</el-button>
+
         </el-form-item>
+
       </el-form>
     </div>
   </ContentWrap>
@@ -72,6 +78,10 @@ import Form from './Form.vue'
 import { formatTime } from '@/utils'
 import { formatDate } from '@/utils/formatTime'
 import { useUserStore } from '@/store/modules/user'
+import ExcelJS from 'exceljs'
+import { saveAs } from 'file-saver'
+import { getAccessToken } from '@/utils/auth'
+import { dayjs } from 'element-plus'
 const userStore = useUserStore()
 const formRef = ref()
 const openForm = (row: any = {}, detail: boolean = false) => {
@@ -129,6 +139,84 @@ const getTenantList = async () => {
   // }
 }
 
+const exportPort = async () => {
+  const params = new URLSearchParams()
+  params.append('month', queryParams.month)
+  queryParams.tenantIds.map(item => {
+    params.append('tenantIds', item)
+  })
+  const listData = await getMonthlyActivityByMonth(params)
+  const exportList = listData || []
+
+  const workbook = new ExcelJS.Workbook()
+  const worksheet = workbook.addWorksheet('月度活动')
+
+  const activityTypeMap: Record<string, string> = {
+    '1': '节日庆典',
+    '2': '健康讲座',
+    '3': '文艺活动',
+    '4': '体育健身',
+    '5': '志愿服务',
+    '6': '其他'
+  }
+  const statusMap: Record<number, string> = {
+    0: '未开始',
+    1: '进行中',
+    2: '已结束'
+  }
+
+  worksheet.columns = [
+    { header: '活动主题', key: 'activityTitle', width: 50 },
+    { header: '活动类型', key: 'activityTypeText', width: 15 },
+    { header: '活动日期', key: 'activityDate', width: 20 },
+    { header: '活动开始时间', key: 'activityStartTime', width: 20 },
+    { header: '活动结束时间', key: 'activityEndTime', width: 20 },
+    { header: '活动地点', key: 'activityAddress', width: 30 },
+    { header: '参与人数', key: 'number', width: 15 },
+    { header: '报名开始时间', key: 'registrationStartTime', width: 20 },
+    { header: '报名结束时间', key: 'registrationEndTime', width: 20 },
+    { header: '状态', key: 'statusText', width: 15 },
+    { header: '负责人', key: 'supervisorName', width: 15 },
+    { header: '创建人', key: 'createdBy', width: 15 },
+    { header: '活动说明', key: 'remarks', width: 60 }
+  ]
+
+  const headerRow = worksheet.getRow(1)
+  headerRow.font = { bold: true, size: 12 }
+  headerRow.fill = {
+    type: 'pattern',
+    pattern: 'solid',
+    fgColor: { argb: 'FFE0E0E0' }
+  }
+  headerRow.alignment = { horizontal: 'center', vertical: 'middle' }
+
+  for (let i = 0; i < exportList.length; i++) {
+    const item = exportList[i]
+    const row = worksheet.addRow({
+      activityTitle: item.activityTitle,
+      activityTypeText: activityTypeMap[item.activityType] || item.activityType,
+      activityDate: item.activityDate,
+      activityStartTime: item.activityStartTime,
+      activityEndTime: item.activityEndTime,
+      activityAddress: item.activityAddress,
+      number: item.number,
+      registrationStartTime: item.registrationStartTime,
+      registrationEndTime: item.registrationEndTime,
+      statusText: statusMap[item.status] || item.status,
+      supervisorName: item.supervisorName,
+      createdBy: item.createdBy,
+      remarks: item.remarks
+    })
+    row.alignment = { vertical: 'top', wrapText: true }
+  }
+
+  const buffer = await workbook.xlsx.writeBuffer()
+  const blob = new Blob([buffer], {
+    type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+  })
+  saveAs(blob, `月度活动_${queryParams.month}_${dayjs().format('YYYY-MM-DD')}.xlsx`)
+}
+
 const calendarMonth = ref()
 const monthInfo = ref({})
 const queryParams = reactive({
@@ -163,6 +251,17 @@ const getList = async () => {
   monthInfo.value = dataInfo
 }
 
+// // 在 script setup 中添加
+// watch(calendarMonth, (newVal) => {
+//   if (newVal) {
+//     // formatDate 是你已经引入的工具函数,格式化为 'YYYY-MM'
+//     queryParams.month = formatDate(newVal, 'YYYY-MM')
+//     console.log(queryParams.month)
+//     // 如果 formatDate 不合适,也可以手动格式化:
+//     // queryParams.month = dayjs(newVal).format('YYYY-MM')
+//   }
+// })
+
 const changeMonth = () => {
   calendarMonth.value = queryParams.month
   getList()

+ 16 - 0
src/views/elderly/elder/bed-change/index.vue

@@ -16,6 +16,21 @@
       <el-form-item label="床位号" prop="expectId">
         <SelectRoom v-model="queryParams.expectId" placeholder="请输入床位号" class="!w-240px" :tId="queryParams.tenantIds"/>
       </el-form-item>
+
+      <el-form-item label="生效时间" prop="expectId">
+          <el-date-picker
+            style="width: 240px"
+            v-model="queryParams.changeDate"
+            :clearable="true"
+            type="daterange"
+            placeholder="选择时间"
+            value-format="YYYY-MM-DD"
+            format="YYYY-MM-DD"
+            date-format="YYYY-MM-DD"
+          />
+      </el-form-item>
+
+
       <el-form-item label="审批状态" prop="type">
         <el-select v-model="queryParams.type" placeholder="请选择" class="!w-240px">
           <el-option
@@ -89,6 +104,7 @@ const list = ref([]) // 列表的数据
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
+  changeDate: [],
   elderName: undefined,
   expectId: undefined,
   type: undefined,

+ 131 - 0
src/views/system/little-tools/AddItemForm.vue

@@ -0,0 +1,131 @@
+<template>
+  <Dialog
+    v-model="dialogVisible"
+    :title="titleName"
+    width="80%"
+    class="form-tag-dialog check-in-request-form"
+    scroll
+    @close="handleClosed"
+  >
+    <ProcessAddItem ref="processRef" :toggleType="isDetail" />
+    <template #footer>
+      <el-button @click="handleClosed">关闭</el-button>
+      <el-button v-loading="formLoading" type="primary" @click="submitForm" v-if="!isDetail">提交</el-button>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import {
+  getElderInfoById,
+} from '@/api/elderly/elder/elderly-Info'
+import { DICT_TYPE, getDictLabel } from '@/utils/dict'
+import ProcessAddItem from './ProcessAddItem.vue'
+import {createProcessExpense} from "@/views/system/little-tools/api";
+defineOptions({ name: 'CheckInRequestForm' })
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const dialogVisible = ref(false) // 弹窗
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const isDetail = ref(false)
+let titleName = ref('')
+
+/** 打开弹窗 */
+const processRef = ref()
+const pageType = ref()
+const open = async (id, detail, title, type, tId) => {
+  dialogVisible.value = true
+  pageType.value = type
+  titleName.value = '新增' + title
+  isDetail.value = detail
+  if (id) {
+    try {
+      const res = await getElderInfoById(id)
+      processRef.value.open(res, detail, type, tId)
+      titleName.value =
+        '编辑' + title + '(' + getDictLabel(DICT_TYPE.IN_STATUS_TYPE, res.inStatusType) + ')'
+    } catch (err) {}
+  }else{
+    await nextTick(() => {
+      processRef.value.init(tId, false, undefined)
+    })
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  if(formLoading.value){
+    return
+  }
+  formLoading.value = true
+  try {
+    let { valid, dataForm } = await processRef.value.submitForm()
+    if(!valid){
+      return
+    }
+
+    let n = 0
+    let i = {}
+    for (const item of dataForm.expenseBO.monthlyExpenses) {
+      if(item.itemId && item.itemId!=""){
+        i = item
+        n+=1
+      }
+    }
+    if(n>1){
+      message.error("只能添加一个月度费用")
+      return
+    }
+
+    let upData = {
+      "elderId": dataForm.elderlyId,
+      "itemId": '',
+      "itemCategoryName": '',
+      "itemCategoryId": '',
+      "itemName": '',
+      "type": '',
+      "amount": 0,
+      "actualAmount": 0,
+      "count": 0,
+      "startDate": '',
+      "endDate": '',
+      "remark": '',
+      "tenantId": 0
+    }
+
+    upData.itemId = i.itemId
+    upData.itemCategoryId = i.itemCategoryId
+    upData.itemCategoryName = i.itemCategoryName
+    upData.itemName = i.itemName
+    upData.type = i.type??null
+    upData.amount = i.amount
+    upData.count = i.count
+    upData.actualAmount = i.actualAmount
+    upData.startDate = dataForm.expenseBO.startDate
+    upData.endDate = dataForm.expenseBO.endDate
+    upData.remark = dataForm.expenseBO.remark
+    upData.tenantId = dataForm.expenseBO.tenantId
+
+
+    // 提交请求
+    const res = await createProcessExpense(upData)
+    if (res) {
+      message.success(t('common.updateSuccess'))
+      // 发送操作成功的事件
+      emit('success')
+      handleClosed()
+    }
+  } finally {
+    setTimeout(()=>{
+      formLoading.value = false
+    },500)
+  }
+}
+
+// 关闭表单
+const handleClosed = () => {
+  processRef.value && processRef.value.resetForm()
+  dialogVisible.value = false
+}
+</script>

+ 1067 - 0
src/views/system/little-tools/ProcessAddItem.vue

@@ -0,0 +1,1067 @@
+<template>
+  <el-form
+    class="-mb-15px"
+    :model="dataForm"
+    ref="formRef"
+    label-width="110px"
+    :rules="dataRule"
+    scroll
+    v-loading="loading"
+    :toggleType="isDetail"
+  >
+    <div class="info-title">长者信息</div>
+    <div class="info-wrap">
+      <el-row :gutter="10">
+        <el-col :lg="12" :md="12" :sm="24" :xs="24">
+          <el-form-item label="选择长者" prop="elderId">
+
+            <SelectElder v-model="dataForm.elderId" type="2" @elder="handleSelectElder" :tId="dataForm.tenantId"/>
+
+          </el-form-item>
+        </el-col>
+        <el-col :lg="12" :md="12" :sm="24" :xs="24">
+          <el-form-item label="床位号" prop="familyDiseases">
+
+            <el-text>{{dataForm.bedName}}</el-text>
+
+          </el-form-item>
+        </el-col>
+        <el-col :lg="12" :md="12" :sm="24" :xs="24">
+          <el-form-item label="开始日期" prop="startDate">
+
+            <TgDatePicker type="date"   v-model="dataForm.startDate" placeholder="选择日期"   :toggle-type="isDetail"/>
+
+          </el-form-item>
+        </el-col>
+        <el-col :lg="12" :md="12" :sm="24" :xs="24">
+          <el-form-item label="结束日期" prop="endDate">
+
+            <TgDatePicker type="date"  v-model="dataForm.endDate" placeholder="选择日期"   :toggle-type="isDetail"/>
+
+          </el-form-item>
+        </el-col>
+
+
+      </el-row>
+
+    </div>
+
+    <div class="info-title">{{
+        dataForm.inStatusType == '1' ? '月固定收费项目' : '固定收费项目'
+      }}</div>
+    <div class="info-wrap">
+      <el-row :gutter="10">
+
+        <template v-if="dataForm.inStatusType == '1'">
+          <template v-for="(item, index) in arr" :key="index">
+            <el-col :lg="7" :md="24" :sm="24" :xs="24">
+              <el-form-item
+                :label="item.label1"
+                class="mb12"
+              >
+                <TgSelect
+                  v-model="item.itemId"
+                  placeholder="请选择"
+                  :clearable="false"
+                  @change="(arg) => handleChange(arg, index, item, 1)"
+                  :list="item.list"
+                  dict-label="chargeName"
+                  dict-value="id"
+                >
+                  <el-option
+                    v-for="(b, index) in item.list"
+                    :key="index"
+                    :label="`${b.chargeName}(${b.price}元${getDictLabel(DICT_TYPE.FEE_CHARGE_TYPE, b.chargeType)})`"
+                    :value="b.id"
+                  />
+                </TgSelect>
+              </el-form-item>
+            </el-col>
+            <el-col :lg="7" :md="24" :sm="24" :xs="24">
+              <el-form-item :label="item.label2">
+                <TgInput input-type="number" v-model="item.actualAmount" @blur="handleBlur(item, 3)"/>
+              </el-form-item>
+            </el-col>
+            <el-col :lg="5" :md="24" :sm="24" :xs="24">
+              <el-form-item label="是否打折" prop="isDiscount">
+                <TgSwitch
+                  v-model="item.isDiscount"
+                  inline-prompt
+                  active-text="是"
+                  inactive-text="否"
+                  :disabled="!item.itemId"
+                  :active-value="1"
+                  :inactive-value="0"
+                  @click="handleChangeDiscount(item)"
+                />
+              </el-form-item>
+            </el-col>
+            <template v-if="item.isDiscount">
+              <el-col :lg="7" :md="24" :sm="24" :xs="24">
+                <el-form-item label="折扣金额" prop="discountAmount">
+                  <TgInput
+                    v-model="item.discountAmountTemp"
+                    append-text="¥"
+                    input-type="number"
+                    @input="(e)=>updateNum(e.target.value, item, 'discountAmount')"
+                    @blur="handleBlur(item, 1)"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :lg="7" :md="24" :sm="24" :xs="24">
+                <el-form-item label="折扣率" prop="isDiscount">
+                  <TgInputNumber
+                    :controls="false"
+                    v-model="item.discountTemp"
+                    @input="(e)=>updateNum(e, item, 'discount')"
+                    @blur="handleBlur(item, 2)"
+                    :max="10"
+                    style="width: 90%"
+                  />
+                  <el-tooltip
+                    class="item"
+                    effect="dark"
+                    content="输入0至10之间数值;例如:输入8.5为85折。(不包含0和10)"
+                    placement="top-start"
+                  >
+                    <Icon icon="ep:info-filled" />
+                  </el-tooltip>
+                </el-form-item>
+              </el-col>
+            </template>
+            <el-col
+              :lg="5"
+              :md="24"
+              :sm="24"
+              :xs="24"
+              :offset="item.isDiscount ? (smallerThanLg ? 0 : 5) : 0"
+            >
+              <el-form-item label="单项小计">
+                <span class="price">¥{{ formatNum(item.totalAmount) }}元/月</span>
+              </el-form-item>
+            </el-col>
+
+          </template>
+
+          <el-col :span="24">
+            <el-col :span="22" :offset="2"><el-divider /></el-col>
+          </el-col>
+          <el-col :span="24" class="mb5" v-if="!isDetail">
+            <el-button @click="handleAddMonth">
+              <Icon icon="ep:zoom-in" />添加固定项目
+            </el-button>
+          </el-col>
+          <el-col :span="24" v-for="(item, index) in dataForm.monthlyExpenses" :key="index">
+            <el-row :gutter="10">
+              <el-col :lg="1" :md="24" :sm="24" :xs="24" v-if="!isDetail">
+                <Icon
+                  :size="26"
+                  color="#f09d31"
+                  icon="ep:remove"
+                  @click="handleDelMonth(index)"
+                />
+              </el-col>
+              <el-col :lg="6" :md="24" :sm="24" :xs="24">
+                <el-form-item label="项目类别" prop="itemCategoryId">
+                  <TgTreeSelect
+                    v-model="item.itemCategoryId"
+                    :data="monthlyTreeList"
+                    @change="(arg) => handleChangeCategory(arg, item)"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :lg="6" :md="24" :sm="24" :xs="24">
+                <el-form-item label="项目名称" prop="itemId">
+                  <TgSelect
+                    v-model="item.itemId"
+                    placeholder="请选择"
+                    clearable
+                    @change="(arg) => handleChange(arg, index, item, 2)"
+                    dict-label="chargeName"
+                    dict-value="id"
+                    :list="item.list"
+                  >
+                    <el-option
+                      v-for="t in item.list"
+                      :key="t.id"
+                      :label="`${t.chargeName}(${t.price}元${getDictLabel(DICT_TYPE.FEE_CHARGE_TYPE, t.chargeType)})`"
+                      :value="t.id"
+                    />
+                  </TgSelect>
+                </el-form-item>
+              </el-col>
+              <el-col :lg="6" :md="24" :sm="24" :xs="24">
+                <el-form-item label="费用" prop="actualAmount">
+                  <TgInput input-type="number" v-model="item.actualAmount" @blur="handleBlur(item, 3)"/>
+                </el-form-item>
+              </el-col>
+              <el-col :lg="5" :md="24" :sm="24" :xs="24">
+                <el-form-item label="是否打折" prop="isDiscount">
+                  <TgSwitch
+                    v-model="item.isDiscount"
+                    inline-prompt
+                    active-text="是"
+                    inactive-text="否"
+                    :disabled="!item.itemId"
+                    :active-value="1"
+                    :inactive-value="0"
+                    @click="handleChangeDiscount(item)"
+                  />
+                </el-form-item>
+              </el-col>
+              <template v-if="item.isDiscount">
+                <el-col
+                  :lg="6"
+                  :md="24"
+                  :sm="24"
+                  :xs="24"
+                  :offset="item.isDiscount ? (smallerThanLg ? 0 : 1) : 0"
+                >
+                  <el-form-item label="折扣金额" prop="discountAmount">
+                    <TgInput
+                      v-model="item.discountAmountTemp"
+                      append-text="¥"
+                      input-type="number"
+                      @input="(e)=>updateNum(e.target.value, item, 'discountAmount')"
+                      @blur="handleBlur(item, 1)"
+                    />
+                  </el-form-item>
+                </el-col>
+                <el-col :lg="6" :md="24" :sm="24" :xs="24">
+                  <el-form-item label="折扣率" prop="isDiscount">
+                    <TgInputNumber
+                      :controls="false"
+                      v-model="item.discountTemp"
+                      @input="(e)=>updateNum(e, item, 'discount')"
+                      @blur="handleBlur(item, 2)"
+                      :max="10"
+                      style="width: 90%"
+                    />
+                    <el-tooltip
+                      class="item"
+                      effect="dark"
+                      content="输入0至10之间数值;例如:输入8.5为85折。(不包含0和10)"
+                      placement="top-start"
+                    >
+                      <Icon icon="ep:info-filled" />
+                    </el-tooltip>
+                  </el-form-item>
+                </el-col>
+              </template>
+              <el-col
+                :offset="item.isDiscount ?  (smallerThanLg ? 0 : 19) : 19"
+              >
+                <el-form-item label="单项小计">
+                  <span class="price">¥{{ formatNum(item.totalAmount) }}元/月</span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="24">
+                <el-col :span="22" :offset="2"><el-divider /></el-col>
+              </el-col>
+            </el-row>
+          </el-col>
+          <el-col :span="24">
+            <p class="tR" style="text-align: right">
+              月固定金额合计 <span class="totalNum" style="color:#ff0000;font-weight: bold;font-size: 18px">¥{{ formatNum(totalMonthFee) }}元</span>
+            </p>
+          </el-col>
+        </template>
+      </el-row>
+    </div>
+
+
+
+    <div class="info-title">备注</div>
+    <div class="info-wrap">
+      <el-form-item label="费用备注">
+        <TgTextarea v-model="dataForm.remark" />
+      </el-form-item>
+    </div>
+  </el-form>
+
+</template>
+<script setup lang="ts">
+import {
+  DICT_TYPE,
+  getDictLabel,
+  getDictOptions,
+  getIntDictOptions
+} from '@/utils/dict'
+import { getNursingLevelPage } from '@/api/elderly/nursing'
+import { getOverheadListByType, getOverheadPage } from '@/api/elderly/fee/overheadCharge'
+import {getBedIdByIdCardFun, getChargeCategoryTree} from '@/api/elderly/fee/chargeCategory'
+import { filteredTreeData, findTreeNode } from '@/utils/tree'
+import { dayjs, FormRules } from 'element-plus'
+import { formatDecimal, formatNum, formatRid } from '@/utils/formatter'
+import { breakpointsTailwind, useBreakpoints } from '@vueuse/core'
+import { InfoFilled } from '@element-plus/icons-vue'
+import { getParentNodesById } from '@/utils'
+import { checkPrivateRoom } from '@/api/elderly/elder/bed-change'
+import { getTenantId } from '@/utils/auth'
+import { getBusinessId } from '@/api/elderly/common'
+defineOptions({ name: 'CheckInForm' })
+const message = useMessage() // 消息弹窗
+const formRef = ref() // 表单 Ref
+const loading = ref(false)
+const selectRoomRef = ref()
+
+const breakpoints = useBreakpoints(breakpointsTailwind)
+const smallerThanLg = breakpoints.smaller('xl') // only larger than md
+const isDetail = ref(false)
+const state = reactive({
+  dataForm: {
+    // 表单字段
+    tenantId: undefined,
+    id: '',
+    elderId: '',
+    elderName: '',
+    elderSex: '',
+    startDate: '',
+    endDate: '',
+    idCard: '',
+    iphone: '',
+    checkInDeadlineTime: '',
+    expireTime: '',
+    times: '',
+    totalAmount: '',
+    remark: '',
+    contractNumber: '',
+    nurseLevelId: '',
+    monthlyExpenses: [],
+    oneTimeExpenses: [],
+    bedId: '',
+    checkInTime: '',
+    checkOutTime: '',
+    inStatusType: '1',
+    isPrivateRoom: 0,
+    relativesList: [],
+    specialCareNotes: '',
+    status: '',
+    startTenantId: '',
+    recommendedNursingLevel: '', // 推荐护理字段
+    stageExpenses: []
+  },
+  dataRule: {
+    elderId: [
+      {
+        required: true,
+        message: '姓名不能为空',
+        trigger: 'blur'
+      }
+    ],
+    startDate: [
+      {
+        required: true,
+        message: '开始日期不能为空',
+        trigger: ['blur', 'change']
+      }
+    ],
+    endDate: [
+      {
+        required: true,
+        message: '结束日期不能为空',
+        trigger: 'change'
+      },
+      {
+        validator: (rule, value, callback) => {
+          if (value && dataForm.value.checkInTime) {
+            const checkInTime = new Date(dataForm.value.checkInTime).getTime()
+            const checkOutTime = new Date(value).getTime()
+
+            if (checkOutTime <= checkInTime) {
+              callback(new Error('合同结束日期必须大于开始日期'))
+            } else {
+              callback()
+            }
+          } else {
+            callback()
+          }
+        },
+        trigger: 'change'
+      }
+    ],
+    contractNumber: [
+      {
+        required: true,
+        message: '合同编号不能为空',
+        trigger: 'blur'
+      }
+    ],
+    nurseLevelId: [
+      {
+        required: true,
+        message: '护理等级不能为空',
+        trigger: 'blur'
+      }
+    ],
+    bedId: [
+      {
+        required: true,
+        message: '床位号不能为空',
+        trigger: 'blur'
+      }
+    ]
+  }
+})
+const { dataForm, dataRule } = toRefs(state)
+const resetFormField = reactive({...dataForm.value})
+const rowItem = ref({})
+
+const handleSelectElder = (item) => {
+  dataForm.value.elderId = item.id
+  dataForm.value.bedName = item.bedName
+}
+
+/** 打开弹窗 */
+const init = async (row, detail=false, status) => {
+  dataForm.value.startTenantId = getTenantId()
+  isDetail.value = detail
+
+
+  //getNurseLevelList()
+  getOverheadByType(1)
+  getOverheadByType(2)
+  getOverheadByType(3)
+  getOverheadByType(7)
+  getTreeData()
+  //根据身份证查询床位 (定金预定的情况)
+
+}
+
+
+const changeOutTime = ()=>{
+  dataForm.value.times = ''
+
+}
+
+
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  if (!formRef.value) return
+  const valid = await formRef.value.validate()
+  if (!valid) return
+  
+  //计算所有费用金额,合同金额,(优惠后的)
+
+  let data = {
+    id: dataForm.value.id,
+    elderlyId: dataForm.value.elderId,
+    elderlyContractDO: {
+      elderId: dataForm.value.elderId,
+      elderName: dataForm.value.elderName,
+      beginTime: dataForm.value.checkInTime,
+      contractTerm: dataForm.value.times,
+      expireTime: dataForm.value.checkOutTime,
+      amount: formatRid(Number(formatDecimal(totalMonthFee.value)) + Number(formatDecimal(totalOneTimeFee.value))  + Number(formatDecimal(stageExpandFee.value))),
+      //expireTime: deathTime.value.substring(0, 10),
+      contractNumber: dataForm.value.contractNumber,
+      details: fileList.value,
+      specialCareNotes: dataForm.value.specialCareNotes,
+      inStatusType: dataForm.value.inStatusType,
+      tenantId: dataForm.value.tenantId,
+    },
+    expenseBO: {
+      elderId: dataForm.value.elderId,
+      startDate:dataForm.value.startDate,
+      endDate:dataForm.value.endDate,
+      totalAmount: formatRid(Number(formatDecimal(totalMonthFee.value)) + Number(formatDecimal(totalOneTimeFee.value))  + Number(formatDecimal(stageExpandFee.value))),
+      remark: dataForm.value.remark,
+      monthlyExpenses: JSON.parse(JSON.stringify(dataForm.value.monthlyExpenses)),
+      oneTimeExpenses: JSON.parse(JSON.stringify(dataForm.value.oneTimeExpenses)),
+      stageExpenses: JSON.parse(JSON.stringify(dataForm.value.stageExpenses)),
+      bedId: dataForm.value.bedId,
+      checkInTime: dataForm.value.checkInTime,
+      checkInDeadlineTime: dataForm.value.checkInDeadlineTime,
+      nurseLevelId: dataForm.value.nurseLevelId,
+      isPrivateRoom: dataForm.value.isPrivateRoom,
+      specialCareNotes: dataForm.value.specialCareNotes,
+      tenantId: dataForm.value.tenantId,
+    },
+    tenantId: dataForm.value.tenantId,
+  }
+
+
+
+  if (dataForm.value.inStatusType == '1') {
+    data.expenseBO.monthlyExpenses.push(...arr)
+  }
+  data.expenseBO.monthlyExpenses.map((item) => {
+    item.list = undefined
+  })
+  data.expenseBO.oneTimeExpenses.map((item) => {
+    item.list = undefined
+  })
+  // 去除阶段性的actualAmount
+  data.expenseBO.stageExpenses.map(item=>{
+    item.list = undefined
+    if(item.isFreeGift == 1){
+      item.actualAmount = 0
+    }else if(item.isHirePurchase == 1){
+      item.actualAmount = item.hirePurchaseAmount
+    }
+  })
+
+  // 提交请求
+  return {
+    valid,
+    dataForm: data
+  }
+}
+
+
+
+// 文件列表
+const fileList = ref<{ fileUrl: string; fileName: string }[]>([])
+
+/** 重置表单 */
+const resetForm = () => {
+  dataForm.value = {...resetFormField}
+  formRef.value?.resetFields()
+}
+
+//重置数据
+const resetData = () => {
+  dataForm.value.checkInTime = ''
+  dataForm.value.times = ''
+  dataForm.value.contractNumber = ''
+  dataForm.value.checkInDeadlineTime = ''
+  dataForm.value.monthlyExpenses = []
+  dataForm.value.oneTimeExpenses = []
+  dataForm.value.stageExpenses = []
+
+}
+
+const processType = ref()
+const getProcess = async (id, type, status) => {
+  const res = await getBusinessId(id)
+  init({bpmStatus: status, elderId: res.businessId2, id: res.businessId}, true, status)
+  processType.value = type
+}
+
+/** 查询护理等级列表 */
+const nurseLevelList = ref<{ id: number; nurseLevelName: string }[]>([])
+const getNurseLevelList = async () => {
+  try {
+    const data = await getNursingLevelPage({
+      pageNum: 1,
+      pageSize: 100
+    })
+    nurseLevelList.value = data.list
+  } finally {
+  }
+}
+
+// 查询床位类型 1
+// 查询护理标准 2
+// 餐饮标准 3
+const bedList = ref<{ chargeName: string; id: string; price: number }[]>([])
+const nurseList = ref<{ chargeName: string; id: string; price: number }[]>([])
+const foodList = ref<{ chargeName: string; id: string; price: number }[]>([])
+const serveList = ref<{ chargeName: string; id: string; price: number }[]>([])
+const getOverheadByType = async (val) => {
+  try {
+    const res = await getOverheadListByType(val, dataForm.value.startTenantId)
+    if (val == 1) {
+      bedList.value = res
+      arr[0].list = res
+      arr[0].itemCategoryId = res ? res[0].superiorsId : ''
+    } else if (val == 2) {
+      nurseList.value = res
+      arr[1].list = res
+      arr[1].itemCategoryId = res ? res[0].superiorsId : ''
+    } else if (val == 3) {
+      foodList.value = res
+      arr[2].list = res
+      arr[2].itemCategoryId = res ? res[0].superiorsId : ''
+    }else if (val == 7) {
+      foodList.value = res
+      arr[3].list = res
+      arr[3].itemCategoryId = res ? res[0].superiorsId : ''
+    }
+  }catch (e) {}
+
+}
+
+// 更新费用
+const handleChange = (id, index: number, item, type: number = 1) => {
+  // 固定费用中不需要选分类的几项
+  if (type == 1) {
+    let obj = arr[index].list.find((item) => item.id === id)
+    arr[index].itemName = obj?.chargeName
+    arr[index].actualAmount = item.isDiscount
+      ? item.discount
+        ? ((obj?.price * item.discount) / 100) * 10
+        : obj?.price
+      : obj?.price
+    arr[index].totalAmount = arr[index].actualAmount
+    arr[index].amount = obj?.price
+
+    // 在tree中找到这棵树的上一级
+    let node = findTreeNode(treeList.value, item.itemCategoryId, 'id', 'childrenList')
+    // 找到对应的名称
+    const res = getParentNodesById(treeList.value, node.parentId, node.id, 'name', 'parentId', 'childrenList')
+    // 只保留最后两位
+    if(res.length - 2 > 0){
+      for(let i = 0; i <= res.length - 2; i++){
+        res.pop()
+      }
+    }
+    arr[index].itemCategoryName = res.reverse().join('-')
+  } else {
+    let obj = item.list.find((item) => item.id === id)
+    item.itemName = obj?.chargeName
+    if(type != 4){
+      item.actualAmount = item.isDiscount
+        ? item.discount
+          ? ((obj?.price * item.discount) / 100) * 10
+          : obj?.price
+        : obj?.price
+      item.totalAmount = type == 2 ? item.actualAmount : item.actualAmount * item.count
+      item.amount = obj?.price
+    }else{
+      item.actualAmount = obj.price
+      item.totalAmount = item.isFreeGift == 1 ? 0 : item.actualAmount * item.count
+      item.amount = obj.price
+    }
+  }
+}
+
+const handleChangeOneTimeTotalPrice = (item) => {
+  item.totalAmount = item.actualAmount * item.count
+}
+
+// 更新输入框的值
+const updateNum = (e, item, type) => {
+  item[type] = Number(e.data || e)
+}
+
+// 项目类别
+const monthlyTreeList = ref()
+const treeList = ref()
+const defaultProps = ref({
+  // 树形属性
+  children: 'childrenList',
+  label: 'name',
+  value: 'id',
+  disabled: 'disabled'
+})
+const getTreeData = async () => {
+  try {
+    loading.value = true
+    // 长住
+    if (dataForm.value.inStatusType == '1') {
+      const data = await getChargeCategoryTree()
+      treeList.value = filteredTreeData(data, 'childrenList')
+      console.log("AA",treeList.value)
+      // 添加以下行来过滤 identification == '4' 的项并赋值给 monthlyTreeList
+      monthlyTreeList.value = filteredTreeData(data.filter(item => item.identification !== '4'), 'childrenList')
+
+    } else {
+      // 试住
+      const data = await getChargeCategoryTree()
+      //let item = findTreeNode(data, '5', 'identification', 'childrenList')
+      //treeList.value = [item]
+      treeList.value = filteredTreeData(data, 'childrenList')
+    }
+  } catch (err) {
+    console.log('err', err)
+  } finally {
+    loading.value = false
+  }
+}
+
+// 项目名称
+const handleChangeCategory = async (arg, item) => {
+  item.itemId = ''
+  item.itemName = ''
+  item.isDeposit = ''
+  item.discountAmount = ''
+  item.discount = ''
+  let obj = findTreeNode(treeList.value, arg, 'id', 'childrenList')
+  item.isDeposit = (obj.identification == 4 || obj.identification == 22) ? 1 : 0
+  // 找到对应的名称
+  const res = getParentNodesById(treeList.value, obj.parentId, arg, 'name', 'parentId', 'childrenList')
+  // 只保留最后两位
+  if(res.length - 2 > 0){
+    for(let i = 0; i <= res.length - 2; i++){
+      res.pop()
+    }
+  }
+  item.itemCategoryName = res.reverse().join('-')
+  // 找到匹配的关联节点
+  await getNameList(item)
+}
+const getNameList = async (item) => {
+  try {
+    const data = await getOverheadPage({
+      pageNum: 1,
+      pageSize: 200,
+      categoryId: item.itemCategoryId
+    })
+    item.list = data.list
+  } finally {
+  }
+}
+
+
+
+let arr: any = reactive([
+  {
+    label1: '床位类型',
+    label2: '床位费',
+    list: bedList.value,
+    type: 1,
+    itemCategoryId: '',
+    itemCategoryName: '',
+    itemId: '',
+    itemName: '',
+    amount: '',
+    actualAmount: '',
+    isDiscount: '',
+    isMonthlyExpense: 1,
+    isDeposit: 0,
+    totalAmount: 0,
+    discount: undefined,
+    discountTemp: undefined,
+    discountAmount: '',
+    discountAmountTemp: '',
+    errMsg: ''
+  },
+  {
+    label1: '护理标准',
+    label2: '护理费',
+    list: nurseList.value,
+    type: 2,
+    itemCategoryId: '',
+    itemCategoryName: '',
+    itemId: '',
+    itemName: '',
+    amount: '',
+    actualAmount: '',
+    isDiscount: '',
+    isMonthlyExpense: 1,
+    isDeposit: 0,
+    totalAmount: 0,
+    discount: undefined,
+    discountTemp: undefined,
+    discountAmount: '',
+    discountAmountTemp: '',
+    errMsg: ''
+  },
+  {
+    label1: '餐饮标准',
+    label2: '餐饮费',
+    list: foodList.value,
+    type: 3,
+    itemCategoryId: '',
+    itemCategoryName: '',
+    itemId: '',
+    itemName: '',
+    amount: '',
+    actualAmount: '',
+    isDiscount: '',
+    isMonthlyExpense: 1,
+    isDeposit: 0,
+    totalAmount: 0,
+    discount: undefined,
+    discountTemp: undefined,
+    discountAmount: '',
+    discountAmountTemp: '',
+    errMsg: ''
+  },
+  {
+    label1: '服务标准',
+    label2: '服务费',
+    list: serveList.value,
+    type: 7,
+    itemCategoryId: '',
+    itemCategoryName: '',
+    itemId: '',
+    itemName: '',
+    amount: '',
+    actualAmount: '',
+    isDiscount: '',
+    isMonthlyExpense: 1,
+    isDeposit: 0,
+    totalAmount: 0,
+    discount: undefined,
+    discountTemp: undefined,
+    discountAmount: '',
+    discountAmountTemp: '',
+    errMsg: ''
+  }
+])
+
+// 是否启用打折
+const handleChangeDiscount = (row) => {
+  if (row.isDiscount) {
+    row.totalAmount = row.discount ? row.amount * ((row.discount / 100) * 10) : row.actualAmount
+  } else {
+    row.discount = '' // 折扣率
+    row.discountTemp = ''// 折扣率
+    row.discountAmount = '' // 折扣
+    row.discountAmountTemp = '' // 折扣
+    row.totalAmount = row.amount
+    row.actualAmount = row.amount
+  }
+}
+
+// 折扣和折扣率换算 价格
+const handleBlur = (item, type = 0) => {
+  if(type == 3){
+    // 判断是否有打折
+    if(item.discountTemp){
+      // TODO
+    }else{
+      item.totalAmount = item.actualAmount
+    }
+  }else{
+    // 填写折扣金额
+    if (type == 1) {
+      item.actualAmount = item.amount - item.discountAmount
+      item.discount = item.discountAmount ? (1000 - (item.discountAmount / item.amount) * 1000) * 10 / 1000 : ''
+      item.discountTemp = item.discount ? formatNum(item.discount) : ''
+    } else if (type == 2) { // 折扣率
+      item.actualAmount = item.discountTemp ? item.amount * (item.discountTemp * 1000) / (1000 * 10) : ''
+      item.discountAmount = item.discountTemp ? ((item.amount * (1 - item.discountTemp / 10)) / 10) * 10 : ''
+      item.discountAmountTemp = item.discountAmount ? formatNum(item.discountAmount) : ''
+    }
+    item.totalAmount = item.isDiscount
+      ? item.discount
+        ? item.actualAmount
+        : item.amount
+      : item.amount
+  }
+}
+
+const handleAddMonth = () => {
+  dataForm.value.monthlyExpenses.push({
+    itemCategoryId: '',
+    itemCategoryName: '',
+    itemId: '',
+    itemName: '',
+    amount: '',
+    actualAmount: '',
+    isDiscount: '',
+    isMonthlyExpense: 1,
+    isDeposit: '', // 是否打折
+    discount: undefined, // 折扣率
+    discountTemp: undefined, // 折扣率
+    discountAmount: '', // 折扣
+    discountAmountTemp: '',
+    totalAmount: 0,
+    list: []
+  })
+}
+
+const handleDelMonth = (index: number) => {
+  dataForm.value.monthlyExpenses.splice(index, 1)
+}
+
+const totalMonthFee = computed(() => {
+  let total = 0
+  dataForm.value.monthlyExpenses.map((item) => {
+    total += Number(item.totalAmount)
+  })
+  arr.map((item) => {
+    total += Number(item.totalAmount)
+  })
+  return total
+})
+
+const stageExpandFee = computed(()=>{
+  let total = 0
+  dataForm.value.stageExpenses.map((item) => {
+    if(item.isHirePurchase == 1)
+      total += item.totalAmount
+  })
+  return total
+})
+
+const handleAddOneTime = () => {
+  dataForm.value.oneTimeExpenses.push({
+    itemCategoryId: '',
+    itemCategoryName: '',
+    itemId: '',
+    itemName: '',
+    amount: '',
+    actualAmount: undefined,
+    count: 1,
+    isOneTimeFee: 1,
+    isDeposit: '',
+    totalAmount: 0,
+    list: []
+  })
+}
+
+const totalOneTimeFee = computed(() => {
+  let total = 0
+  dataForm.value.oneTimeExpenses.map((item) => {
+    total += item.totalAmount
+  })
+  return total
+})
+
+const handleDelOneTime = (index: number) => {
+  dataForm.value.oneTimeExpenses.splice(index, 1)
+}
+
+
+
+// 校验
+const handleValidate = (item) => {
+  if (item.itemId || item.label1=='服务标准') {
+    item.errMsg = ''
+  } else {
+    item.errMsg = item.label1 + '不能为空'
+  }
+}
+
+
+
+defineExpose({ init, submitForm, resetForm, getProcess }) // 提供 open 方法,用于打开弹窗
+</script>
+
+<style lang="scss" scoped>
+.check-in-check {
+  .el-form {
+    padding: 15px !important;
+  }
+
+  .info-title {
+    margin-left: -15px;
+    min-width: 75px;
+    max-width: 150px;
+    padding: 15px;
+    font-weight: bolder;
+    background-color: #f3f6fb;
+    border-top-right-radius: 50px;
+    border-bottom-right-radius: 50px;
+  }
+
+  .info-wrap {
+    padding: 15px 0;
+    box-sizing: border-box;
+
+    &.fb12 {
+      .el-form-item {
+        margin-bottom: 12px !important;
+      }
+    }
+
+    .mb12 {
+      margin-bottom: 12px !important;
+    }
+
+    .el-divider--horizontal {
+      margin: 15px !important;
+      margin-top: 0 !important;
+    }
+
+    .info-item {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 20px;
+      background-color: #f3f6fb;
+      border-radius: 10px;
+
+      p {
+        margin: 10px;
+      }
+
+      &:first-of-type {
+        margin-bottom: 15px;
+      }
+
+      .bold {
+        display: inline-block;
+        margin-right: 10px;
+        font-weight: bolder;
+      }
+
+      i {
+        cursor: pointer;
+      }
+    }
+
+    .w100 {
+      width: 100% !important;
+      text-align: left;
+    }
+
+    .el-divider {
+      background-color: #f5f5f5;
+    }
+
+    .mt18 {
+      margin-top: 18px;
+    }
+
+    .mb18 {
+      margin-bottom: 18px;
+    }
+
+    .m10 {
+      margin: 10px 0;
+    }
+
+    .c9 {
+      color: #999;
+    }
+
+    .desc {
+      color: #7a95e5;
+      padding-left: 40px;
+    }
+    .flex-between{
+      display: flex;
+    }
+
+    .btn-group-box {
+      width: 100%;
+
+      .btn {
+        display: inline-block;
+        width: 30%;
+        margin-right: 10px;
+        text-align: center;
+        cursor: pointer;
+        background-color: #f2f5f8;
+        border-radius: 8px;
+
+        &:active {
+          background-color: #7a95e5;
+          color: #fff;
+        }
+      }
+    }
+
+    .noLabel {
+      :deep(.el-form-item__content) {
+        margin-left: 30px !important;
+      }
+    }
+
+    .price {
+      display: inline-block;
+      min-width: 10px;
+      color: #ef9321;
+    }
+
+    .tR {
+      text-align: right;
+      font-weight: bolder;
+
+      .totalNum {
+        color: #ef9321;
+        font-size: 18px;
+        font-weight: bolder;
+      }
+    }
+  }
+}
+</style>

+ 19 - 0
src/views/system/little-tools/api.ts

@@ -6,3 +6,22 @@ export const markCheckinBillsPaid = (data: any) => {
   return request.post({ url: '/elderly/expenseOrder/markCheckinBillsPaid', data })
 }
 
+
+export interface ProcessExpenseAddVO {
+  elderId: number
+  itemId: number
+  itemCategoryName: string
+  itemName: string
+  type: number
+  amount: number
+  actualAmount: number
+  count: number
+  startDate: string
+  endDate: string
+  remark: string
+  tenantId: number
+}
+
+export const createProcessExpense = async (data: ProcessExpenseAddVO) => {
+  return await request.post({ url: '/elderly/expense/addFixedExpense', data })
+}

+ 7 - 0
src/views/system/little-tools/index.vue

@@ -13,18 +13,22 @@
     </div>
 
     <MarkCheckinBillsPaidForm  ref="refMarkCheckinBillsPaid"/>
+    <AddItemForm  ref="addItemForm"/>
 
   </div>
 </template>
 <script setup lang="ts">
 import MarkCheckinBillsPaidForm from "./MarkCheckinBillsPaidForm.vue"
+import AddItemForm from "./AddItemForm.vue"
 import {useUserStore} from "@/store/modules/user";
 const message = useMessage() // 消息弹窗
 const userStore = useUserStore()
 const refMarkCheckinBillsPaid = ref()
+const addItemForm = ref()
 
 const cards = ref([
   { id: 0, title: '把入院账单设置成已缴费状态', content: '只操作本机构的,集团账号时不要操作' },
+  { id: 1, title: '为长者增加月度费用', content: '只操作本机构的,集团账号时不要操作' },
 
 ])
 
@@ -37,7 +41,10 @@ const itemClick=(id:any)=>{
       refMarkCheckinBillsPaid.value.open(userStore.orgTenantId)
 
       break
+    case 1: //增加月度费用
+      addItemForm.value.open(undefined,false,"月度费用",undefined,userStore.orgTenantId)
 
+      break
   }
 
 }