Преглед изворни кода

优化辨识仪配置的布局上下固定 中间自适应

张田田 пре 6 месеци
родитељ
комит
7bf3c32845

+ 46 - 246
src/components/EditConfigured.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import { VxeUI, type VxeFormProps, type VxeFormListeners } from 'vxe-pc-ui';
 import { useRequest } from 'alova/client';
 import { getDeviceManageDetailMethod, updateDeviceManageMethod } from '@/request/api/device.api';
 import { branchMethod } from '@/request/api/system.api';
@@ -23,16 +22,11 @@ const getDetail = async () => {
     const res = await getDeviceManageDetailMethod(props.data);
     if (res && JSON.stringify(res) !== '{}') {
       flowData.value = { ...res } as FlowRequestData;
-      console.log(flowData.value, 'flowData.value');
       loading.value = false;
       model.value = { ...res };
     }
   } catch (error: any) {
     console.error(error, 'error');
-    // notification.error({
-    //   message: error?.message,
-    //   // description: error?.message ?? '获取一体机配置详情失败',
-    // });
     loading.value = false;
   }
 };
@@ -63,107 +57,13 @@ useRequest(branchMethod(0, 1, 1)).onSuccess(({ data }) => {
 const { loading: submitting, send: submit } = useRequest(updateDeviceManageMethod, { immediate: false }).onSuccess(() => {
   emits('submit');
 });
-// (配置弹窗无需设备名称下拉,保留最小依赖)
-// const showDept = ref(false);
-// const insArr = ref<any[]>([]);
-// const insLoading = ref(false);
-// async function getInstitution(orgId: string | number) {
-//   insLoading.value = true;
-//   const res = await branchMethod(1, 0, Number(orgId));
-//   if (res && res.length > 0) {
-//     insArr.value = res;
-//   }
-//   insLoading.value = false;
-// }
-// watch(
-//   () => model.value?.orgId,
-//   async (newVal, oldVal) => {
-//     showDept.value = !!newVal;
-//     if (showDept.value) {
-//       // 加载机构列表,确保编辑时机构名称可显示
-//       await getInstitution(newVal ?? '');
-//     } else {
-//       insArr.value = [];
-//     }
-//     // 仅当组织实际发生切换时清空机构
-//     if (oldVal !== undefined && newVal !== oldVal) {
-//       model.value.institutionId = '';
-//     }
-//   },
-//   { immediate: true }
-// );
-// 顶部摘要展示用
-// 概要信息直接在模板中从 model 读取
-const formItems = computed(() => {
-  const baseItems: any[] = [
-    { field: 'summary', span: 24, slots: { default: 'summarySlot' } },
-    { field: 'processConfig', span: 24, slots: { default: 'processConfigSlot' } },
-    { align: 'center', span: 24, slots: { default: 'active' } },
-  ];
 
-  // 摘要展示不需要机构选择器
-
-  return baseItems;
-});
-
-const formProps = reactive<VxeFormProps>({
-  titleWidth: 100,
-  titleAlign: 'right',
-  titleColon: true,
-  data: computed(() => model.value),
-  items: [] as any, // 临时设置为空数组,我们将在模板中使用动态items
-  rules: {},
-});
-
-// const formEmits: VxeFormListeners = {
-//   submit({ data }) {
-//     // submit(data).then(() => {
-//     //   notification.success({
-//     //     message: '操作成功',
-//     //   });
-//     //   VxeUI.modal.close('equipment-modal');
-//     // });
-//   },
-// };
-
-// 设备ID增删在本弹窗不需要
-
-// onBeforeMount(async () => {
-//   if (props.data) {
-//     model.value = { ...defaultModel, ...props.data };
-//   }
-// });
-// const mock = () => {
-//   return {
-//     tabletProcessModules: ['patient_file', 'tongueface_upload', 'tongueface_analysis', 'alcohol_upload_result', 'health_analysis?'],
-//     tabletFileFields: ['phone:required', 'cardno', 'name', 'sex', 'age', 'height', 'weight', 'is_easy_allergy'],
-//     tabletRequiredPageOperationElements: [
-//       'tongueface_upload_report_page_appletscan',
-//       'health_analysis_report_page_appletbutton',
-//       'health_analysis_report_page_appletscan',
-//       'health_analysis_scheme_page_appletbutton',
-//     ],
-//     technicalSupporter: '杭州六智科技有限公司',
-//   };
-// };
-// const request = (timeout = 1000) => {
-//   loading.value = true;
-//   // setTimeout(() => {
-//   flowData.value = mock();
-//   console.log(flowData.value, '111');
-//   loading.value = false;
-//   // }, timeout);
-// };
-// 模拟请求
-// request();
 const flowRef = useTemplateRef<InstanceType<typeof AioFlowConfig>>('flow');
 const save = async () => {
   // 改为仅透传提交事件,由父级统一关闭弹窗,避免重复 close 导致内部状态异常
   try {
     await flowRef.value!.validate(/* 传入 false 不展示错误信息 */ true);
     flowData.value!.id = model.value?.id as string;
-    // emits('submit', flowData.value as any);
-    console.log('获取修改的数据', flowData.value);
     submit(flowData.value as any);
   } catch (error: any) {
     console.error('保存错误', error.message);
@@ -176,176 +76,76 @@ const reset = () => {
 
 <template>
   <div class="form-container">
-    <vxe-form
-      :title-width="formProps.titleWidth"
-      :title-align="formProps.titleAlign"
-      :title-colon="formProps.titleColon"
-      :data="formProps.data"
-      :items="formItems"
-      :rules="formProps.rules"
-      :loading="submitting"
-    >
-      <template #deviceIdTitleSlot> <span style="color: #f56c6c; font-size: 20px">*</span> 设备ID </template>
-
-      <template #summarySlot>
-        <div class="summary-container">
-          <div class="summary-item mb-3">
-            <span class="label" v-if="model && model.warrant">设备ID:</span><span class="value">{{ model.warrant }}</span>
-          </div>
-          <div class="flex">
-            <div class="summary-item mr-6" v-if="model && model.orgName">
-              <span class="label">组织名称:</span><span class="value">{{ model.orgName }}</span>
-            </div>
-            <div class="summary-item" v-if="model && model.institutionName">
-              <span class="label">机构名称:</span><span class="value">{{ model.institutionName }}</span>
-            </div>
-          </div>
+    <div class="summary-container">
+      <div class="summary-item mb-3">
+        <span class="label" v-if="model?.warrant">设备ID:</span><span class="value">{{ model.warrant }}</span>
+      </div>
+      <div class="flex">
+        <div class="summary-item mr-6" v-if="model && model.orgName">
+          <span class="label">组织名称:</span><span class="value">{{ model.orgName }}</span>
         </div>
-      </template>
-
-      <template #processConfigSlot>
-        <div class="flex-auto content-container">
-          <div class="title">流程配置</div>
-          <span class="section-divider"></span>
-          <!-- validate 方法通过后会自动更新 -->
-          <AioFlowConfig ref="flow" :loading="loading" v-model:request-data="flowData"></AioFlowConfig>
+        <div class="summary-item" v-if="model && model.institutionName">
+          <span class="label">机构名称:</span><span class="value">{{ model.institutionName }}</span>
         </div>
-      </template>
-
-      <template #active>
-        <vxe-button type="reset" content="重置" @click="reset()"></vxe-button>
-        <vxe-button type="submit" status="primary" content="保存" @click="save()"></vxe-button>
-      </template>
-    </vxe-form>
+      </div>
+    </div>
+    <!-- 流程配置 -->
+    <div class="content-container">
+      <div class="title">流程配置</div>
+      <span class="section-divider"></span>
+      <!-- validate 方法通过后会自动更新 -->
+      <AioFlowConfig ref="flow" :loading="loading" v-model:request-data="flowData"></AioFlowConfig>
+    </div>
+    <!-- 保存和重置 -->
+    <div class="button-container">
+      <vxe-button type="reset" content="重置" @click="reset()"></vxe-button>
+      <vxe-button type="submit" status="primary" content="保存" @click="save()" :loading="submitting"></vxe-button>
+    </div>
   </div>
 </template>
 
 <style scoped lang="scss">
+.form-container {
+  padding: 20px;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+}
+
+.summary-container {
+  flex: none;
+  margin-bottom: 20px;
+}
+
 .content-container {
-  width: 100%;
-  height: 600px;
+  flex: 1;
   display: flex;
   flex-direction: column;
+  min-height: 0; 
   > div:not(.title) {
     flex: auto;
+    overflow: auto; 
   }
   > .title {
     flex: none;
-    padding: 12px;
+    padding: 12px 12px 12px 0;
     font-size: 16px;
     font-weight: 800;
   }
 }
+
 .section-divider {
   height: 1px !important;
   background-color: #d9d9d9;
   margin-bottom: 15px !important;
 }
-.form-container {
-  padding: 20px;
-}
 
-.device-ids-container {
+.button-container {
+  flex: none;
   display: flex;
-  flex-direction: row;
-  flex-wrap: wrap;
-  gap: 8px;
-  align-items: flex-start;
-
-  .device-id-item {
-    display: flex;
-    align-items: center;
-    gap: 8px;
-    margin-bottom: 8px;
-  }
-}
-
-.section-container {
-  width: 100%;
-  height: 800px;
-  margin-bottom: 20px;
-  .section-title {
-    font-size: 16px;
-    font-weight: bold;
-    margin-bottom: 10px;
-    color: #333;
-  }
-}
-
-.process-config {
-  .config-item {
-    display: flex;
-    align-items: center;
-    margin-bottom: 16px;
-    flex-wrap: wrap;
-    gap: 8px;
-
-    .config-label {
-      font-weight: bold;
-      min-width: 80px;
-    }
-
-    .report-label {
-      margin-left: 40px;
-      color: #666;
-      margin-right: 10px;
-    }
-
-    .radio-group {
-      display: flex;
-      align-items: center;
-      gap: 30px;
-
-      .radio-item {
-        display: flex;
-        align-items: center;
-        gap: 4px;
-        cursor: pointer;
-
-        input[type='radio'] {
-          margin: 0;
-          cursor: pointer;
-        }
-
-        span {
-          font-size: 14px;
-        }
-      }
-
-      .badge {
-        background-color: #faad14;
-        color: white;
-        border-radius: 12px;
-        padding: 2px 8px;
-        font-size: 12px;
-        min-width: 20px;
-        text-align: center;
-      }
-    }
-  }
-}
-
-:deep(.vxe-form--item) {
-  .vxe-form--item-wrapper {
-    .vxe-form--item-content {
-      .vxe-input {
-        width: 100%;
-      }
-    }
-  }
-}
-
-.required-field {
-  :deep(.vxe-form--item-title) {
-    position: relative;
-
-    &::before {
-      content: '*';
-      color: #ff4d4f;
-      position: absolute;
-      left: -8px;
-      top: 0;
-    }
-  }
+  justify-content: center;
+  align-items: center;
+  gap: 16px;
+  padding-top: 20px;
 }
 </style>

+ 0 - 3
src/components/EditEquirement.vue

@@ -69,13 +69,11 @@ async function getDeviceType() {
   deviceTypesLoading.value = true;
   const res = await getDictionaryMethod('fdhb_device_type');
   if (res && res.length > 0) {
-    console.log(res, 'res==>');
     deviceTypes.value = res.map((item: any) => ({
       id: item.value,
       name: item.label,
     }));
   }
-  console.log(deviceTypes.value, 'deviceTypes==>');
   // 设备类型加载后,若当前值是名称则映射成对应的id
   normalizeDeviceTypeToId();
   deviceTypesLoading.value = false;
@@ -249,7 +247,6 @@ const formEmits: VxeFormListeners = {
       data.deviceCode = data.deviceIds[0];
     }
     data.remark ??= '';
-    console.log(data, 'data==>');
     submit(data).then(() => {
       notification.success({
         message: '操作成功',

+ 25 - 159
src/components/EditMoreConfigured.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import { type VxeFormProps, type VxeFormListeners } from 'vxe-pc-ui';
 import { useRequest } from 'alova/client';
 import { batchUpdateDeviceManageMethod, getDeviceManageDetailMethod, updateDeviceManageMethod } from '@/request/api/device.api';
 import { notification } from 'ant-design-vue';
@@ -7,7 +6,7 @@ import { AioFlowConfig, type FlowRequestData } from '@/pages/aio/flow-config/ind
 import type { DeviceManageModel } from '@/model/device.model';
 const flowData = ref<FlowRequestData>();
 const loading = ref(false);
-const defaultModel: DeviceManageModel = {};
+// const defaultModel: DeviceManageModel = {};
 
 const props = defineProps<{ data: DeviceManageModel[] }>();
 
@@ -16,44 +15,23 @@ const emits = defineEmits<{
   submitSingle: [];
 }>();
 
-const model = ref<DeviceManageModel>({ ...defaultModel });
-
-watchEffect(() => {
-  if (props.data) {
-    model.value = { ...defaultModel, ...props.data };
-  }
-});
-
+// 批量修改
 const { loading: submitting, send: submit } = useRequest(batchUpdateDeviceManageMethod, { immediate: false }).onSuccess(() => {
   emits('submit');
   notification.success({ message: '修改成功' });
 });
+// 单个修改
 const { loading: submittingSingle, send: submitSingle } = useRequest(updateDeviceManageMethod, { immediate: false }).onSuccess(() => {
   emits('submitSingle');
   notification.success({ message: '修改成功' });
 });
-// 右侧设备列表(兼容数组/对象形式)
-const tableData = computed<any[]>(() => {
+// 右侧设备列表
+const tableData = computed<DeviceManageModel[]>(() => {
   const src = props.data as any;
   if (Array.isArray(src)) return src;
   if (src && Array.isArray(src.data)) return src.data;
   return src ? [src] : [];
 });
-const formItems = computed<any[]>(() => {
-  return [
-    { field: 'processConfig', span: 24, slots: { default: 'processConfigSlot' } },
-    { field: 'actions', span: 24, slots: { default: 'active' } },
-  ];
-});
-
-const formProps = reactive<VxeFormProps>({
-  titleWidth: 100,
-  titleAlign: 'right',
-  titleColon: true,
-  data: computed(() => model.value),
-  items: [] as any, // 临时设置为空数组,我们将在模板中使用动态items
-  rules: {},
-});
 
 // 设备ID增删在批量配置不需要
 let ids = ref<string[]>([]);
@@ -62,7 +40,6 @@ onBeforeMount(async () => {
     props.data?.forEach((item: any) => {
       ids.value.push(item.id);
     });
-    model.value = { ...(Array.isArray(props.data) ? {} : props.data) };
     flowData.value = mock();
   } else if (props.data && props.data.length === 1) {
     flowData.value = (await getDeviceManageDetailMethod({ id: props.data[0].id })) as FlowRequestData;
@@ -83,6 +60,7 @@ const mock = () => {
   };
 };
 const flowRef = useTemplateRef<InstanceType<typeof AioFlowConfig>>('flow');
+// 保存
 const save = async () => {
   // 改为仅透传提交事件,由父级统一关闭弹窗,避免重复 close 导致内部状态异常
   await flowRef.value!.validate(/* 传入 false 不展示错误信息 */ true);
@@ -100,32 +78,20 @@ const reset = () => {
 <template>
   <div class="two-pane">
     <div class="left form-container">
-      <vxe-form
-        :title-width="formProps.titleWidth"
-        :title-align="formProps.titleAlign"
-        :title-colon="formProps.titleColon"
-        :data="formProps.data"
-        :items="formItems"
-        :rules="formProps.rules"
-        :loading="submitting"
-      >
-        <template #processConfigSlot>
-          <div class="flex-auto content-container">
-            <div class="title">流程配置</div>
-            <!-- validate 方法通过后会自动更新 -->
-            <AioFlowConfig ref="flow" :loading="loading" v-model:request-data="flowData"></AioFlowConfig>
-          </div>
-        </template>
+      <!-- 流程配置 -->
+      <div class="flex-auto content-container">
+        <div class="title">流程配置</div>
+        <!-- validate 方法通过后会自动更新 -->
+        <AioFlowConfig ref="flow" :loading="loading" v-model:request-data="flowData"></AioFlowConfig>
+      </div>
 
-        <template #active>
-          <div style="text-align: center">
-            <vxe-button type="reset" content="重置" @click="reset()"></vxe-button>
-            <vxe-button type="submit" status="primary" content="保存" @click="save()"></vxe-button>
-          </div>
-        </template>
-      </vxe-form>
+      <!-- 保存和重置 -->
+      <div class="button-container">
+        <vxe-button type="reset" content="重置" @click="reset()"></vxe-button>
+        <vxe-button type="submit" status="primary" content="保存" @click="save()" :loading="submitting || submittingSingle"></vxe-button>
+      </div>
     </div>
-
+    <!-- 右侧设备列表 -->
     <div class="right table-container">
       <div class="table-title">待配置设备</div>
       <div class="table-wrapper">
@@ -199,117 +165,17 @@ const reset = () => {
 .form-container {
   padding: 20px;
 }
-
-.device-ids-container {
-  display: flex;
-  flex-direction: row;
-  flex-wrap: wrap;
-  gap: 8px;
-  align-items: flex-start;
-
-  .device-id-item {
-    display: flex;
-    align-items: center;
-    gap: 8px;
-    margin-bottom: 8px;
-  }
-}
 .section-divider {
   height: 1px;
   background-color: #d9d9d9;
   margin-bottom: 15px;
 }
-.section-container {
-  margin-bottom: 20px;
-
-  .section-title {
-    font-size: 16px;
-    font-weight: bold;
-    margin-bottom: 10px;
-    color: #333;
-  }
-
-  .section-divider {
-    height: 1px;
-    background-color: #d9d9d9;
-    margin-bottom: 15px;
-  }
-}
-
-.process-config {
-  .config-item {
-    display: flex;
-    align-items: center;
-    margin-bottom: 16px;
-    flex-wrap: wrap;
-    gap: 8px;
-
-    .config-label {
-      font-weight: bold;
-      min-width: 80px;
-    }
-
-    .report-label {
-      margin-left: 40px;
-      color: #666;
-      margin-right: 10px;
-    }
-
-    .radio-group {
-      display: flex;
-      align-items: center;
-      gap: 30px;
-
-      .radio-item {
-        display: flex;
-        align-items: center;
-        gap: 4px;
-        cursor: pointer;
-
-        input[type='radio'] {
-          margin: 0;
-          cursor: pointer;
-        }
-
-        span {
-          font-size: 14px;
-        }
-      }
-
-      .badge {
-        background-color: #faad14;
-        color: white;
-        border-radius: 12px;
-        padding: 2px 8px;
-        font-size: 12px;
-        min-width: 20px;
-        text-align: center;
-      }
-    }
-  }
-}
-
-:deep(.vxe-form--item) {
-  .vxe-form--item-wrapper {
-    .vxe-form--item-content {
-      .vxe-input {
-        width: 100%;
-      }
-    }
-  }
-}
-
-.required-field {
-  :deep(.vxe-form--item-title) {
-    position: relative;
-
-    &::before {
-      content: '*';
-      color: #ff4d4f;
-      position: absolute;
-      left: -8px;
-      top: 0;
-    }
-  }
+.button-container {
+  flex: none;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  gap: 16px;
+  padding-top: 20px;
 }
 </style>

+ 1 - 0
src/model/device.model.ts

@@ -22,6 +22,7 @@ export type EquirementQuery = Partial<EquirementModel>;
 
 export interface DeviceManageModel{
   id?:string; //一体机id
+  warrant?:string; // 设备ID
   partner?:string; // 合作伙伴
   technicalSupporter?:string; // 技术支持
   tabletProcessModules?:string[]; // 流程模块