|
@@ -0,0 +1,550 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="safety-platform-container">
|
|
|
|
|
+ <header class="safety-platform-container__header">
|
|
|
|
|
+ <div class="breadcrumb-title">区域检查计划任务(管理员)</div>
|
|
|
|
|
+ </header>
|
|
|
|
|
+ <main class="safety-platform-container__main">
|
|
|
|
|
+ <div class="search-table-container">
|
|
|
|
|
+ <header>
|
|
|
|
|
+ <div style="position: relative">
|
|
|
|
|
+ <el-button plain class="search-table-container--button" @click="handleImport"> 导入 </el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="act-search">
|
|
|
|
|
+ <section class="select-box">
|
|
|
|
|
+ <div class="select-box--item">
|
|
|
|
|
+ <span>检查场所/检查人员:</span>
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ v-model="tableQuery.queryParam.keyword"
|
|
|
|
|
+ placeholder="搜索检查场所或计划名称"
|
|
|
|
|
+ class="act-search-input"
|
|
|
|
|
+ style="min-width: 200px;"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="select-box--item">
|
|
|
|
|
+ <span>状态:</span>
|
|
|
|
|
+ <el-select v-model="tableQuery.queryParam.status" placeholder="请选择状态" clearable>
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ v-for="item in AREA_CHECK_PLAN_STATUS_OPTIONS"
|
|
|
|
|
+ :key="String(item.value)"
|
|
|
|
|
+ :label="item.label"
|
|
|
|
|
+ :value="item.value"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="select-box--item">
|
|
|
|
|
+ <span>日期范围:</span>
|
|
|
|
|
+ <el-date-picker
|
|
|
|
|
+ v-model="dateRange"
|
|
|
|
|
+ type="daterange"
|
|
|
|
|
+ range-separator="-"
|
|
|
|
|
+ start-placeholder="开始日期"
|
|
|
|
|
+ end-placeholder="结束日期"
|
|
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
|
|
+ format="YYYY-MM-DD"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </section>
|
|
|
|
|
+ <section class="search-btn">
|
|
|
|
|
+ <el-button type="primary" @click="handleSearch">查询</el-button>
|
|
|
|
|
+ <el-button @click="handleReset">重置</el-button>
|
|
|
|
|
+ <el-button plain @click="handleDownload"> 导出 </el-button>
|
|
|
|
|
+ </section>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </header>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="batch-table">
|
|
|
|
|
+ <BasicTable
|
|
|
|
|
+ ref="basicTableRef"
|
|
|
|
|
+ :tableData="tableData"
|
|
|
|
|
+ :tableConfig="tableConfig"
|
|
|
|
|
+ @update:pageSize="handleSizeChange"
|
|
|
|
|
+ @update:pageNumber="handleCurrentChange"
|
|
|
|
|
+ >
|
|
|
|
|
+ <template #status="scope">
|
|
|
|
|
+ <span>{{ AREA_CHECK_PLAN_STATUS_LABEL[String(scope.row.status)] ?? '-' }}</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #needOverallDesc="scope">
|
|
|
|
|
+ <span>{{
|
|
|
|
|
+ scope.row.status === 0 ? '-' : scope.row.needOverallDesc === true ? '是' : scope.row.needOverallDesc === false ? '否' : '-'
|
|
|
|
|
+ }}</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #primaryResponsibleDeptName="scope">
|
|
|
|
|
+ <!-- 如果有下发按钮就展示原来的字段primaryResponsibleDeptName,没有下发按钮就展示responsibleDeptName -->
|
|
|
|
|
+ {{ Number(scope.row.status) === 0 ? scope.row.primaryResponsibleDeptName: scope.row.responsibleDeptName}}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #needSigneeSign="scope">
|
|
|
|
|
+ <span>{{
|
|
|
|
|
+ scope.row.status === 0 ? '-' : scope.row.needSigneeSign === true ? '是' : scope.row.needSigneeSign === false ? '否' : '-'
|
|
|
|
|
+ }}</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #planStartTime="scope">
|
|
|
|
|
+ <span>{{ scope.row.planStartTime ?? '-' }}</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #planEndTime="scope">
|
|
|
|
|
+ <span>{{ scope.row.planEndTime ?? '-' }}</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #action="scope">
|
|
|
|
|
+ <div class="action-container--div" style="justify-content: left">
|
|
|
|
|
+ <template v-if="Number(scope.row.status) === 0">
|
|
|
|
|
+ <ActionButton text="查看" @click="handleView(scope.row.id)" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </BasicTable>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </main>
|
|
|
|
|
+
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup lang="ts">
|
|
|
|
|
+ import { onMounted, reactive, ref } from 'vue';
|
|
|
|
|
+ import { ElMessage } from 'element-plus';
|
|
|
|
|
+ import BasicTable from '@/components/BasicTable.vue';
|
|
|
|
|
+ import useTableConfig from '@/hooks/useTableConfigHook';
|
|
|
|
|
+ import ActionButton from '@/components/ActionButton.vue';
|
|
|
|
|
+ import { Plus } from '@element-plus/icons-vue';
|
|
|
|
|
+ import {
|
|
|
|
|
+ TABLE_OPTIONS,
|
|
|
|
|
+ AREA_CHECK_PLAN_TABLE_COLUMNS,
|
|
|
|
|
+ AREA_CHECK_PLAN_STATUS_OPTIONS,
|
|
|
|
|
+ AREA_CHECK_PLAN_STATUS_LABEL,
|
|
|
|
|
+ } from './configs/tables';
|
|
|
|
|
+ import { useRouter } from 'vue-router';
|
|
|
|
|
+ import type { QueryPageRequest } from '@/types/basic-query';
|
|
|
|
|
+ import type { AreaCheckPlanQuery, AreaCheckPlanRecord } from './configs/types';
|
|
|
|
|
+ import {
|
|
|
|
|
+ queryAreaCheckPlanManagePage,
|
|
|
|
|
+ deleteAreaCheckPlanManage,
|
|
|
|
|
+ sendAreaCheckPlanToDep,
|
|
|
|
|
+ cancelAreaCheckPlanManage,
|
|
|
|
|
+ queryAreaCheckPlanManageDetail,
|
|
|
|
|
+ mapAreaCheckPlanApiRecordToUi,
|
|
|
|
|
+ exportAreaCheckPlanAdministration,
|
|
|
|
|
+ } from '@/api/production-safety-system';
|
|
|
|
|
+ import { getAllDepartments } from '@/api/auth/dept';
|
|
|
|
|
+ import type { DeptTree } from '@/types/dept/type';
|
|
|
|
|
+ import { queryUserGroupPage } from '@/api/system/person-group';
|
|
|
|
|
+ import type { PersonGroupListItem } from '@/types/person-group/type';
|
|
|
|
|
+ import BatchImport from '@/components/batch-import/BatchImport.vue';
|
|
|
|
|
+ import { useGlobSetting } from '@/hooks/setting';
|
|
|
|
|
+ import urlJoin from 'url-join';
|
|
|
|
|
+ import { downloadByData } from '@/utils/file/download';
|
|
|
|
|
+ const router = useRouter();
|
|
|
|
|
+
|
|
|
|
|
+ const basicTableRef = ref<InstanceType<typeof BasicTable>>();
|
|
|
|
|
+ const { tableConfig, pagination } = useTableConfig(AREA_CHECK_PLAN_TABLE_COLUMNS, TABLE_OPTIONS);
|
|
|
|
|
+ const tableData = ref<AreaCheckPlanRecord[]>([]);
|
|
|
|
|
+ const dateRange = ref<[string, string] | null>(null);
|
|
|
|
|
+
|
|
|
|
|
+ // 场所所属类别选项(示例数据,本页面不调用接口)
|
|
|
|
|
+ const venueCategoryOptions = ref<Array<{ label: string; value: string }>>([]);
|
|
|
|
|
+
|
|
|
|
|
+ // 下发弹窗
|
|
|
|
|
+ const showIssueDialog = ref(false);
|
|
|
|
|
+ const currentIssuePlanId = ref<number | null>(null);
|
|
|
|
|
+ const issueFormRef = ref();
|
|
|
|
|
+ const issueResponsibleDeptCascaderRef = ref();
|
|
|
|
|
+ const issueForm = reactive({
|
|
|
|
|
+ responsibleDeptIds: [] as number[],
|
|
|
|
|
+ responsibleDeptPersonnelGroupCode: undefined as string | undefined,
|
|
|
|
|
+ safetyEmergencyDeptId: undefined as number | undefined,
|
|
|
|
|
+ safetyEmergencyGroupId: undefined as number | undefined,
|
|
|
|
|
+ hospitalLeaderDeptId: undefined as number | undefined,
|
|
|
|
|
+ hospitalLeaderGroupId: undefined as number | undefined,
|
|
|
|
|
+ planStartTime: '',
|
|
|
|
|
+ planEndTime: '',
|
|
|
|
|
+ needOverallDesc: false,
|
|
|
|
|
+ needSigneeSign: false,
|
|
|
|
|
+ });
|
|
|
|
|
+ const issueRules = {
|
|
|
|
|
+ responsibleDeptIds: [{ required: true, message: '请选择责任部门', trigger: 'change', type: 'array', min: 1 }],
|
|
|
|
|
+ responsibleDeptPersonnelGroupCode: [{ required: true, message: '请选择责任部门人员分组', trigger: 'change' }],
|
|
|
|
|
+ safetyEmergencyDeptId: [{ required: true, message: '请选择安全应急部门', trigger: 'change' }],
|
|
|
|
|
+ safetyEmergencyGroupId: [{ required: true, message: '请选择安全应急部人员分组', trigger: 'change' }],
|
|
|
|
|
+ hospitalLeaderDeptId: [{ required: true, message: '请选择院领导部门', trigger: 'change' }],
|
|
|
|
|
+ hospitalLeaderGroupId: [{ required: true, message: '请选择院领导人员分组', trigger: 'change' }],
|
|
|
|
|
+ planStartTime: [{ required: true, message: '请选择计划开始日期', trigger: 'change' }],
|
|
|
|
|
+ planEndTime: [{ required: true, message: '请选择计划结束时间', trigger: 'change' }],
|
|
|
|
|
+ needOverallDesc: [{ required: true, message: '请选择是否需要整体检查情况描述', trigger: 'change' }],
|
|
|
|
|
+ needSigneeSign: [{ required: true, message: '请选择是否需要被检查人签字', trigger: 'change' }],
|
|
|
|
|
+ };
|
|
|
|
|
+ // 下发弹窗:责任部门/安全应急部门/院领导部门复用新增区域检查计划的主责部门下拉(getAllDepartments)
|
|
|
|
|
+ const issueDeptTree = ref<DeptTree[]>([]);
|
|
|
|
|
+ const issueDeptTreeTow = ref<DeptTree[]>([]);
|
|
|
|
|
+ const cascaderDeptProp = {
|
|
|
|
|
+ checkStrictly: true,
|
|
|
|
|
+ expandTrigger: 'hover' as const,
|
|
|
|
|
+ value: 'id',
|
|
|
|
|
+ label: 'deptName',
|
|
|
|
|
+ emitPath: false,
|
|
|
|
|
+ };
|
|
|
|
|
+ const cascaderDeptPropMultiple = {
|
|
|
|
|
+ ...cascaderDeptProp,
|
|
|
|
|
+ multiple: true,
|
|
|
|
|
+ };
|
|
|
|
|
+ // 责任部门人员分组/安全应急部人员分组/院领导人员分组复用 queryUserGroupPage 查询用户分组接口
|
|
|
|
|
+ const userGroupOptions = ref<PersonGroupListItem[]>([]);
|
|
|
|
|
+
|
|
|
|
|
+ /** 下发弹窗打开时加载部门树(与新增区域检查计划主责部门一致) */
|
|
|
|
|
+ const loadIssueDeptTree = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await getAllDepartments();
|
|
|
|
|
+ issueDeptTree.value = res?.[0]?.children ?? [];
|
|
|
|
|
+ issueDeptTreeTow.value = res?.[0]?.children.map(item => ({
|
|
|
|
|
+ ...item,
|
|
|
|
|
+ children: []
|
|
|
|
|
+ }));
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('获取部门树失败:', e);
|
|
|
|
|
+ issueDeptTree.value = [];
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ /** 下发弹窗打开时加载用户分组列表 */
|
|
|
|
|
+ const loadUserGroupOptions = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await queryUserGroupPage({
|
|
|
|
|
+ pageNumber: 1,
|
|
|
|
|
+ pageSize: 9999,
|
|
|
|
|
+ queryParam: '',
|
|
|
|
|
+ });
|
|
|
|
|
+ userGroupOptions.value = res?.records ?? [];
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('获取用户分组列表失败:', e);
|
|
|
|
|
+ userGroupOptions.value = [];
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const onIssueDialogOpen = async () => {
|
|
|
|
|
+ await Promise.all([loadIssueDeptTree(), loadUserGroupOptions()]);
|
|
|
|
|
+
|
|
|
|
|
+ if (!currentIssuePlanId.value) return;
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const raw = await queryAreaCheckPlanManageDetail(currentIssuePlanId.value);
|
|
|
|
|
+ const detail = mapAreaCheckPlanApiRecordToUi(raw);
|
|
|
|
|
+
|
|
|
|
|
+ const responsibleDeptIdsByCode = parseNumberList(
|
|
|
|
|
+ detail.primaryResponsibleDeptCode ?? (detail as Record<string, unknown>).responsibleDeptCode,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ issueForm.responsibleDeptIds = responsibleDeptIdsByCode.length
|
|
|
|
|
+ ? responsibleDeptIdsByCode
|
|
|
|
|
+ : (detail.primaryResponsibleDeptName || '')
|
|
|
|
|
+ .split(',')
|
|
|
|
|
+ .map((name) => findDeptIdByName(issueDeptTree.value, name.trim()))
|
|
|
|
|
+ .filter((id): id is number => id != null);
|
|
|
|
|
+
|
|
|
|
|
+ const safetyEmergencyDeptIdByCode = parseNumber(detail.safetyEmergencyDeptCode);
|
|
|
|
|
+ issueForm.safetyEmergencyDeptId =
|
|
|
|
|
+ safetyEmergencyDeptIdByCode ?? findDeptIdByName(issueDeptTree.value, detail.safetyEmergencyDeptName);
|
|
|
|
|
+
|
|
|
|
|
+ const hospitalLeaderDeptIdByCode = parseNumber(detail.hospitalLeaderDeptCode);
|
|
|
|
|
+ issueForm.hospitalLeaderDeptId =
|
|
|
|
|
+ hospitalLeaderDeptIdByCode ?? findDeptIdByName(issueDeptTree.value, detail.hospitalLeaderDeptName);
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('加载下发默认数据失败:', e);
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const findDeptNameById = (nodes: DeptTree[] | undefined, id: number | undefined): string | undefined => {
|
|
|
|
|
+ if (!nodes?.length || id == null) return undefined;
|
|
|
|
|
+ for (const n of nodes) {
|
|
|
|
|
+ if (n.id === id) return n.deptName;
|
|
|
|
|
+ const found = findDeptNameById(n.children, id);
|
|
|
|
|
+ if (found) return found;
|
|
|
|
|
+ }
|
|
|
|
|
+ return undefined;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const findDeptIdByName = (nodes: DeptTree[] | undefined, name: string | undefined): number | undefined => {
|
|
|
|
|
+ if (!nodes?.length || !name) return undefined;
|
|
|
|
|
+ for (const n of nodes) {
|
|
|
|
|
+ if (n.deptName === name) return n.id ?? undefined;
|
|
|
|
|
+ const found = findDeptIdByName(n.children, name);
|
|
|
|
|
+ if (found != null) return found;
|
|
|
|
|
+ }
|
|
|
|
|
+ return undefined;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const parseNumber = (val: unknown): number | undefined => {
|
|
|
|
|
+ if (val == null || val === '') return undefined;
|
|
|
|
|
+ const n = Number(val);
|
|
|
|
|
+ return Number.isFinite(n) ? n : undefined;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const parseNumberList = (val: unknown): number[] => {
|
|
|
|
|
+ if (val == null || val === '') return [];
|
|
|
|
|
+ return String(val)
|
|
|
|
|
+ .split(',')
|
|
|
|
|
+ .map((s) => parseNumber(s.trim()))
|
|
|
|
|
+ .filter((n): n is number => n != null);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const findDeptNamesByIds = (nodes: DeptTree[] | undefined, ids: number[] | undefined): string[] => {
|
|
|
|
|
+ const list = (ids ?? []).filter((v) => v != null);
|
|
|
|
|
+ if (!list.length) return [];
|
|
|
|
|
+ return list
|
|
|
|
|
+ .map((id) => findDeptNameById(nodes, id))
|
|
|
|
|
+ .filter((name): name is string => !!name && String(name).trim().length > 0);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const findGroupNameById = (id: number | undefined): string | undefined => {
|
|
|
|
|
+ if (id == null) return undefined;
|
|
|
|
|
+ return userGroupOptions.value.find((g) => g.id === id)?.name;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const resetIssueForm = () => {
|
|
|
|
|
+ issueForm.responsibleDeptIds = [];
|
|
|
|
|
+ issueForm.responsibleDeptPersonnelGroupCode = undefined;
|
|
|
|
|
+ issueForm.safetyEmergencyDeptId = undefined;
|
|
|
|
|
+ issueForm.safetyEmergencyGroupId = undefined;
|
|
|
|
|
+ issueForm.hospitalLeaderDeptId = undefined;
|
|
|
|
|
+ issueForm.hospitalLeaderGroupId = undefined;
|
|
|
|
|
+ issueForm.planStartTime = '';
|
|
|
|
|
+ issueForm.planEndTime = '';
|
|
|
|
|
+ issueForm.needOverallDesc = false;
|
|
|
|
|
+ issueForm.needSigneeSign = false;
|
|
|
|
|
+ issueFormRef.value?.resetFields?.();
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const tableQuery = reactive<QueryPageRequest<AreaCheckPlanQuery>>({
|
|
|
|
|
+ pageNumber: pagination.pageNumber,
|
|
|
|
|
+ pageSize: pagination.pageSize,
|
|
|
|
|
+ queryParam: {
|
|
|
|
|
+ keyword: '',
|
|
|
|
|
+ status: '' as AreaCheckPlanQuery['status'],
|
|
|
|
|
+ venueCategory: '',
|
|
|
|
|
+ planStartTime: '',
|
|
|
|
|
+ planEndTime: '',
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const handleSizeChange = (value: number) => {
|
|
|
|
|
+ pagination.pageSize = value;
|
|
|
|
|
+ tableQuery.pageSize = value;
|
|
|
|
|
+ getTableData();
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleCurrentChange = (value: number) => {
|
|
|
|
|
+ pagination.pageNumber = value;
|
|
|
|
|
+ tableQuery.pageNumber = value;
|
|
|
|
|
+ getTableData();
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ async function getTableData() {
|
|
|
|
|
+ tableConfig.loading = true;
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await queryAreaCheckPlanManagePage({
|
|
|
|
|
+ pageNumber: tableQuery.pageNumber,
|
|
|
|
|
+ pageSize: tableQuery.pageSize,
|
|
|
|
|
+ queryParam: tableQuery.queryParam,
|
|
|
|
|
+ });
|
|
|
|
|
+ const raw = (res as { data?: { records?: unknown[]; totalRow?: number } })?.data ?? res;
|
|
|
|
|
+ const list = raw?.records ?? [];
|
|
|
|
|
+ tableData.value = list.map((r: unknown) => mapAreaCheckPlanApiRecordToUi(r));
|
|
|
|
|
+ pagination.total = raw?.totalRow ?? 0;
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('查询区域检查计划列表失败:', e);
|
|
|
|
|
+ tableData.value = [];
|
|
|
|
|
+ pagination.total = 0;
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ tableConfig.loading = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const handleSearch = () => {
|
|
|
|
|
+ if (dateRange.value && dateRange.value.length === 2) {
|
|
|
|
|
+ tableQuery.queryParam.planStartTime = dateRange.value[0];
|
|
|
|
|
+ tableQuery.queryParam.planEndTime = dateRange.value[1];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ tableQuery.queryParam.planStartTime = '';
|
|
|
|
|
+ tableQuery.queryParam.planEndTime = '';
|
|
|
|
|
+ }
|
|
|
|
|
+ pagination.pageNumber = 1;
|
|
|
|
|
+ tableQuery.pageNumber = 1;
|
|
|
|
|
+ getTableData();
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleReset = () => {
|
|
|
|
|
+ tableQuery.queryParam.keyword = '';
|
|
|
|
|
+ tableQuery.queryParam.status = '';
|
|
|
|
|
+ tableQuery.queryParam.venueCategory = '';
|
|
|
|
|
+ tableQuery.queryParam.planStartTime = '';
|
|
|
|
|
+ tableQuery.queryParam.planEndTime = '';
|
|
|
|
|
+ dateRange.value = null;
|
|
|
|
|
+ handleSearch();
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ const handleEdit = (id: number) => {
|
|
|
|
|
+ router.push({
|
|
|
|
|
+ name: 'areaCheckPlanManagementItem',
|
|
|
|
|
+ query: { id, operate: 'area-check-plan-edit' },
|
|
|
|
|
+ });
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleView = (id: number) => {
|
|
|
|
|
+ router.push({
|
|
|
|
|
+ name: 'areaCheckPlanManagementItem',
|
|
|
|
|
+ query: { id, operate: 'area-check-plan-view' },
|
|
|
|
|
+ });
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleDelete = async (id: number) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await deleteAreaCheckPlanManage(id);
|
|
|
|
|
+ ElMessage.success('删除成功');
|
|
|
|
|
+ getTableData();
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('删除失败:', e);
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleIssue = (id: number) => {
|
|
|
|
|
+ currentIssuePlanId.value = id;
|
|
|
|
|
+ resetIssueForm();
|
|
|
|
|
+ showIssueDialog.value = true;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleIssueSave = async () => {
|
|
|
|
|
+ if (!issueFormRef.value || !currentIssuePlanId.value) return;
|
|
|
|
|
+ const valid = await issueFormRef.value.validate().catch(() => false);
|
|
|
|
|
+ if (!valid) return;
|
|
|
|
|
+ if (
|
|
|
|
|
+ issueForm.planStartTime &&
|
|
|
|
|
+ issueForm.planEndTime &&
|
|
|
|
|
+ new Date(issueForm.planStartTime) > new Date(issueForm.planEndTime)
|
|
|
|
|
+ ) {
|
|
|
|
|
+ ElMessage.error('计划开始日期不能大于计划结束日期');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 仅提交:弹窗页面字段 + id(下拉同时提交 name + value)
|
|
|
|
|
+ const responsibleDeptIds = (issueForm.responsibleDeptIds ?? []).filter((v) => v != null);
|
|
|
|
|
+ const responsibleDeptNames = findDeptNamesByIds(issueDeptTree.value, responsibleDeptIds);
|
|
|
|
|
+ const responsibleDeptName = responsibleDeptNames.length ? responsibleDeptNames.join(',') : undefined;
|
|
|
|
|
+ const responsibleDeptCode = responsibleDeptIds.length ? responsibleDeptIds.join(',') : undefined;
|
|
|
|
|
+
|
|
|
|
|
+ const responsibleDeptPersonnelGroupName = (() => {
|
|
|
|
|
+ const code = issueForm.responsibleDeptPersonnelGroupCode;
|
|
|
|
|
+ if (code == null || code === '') return undefined;
|
|
|
|
|
+ const byId = userGroupOptions.value.find((g) => String(g.id) === code);
|
|
|
|
|
+ return byId?.name ?? undefined;
|
|
|
|
|
+ })();
|
|
|
|
|
+
|
|
|
|
|
+ const safetyEmergencyDeptName = findDeptNameById(issueDeptTree.value, issueForm.safetyEmergencyDeptId);
|
|
|
|
|
+ const hospitalLeaderDeptName = findDeptNameById(issueDeptTree.value, issueForm.hospitalLeaderDeptId);
|
|
|
|
|
+
|
|
|
|
|
+ const payload = {
|
|
|
|
|
+ id: currentIssuePlanId.value,
|
|
|
|
|
+ responsibleDeptName,
|
|
|
|
|
+ responsibleDeptCode,
|
|
|
|
|
+ responsibleDeptPersonnelGroupName,
|
|
|
|
|
+ responsibleDeptPersonnelGroupCode: issueForm.responsibleDeptPersonnelGroupCode,
|
|
|
|
|
+
|
|
|
|
|
+ // 安全应急部门
|
|
|
|
|
+ safetyEmergencyDeptName,
|
|
|
|
|
+ SafetyEmergencyDeptCode: issueForm.safetyEmergencyDeptId,
|
|
|
|
|
+ safetyEmergencyExecutorGroupName: findGroupNameById(issueForm.safetyEmergencyGroupId),
|
|
|
|
|
+ safetyEmergencyExecGroupCode:
|
|
|
|
|
+ issueForm.safetyEmergencyGroupId != null ? String(issueForm.safetyEmergencyGroupId) : undefined,
|
|
|
|
|
+
|
|
|
|
|
+ // 院领导部门
|
|
|
|
|
+ hospitalLeaderDeptName,
|
|
|
|
|
+ hospitalLeaderDeptCode: issueForm.hospitalLeaderDeptId,
|
|
|
|
|
+ hospitalLeaderExecutorGroupName: findGroupNameById(issueForm.hospitalLeaderGroupId),
|
|
|
|
|
+ hospitalLeaderExecGroupCode:
|
|
|
|
|
+ issueForm.hospitalLeaderGroupId != null ? String(issueForm.hospitalLeaderGroupId) : undefined,
|
|
|
|
|
+
|
|
|
|
|
+ // 计划时间与开关项
|
|
|
|
|
+ planStartTime: issueForm.planStartTime,
|
|
|
|
|
+ planEndTime: issueForm.planEndTime,
|
|
|
|
|
+ needOverallDesc: issueForm.needOverallDesc,
|
|
|
|
|
+ needSigneeSign: issueForm.needSigneeSign,
|
|
|
|
|
+ } as AreaCheckPlanRecord & { id: number } & Record<string, unknown>;
|
|
|
|
|
+
|
|
|
|
|
+ await sendAreaCheckPlanToDep(payload);
|
|
|
|
|
+ ElMessage.success('下发成功');
|
|
|
|
|
+ showIssueDialog.value = false;
|
|
|
|
|
+ getTableData();
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ ElMessage.error(e.message);
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleCancel = async (id: number) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await cancelAreaCheckPlanManage(id);
|
|
|
|
|
+ ElMessage.success('作废成功');
|
|
|
|
|
+ getTableData();
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('作废失败:', e);
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ const handleDownload = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const response = await exportAreaCheckPlanAdministration(tableQuery.queryParam);
|
|
|
|
|
+ if (response) {
|
|
|
|
|
+ const fileName = `区域检查计划管理_${new Date().toISOString().split('T')[0]}.xlsx`;
|
|
|
|
|
+ downloadByData(response, fileName);
|
|
|
|
|
+ ElMessage.success('导出成功');
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('导出院级文件失败:', e);
|
|
|
|
|
+ ElMessage.error('导出失败,请重试');
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ onMounted(() => {
|
|
|
|
|
+ venueCategoryOptions.value = [
|
|
|
|
|
+ { label: '各级风险点', value: '各级风险点' },
|
|
|
|
|
+ { label: '关键业务活动', value: '关键业务活动' },
|
|
|
|
|
+ { label: '日常安全', value: '日常安全' },
|
|
|
|
|
+ { label: '各级危险点', value: '各级危险点' },
|
|
|
|
|
+ { label: '试验室及试验过程', value: '试验室及试验过程' },
|
|
|
|
|
+ {
|
|
|
|
|
+ label: '办公区域(含地下车库、图书馆、档案库房、仓库等)',
|
|
|
|
|
+ value: '办公区域(含地下车库、图书馆、档案库房、仓库等)',
|
|
|
|
|
+ },
|
|
|
|
|
+ { label: '老旧厂房', value: '老旧厂房' },
|
|
|
|
|
+ { label: '施工现场', value: '施工现场' },
|
|
|
|
|
+ { label: '职工食堂', value: '职工食堂' },
|
|
|
|
|
+ { label: '职工宿舍', value: '职工宿舍' },
|
|
|
|
|
+ { label: '体育活动场所', value: '体育活动场所' },
|
|
|
|
|
+ { label: '托育园', value: '托育园' },
|
|
|
|
|
+ { label: '租、出借房屋', value: '租、出借房屋' },
|
|
|
|
|
+ { label: '院内经营服务场所', value: '院内经营服务场所' },
|
|
|
|
|
+ { label: '垃圾房', value: '垃圾房' },
|
|
|
|
|
+ { label: '院内交通', value: '院内交通' },
|
|
|
|
|
+ { label: '消防设施设备', value: '消防设施设备' },
|
|
|
|
|
+ { label: '特种设备', value: '特种设备' },
|
|
|
|
|
+ { label: '防雷设施', value: '防雷设施' },
|
|
|
|
|
+ { label: '供、配电设施设备(含弱电)', value: '供、配电设施设备(含弱电)' },
|
|
|
|
|
+ { label: '公务车辆', value: '公务车辆' },
|
|
|
|
|
+ { label: '燃气管道设施(含报警装置)', value: '燃气管道设施(含报警装置)' },
|
|
|
|
|
+ { label: '建筑物外墙标识物、装饰物', value: '建筑物外墙标识物、装饰物' },
|
|
|
|
|
+ { label: 'UPS电源', value: 'UPS电源' },
|
|
|
|
|
+ { label: '危险化学品', value: '危险化学品' },
|
|
|
|
|
+ { label: '设施设备应急操作流程', value: '设施设备应急操作流程' },
|
|
|
|
|
+ { label: '堆场、物资库房', value: '堆场、物资库房' },
|
|
|
|
|
+ { label: '室内外停车场', value: '室内外停车场' },
|
|
|
|
|
+ ];
|
|
|
|
|
+ getTableData();
|
|
|
|
|
+ });
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
|
+ @use '@/styles/page-details-layout.scss' as *;
|
|
|
|
|
+ @use '@/styles/page-main-layout.scss' as *;
|
|
|
|
|
+ @use '@/styles/basic-table-action.scss' as *;
|
|
|
|
|
+ @use '@/views/traffic/violation/style/act-search-table.scss' as *;
|
|
|
|
|
+</style>
|