Sfoglia il codice sorgente

Merge branch 'master' of http://47.107.245.0:3000/xiongxing/kyj-yanglao-web-new

unknown 1 mese fa
parent
commit
8011a1d6b1

+ 10 - 0
src/api/bpm/processInstance/index.ts

@@ -134,4 +134,14 @@ export const getProcessInstanceBpmnCount = async () => {
 // 获取流程实例未读数量
 export const updateMyCreateReadById = async (id) => {
   return await request.put({ url: `/system/notify-message/updateMyCreateReadById?processInstanceId=${id}` })
+}
+
+//  获取长者轮候列表
+export const getCheckInWaitPage = async (params: any)=>{
+  return await request.get({ url: '/bpm/process-instance/check-in-wait-page', params })
+}
+
+// 获取长者轮候详情
+export const getWaitElderDetail = async(id: number)=>{
+  return await request.get({ url:'/bpm/check-in-wait/detail?id=' + id })
 }

+ 20 - 11
src/components/UploadFile/src/UploadFile.vue

@@ -173,29 +173,38 @@ watch(
   (val) => {
     // 字符串的情况下要先记住值
     const temp = JSON.parse(JSON.stringify(fileList.value))
-    if (!val[0]) {
+    const modelValue = val[0]
+    const fileNameValue = val[1]
+
+    if (!modelValue) {
       fileList.value = [] // fix:处理掉缓存,表单重置后上传组件的内容并没有重置
       return
     }
 
+    // 统一 fileName 为数组,避免 val[1] 为 undefined / string 时取下标报错
+    const fileNameList = Array.isArray(fileNameValue)
+      ? fileNameValue
+      : isString(fileNameValue)
+        ? fileNameValue.split(',')
+        : []
+
     fileList.value = [] // 保障数据为空
     // 情况1:字符串
-    if (isString(val[0])) {
+    if (isString(modelValue)) {
       fileList.value.push(
-        ...val[0]
-          .split(',')
-          .map((url, index) => ({
-            fileName: val[1] ? val[1][index] : temp[0].fileName,
-            name: url.substring(url.lastIndexOf('/') + 1),
-            url
-          }))
+        ...modelValue.split(',').map((url, index) => ({
+          fileName: fileNameList[index] || temp[index]?.fileName || '',
+          name: url.substring(url.lastIndexOf('/') + 1),
+          url
+        }))
       )
       return
     }
+
     // 情况2:数组
     fileList.value.push(
-      ...(val[0] as string[]).map((url, index) => ({
-        fileName: val[1][index],
+      ...(modelValue as string[]).map((url, index) => ({
+        fileName: fileNameList[index] || temp[index]?.fileName || '',
         name: url.substring(url.lastIndexOf('/') + 1),
         url
       }))

+ 36 - 11
src/utils/formCreate.ts

@@ -13,40 +13,65 @@ export const encodeFields = (designerRef: object) => {
   // @ts-ignore
   const rule = designerRef.value.getRule()
   const fields: string[] = []
-  rule.forEach((item) => {
+  rule.forEach((item: any) => {
     fields.push(JSON.stringify(item))
   })
   return fields
 }
 
 // 解码表单 Fields
-export const decodeFields = (fields, type: string) => {
+export const decodeFields = (fields: any) => {
   const rule: object[] = []
-  if (type == '1') {
+  if (!fields) {
+    return rule
+  }
+
+  // 兼容:fields 为数组(每项是 JSON 字符串)
+  if (Array.isArray(fields)) {
     fields.forEach((item) => {
-      rule.push(JSON.parse(item))
-    })
-  } else {
-    JSON.parse(fields).forEach((item) => {
-      rule.push(item)
+      if (typeof item === 'string') {
+        rule.push(JSON.parse(item))
+      } else if (item && typeof item === 'object') {
+        rule.push(item)
+      }
     })
+    return rule
+  }
+
+  // 兼容:fields 为 JSON 字符串(可能是对象或数组)
+  if (typeof fields === 'string') {
+    const parsed = JSON.parse(fields)
+    if (Array.isArray(parsed)) {
+      parsed.forEach((item) => {
+        rule.push(item)
+      })
+    } else if (parsed && typeof parsed === 'object') {
+      rule.push(parsed)
+    }
+    return rule
+  }
+
+  // 兜底:fields 为对象
+  if (typeof fields === 'object') {
+    rule.push(fields)
   }
+
   return rule
 }
 
 // 设置表单的 Conf 和 Fields,适用 FcDesigner 场景
-export const setConfAndFields = (designerRef: object, conf: string, fields, type: string = '1') => {
+export const setConfAndFields = (designerRef: object, conf: string, fields: any) => {
   // @ts-ignore
   designerRef.value.setOption(JSON.parse(conf))
   // @ts-ignore
-  designerRef.value.setRule(decodeFields(fields, type))
+  designerRef.value.setRule(decodeFields(fields))
 }
 
 // 设置表单的 Conf 和 Fields,适用 form-create 场景
 export const setConfAndFields2 = (
   detailPreview: object,
   conf: string,
-  fields: string[],
+  fields: any,
   value?: string
 ) => {
   if (isRef(detailPreview)) {

+ 1 - 1
src/views/bpm/processInstance/detail/ProcessInstanceTaskList.vue

@@ -46,7 +46,7 @@
   </el-table>
 
   <!-- 弹窗:表单 -->
-  <Dialog title="表单详情" v-model="taskFormVisible" width="600">
+  <Dialog title="表单详情" v-model="taskFormVisible" width="60%">
     <form-create
       ref="fApi"
       v-model="taskForm.value"

+ 28 - 0
src/views/elderly/elder/column.ts

@@ -414,3 +414,31 @@ export const DiscountFees = reactive([
   //   type: '2'
   // }
 ])
+
+// ================待入住长者===================
+export const WaitElderColumns = reactive([
+  {
+    label: '所属机构',
+    field: 'tenantName',
+    type: '99'
+  },
+  {
+    label: '长者姓名',
+    field: 'elderName',
+  },
+  {
+    label: '证件号码',
+    field: 'idCard',
+  },
+  {
+    label: '审批状态',
+    field: 'bpmStatus',
+    dictArr: DICT_TYPE.APPROVAL_STATUS,
+    type: '2'
+  },
+  {
+    label: '创建时间',
+    field: 'createdTime',
+    format: true
+  }
+])

+ 46 - 0
src/views/elderly/elder/wait-elder/Detail.vue

@@ -0,0 +1,46 @@
+<template>
+  <Dialog
+    v-model="dialogVisible"
+    title="详情"
+    width="60%"
+    scroll
+    class="form-tag-dialog"
+    @close="handleClosed"
+  >
+    <ProcessForm :toggleType="true" ref="processRef" />
+    <BusinessFormComponent :id="businessKey" ref="formRef" v-if="statusType != 5"/>
+    <template #footer>
+      <el-button @click="handleClosed">关闭</el-button>
+    </template>
+  </Dialog>
+</template>
+
+<script lang="ts" setup>
+import { ref } from 'vue'
+import { registerComponent } from '@/utils/routerHelper'
+import ProcessForm from './ProcessForm.vue'
+defineOptions({ name: 'WaitElderDetail' })
+
+const dialogVisible = ref(false) // 弹窗
+const BusinessFormComponent = ref() // 异步组件
+const businessKey = ref('')
+const statusType = ref()
+const processRef = ref()
+/** 打开弹窗 */
+const open = async (tId, id, processId, status) => {
+  dialogVisible.value = true
+  businessKey.value = processId
+  statusType.value = status
+  BusinessFormComponent.value = registerComponent('/bpm/task/process-list/process')
+  nextTick(() => {
+    processRef.value.setTenantId(tId)
+    processRef.value.init(id, true, status)
+  })
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+// 关闭表单
+const handleClosed = () => {
+  dialogVisible.value = false
+}
+</script>

+ 223 - 0
src/views/elderly/elder/wait-elder/ProcessForm.vue

@@ -0,0 +1,223 @@
+<template>
+  <el-form
+    ref="formRef"
+    :model="form"
+    :rules="rules"
+    label-width="120px"
+    label-position="top"
+    status-icon
+    class="wait-elder-form"
+  >
+    <el-form-item label="长者姓名" prop="elderName" required>
+      <div class="view-value">{{ form.elderName || '-' }}</div>
+    </el-form-item>
+
+    <el-form-item label="身份证号" prop="idCard" required>
+      <div class="view-value">{{ form.idCard || '-' }}</div>
+    </el-form-item>
+
+    <el-form-item label="近期居住情况(视频)" prop="recentLivingSituation" required>
+      <div class="view-files">
+        <div v-if="!form.recentLivingSituation.length" class="empty">-</div>
+        <ul v-else>
+          <li v-for="(item, index) in form.recentLivingSituation" :key="`life-${index}`">
+            <a :href="item" target="_blank" rel="noopener noreferrer">{{ getFileName(item) }}</a>
+          </li>
+        </ul>
+      </div>
+    </el-form-item>
+
+    <el-form-item label="行走情况(视频)" prop="walkSituationVideo" required>
+      <div class="view-files">
+        <div v-if="!form.walkSituationVideo.length" class="empty">-</div>
+        <ul v-else>
+          <li v-for="(item, index) in form.walkSituationVideo" :key="`walk-${index}`">
+            <a :href="item" target="_blank" rel="noopener noreferrer">{{ getFileName(item) }}</a>
+          </li>
+        </ul>
+      </div>
+    </el-form-item>
+
+    <el-form-item label="近半年内病历" prop="medicalRecordsWithinSixMonth" required>
+      <div class="view-files">
+        <div v-if="!form.medicalRecordsWithinSixMonth.length" class="empty">-</div>
+        <ul v-else>
+          <li v-for="(item, index) in form.medicalRecordsWithinSixMonth" :key="`medical-${index}`">
+            <a :href="item" target="_blank" rel="noopener noreferrer">{{ getFileName(item) }}</a>
+          </li>
+        </ul>
+      </div>
+    </el-form-item>
+
+    <el-form-item label="身份证照片" prop="idCardPhoto" required>
+      <div class="view-files">
+        <div v-if="!form.idCardPhoto.length" class="empty">-</div>
+        <ul v-else>
+          <li v-for="(item, index) in form.idCardPhoto" :key="`idimg-${index}`">
+            <a :href="item" target="_blank" rel="noopener noreferrer">{{ getFileName(item) }}</a>
+          </li>
+        </ul>
+      </div>
+    </el-form-item>
+
+    <el-form-item label="近期出院小结(视频)" prop="recentDischargeSummary">
+      <div class="view-files">
+        <div v-if="!form.recentDischargeSummary.length" class="empty">-</div>
+        <ul v-else>
+          <li v-for="(item, index) in form.recentDischargeSummary" :key="`discharge-${index}`">
+            <a :href="item" target="_blank" rel="noopener noreferrer">{{ getFileName(item) }}</a>
+          </li>
+        </ul>
+      </div>
+    </el-form-item>
+    <el-form-item label="是否精防" prop="remark">
+      <div class="view-value">{{ form.isPsychosis || '-' }}</div>
+    </el-form-item>
+    <el-form-item label="照护等级" prop="nurseLevelId">
+      <div class="view-value">{{ form.nurseLevelId || '-' }}</div>
+    </el-form-item>
+    <el-form-item label="床位预排备注" prop="remark">
+      <div class="view-value">{{ form.remark || '-' }}</div>
+    </el-form-item>
+    <el-form-item label="体检报告" prop="physicalExaminationReport">
+      <div class="view-files">
+        <div v-if="!form.physicalExaminationReport.length" class="empty">-</div>
+        <ul v-else>
+          <li v-for="(item, index) in form.physicalExaminationReport" :key="`physical-${index}`">
+            <a :href="item" target="_blank" rel="noopener noreferrer">{{ getFileName(item) }}</a>
+          </li>
+        </ul>
+      </div>
+    </el-form-item>
+    <el-form-item label="最终床位信息" prop="bedId">
+      <div class="view-value">{{ form.bedId || '-' }}</div>
+    </el-form-item>
+  </el-form>
+</template>
+
+<script setup lang="ts">
+import { getBusinessId } from '@/api/elderly/common'
+import { getWaitElderDetail } from '@/api/bpm/processInstance'
+
+defineOptions({ name: 'BedChangeProcessForm' })
+
+const formRef = ref()
+
+const form = reactive({
+  elderName: '',
+  idCard: '',
+  recentLivingSituation: [] as any[],
+  walkSituationVideo: [] as any[],
+  medicalRecordsWithinSixMonth: [] as any[],
+  idCardPhoto: [] as any[],
+  recentDischargeSummary: [] as any[],
+  physicalExaminationReport: [] as any[],
+  remark: ''
+})
+
+const rules = reactive({})
+
+const parseFileList = (value: any) => {
+  if (!value) return []
+  if (Array.isArray(value)) return value
+  if (typeof value === 'string') {
+    return value
+      .split(',')
+      .map((item) => item.trim())
+      .filter(Boolean)
+  }
+  return []
+}
+
+const mapSourceToForm = (source: Record<string, any> = {}) => {
+  form.elderName = source.elderName || ''
+  form.idCard = source.idCard || ''
+  form.recentLivingSituation = parseFileList(source.recentLivingSituation)
+  form.walkSituationVideo = parseFileList(source.walkSituationVideo)
+  form.medicalRecordsWithinSixMonth = parseFileList(source.medicalRecordsWithinSixMonth)
+  form.idCardPhoto = parseFileList(source.idCardPhoto)
+  form.recentDischargeSummary = parseFileList(source.recentDischargeSummary)
+  form.physicalExaminationReport = parseFileList(source.physicalExaminationReport)
+  form.remark = source.remark || ''
+}
+
+const getFileName = (file: any) => {
+  if (typeof file === 'string') {
+    return file.split('/').pop() || file
+  }
+  return file?.name || file?.fileName || file?.url || '-'
+}
+
+const init = async (id?: string) => {
+  if (!id) return
+  const res = await getWaitElderDetail(Number(id))
+  mapSourceToForm(res || {})
+}
+
+const submitForm = async () => {
+  return {
+    valid: true,
+    dataForm: { ...form }
+  }
+}
+
+const resetForm = () => {
+  form.elderName = ''
+  form.idCard = ''
+  form.recentLivingSituation = []
+  form.walkSituationVideo = []
+  form.medicalRecordsWithinSixMonth = []
+  form.idCardPhoto = []
+  form.recentDischargeSummary = []
+  form.physicalExaminationReport = []
+  form.remark = ''
+  formRef.value?.clearValidate?.()
+}
+
+const processType = ref<number | string>()
+const getProcess = async (id: number | string, type: number | string, _status: number | string) => {
+  const res = await getBusinessId(id)
+  await init(String(res.businessId))
+  processType.value = type
+}
+
+const setTenantId = (_tId: number | string) => {}
+
+defineExpose({ init, submitForm, getProcess, resetForm, setTenantId })
+</script>
+
+<style lang="scss" scoped>
+.wait-elder-form {
+  .view-value {
+    min-height: 32px;
+    line-height: 32px;
+    padding: 0 11px;
+    border: 1px solid var(--el-border-color);
+    border-radius: 4px;
+    background: var(--el-fill-color-blank);
+    color: var(--el-text-color-primary);
+  }
+
+  .view-files {
+    min-height: 32px;
+    padding: 8px 11px;
+    border: 1px solid var(--el-border-color);
+    border-radius: 4px;
+    background: var(--el-fill-color-blank);
+
+    .empty {
+      color: var(--el-text-color-secondary);
+    }
+
+    ul {
+      margin: 0;
+      padding-left: 18px;
+
+      li {
+        line-height: 24px;
+        color: var(--el-text-color-primary);
+      }
+    }
+  }
+}
+</style>

+ 113 - 0
src/views/elderly/elder/wait-elder/index.vue

@@ -0,0 +1,113 @@
+<template>
+  <!-- 搜索 -->
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="80px"
+    >
+      <TenantSelect v-model="queryParams.tenantIds" placeholder="请选择机构名称" prop="tenantIds"/>
+      <el-form-item label="长者姓名" prop="elderName">
+        <el-input @keyup.enter="handleQuery" clearable v-model="queryParams.elderName" placeholder="请输入长者姓名" class="!w-240px" />
+      </el-form-item>
+      <el-form-item label="审批状态" prop="bpmStatus">
+        <el-select v-model="queryParams.bpmStatus" placeholder="请选择" class="!w-240px" clearable>
+          <el-option
+            v-for="(dict, index) in getIntDictOptions(DICT_TYPE.APPROVAL_STATUS)"
+            :key="index"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <Table2
+      v-loading="loading"
+      :data="list"
+      :columns="WaitElderColumns"
+      :queryParams="queryParams"
+      @detail="openDetail"
+    />
+
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
+
+
+  <Detail ref="detailRef" />
+</template>
+<script lang="ts" setup>
+
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { getCheckInWaitPage } from '@/api/bpm/processInstance'
+import { WaitElderColumns } from '../column'
+import Detail from './Detail.vue'
+import { useUserStore } from '@/store/modules/user'
+defineOptions({ name: 'WaitElder' })
+const userStore = useUserStore()
+const loading = ref(true) // 列表的加载中
+const total = ref(0) // 列表的总页数
+const list = ref([]) // 列表的数据
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  elderName: undefined,
+  bpmStatus: undefined,
+  tenantIds: userStore.orgTenantId
+})
+const queryFormRef = ref() // 搜索的表单
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await getCheckInWaitPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = async () => {
+  if (!queryFormRef.value) return
+  const valid = await queryFormRef.value.validate()
+  if (!valid) return
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+// 详情
+const detailRef = ref()
+const openDetail = (row: any = {}) => {
+  detailRef.value.open(row.tenantId, row.id, row.processInstanceId, row.status)
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>

+ 1 - 0
src/views/warehouses/materialsIn/index.vue

@@ -23,6 +23,7 @@
             start-placeholder="开始日期"
             end-placeholder="结束日期"
             value-format="YYYY-MM-DD"
+            :unlink-panels="true"
           />
         </el-form-item>
         <el-form-item label="入库单号" prop="orderNo">

+ 1 - 0
src/views/warehouses/materialsOut/index.vue

@@ -23,6 +23,7 @@
             start-placeholder="开始日期"
             end-placeholder="结束日期"
             value-format="YYYY-MM-DD"
+            :unlink-panels="true"
           />
         </el-form-item>
         <el-form-item label="出库单号" prop="orderNo">