Kaynağa Gözat

完成脚本确认

chauncey 9 ay önce
ebeveyn
işleme
a0a8adbeee

+ 11 - 0
src/api/emergency-drill/emergency-drill.ts

@@ -112,3 +112,14 @@ export const getDrillSignList = (data: QueryPageRequest<DrillSignlistQuery>) =>
     data,
   });
 };
+
+/**
+ * 确认演练脚本
+ */
+export const signDrillScript = (data: { drillPlanId: number; planToParticipateCount: number }) => {
+  return http.request({
+    url: '/emergencyDrill/signEmergencyDrillScript',
+    method: 'post',
+    data,
+  });
+};

+ 1 - 0
src/components/BasicDialog.vue

@@ -34,6 +34,7 @@
   .basic-dialog-container {
     display: flex;
     flex-direction: column;
+    gap: 20px;
     align-items: space-between;
     height: 100%;
   }

+ 10 - 4
src/components/BasicSearch.vue

@@ -26,22 +26,28 @@
 </template>
 
 <script lang="ts" setup>
-import type { SearchConfig } from '@/types/basic-search';
+  import type { SearchConfig } from '@/types/basic-search';
   const props = defineProps<{
     searchConfig: SearchConfig[];
     searchData: any;
+    customReset?: boolean;
   }>();
-  const emit = defineEmits<{
+  const emits = defineEmits<{
     (e: 'update:searchData'): void;
+    (e: 'custom-reset'): void;
   }>();
   const handleSearch = () => {
-    emit('update:searchData');
+    emits('update:searchData');
   };
   const handleReset = () => {
+    if (props.customReset) {
+      emits('custom-reset');
+      return;
+    }
     for (const key in props.searchData) {
       props.searchData[key] = null;
     }
-    emit('update:searchData');
+    emits('update:searchData');
   };
 </script>
 

+ 2 - 2
src/router/routers/emergency.ts

@@ -258,9 +258,9 @@ const emergencyManagementRoute = {
           parentId: 2009,
           component: '/emergency/emergency-drill/PageDrillSignItem',
           name: 'emergency-drill-sign-item',
-          path: 'emergency-drill-sign-item',
+          path: 'emergency-drill-sign-item/:id',
           meta: {
-            activeMenu: '/emergency-drill/emergency-drill-sign',
+            activeMenu: '/emergency-management/emergency-drill/emergency-drill-sign',
             title: '演练会签详情',
             hidden: true,
           },

+ 0 - 1
src/styles/common.scss

@@ -51,7 +51,6 @@
 }
 
 .el-dialog {
-  min-height: 500px;
   .el-dialog__title {
     color: rgba(0, 0, 0, 0.88);
     font-weight: 600;

+ 0 - 1
src/styles/custom-component.scss

@@ -21,7 +21,6 @@
 }
 
 .basic-dialog--custom {
-  height: 500px;
   max-height: 60vh;
   overflow-y: auto;
   display: flex;

+ 1 - 0
src/types/emergency-drill/index.ts

@@ -14,6 +14,7 @@ export interface DrillSignlistQuery extends Omit<DrillSignSearch, 'drillTime'> {
 }
 
 export interface DrillSignListResponse {
+  drillPlanId: number;
   signType: number;
   drillScope: string;
   drillContent: string;

+ 28 - 25
src/views/emergency/emergency-drill/PageDrillSignItem.vue

@@ -4,43 +4,46 @@
       <BreadcrumbBack />
       <span class="breadcrumb-title">{{ headerTitle }}</span>
     </header>
-    <main class="safety-platform-container__main">
-      <component :is="dynamicComponent" :id="id" ref="dynamicComponentRef" />
-    </main>
-    <footer class="safety-platform-container__footer" v-if="operate">
-      <!-- 提交按钮 -->
-    </footer>
-    <UploadLoading :form-loading="formLoading" v-if="formLoading" />
+    <component :is="dynamicComponent" :id="id" :status="status" />
   </div>
 </template>
 
 <script setup lang="ts">
-  import UploadLoading from '@/components/UploadLoading.vue';
-  import { ref, computed, defineAsyncComponent } from 'vue';
   import { useRoute } from 'vue-router';
+  import { computed, defineAsyncComponent } from 'vue';
+  import { DRILL_SIGN_TYPE } from './constants';
 
-  const formLoading = ref(false);
   const route = useRoute();
-  const operate = route.query.operate;
-  const id = route.query.id;
+  const id = route.params.id;
+  const type = Number(route.query.type);
+  const status = Number(route.query.status);
   const headerTitle = computed(() => {
-    switch (operate) {
-      case 'script':
-        return `演练脚本确认`;
-      case 'record':
-        return `演练记录确认`;
-      default:
-        return '未知操作';
+    let title;
+    if (type === DRILL_SIGN_TYPE.SCRIPT) {
+      title = '脚本';
+    } else if (type === DRILL_SIGN_TYPE.RECORD) {
+      title = '评估报告';
+    } else {
+      title = '';
     }
+    return `演练${title}确认`;
   });
   const dynamicComponent = computed(() => {
-    switch (operate) {
-      case 'script':
-        return defineAsyncComponent(() => import('./components/DrillSignScriptItem.vue'));
-      case 'record':
-        return defineAsyncComponent(() => import('./components/DrillSignRecordItem.vue'));
+    if (type === DRILL_SIGN_TYPE.SCRIPT) {
+      return defineAsyncComponent(() => import('./components/DrillSignScriptItem.vue'));
+    } else if (type === DRILL_SIGN_TYPE.RECORD) {
+      return defineAsyncComponent(() => import('./components/DrillSignRecordItem.vue'));
+    } else {
+      return '';
     }
   });
 </script>
 
-<style scoped></style>
+<style lang="scss" scoped>
+  @use '@/styles/page-details-layout.scss' as *;
+  .safety-platform-container__header {
+    flex-direction: row !important;
+    justify-content: flex-start !important;
+    gap: 8px !important;
+  }
+</style>

+ 50 - 3
src/views/emergency/emergency-drill/PageDrillSignList.vue

@@ -30,16 +30,39 @@
             />
           </template>
         </BasicSearch>
-        <BasicTable :table-data="tableData" :table-config="tableConfig"> </BasicTable>
+        <BasicTable
+          :table-data="tableData"
+          :table-config="tableConfig"
+          @update:pageSize="handleSizeChange"
+          @update:pageNumber="handleCurrentChange"
+        >
+          <template #signType="scope">
+            <span>{{ DRILI_SIGN_TYPE_MAP[scope.row.signType] }}</span>
+          </template>
+          <template #drillScope="scope">
+            <span>{{ getDrillScope(scope.row.drillScope) }}</span>
+          </template>
+          <template #confirmStatus="scope">
+            <span>{{ CONFIRM_STATUS_MAP[scope.row.confirmStatus] }}</span>
+          </template>
+          <template #action="scope">
+            <ActionButton
+              text="查看"
+              @click="handleView(scope.row.drillPlanId, scope.row.signType, scope.row.confirmStatus)"
+            />
+          </template>
+        </BasicTable>
       </div>
     </main>
   </div>
 </template>
 
 <script setup lang="ts">
+  import { useRouter } from 'vue-router';
   import { onMounted, reactive, ref } from 'vue';
   import BasicSearch from '@/components/BasicSearch.vue';
   import BasicTable from '@/components/BasicTable.vue';
+  import ActionButton from '@/components/ActionButton.vue';
   import { useEmergencyDrillHook } from './hook';
   import useTableConfig from '@/hooks/useTableConfigHook';
   import type { QueryPageRequest } from '@/types/basic-query';
@@ -50,10 +73,12 @@
     DRILL_SIGN_LIST_TABLE_OPTIONS,
     DRILI_SIGN_LIST_TABLE_COLUMNS,
   } from './configs/sign';
+  import { DRILI_SIGN_TYPE_MAP, CONFIRM_STATUS_MAP } from './constants';
   import dayjs from 'dayjs';
 
-  const { drillScopeDice, getDrillScopeDict } = useEmergencyDrillHook();
+  const { drillScopeDice, getDrillScopeDict, getDrillScope } = useEmergencyDrillHook();
   const { tableConfig, pagination } = useTableConfig(DRILI_SIGN_LIST_TABLE_COLUMNS, DRILL_SIGN_LIST_TABLE_OPTIONS);
+  const router = useRouter();
   const searchData = reactive<DrillSignSearch>({
     signType: null,
     drillScope: null,
@@ -68,7 +93,7 @@
   };
   const handleSearch = () => {
     drillSignListQuery.queryParam = {};
-    if (searchData.signType !== null) {
+    if (searchData.signType) {
       drillSignListQuery.queryParam.signType = searchData.signType;
     }
     if (searchData.drillScope) {
@@ -94,6 +119,28 @@
     pagination.total = res.totalRow;
     tableConfig.loading = false;
   };
+  const handleSizeChange = (value: number) => {
+    pagination.pageSize = value;
+    drillSignListQuery.pageSize = value;
+    getTableData();
+  };
+  const handleCurrentChange = (value: number) => {
+    pagination.pageNumber = value;
+    drillSignListQuery.pageNumber = value;
+    getTableData();
+  };
+  const handleView = (id: number, type: number, status: number) => {
+    router.push({
+      name: 'emergency-drill-sign-item',
+      params: {
+        id,
+      },
+      query: {
+        type,
+        status,
+      },
+    });
+  };
   onMounted(() => {
     getDrillScopeDict();
     getTableData();

+ 102 - 0
src/views/emergency/emergency-drill/components/DrillActivity.vue

@@ -0,0 +1,102 @@
+<template>
+  <div class="drill-activity-container">
+    <div class="drill-container__title">
+      <div class="drill-container--line"></div>
+      <span>演练活动</span>
+    </div>
+    <div class="drill-container__content">
+      <el-row :gutter="20">
+        <el-col :span="8">
+          <div class="drill-container__content--item">
+            <span class="label">演练规模:</span>
+            <span class="value">{{ getDrillScope(drillPlanItemDetail.drillScope) }}</span>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="drill-container__content--item">
+            <span class="label">演练内容:</span>
+            <span class="value">{{ drillPlanItemDetail.drillContent }}</span>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="drill-container__content--item">
+            <span class="label">计划完成时间:</span>
+            <span class="value">{{ drillPlanItemDetail.dueCompleteTime }}</span>
+          </div>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="8">
+          <div class="drill-container__content--item">
+            <span class="label">责任部门:</span>
+            <template
+              v-for="(dept, index) in safatyJsonParse(drillPlanItemDetail.responsibleDeptNameList)"
+              :key="index"
+            >
+              <span class="value">
+                {{ dept }}
+                <span v-if="index !== safatyJsonParse(drillPlanItemDetail.responsibleDeptNameList).length - 1">、</span>
+              </span>
+            </template>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="drill-container__content--item" v-if="drillPlanItemDetail.coordinateDeptNameList">
+            <span class="label">配合部门:</span>
+            <template v-for="(dept, index) in safatyJsonParse(drillPlanItemDetail.coordinateDeptNameList)" :key="index">
+              <span class="value">
+                {{ dept }}
+                <span v-if="index !== safatyJsonParse(drillPlanItemDetail.coordinateDeptNameList).length - 1">、</span>
+              </span>
+            </template>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="drill-container__content--item">
+            <span class="label">关联应急预案:</span>
+            <span class="value font-primary">应急预案还没做</span>
+          </div>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col>
+          <div class="drill-container__content--item">
+            <span class="label">审批流程:</span>
+            <span class="value">{{ getApprovalName(drillPlanItemDetail.approvalTemplateId) }}</span>
+          </div>
+        </el-col>
+      </el-row>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { ref, onMounted } from 'vue';
+  import { useEmergencyDrillHook } from '../hook';
+  import { DrillPlanItemDetail } from '../types';
+  import { ApprovalInstanceType } from '@/views/system/approval/types';
+  import { getAllApproval } from '@/api/approval/approval';
+
+  const approvalList = ref<ApprovalInstanceType[]>([]);
+  const { getDrillScopeDict, getDrillScope } = useEmergencyDrillHook();
+  const safatyJsonParse = (str: string) => {
+    return str.slice(1, -1).split(',');
+  };
+  const getApprovalList = async () => {
+    approvalList.value = await getAllApproval();
+  };
+  const getApprovalName = (id: number) => {
+    return approvalList.value.find((item) => item.id === id)?.templateName;
+  };
+  defineProps<{
+    drillPlanItemDetail: DrillPlanItemDetail;
+  }>();
+  onMounted(() => {
+    getDrillScopeDict();
+    getApprovalList();
+  });
+</script>
+
+<style lang="scss" scoped>
+  @use '../style/common.scss' as *;
+</style>

+ 73 - 0
src/views/emergency/emergency-drill/components/DrillImplementation.vue

@@ -0,0 +1,73 @@
+<template>
+  <div class="drill-activity-container">
+    <div class="drill-container__title">
+      <div class="drill-container--line"></div>
+      <span>演练实施</span>
+    </div>
+    <div class="drill-container__content">
+      <el-row :gutter="20">
+        <el-col :span="8">
+          <div class="drill-container__content--item">
+            <span class="label">演练时间:</span>
+            <span class="value">{{ drillPlanItemDetail.drillTime }}</span>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="drill-container__content--item">
+            <span class="label">演练地点:</span>
+            <span class="value">{{ drillPlanItemDetail.drillLocation }}</span>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="drill-container__content--item">
+            <span class="label">演练负责人:</span>
+            <span class="value">{{ drillPlanItemDetail.personInChargeName }}</span>
+          </div>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="8">
+          <div class="drill-container__content--item" v-if="drillPlanItemDetail.drillScript">
+            <span class="label">演练脚本:</span>
+            <span class="value font-primary link" @click="handlePreviewScript(drillPlanItemDetail.drillScript)">{{
+              JSON.parse(drillPlanItemDetail.drillScript).fileName
+            }}</span>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="drill-container__content--item">
+            <span class="label">签到码:</span>
+            <span class="value font-primary">APP端还没做</span>
+          </div>
+        </el-col>
+      </el-row>
+    </div>
+    <PreviewOnline ref="previewOnlineRef" />
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { ref } from 'vue';
+  import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
+  import { DrillPlanItemDetail } from '../types';
+  import { FILE_TYPE_ICON } from '@/views/disaster/constant';
+
+  defineProps<{
+    drillPlanItemDetail: DrillPlanItemDetail;
+  }>();
+  const previewOnlineRef = ref<InstanceType<typeof PreviewOnline>>();
+  const handlePreviewScript = (str: string) => {
+    const file = JSON.parse(str);
+    const url = file.fileUrl;
+    const type = file.fileType as keyof typeof FILE_TYPE_ICON;
+    if (!url) return;
+    previewOnlineRef.value?.open(url, type);
+  };
+</script>
+
+<style lang="scss" scoped>
+  @use '../style/common.scss' as *;
+  .link {
+    cursor: pointer;
+  }
+</style>

+ 13 - 6
src/views/emergency/emergency-drill/components/DrillSignRecordItem.vue

@@ -1,13 +1,20 @@
 <template>
-    <div>
-
-    </div>
+  <main class="safety-platform-container__main">
+    this is record page
+  </main>
+  <footer class="safety-platform-container__footer" v-if="status === CONFIRM_STATUS_TYPE.WAIT_CONFIRM">
+    <el-button type="primary">审批</el-button>
+  </footer>
 </template>
 
 <script lang="ts" setup>
-
+  import { CONFIRM_STATUS_TYPE } from '../constants';
+  defineProps<{
+    id: number;
+    status: number;
+  }>();
 </script>
 
 <style lang="scss" scoped>
-
-</style>
+  @use '@/styles/page-details-layout.scss' as *;
+</style>

+ 93 - 4
src/views/emergency/emergency-drill/components/DrillSignScriptItem.vue

@@ -1,13 +1,102 @@
 <template>
-    <div>
-
+  <main class="safety-platform-container__main">
+    <div class="info-container" v-if="drillDetailData">
+      <DrillActivity :drill-plan-item-detail="drillDetailData" />
+      <DrillImplementation :drill-plan-item-detail="drillDetailData" />
     </div>
+  </main>
+  <footer class="safety-platform-container__footer" v-if="status === CONFIRM_STATUS_TYPE.WAIT_CONFIRM">
+    <el-button type="primary" @click="openDialog">确认演练脚本</el-button>
+    <BasicDialog ref="basicDialogRef" title="演练确认" @refresh="refreshFromData">
+      <template #form>
+        <div class="form">
+          <span>请提交你的部门参与人数</span>
+          <BasicForm ref="basicFormRef" :formData="ruleFormData" :formRules="formRules" :formConfig="ruleFormConfig">
+            <template #planToParticipateCount>
+              <el-input
+                v-model="ruleFormData.planToParticipateCount"
+                placeholder="请输入参与人数"
+                @input="handleInputNumber"
+              />
+            </template>
+          </BasicForm>
+        </div>
+      </template>
+      <template #footer>
+        <el-button type="primary" @click="handleSumbit">提交</el-button>
+        <el-button @click="basicDialogRef?.closeDialog">取消</el-button>
+      </template>
+    </BasicDialog>
+  </footer>
 </template>
 
 <script lang="ts" setup>
+  import { useRouter } from 'vue-router';
+  import { onMounted, ref } from 'vue';
+  import { ElMessage } from 'element-plus';
+  import BasicDialog from '@/components/BasicDialog.vue';
+  import BasicForm from '@/components/BasicForm.vue';
+  import DrillActivity from './DrillActivity.vue';
+  import DrillImplementation from './DrillImplementation.vue';
+  import { useFormConfigHook } from '@/hooks/useFormConfigHook';
+  import type { DrillPlanItemDetail } from '../types';
+  import { queryEmergencyDrillPlanDetail, signDrillScript } from '@/api/emergency-drill/emergency-drill';
+  import { DRILL_SIGN_FROM_CONFIG, DRILL_SIGN_FROM_DATA, DRILL_SIGN_FROM_RULES } from '../configs/sign';
+  import { CONFIRM_STATUS_TYPE } from '../constants';
 
+  const props = defineProps<{
+    id: number;
+    status: number;
+  }>();
+  const router = useRouter();
+  const { ruleFormConfig, ruleFormData, formRules } = useFormConfigHook<{ planToParticipateCount: number | null }>(
+    DRILL_SIGN_FROM_CONFIG,
+    DRILL_SIGN_FROM_DATA,
+    DRILL_SIGN_FROM_RULES,
+  );
+  const basicDialogRef = ref<InstanceType<typeof BasicDialog>>();
+  const basicFormRef = ref<InstanceType<typeof BasicForm>>();
+  const drillDetailData = ref<DrillPlanItemDetail>();
+  const getDetailData = async () => {
+    drillDetailData.value = await queryEmergencyDrillPlanDetail(props.id);
+  };
+  const openDialog = () => {
+    basicDialogRef.value?.openDialog();
+  };
+  const refreshFromData = () => {
+    basicFormRef.value?.clearValidate();
+  };
+  const handleInputNumber = (value: string) => {
+    const onlyNumber = value.replace(/[^\d]/g, '');
+    const num = onlyNumber === '' ? null : Number(onlyNumber);
+    ruleFormData.planToParticipateCount = num;
+  };
+  const handleSumbit = async () => {
+    const validate = await basicFormRef.value?.validateForm();
+    if (!validate) return;
+    await signDrillScript({ drillPlanId: props.id, planToParticipateCount: ruleFormData.planToParticipateCount! });
+    basicDialogRef.value?.closeDialog();
+    ElMessage.success('确认演练脚本成功');
+    router.back();
+  };
+  onMounted(async () => {
+    getDetailData();
+  });
 </script>
 
 <style lang="scss" scoped>
-
-</style>
+  @use '@/styles/page-details-layout.scss' as *;
+  .info-container {
+    display: flex;
+    flex-direction: column;
+    gap: 20px;
+    overflow-y: auto;
+    overflow-x: hidden;
+  }
+  .form {
+    display: flex;
+    flex-direction: column;
+    gap: 10px;
+    height: 80px;
+  }
+</style>

+ 20 - 0
src/views/emergency/emergency-drill/configs/sign/form.ts

@@ -0,0 +1,20 @@
+import type { FormConfig } from '@/types/basic-form';
+
+// 演练确认人数表单
+export const DRILL_SIGN_FROM_CONFIG: FormConfig[] = [
+  {
+    label: '参与人数:',
+    prop: 'planToParticipateCount',
+    slot: 'planToParticipateCount',
+  },
+];
+
+// 演练确认人数表单数据
+export const DRILL_SIGN_FROM_DATA = {
+  planToParticipateCount: null,
+};
+
+// 演练确认人数表单表单规则
+export const DRILL_SIGN_FROM_RULES = {
+  planToParticipateCount: [{ required: true, message: '请输入参与人数', trigger: 'blur' }],
+};

+ 9 - 1
src/views/emergency/emergency-drill/configs/sign/index.ts

@@ -1,3 +1,11 @@
 import { DRILL_SIGN_LIST_SEARCH_CONFIG } from './search';
 import { DRILL_SIGN_LIST_TABLE_OPTIONS, DRILI_SIGN_LIST_TABLE_COLUMNS } from './table';
-export { DRILL_SIGN_LIST_SEARCH_CONFIG, DRILL_SIGN_LIST_TABLE_OPTIONS, DRILI_SIGN_LIST_TABLE_COLUMNS };
+import { DRILL_SIGN_FROM_CONFIG, DRILL_SIGN_FROM_DATA, DRILL_SIGN_FROM_RULES } from './form';
+export {
+  DRILL_SIGN_LIST_SEARCH_CONFIG,
+  DRILL_SIGN_LIST_TABLE_OPTIONS,
+  DRILI_SIGN_LIST_TABLE_COLUMNS,
+  DRILL_SIGN_FROM_CONFIG,
+  DRILL_SIGN_FROM_DATA,
+  DRILL_SIGN_FROM_RULES,
+};

+ 5 - 1
src/views/emergency/emergency-drill/configs/sign/table.ts

@@ -16,6 +16,7 @@ export const DRILI_SIGN_LIST_TABLE_COLUMNS: TableColumnProps[] = [
     label: '序号',
     type: 'index',
     width: '80px',
+    align: 'center'
   },
   {
     label: '会签类型',
@@ -59,6 +60,9 @@ export const DRILI_SIGN_LIST_TABLE_COLUMNS: TableColumnProps[] = [
   },
   {
     label: '操作',
-    slot: 'action'
+    slot: 'action',
+    width: '80px',
+    align: 'center',
+    fixed: 'right'
   }
 ];

+ 13 - 1
src/views/emergency/emergency-drill/constants.ts

@@ -132,7 +132,7 @@ export const DRILL_VIEW_RECORD = [
 ];
 
 export enum DRILL_SIGN_TYPE {
-  SCRIPT = 0,
+  SCRIPT = 1,
   RECORD,
 }
 
@@ -145,3 +145,15 @@ export const DRILI_SIGN_TYPE_OPTIONS = [
   { label: DRILI_SIGN_TYPE_MAP[DRILL_SIGN_TYPE.SCRIPT], value: DRILL_SIGN_TYPE.SCRIPT },
   { label: DRILI_SIGN_TYPE_MAP[DRILL_SIGN_TYPE.RECORD], value: DRILL_SIGN_TYPE.RECORD },
 ];
+
+export enum CONFIRM_STATUS_TYPE {
+  WAIT_CONFIRM = 1,
+  CONFIRMED,
+  REJECT,
+}
+
+export const CONFIRM_STATUS_MAP = {
+  [CONFIRM_STATUS_TYPE.WAIT_CONFIRM]: '待确认',
+  [CONFIRM_STATUS_TYPE.CONFIRMED]: '已确认',
+  [CONFIRM_STATUS_TYPE.REJECT]: '已退回',
+};

+ 4 - 0
src/views/emergency/emergency-drill/hook.ts

@@ -12,8 +12,12 @@ export const useEmergencyDrillHook = () => {
     const res = await queryDictTypeDetail(DICT_CODE.DRILL_SIGN_TYPE);
     drillScopeDice.value = res.sysDictDataList;
   };
+  const getDrillScope = (drillScope: string) => {
+    return drillScopeDice.value.find((item) => item.itemCode === drillScope)?.itemValue;
+  };
   return {
     drillScopeDice,
     getDrillScopeDict,
+    getDrillScope,
   };
 };

+ 46 - 0
src/views/emergency/emergency-drill/style/common.scss

@@ -0,0 +1,46 @@
+@use '@/styles/variables.scss' as *;
+.drill-activity-container {
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+}
+.drill-container {
+  &__title {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+    font-weight: 550;
+    font-size: 16px;
+    color: rgba(0, 0, 0, 0.85);
+  }
+  &--line {
+    width: 2px;
+    height: 20px;
+    background: $primary-color;
+  }
+  &__content {
+    display: flex;
+    flex-direction: column;
+    gap: 20px;
+    padding-left: 12px;
+    &--item {
+      display: flex;
+      font-size: 14px;
+      font-weight: 0;
+      .label {
+        flex-shrink: 0;
+        color: rgba(0, 0, 0, 0.85);
+      }
+      .value {
+        flex: 1;
+        color: rgba(0, 0, 0, 0.65);
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
+    }
+  }
+}
+.font-primary {
+  color: $primary-color !important;
+}

+ 6 - 6
src/views/emergency/emergency-drill/types.ts

@@ -67,15 +67,15 @@ export interface DrillPlanItemDetail {
   /*自增主键 */
   id?: number;
   /*演练规模(字典) */
-  drillScope?: string;
+  drillScope: string;
   /*演练内容 */
-  drillContent?: string;
+  drillContent: string;
   /*计划完成时间 */
-  dueCompleteTime?: string;
+  dueCompleteTime: string;
   /*责任部门id列表 */
-  responsibleDeptIdList?: string;
+  responsibleDeptIdList: string;
   /*责任部门名称列表 */
-  responsibleDeptNameList?: string;
+  responsibleDeptNameList: string;
   /*配合部门id列表 */
   coordinateDeptIdList?: string;
   /*配合部门名称列表 */
@@ -84,7 +84,7 @@ export interface DrillPlanItemDetail {
   emergencyPlanId?: number;
   emergencyPlanFile?: string;
   /*审批模板id */
-  approvalTemplateId?: number;
+  approvalTemplateId: number;
   approvalTemplateName?: string;
   /*状态?: 1-待传脚本,2-脚本会签,3-待执行,4-待记录,5-记录待审批,6-已完成 */
   status?: number;

+ 23 - 9
src/views/emergency/emergency-supplies/PageEmergencyList.vue

@@ -62,7 +62,12 @@
             </template>
           </BasicSearch>
         </header>
-        <BasicTable :tableData="tableData" :tableConfig="tableConfig">
+        <BasicTable
+          :tableData="tableData"
+          :tableConfig="tableConfig"
+          @update:pageSize="handleSizeChange"
+          @update:pageNumber="handleCurrentChange"
+        >
           <template #emergencyType="scope">
             <span>{{ getEmergencyEvent(scope.row.emergencyType) }}</span>
           </template>
@@ -94,7 +99,7 @@
           </template>
           <template #action="scope">
             <div class="action-container--div">
-              <ActionButton text="查看" @click="handleViewDetail(scope.row.id)"/>
+              <ActionButton text="查看" @click="handleViewDetail(scope.row.id)" />
               <ActionButton text="编辑" v-if="emergencySupplyPermissions" @click="handleEditSupply(scope.row.id)" />
               <ActionButton
                 text="删除"
@@ -205,7 +210,16 @@
     pagination.total = res.totalRow;
     tableConfig.loading = false;
   };
-
+  const handleSizeChange = (value: number) => {
+    pagination.pageSize = value;
+    emergencySupplyListQuery.pageSize = value;
+    getTableData();
+  };
+  const handleCurrentChange = (value: number) => {
+    pagination.pageNumber = value;
+    emergencySupplyListQuery.pageNumber = value;
+    getTableData();
+  };
   const handleDeleteSupply = async (id: number) => {
     await deleteEmergencySupplyList(id);
     await getTableData();
@@ -234,14 +248,14 @@
       },
     });
   };
-  const handleViewDetail = (id:number) => {
+  const handleViewDetail = (id: number) => {
     router.push({
       name: 'emergency-list-detail',
-      params:{
-        id
-      }
-    })
-  }
+      params: {
+        id,
+      },
+    });
+  };
 
   onMounted(() => {
     getEmergencyEventDict();

+ 35 - 16
src/views/emergency/emergency-supplies/PageInventoryCheck.vue

@@ -9,7 +9,9 @@
           <BasicSearch
             :searchConfig="INVENTORY_LIST_SEARCH_CONFIG"
             :searchData="searchData"
+            custom-reset
             @update:searchData="handleSearch"
+            @custom-reset="handleReset"
           >
             <template #taskId>
               <el-select v-model="searchData.taskId" placeholder="请选择盘点任务" filterable @change="handleTaskChange">
@@ -49,7 +51,12 @@
             >
           </div>
         </header>
-        <BasicTable :tableData="tableData" :tableConfig="tableConfig">
+        <BasicTable
+          :tableData="tableData"
+          :tableConfig="tableConfig"
+          @update:pageSize="handleSizeChange"
+          @update:pageNumber="handleCurrentChange"
+        >
           <template #emergencyType="scope">
             <span>{{ getEmergencyEvent(scope.row.emergencyType) }}</span>
           </template>
@@ -94,7 +101,10 @@
                 :content="scope.row.remark"
                 placement="top"
                 effect="light"
-                :popper-class="['custom-tooltip', scope.row.remark && scope.row.remark.length > 10 ? '' : 'custom-tooltip--opacity0']"
+                :popper-class="[
+                  'custom-tooltip',
+                  scope.row.remark && scope.row.remark.length > 10 ? '' : 'custom-tooltip--opacity0',
+                ]"
               >
                 <span>{{ scope.row.remark }}</span>
               </el-tooltip>
@@ -224,6 +234,16 @@
     pagination.total = res.totalRow;
     tableConfig.loading = false;
   };
+  const handleSizeChange = (value: number) => {
+    pagination.pageSize = value;
+    inventoryCheckListQuery.pageSize = value;
+    getTableData();
+  };
+  const handleCurrentChange = (value: number) => {
+    pagination.pageNumber = value;
+    inventoryCheckListQuery.pageNumber = value;
+    getTableData();
+  };
 
   const getFirstTaskInfo = () => {
     const firstTask = inventoryTaskOptions.value[0];
@@ -238,12 +258,24 @@
     handleSearch();
   };
 
-  const handleTaskChange = (id: number) => {
+  const handleTaskChange = async (id: number) => {
+    await checkTaskStatus();
+    startPolling();
+    handleReset();
     const task = inventoryTaskOptions.value.find((item) => item.id === id);
     if (!task) return;
     endTime.value = task.endTime;
   };
 
+  const handleReset = () => {
+    for (const key in searchData) {
+      if (key !== 'taskId') {
+        searchData[key] = null;
+      }
+    }
+    handleSearch();
+  };
+
   // 检查任务状态
   const checkTaskStatus = async () => {
     if (!searchData.taskId) return;
@@ -295,19 +327,6 @@
     }
   });
 
-  watch(
-    () => searchData.taskId,
-    async (newId) => {
-      if (newId === null) {
-        getFirstTaskInfo();
-      } else {
-        // 任务ID变化时检查状态
-        await checkTaskStatus();
-        // 任务ID变化时重新启动轮询
-        startPolling();
-      }
-    },
-  );
   watch(
     () => endTime.value,
     () => {

+ 1 - 0
utils/devProxy/staff/proxy.ts

@@ -5,6 +5,7 @@ import path from 'path';
 const proxyStaff: PROXY_TYPE = {
   serverHost: 'http://192.168.13.68:8802/',
   // serverHost: 'http://192.168.22.121:8802/',
+  // serverHost: 'http://192.168.22.146:8802/',
   loginHost: 'http://192.168.13.68:7200/login/#/',
   fileUploadHost: 'http://192.168.13.102:9000/',
   push_stream_host: 'http://192.168.13.68:7000/skyeye-admin/push_stream_host/',