Bladeren bron

1.取消出入库搜索日期的面板联动2.优化审批流自定义表单代码3.优化审批流关于附件取值结构代码

xiongxing 3 maanden geleden
bovenliggende
commit
93f1f2ddc4

+ 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"

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

@@ -0,0 +1,55 @@
+<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: 'BakCheckOutDetail' })
+
+const dialogVisible = ref(false) // 弹窗
+const BusinessFormComponent = ref() // 异步组件
+const formRef = 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/processInstance/detail/index')
+  BusinessFormComponent.value = registerComponent('/bpm/task/process-list/process')
+  nextTick(() => {
+    processRef.value.setTenantId(tId)
+    processRef.value.init(id, true, status)
+  })
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+// watch(
+//   () => formRef.value,
+//   (val) => {
+//     val && val.init(1, businessKey.value, statusType.value, false)
+//   }
+// )
+
+// 关闭表单
+const handleClosed = () => {
+  dialogVisible.value = false
+}
+</script>

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

@@ -0,0 +1,204 @@
+<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="idCardNo" required>
+      <div class="view-value">{{ form.idCardNo || '-' }}</div>
+    </el-form-item>
+
+    <el-form-item label="院区" prop="campus" required>
+      <div class="view-value">{{ campusLabel(form.campus) }}</div>
+    </el-form-item>
+
+    <el-form-item label="近期生活状态(视频)" prop="lifeStatusVideo" required>
+      <div class="view-files">
+        <div v-if="!form.lifeStatusVideo.length" class="empty">-</div>
+        <ul v-else>
+          <li v-for="(item, index) in form.lifeStatusVideo" :key="`life-${index}`">{{ getFileName(item) }}</li>
+        </ul>
+      </div>
+    </el-form-item>
+
+    <el-form-item label="行走情况(视频)" prop="walkingVideo" required>
+      <div class="view-files">
+        <div v-if="!form.walkingVideo.length" class="empty">-</div>
+        <ul v-else>
+          <li v-for="(item, index) in form.walkingVideo" :key="`walk-${index}`">{{ getFileName(item) }}</li>
+        </ul>
+      </div>
+    </el-form-item>
+
+    <el-form-item label="近半年内病历" prop="medicalRecord" required>
+      <div class="view-files">
+        <div v-if="!form.medicalRecord.length" class="empty">-</div>
+        <ul v-else>
+          <li v-for="(item, index) in form.medicalRecord" :key="`medical-${index}`">{{ getFileName(item) }}</li>
+        </ul>
+      </div>
+    </el-form-item>
+
+    <el-form-item label="身份证正反面" prop="idCardImages" required>
+      <div class="view-files">
+        <div v-if="!form.idCardImages.length" class="empty">-</div>
+        <ul v-else>
+          <li v-for="(item, index) in form.idCardImages" :key="`idimg-${index}`">{{ getFileName(item) }}</li>
+        </ul>
+      </div>
+    </el-form-item>
+
+    <el-form-item label="近期出院小结(视频)" prop="dischargeSummaryVideo">
+      <div class="view-files">
+        <div v-if="!form.dischargeSummaryVideo.length" class="empty">-</div>
+        <ul v-else>
+          <li v-for="(item, index) in form.dischargeSummaryVideo" :key="`discharge-${index}`">{{ getFileName(item) }}</li>
+        </ul>
+      </div>
+    </el-form-item>
+  </el-form>
+</template>
+
+<script setup lang="ts">
+import { getBusinessId } from '@/api/elderly/common'
+import { getBedChangeRecordById, getBedChangeRecordElderlyById } from '@/api/elderly/elder/bed-change'
+
+defineOptions({ name: 'BedChangeProcessForm' })
+
+const formRef = ref()
+
+const form = reactive({
+  elderName: '',
+  idCardNo: '',
+  campus: '',
+  lifeStatusVideo: [] as any[],
+  walkingVideo: [] as any[],
+  medicalRecord: [] as any[],
+  idCardImages: [] as any[],
+  dischargeSummaryVideo: [] as any[]
+})
+
+const rules = reactive({})
+
+const campusOptions = ref<{ label: string; value: string }[]>([])
+
+const parseToArray = (value: any) => {
+  if (!value) return []
+  if (Array.isArray(value)) return value
+  if (typeof value === 'string') {
+    try {
+      const parsed = JSON.parse(value)
+      return Array.isArray(parsed) ? parsed : []
+    } catch (_e) {
+      return []
+    }
+  }
+  return []
+}
+
+const mapSourceToForm = (source: Record<string, any> = {}) => {
+  form.elderName = source.elderName || source.name || ''
+  form.idCardNo = source.idCardNo || source.idCard || ''
+  form.campus = source.campus || source.campusId || ''
+  form.lifeStatusVideo = parseToArray(source.lifeStatusVideo)
+  form.walkingVideo = parseToArray(source.walkingVideo)
+  form.medicalRecord = parseToArray(source.medicalRecord)
+  form.idCardImages = parseToArray(source.idCardImages)
+  form.dischargeSummaryVideo = parseToArray(source.dischargeSummaryVideo)
+}
+
+const campusLabel = (value: string) => {
+  const item = campusOptions.value.find((it) => it.value === value)
+  return item?.label || value || '-'
+}
+
+const getFileName = (file: any) => {
+  return file?.name || file?.fileName || file?.url || '-'
+}
+
+const init = async (id?: string, _detail?: boolean, status?: string, elderly = undefined as any) => {
+  if (elderly?.elderId) {
+    const elderInfo = await getBedChangeRecordElderlyById(elderly.elderId)
+    mapSourceToForm(elderInfo || {})
+  }
+
+  if (id) {
+    const res = await getBedChangeRecordById(id, status, true)
+    mapSourceToForm(res || {})
+  }
+}
+
+const submitForm = async () => {
+  return {
+    valid: true,
+    dataForm: { ...form }
+  }
+}
+
+const resetForm = () => {
+  form.elderName = ''
+  form.idCardNo = ''
+  form.campus = ''
+  form.lifeStatusVideo = []
+  form.walkingVideo = []
+  form.medicalRecord = []
+  form.idCardImages = []
+  form.dischargeSummaryVideo = []
+  formRef.value?.clearValidate?.()
+}
+
+const processType = ref()
+const getProcess = async (id, type, status) => {
+  const res = await getBusinessId(id)
+  await init(res.businessId, true, status)
+  processType.value = type
+}
+
+const setTenantId = (_tId) => {}
+
+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" v-model="queryParams.elderName" placeholder="请输入长者姓名" class="!w-240px" />
+      </el-form-item>
+      <el-form-item label="审批状态" prop="type">
+        <el-select v-model="queryParams.type" placeholder="请选择" class="!w-240px">
+          <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="BedChangeColumns"
+      :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 { getBedChangePage } from '@/api/elderly/elder/bed-change'
+import { BedChangeColumns } from '../column'
+import Detail from './Detail.vue'
+import { useUserStore } from '@/store/modules/user'
+defineOptions({ name: 'BedChange' })
+const userStore = useUserStore()
+const loading = ref(true) // 列表的加载中
+const total = ref(0) // 列表的总页数
+const list = ref([]) // 列表的数据
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  elderName: undefined,
+  expectId: undefined,
+  type: undefined,
+  tenantIds: userStore.orgTenantId
+})
+const queryFormRef = ref() // 搜索的表单
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await getBedChangePage(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">