|
|
@@ -6,10 +6,6 @@
|
|
|
<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">
|
|
|
@@ -65,10 +61,8 @@
|
|
|
<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 #frequency="scope">
|
|
|
+ <span>{{ FREQUENCY_TO_LABEL[scope.row.frequency] ?? '-' }}</span>
|
|
|
</template>
|
|
|
<template #sign="scope">
|
|
|
<div class="file-list">
|
|
|
@@ -85,34 +79,252 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
- <template #needSigneeSign="scope">
|
|
|
+ <template #checkItemTotal="scope">
|
|
|
<span>{{
|
|
|
- scope.row.status === 0 ? '-' : scope.row.needSigneeSign === true ? '是' : scope.row.needSigneeSign === false ? '否' : '-'
|
|
|
+ scope.row.checkItemTotal ? scope.row.checkItemTotal+'项' : '-'
|
|
|
}}</span>
|
|
|
</template>
|
|
|
- <template #startDate="scope">
|
|
|
- <span>{{ scope.row.startDate ?? '-' }}</span>
|
|
|
+ <template #qualifiedItemNum="scope">
|
|
|
+ <span>{{ scope.row.qualifiedItemNum ? scope.row.qualifiedItemNum+'项' : '-' }}</span>
|
|
|
</template>
|
|
|
- <template #endDate="scope">
|
|
|
- <span>{{ scope.row.endDate ?? '-' }}</span>
|
|
|
+ <template #unqualifiedItemNum="scope">
|
|
|
+ <span style="color:#1777ff;" v-if="scope.row.unqualifiedItemNum" @click="openUnqualifiedDialog(scope.row)">{{ scope.row.unqualifiedItemNum+'项'}}</span>
|
|
|
+ <span v-else>-</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 class="action-container--div" style="justify-content: flex-start">
|
|
|
+ <ActionButton text="查看" @click="handleView(scope.row)" />
|
|
|
</div>
|
|
|
</template>
|
|
|
</BasicTable>
|
|
|
</div>
|
|
|
</div>
|
|
|
</main>
|
|
|
-
|
|
|
+ <PreviewOnline ref="previewOnlineRef" />
|
|
|
+
|
|
|
+
|
|
|
+ <!-- 检查不合格数据弹窗(部门) -->
|
|
|
+ <el-dialog
|
|
|
+ v-model="showUnqualifiedDialog"
|
|
|
+ title="检查不合格数据"
|
|
|
+ width="800px"
|
|
|
+ destroy-on-close
|
|
|
+ >
|
|
|
+ <BasicTable
|
|
|
+ :tableData="unqualifiedList"
|
|
|
+ :tableConfig="unqualifiedTableConfig"
|
|
|
+ @update:pageSize="handleUnqualifiedSizeChange"
|
|
|
+ @update:pageNumber="handleUnqualifiedPageChange"
|
|
|
+ >
|
|
|
+ <template #action="scope">
|
|
|
+ <el-button
|
|
|
+ v-if="Number(scope.row.IsSand) == 0"
|
|
|
+ type="primary"
|
|
|
+ link
|
|
|
+ size="small"
|
|
|
+ @click="handleSandToHiddenDangerDept(scope.row)"
|
|
|
+ >
|
|
|
+ 入账
|
|
|
+ </el-button>
|
|
|
+ <span v-else-if="Number(scope.row.IsSand) == 1" style="color: #999999">已入账</span>
|
|
|
+ <span v-else>-</span>
|
|
|
+ </template>
|
|
|
+ </BasicTable>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 部门端:检查记录入账隐患台账确认弹窗(仅查看提示,不真正入账) -->
|
|
|
+ <el-dialog
|
|
|
+ v-model="showSandConfirmDialogDept"
|
|
|
+ title="检查记录入账隐患台账"
|
|
|
+ width="900px"
|
|
|
+ destroy-on-close
|
|
|
+ >
|
|
|
+ <el-form ref="sandHiddenDangerFormRefDept" label-width="150px" :model="sandHiddenDangerFormDataDept" :rules="sandHiddenDangerFormRulesDept">
|
|
|
+ <el-form-item prop="typeId" label="隐患问题类别:" style="width: 70%;">
|
|
|
+ <el-select
|
|
|
+ v-model="sandHiddenDangerFormDataDept.typeId"
|
|
|
+ placeholder="请选择隐患问题类别"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ style="width: 100%"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="item in dangerTypeList"
|
|
|
+ :key="item.id"
|
|
|
+ :label="item.categoryName"
|
|
|
+ :value="item.id"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="隐患问题:" prop="dangerProblem">
|
|
|
+ <el-input
|
|
|
+ v-model="sandHiddenDangerFormDataDept.dangerProblem"
|
|
|
+ placeholder="请输入隐患问题描述"
|
|
|
+ style="width: 450px"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="问题主要原因:" prop="reasonId">
|
|
|
+ <el-select
|
|
|
+ v-model="sandHiddenDangerFormDataDept.reasonId"
|
|
|
+ placeholder="请选择问题主要原因"
|
|
|
+ clearable
|
|
|
+ filterable
|
|
|
+ style="width: 450px"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="option in REASON_OPTIONS"
|
|
|
+ :key="option.value"
|
|
|
+ :label="option.label"
|
|
|
+ :value="option.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="任务来源:" prop="taskSource">
|
|
|
+ <el-input
|
|
|
+ v-model="sandHiddenDangerFormDataDept.taskSource"
|
|
|
+ placeholder="如:上级检查、院内自查"
|
|
|
+ style="width: 450px"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="整改要求:" prop="rectificationRequirement">
|
|
|
+ <el-input
|
|
|
+ v-model="sandHiddenDangerFormDataDept.rectificationRequirement"
|
|
|
+ placeholder="请输入整改要求"
|
|
|
+ style="width: 450px"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item prop="rectificationDepartmentIds" label="整改责任部门:">
|
|
|
+ <el-cascader
|
|
|
+ ref="cascaderDeptRef"
|
|
|
+ v-model="sandHiddenDangerFormDataDept.rectificationDepartmentIds"
|
|
|
+ :options="issueDeptTree"
|
|
|
+ :props="cascaderDeptProp"
|
|
|
+ :show-all-levels="false"
|
|
|
+ placeholder="请选择整改责任部门"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ style="width: 450px"
|
|
|
+ @change="onIssueDeptChange"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item prop="rectificationResponsibleIds" label="整改负责人">
|
|
|
+ <el-select
|
|
|
+ v-model="sandHiddenDangerFormDataDept.rectificationResponsibleIds"
|
|
|
+ placeholder="选择整改负责人"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ style="width: 450px"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="user in issueUserList"
|
|
|
+ :key="user.id"
|
|
|
+ :label="user.realname ?? user.username"
|
|
|
+ :value="user.id"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="整改日期:" prop="rectificationDeadline">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="sandHiddenDangerFormDataDept.rectificationDeadline"
|
|
|
+ type="date"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ placeholder="请选择整改日期"
|
|
|
+ style="width: 450px"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item prop="reviewDepartmentId" label="复查人员所属部门:">
|
|
|
+ <el-cascader
|
|
|
+ ref="reviewDeptRef"
|
|
|
+ v-model="sandHiddenDangerFormDataDept.reviewDepartmentId"
|
|
|
+ :options="issueDeptTree"
|
|
|
+ :props="cascaderDeptProp"
|
|
|
+ :show-all-levels="false"
|
|
|
+ placeholder="请选择复查人员所属部门"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ style="width: 450px"
|
|
|
+ @change="onReviewDeptChange"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="复查人员:" prop="reviewPersonId">
|
|
|
+ <el-select
|
|
|
+ v-model="sandHiddenDangerFormDataDept.reviewPersonId"
|
|
|
+ placeholder="请选择复查人员"
|
|
|
+ clearable
|
|
|
+ filterable
|
|
|
+ style="width: 450px"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="u in reviewUserListDept"
|
|
|
+ :key="u.id"
|
|
|
+ :label="u.realname || u.username"
|
|
|
+ :value="u.id"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="举一反三是否推送:" prop="isDrawLessonsPush">
|
|
|
+ <el-radio-group v-model="sandHiddenDangerFormDataDept.isDrawLessonsPush" >
|
|
|
+ <el-radio :value="0">否</el-radio>
|
|
|
+ <el-radio :value="1">是</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label-width="150px" v-if="sandHiddenDangerFormDataDept.isDrawLessonsPush === 1">
|
|
|
+ <el-input placeholder="请输入举一反三内容" style="width: 450px" v-model="sandHiddenDangerFormDataDept.drawLessonsContent" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item prop="drawLessonsDepartmentIds" v-if="sandHiddenDangerFormDataDept.isDrawLessonsPush === 1" label="举一反三责任部门:">
|
|
|
+ <el-select
|
|
|
+ v-model="drawLessonsDeptIdsArrayDept"
|
|
|
+ placeholder="请选择举一反三责任部门,可多选"
|
|
|
+ clearable
|
|
|
+ filterable
|
|
|
+ multiple
|
|
|
+ collapse-tags
|
|
|
+ collapse-tags-tooltip
|
|
|
+ style="width: 450px"
|
|
|
+ @change="() => { sandHiddenDangerFormDataDept.drawLessonsDepartmentIds = drawLessonsDeptIdsArrayDept.join(','); }"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="d in deptOptions"
|
|
|
+ :key="d.id"
|
|
|
+ :label="d.deptName"
|
|
|
+ :value="d.id"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item prop="drawLessonsDeadline" label="举一反三时限:" v-if="sandHiddenDangerFormDataDept.isDrawLessonsPush === 1">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="sandHiddenDangerFormDataDept.drawLessonsDeadline"
|
|
|
+ type="date"
|
|
|
+ style="width: 450px"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ placeholder="请选择举一反三截止日期(选填)"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="showSandConfirmDialogDept = false">取消</el-button>
|
|
|
+ <el-button type="primary" :loading="sandConfirmLoadingDept" @click="confirmSandToHiddenDangerDept">
|
|
|
+ 提交
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
- import { onMounted, reactive, ref } from 'vue';
|
|
|
+ import { onMounted, reactive, ref, computed } from 'vue';
|
|
|
import { ElMessage } from 'element-plus';
|
|
|
import BasicTable from '@/components/BasicTable.vue';
|
|
|
import useTableConfig from '@/hooks/useTableConfigHook';
|
|
|
@@ -124,13 +336,22 @@
|
|
|
AREA_CHECK_PLAN_STATUS_OPTIONS,
|
|
|
AREA_CHECK_PLAN_STATUS_LABEL,
|
|
|
} from './configs/tables';
|
|
|
+ import { FREQUENCY_TO_LABEL } from './configs/form';
|
|
|
import { useRouter } from 'vue-router';
|
|
|
import type { QueryPageRequest } from '@/types/basic-query';
|
|
|
+ import type { TableColumnProps } from '@/types/basic-table';
|
|
|
import type { AreaCheckPlanQuery, AreaCheckPlanRecord } from './configs/types';
|
|
|
import {
|
|
|
queryAreaCheckPlanDetailPage,
|
|
|
+ queryAreaInspectionPlanTask,
|
|
|
+ queryAreaCheckPlanDetailDeptPage,
|
|
|
+ queryUnqualifiedItemNumDeptPage,
|
|
|
mapAreaCheckPlanApiRecordToUi,
|
|
|
exportAreaCheckPlanAdministration,
|
|
|
+ sandAreaCheckRecordToProductionHiddenDanger,
|
|
|
+ exportRegionalInspectionPlanTaskDepartmentData,
|
|
|
+ type UnqualifiedItemNumRecord,
|
|
|
+ type SandAreaCheckRecordToHiddenDangerReq,
|
|
|
} from '@/api/production-safety-system';
|
|
|
import { getAllDepartments } from '@/api/auth/dept';
|
|
|
import type { DeptTree } from '@/types/dept/type';
|
|
|
@@ -141,8 +362,16 @@
|
|
|
import urlJoin from 'url-join';
|
|
|
import { downloadByData } from '@/utils/file/download';
|
|
|
import { downloadFile } from '@/views/disaster/utils';
|
|
|
+ import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
|
|
|
+ import {
|
|
|
+ queryDangerTypePage,
|
|
|
+ } from '@/api/production-safety';
|
|
|
+ import { queryAvailableUserList } from '@/api/production-safety/responsibility-implementation';
|
|
|
+ import BasicForm from '@/components/BasicForm.vue';
|
|
|
+ import type { CascaderInstance } from 'element-plus'
|
|
|
+ import { useFormConfigHook } from '@/hooks/useFormConfigHook';
|
|
|
+ import { HIDDEN_DANGER_FORM_CONFIG, HIDDEN_DANGER_FORM_RULES, REASON_OPTIONS, HIDDEN_DANGER_FORM_DATA } from "./configs/form"
|
|
|
const router = useRouter();
|
|
|
-
|
|
|
const basicTableRef = ref<InstanceType<typeof BasicTable>>();
|
|
|
const { tableConfig, pagination } = useTableConfig(AREA_CHECK_PLAN_TABLE_COLUMNS, TABLE_OPTIONS);
|
|
|
const tableData = ref<AreaCheckPlanRecord[]>([]);
|
|
|
@@ -151,10 +380,8 @@
|
|
|
// 场所所属类别选项(示例数据,本页面不调用接口)
|
|
|
const venueCategoryOptions = ref<Array<{ label: string; value: string }>>([]);
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+ // 预览
|
|
|
+ const previewOnlineRef = ref<InstanceType<typeof PreviewOnline>>();
|
|
|
const previewOnline = (url: string | undefined, type) => {
|
|
|
if (url) {
|
|
|
previewOnlineRef.value?.open(url, type);
|
|
|
@@ -162,20 +389,14 @@
|
|
|
};
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
const tableQuery = reactive<QueryPageRequest<AreaCheckPlanQuery>>({
|
|
|
pageNumber: pagination.pageNumber,
|
|
|
pageSize: pagination.pageSize,
|
|
|
queryParam: {
|
|
|
searchKey: '',
|
|
|
- status: '' as AreaCheckPlanQuery['status'],
|
|
|
- venueCategory: '',
|
|
|
startDate: '',
|
|
|
endDate: '',
|
|
|
+ status: '' as AreaCheckPlanQuery['status'],
|
|
|
},
|
|
|
});
|
|
|
|
|
|
@@ -190,19 +411,32 @@
|
|
|
tableQuery.pageNumber = value;
|
|
|
getTableData();
|
|
|
};
|
|
|
+ // 判断是否有值, 如果有值就转换成JSON.parse
|
|
|
+ const safeJsonParse = (str) => {
|
|
|
+ // 判断是否有有效值
|
|
|
+ if (str === null || str === undefined || str.trim() === '') {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ return JSON.parse(str);
|
|
|
+ } catch (e) {
|
|
|
+ console.warn('JSON 解析失败:', e);
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
async function getTableData() {
|
|
|
tableConfig.loading = true;
|
|
|
try {
|
|
|
- const res = await queryAreaCheckPlanDetailPage({
|
|
|
- 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;
|
|
|
+ const res = await queryAreaInspectionPlanTask(tableQuery);
|
|
|
+ const list = res?.records ?? [];
|
|
|
+ tableData.value = list.map(item=>{
|
|
|
+ // 附件转换格式
|
|
|
+ item.checkedPersonSign = safeJsonParse(item.checkedPersonSign);
|
|
|
+ return item;
|
|
|
+ })
|
|
|
+ pagination.total = res?.totalRow ?? 0;
|
|
|
} catch (e) {
|
|
|
console.error('查询区域检查计划列表失败:', e);
|
|
|
tableData.value = [];
|
|
|
@@ -228,7 +462,6 @@
|
|
|
const handleReset = () => {
|
|
|
tableQuery.queryParam.searchKey = '';
|
|
|
tableQuery.queryParam.status = '';
|
|
|
- tableQuery.queryParam.venueCategory = '';
|
|
|
tableQuery.queryParam.startDate = '';
|
|
|
tableQuery.queryParam.endDate = '';
|
|
|
dateRange.value = null;
|
|
|
@@ -237,19 +470,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
- const handleView = (id: number) => {
|
|
|
+ const handleView = (row) => {
|
|
|
router.push({
|
|
|
- name: 'areaCheckPlanTaskItem',
|
|
|
- query: { id, operate: 'area-check-plan-view' },
|
|
|
+ name: 'areaCheckPlanTaskDeptItem',
|
|
|
+ query: {
|
|
|
+ recordId: row.id,
|
|
|
+ planId: row.areaPlanId,
|
|
|
+ checkType: row.checkType,
|
|
|
+ operate: 'area-check-plan-view'
|
|
|
+ },
|
|
|
});
|
|
|
};
|
|
|
|
|
|
+ const handleCheck = (row: any) => {
|
|
|
+ router.push({
|
|
|
+ name: 'areaCheckPlanTaskDeptItem',
|
|
|
+ query: {
|
|
|
+ recordId: row.id,
|
|
|
+ planId: row.areaPlanId,
|
|
|
+ checkType: row.checkType, // 传递检查类型,后续根据检查类型区分检查项来源
|
|
|
+ operate: 'area-check-plan-create' },
|
|
|
+ });
|
|
|
+ };
|
|
|
|
|
|
|
|
|
|
|
|
const handleDownload = async () => {
|
|
|
try {
|
|
|
- const response = await exportAreaCheckPlanAdministration(tableQuery.queryParam);
|
|
|
+ const response = await exportRegionalInspectionPlanTaskDepartmentData(tableQuery.queryParam);
|
|
|
if (response) {
|
|
|
const fileName = `区域检查计划任务_${new Date().toISOString().split('T')[0]}.xlsx`;
|
|
|
downloadByData(response, fileName);
|
|
|
@@ -296,7 +544,333 @@
|
|
|
{ label: '室内外停车场', value: '室内外停车场' },
|
|
|
];
|
|
|
getTableData();
|
|
|
+ onIssueDialogOpen();
|
|
|
});
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // 检查不合格数据弹窗
|
|
|
+ const showUnqualifiedDialog = ref(false);
|
|
|
+ const currentRecordIdForUnqualified = ref<number | null>(null);
|
|
|
+ const currentRowForUnqualified = ref<Record<string, unknown> | null>(null);
|
|
|
+ const unqualifiedList = ref<UnqualifiedItemNumRecord[]>([]);
|
|
|
+ const UNQUALIFIED_TABLE_COLUMNS: TableColumnProps[] = [
|
|
|
+ { label: '编号', type: 'index', align: 'center', width: '80px' },
|
|
|
+ { label: '检查场所', prop: 'checkPlace', minWidth: '200px' },
|
|
|
+ { label: '发现问题', prop: 'checkProblem', minWidth: '220px' },
|
|
|
+ { label: '检查时间', prop: 'checkTime', minWidth: '180px' },
|
|
|
+ { label: '操作', slot: 'action', align: 'center', width: '100px' },
|
|
|
+ ];
|
|
|
+ const UNQUALIFIED_TABLE_OPTIONS = {
|
|
|
+ emptyText: '暂无不合格数据',
|
|
|
+ loading: false,
|
|
|
+ maxHeight: '400px',
|
|
|
+ stripe: true,
|
|
|
+ };
|
|
|
+
|
|
|
+ const { tableConfig: unqualifiedTableConfig, pagination: unqualifiedPagination } = useTableConfig(
|
|
|
+ UNQUALIFIED_TABLE_COLUMNS,
|
|
|
+ UNQUALIFIED_TABLE_OPTIONS,
|
|
|
+ true,
|
|
|
+ );
|
|
|
+
|
|
|
+ const RECORD_TABLE_COLUMNS: TableColumnProps[] = [
|
|
|
+ { label: '编号', type: 'index', align: 'center', width: '80px' },
|
|
|
+ { label: '完成(检查)时间', prop: 'checkTime', minWidth: '180px' },
|
|
|
+ { label: '状态', prop: 'status', slot: 'status', minWidth: '120px' },
|
|
|
+ { label: '检查人员', prop: 'checkPerson', minWidth: '140px' },
|
|
|
+ { label: '检查场所类别', prop: 'checkPlaceCategory', minWidth: '160px' },
|
|
|
+ { label: '检查场所', prop: 'checkPlace', minWidth: '180px' },
|
|
|
+ { label: '检查项总数', prop: 'checkItemTotal', align: 'center', width: '160px' },
|
|
|
+ { label: '合格项数', prop: 'qualifiedItemNum', align: 'center', width: '140px' },
|
|
|
+ { label: '不合格项数', prop: 'unqualifiedItemNum', slot: 'unqualifiedItemNum', align: 'center', width: '160px' },
|
|
|
+ { label: '整体检查情况描述', prop: 'overallCheckDesc', minWidth: '190px', showOverflowTooltip: true },
|
|
|
+ { label: '被检查人签字', slot: 'sign', align: 'center', width: '180px' },
|
|
|
+ { label: '操作', slot: 'action', align: 'center', width: '220px', fixed: 'right' },
|
|
|
+ ];
|
|
|
+ const RECORD_TABLE_OPTIONS = {
|
|
|
+ emptyText: '暂无检查记录',
|
|
|
+ loading: false,
|
|
|
+ maxHeight: '400px',
|
|
|
+ stripe: true,
|
|
|
+ };
|
|
|
+ const { tableConfig: recordTableConfig, pagination: recordPagination } = useTableConfig(
|
|
|
+ RECORD_TABLE_COLUMNS,
|
|
|
+ RECORD_TABLE_OPTIONS,
|
|
|
+ true,
|
|
|
+ );
|
|
|
+ // 部门端入账弹窗数据(复用隐患台账新增表单字段与样式)
|
|
|
+ const showSandConfirmDialogDept = ref(false);
|
|
|
+ const sandConfirmLoadingDept = ref(false);
|
|
|
+ const sandHiddenDangerFormRefDept = ref<InstanceType<typeof BasicForm>>();
|
|
|
+ const {
|
|
|
+ ruleFormData: sandHiddenDangerFormDataDept,
|
|
|
+ formRules: sandHiddenDangerFormRulesDept,
|
|
|
+ ruleFormConfig: sandHiddenDangerFormConfigDept,
|
|
|
+ } = useFormConfigHook(
|
|
|
+ HIDDEN_DANGER_FORM_CONFIG,
|
|
|
+ HIDDEN_DANGER_FORM_DATA as Record<string, unknown>,
|
|
|
+ HIDDEN_DANGER_FORM_RULES,
|
|
|
+ );
|
|
|
+ const issueDeptTree = ref<DeptTree[]>([]);
|
|
|
+ const issueUserList = ref<Array<{ id: number; realname?: string; username?: string }>>([]);
|
|
|
+ // 部门树与用户下拉:与 onIssueDialogOpen 中加载的 issueDeptTree 同源(整改/复查/举一反三共用)
|
|
|
+ const cascaderDeptProp = {
|
|
|
+ checkStrictly: true,
|
|
|
+ expandTrigger: 'hover' as const,
|
|
|
+ value: 'id',
|
|
|
+ label: 'deptName',
|
|
|
+ emitPath: false,
|
|
|
+ };
|
|
|
+ const drawLessonsDeptIdsArrayDept = ref<number[]>([]);
|
|
|
+ const reviewUserListDept = ref<Array<{ id: number; realname?: string; username?: string }>>([]);
|
|
|
+
|
|
|
+ const deptOptions = computed(() => flattenDeptTree(issueDeptTree.value));
|
|
|
+ const flattenDeptTree = (nodes: DeptTree[] | undefined): Array<{ id: number; deptName: string }> => {
|
|
|
+ if (!nodes?.length) return [];
|
|
|
+ const list: Array<{ id: number; deptName: string }> = [];
|
|
|
+ const walk = (items: DeptTree[]) => {
|
|
|
+ items.forEach((n) => {
|
|
|
+ if (n.id != null) list.push({ id: n.id, deptName: n.deptName });
|
|
|
+ if (n.children?.length) walk(n.children);
|
|
|
+ });
|
|
|
+ };
|
|
|
+ walk(nodes);
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+ const openUnqualifiedDialog = (row: { id?: number } & Record<string, unknown>) => {
|
|
|
+ if (!row.id) return;
|
|
|
+ currentRecordIdForUnqualified.value = Number(row.id);
|
|
|
+ currentRowForUnqualified.value = row;
|
|
|
+ unqualifiedPagination.pageNumber = 1;
|
|
|
+ showUnqualifiedDialog.value = true;
|
|
|
+ loadUnqualifiedList();
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ const loadUnqualifiedList = async () => {
|
|
|
+ if (!currentRecordIdForUnqualified.value) return;
|
|
|
+ unqualifiedTableConfig.loading = true;
|
|
|
+ try {
|
|
|
+ const res = await queryUnqualifiedItemNumDeptPage({
|
|
|
+ pageNumber: unqualifiedPagination.pageNumber,
|
|
|
+ pageSize: unqualifiedPagination.pageSize,
|
|
|
+ queryParam: {
|
|
|
+ id: currentRecordIdForUnqualified.value,
|
|
|
+ checkPlace: String(currentRowForUnqualified.value?.checkPlace ?? ''),
|
|
|
+ checkProblem: String(currentRowForUnqualified.value?.checkProblem ?? ''),
|
|
|
+ checkTime: String(currentRowForUnqualified.value?.checkTime ?? ''),
|
|
|
+ },
|
|
|
+ });
|
|
|
+ const raw = (res as { data?: { records?: UnqualifiedItemNumRecord[]; totalRow?: number } })?.data ?? res;
|
|
|
+ unqualifiedList.value = raw?.records ?? [];
|
|
|
+ unqualifiedPagination.total = raw?.totalRow ?? 0;
|
|
|
+ } catch (e) {
|
|
|
+ console.error('查询不合格数据失败:', e);
|
|
|
+ unqualifiedList.value = [];
|
|
|
+ unqualifiedPagination.total = 0;
|
|
|
+ } finally {
|
|
|
+ unqualifiedTableConfig.loading = false;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleUnqualifiedSizeChange = (value: number) => {
|
|
|
+ unqualifiedPagination.pageSize = value;
|
|
|
+ unqualifiedPagination.pageNumber = 1;
|
|
|
+ loadUnqualifiedList();
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleUnqualifiedPageChange = (value: number) => {
|
|
|
+ unqualifiedPagination.pageNumber = value;
|
|
|
+ loadUnqualifiedList();
|
|
|
+ };
|
|
|
+
|
|
|
+ // 隐患类别数据
|
|
|
+ const dangerTypeList = ref<any[]>([])
|
|
|
+ const dangerTypeData = async ()=> {
|
|
|
+ try {
|
|
|
+ // 将日期范围同步到查询参数
|
|
|
+ let params = {
|
|
|
+ pageNumber: 1,
|
|
|
+ pageSize: 1000,
|
|
|
+ queryParam: {
|
|
|
+ status: 1,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ const res = await queryDangerTypePage(params);
|
|
|
+ if (res) {
|
|
|
+ dangerTypeList.value = res.records || [];
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('获取隐患类别列表失败:', e);
|
|
|
+ dangerTypeList.value = [];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const handleSandToHiddenDangerDept = (row: { id?: number } & Record<string, unknown>) => {
|
|
|
+ if (!row.id) return;
|
|
|
+ dangerTypeData()
|
|
|
+ currentRecordIdForUnqualified.value = Number(row.id);
|
|
|
+ // 部门端入账同样不带入检查记录旧数据,每次打开还原为隐患台账初始表单
|
|
|
+ Object.assign(sandHiddenDangerFormDataDept, HIDDEN_DANGER_FORM_DATA);
|
|
|
+ showSandConfirmDialogDept.value = true;
|
|
|
+ };
|
|
|
+
|
|
|
+ const validateSandHiddenDangerFormDept = async () => {
|
|
|
+ if (!sandHiddenDangerFormRefDept.value) return false;
|
|
|
+ return await sandHiddenDangerFormRefDept.value.validate();
|
|
|
+ };
|
|
|
+
|
|
|
+ const confirmSandToHiddenDangerDept = async () => {
|
|
|
+ if (!currentRecordIdForUnqualified.value) return;
|
|
|
+ const valid = await validateSandHiddenDangerFormDept();
|
|
|
+ if (!valid) return;
|
|
|
+ sandConfirmLoadingDept.value = true;
|
|
|
+ try {
|
|
|
+ const d = sandHiddenDangerFormDataDept;
|
|
|
+ const payload: SandAreaCheckRecordToHiddenDangerReq = {
|
|
|
+ areaCheckRecordId: currentRecordIdForUnqualified.value,
|
|
|
+ sourceType: 4,
|
|
|
+ sourceRefId: currentRecordIdForUnqualified.value,
|
|
|
+ dangerProblem: d.dangerProblem || '',
|
|
|
+ typeId: d.typeId,
|
|
|
+ reasonId: d.reasonId,
|
|
|
+ taskSource: d.taskSource || '',
|
|
|
+ rectificationRequirement: d.rectificationRequirement || '',
|
|
|
+ rectificationDeadline: d.rectificationDeadline || '',
|
|
|
+ rectificationDepartmentIds: d.rectificationDepartmentIds || '',
|
|
|
+ rectificationResponsiblePerson: d.rectificationResponsiblePerson || '',
|
|
|
+ reviewDepartmentId: d.reviewDepartmentId,
|
|
|
+ reviewPersonId: d.reviewPersonId,
|
|
|
+ reviewPersonName: d.reviewPersonName || '',
|
|
|
+ isDrawLessonsPush: d.isDrawLessonsPush ?? 0,
|
|
|
+ drawLessonsContent: d.drawLessonsContent || '',
|
|
|
+ drawLessonsDepartmentIds: d.drawLessonsDepartmentIds || '',
|
|
|
+ drawLessonsDeadline: d.drawLessonsDeadline || '',
|
|
|
+ attachments: d.attachments || '',
|
|
|
+ confirmSandToHiddenDangerDept: d.confirmSandToHiddenDangerDept ?? 0,
|
|
|
+ rectificationResponsibleIds: d.rectificationResponsibleIds || '',
|
|
|
+ drawLessonsContent: d.drawLessonsContent || '',
|
|
|
+ drawLessonsDepartmentIds: d.drawLessonsDepartmentIds || '',
|
|
|
+ drawLessonsDeadline: d.drawLessonsDeadline || '',
|
|
|
+ };
|
|
|
+ await sandAreaCheckRecordToProductionHiddenDanger(payload);
|
|
|
+ ElMessage.success('入账成功');
|
|
|
+ // 关闭入账表单弹窗和“不合格数据”弹窗
|
|
|
+ showSandConfirmDialogDept.value = false;
|
|
|
+ showUnqualifiedDialog.value = false;
|
|
|
+ await loadRecordList();
|
|
|
+ } catch (e:any) {
|
|
|
+ console.error('部门端下入账失败:', e);
|
|
|
+ ElMessage.error(e?.message || e?.data || '下入账失败,请稍后重试');
|
|
|
+ } finally {
|
|
|
+ sandConfirmLoadingDept.value = false;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ const onIssueDialogOpen = async () => {
|
|
|
+ try {
|
|
|
+ const [deptRes, userRes] = await Promise.all([
|
|
|
+ getAllDepartments(),
|
|
|
+ queryAvailableUserList({ pageNumber: 1, pageSize: 9999, queryParam: {} }),
|
|
|
+ ]);
|
|
|
+ const fullTree = (deptRes as DeptTree[]) ?? [];
|
|
|
+ issueDeptTree.value = Array.isArray(fullTree) && fullTree[0]?.children ? fullTree[0].children : [];
|
|
|
+ issueUserList.value = (userRes as any)?.records ?? [];
|
|
|
+ } catch (e:any) {
|
|
|
+ console.error('获取部门/用户列表失败:', e);
|
|
|
+ ElMessage.error(e?.message || e?.data || '加载部门或负责人列表失败');
|
|
|
+ issueDeptTree.value = [];
|
|
|
+ issueUserList.value = [];
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const cascaderDeptRef = ref<CascaderInstance | null>(null)
|
|
|
+ const onIssueDeptChange = async () => {
|
|
|
+ const nodes = cascaderDeptRef.value?.getCheckedNodes()
|
|
|
+
|
|
|
+ if (!nodes || nodes.length === 0) return
|
|
|
+ const currentDept = nodes[0]
|
|
|
+ sandHiddenDangerFormDataDept.rectificationResponsibleIds = undefined;
|
|
|
+ try {
|
|
|
+ const userRes = await queryAvailableUserList({ pageNumber: 1, pageSize: 9999, queryParam: {deptName: currentDept.data.deptName||undefined} });
|
|
|
+ issueUserList.value = (userRes as any)?.records ?? [];
|
|
|
+ } catch (e:any) {
|
|
|
+ ElMessage.error(e?.message || e?.data || '加载部门或负责人列表失败');
|
|
|
+ issueUserList.value = [];
|
|
|
+ }
|
|
|
+ };
|
|
|
+ // 复查人员所属部门
|
|
|
+ const reviewDeptRef = ref<CascaderInstance | null>(null)
|
|
|
+ const onReviewDeptChange = async () => {
|
|
|
+ const nodes = reviewDeptRef.value?.getCheckedNodes()
|
|
|
+
|
|
|
+ if (!nodes || nodes.length === 0) return
|
|
|
+ const currentDept = nodes[0]
|
|
|
+ sandHiddenDangerFormDataDept.reviewPersonId = undefined;
|
|
|
+ try {
|
|
|
+ const userRes = await queryAvailableUserList({ pageNumber: 1, pageSize: 9999, queryParam: {deptName: currentDept.data.deptName||undefined} });
|
|
|
+ reviewUserListDept.value = (userRes as any)?.records ?? [];
|
|
|
+ } catch (e:any) {
|
|
|
+ ElMessage.error(e?.message || e?.data || '加载部门或负责人列表失败');
|
|
|
+ reviewUserListDept.value = [];
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const currentId = ref<number | null>(null);
|
|
|
+ const recordSearchKeyword = ref('');
|
|
|
+ const recordDateRange = ref<[string, string] | null>(null);
|
|
|
+ const statusValue = ref<number | null>(null);
|
|
|
+ const inspectionRecordList = ref<Array<Record<string, unknown>>>([]);
|
|
|
+
|
|
|
+ const paginatedRecordList = computed(() => inspectionRecordList.value);
|
|
|
+ const loadRecordList = async () => {
|
|
|
+ if (!currentRecordIdForUnqualified.value) return;
|
|
|
+ recordTableConfig.loading = true;
|
|
|
+ try {
|
|
|
+ const [start, end] = recordDateRange.value && recordDateRange.value.length === 2
|
|
|
+ ? recordDateRange.value
|
|
|
+ : ['', ''];
|
|
|
+ const res = await queryAreaCheckPlanDetailDeptPage(currentRecordIdForUnqualified.value, {
|
|
|
+ pageNumber: recordPagination.pageNumber,
|
|
|
+ pageSize: recordPagination.pageSize,
|
|
|
+ queryParam: {
|
|
|
+ searchKey: recordSearchKeyword.value || undefined,
|
|
|
+ startDate: start || undefined,
|
|
|
+ endDate: end || undefined,
|
|
|
+ id: currentRecordIdForUnqualified.value,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ const raw = (res as { data?: { records?: Array<Record<string, unknown>>; totalRow?: number } })?.data ?? res;
|
|
|
+ const records = raw?.records ?? [];
|
|
|
+
|
|
|
+ inspectionRecordList.value = records.map((r: Record<string, unknown>) => {
|
|
|
+ let checkedPersonSign: unknown[] = [];
|
|
|
+ const signValue = r.checkedPersonSign;
|
|
|
+ // 兼容所有脏数据
|
|
|
+ if (signValue) {
|
|
|
+ try {
|
|
|
+ const parsed = JSON.parse(signValue as string);
|
|
|
+ checkedPersonSign = Array.isArray(parsed) ? parsed : [];
|
|
|
+ } catch {
|
|
|
+ checkedPersonSign = [signValue];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ ...r,
|
|
|
+ checkedPersonSign,
|
|
|
+ checkPerson: r.checkPerson ?? r.checkPersonName,
|
|
|
+ checkedCompany: r.checkedCompany ?? r.checkedCompanyName,
|
|
|
+ };
|
|
|
+ });
|
|
|
+ recordPagination.total = raw?.totalRow ?? 0;
|
|
|
+ } catch (e) {
|
|
|
+ console.error('查询检查记录失败:', e);
|
|
|
+ inspectionRecordList.value = [];
|
|
|
+ recordPagination.total = 0;
|
|
|
+ } finally {
|
|
|
+ recordTableConfig.loading = false;
|
|
|
+ }
|
|
|
+ };
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
@@ -304,4 +878,10 @@
|
|
|
@use '@/styles/page-main-layout.scss' as *;
|
|
|
@use '@/styles/basic-table-action.scss' as *;
|
|
|
@use '@/views/traffic/violation/style/act-search-table.scss' as *;
|
|
|
+ :deep(.preview-img){
|
|
|
+ img{
|
|
|
+ max-width: 100%;
|
|
|
+ max-height: 80vh;
|
|
|
+ }
|
|
|
+ }
|
|
|
</style>
|