|
|
@@ -1,79 +1,160 @@
|
|
|
<template>
|
|
|
<div class="safety-platform-container">
|
|
|
<header class="safety-platform-container__header">
|
|
|
- <span class="breadcrumb-title">考核对象</span>
|
|
|
- <el-tabs v-model="activeTab" @tab-change="handleTabChange">
|
|
|
- <el-tab-pane label="全部" name="ALL" />
|
|
|
- <el-tab-pane label="未下发" name="0" />
|
|
|
- <el-tab-pane label="待反馈" name="2" />
|
|
|
- <el-tab-pane label="待评分" name="3" />
|
|
|
- <el-tab-pane label="待审核" name="4" />
|
|
|
- <el-tab-pane label="已作废" name="5" />
|
|
|
- <el-tab-pane label="已完成" name="1" />
|
|
|
- </el-tabs>
|
|
|
+ <div class="evaluation-header">
|
|
|
+ <h1 class="evaluation-title">{{ evaluationDetail.exName || '考核对象' }}</h1>
|
|
|
+ <div class="evaluation-meta">
|
|
|
+ <span>考核部门: {{ evaluationDetail.deptNames || '-' }}</span>
|
|
|
+ <span>创建人: {{ evaluationDetail.createdUserName || '-' }}</span>
|
|
|
+ <span>创建时间: {{ formatDateTime(evaluationDetail.createdAt) || '-' }}</span>
|
|
|
+ </div>
|
|
|
+ </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="handleExport">
|
|
|
- 导出
|
|
|
- </el-button>
|
|
|
- <el-button plain class="search-table-container--button" @click="handleBatchDelete">
|
|
|
- 删除
|
|
|
- </el-button>
|
|
|
- </div>
|
|
|
+ <!-- tabs 放在搜索条件上面 -->
|
|
|
+ <div class="header-tabs-wrapper" v-if="showViewTab">
|
|
|
+ <!-- 顶部切换:按状态 / 按部门考核结果(先进集体排名) / 先进个人 -->
|
|
|
+ <el-tabs v-model="viewTab">
|
|
|
+ <el-tab-pane v-if="operate !== 'evaluationSystem-advanced-group'" label="状态" name="status" />
|
|
|
+ <el-tab-pane label="部门考核结果" name="dept" />
|
|
|
+ <el-tab-pane v-if="operate !== 'evaluationSystem-advanced-group'" label="先进个人" name="person" />
|
|
|
+ </el-tabs>
|
|
|
+ <!-- 状态模式下,展示原有状态 tabs -->
|
|
|
+ <el-tabs
|
|
|
+ v-if="viewTab === 'status'"
|
|
|
+ v-model="activeTab"
|
|
|
+ @tab-change="handleTabChange"
|
|
|
+ >
|
|
|
+ <template v-if="showAllTabs">
|
|
|
+ <el-tab-pane label="全部" name="ALL" />
|
|
|
+ <el-tab-pane
|
|
|
+ v-for="item in EVALUATION_SYSTEM_STATUS_OPTIONS"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :name="String(item.value)"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <el-tab-pane :label="singleTabLabel" :name="singleStatus" />
|
|
|
+ </template>
|
|
|
+ </el-tabs>
|
|
|
+ </div>
|
|
|
+ <!-- 从考核对象入口进来(非先进集体/先进个人),仅展示状态 tabs -->
|
|
|
+ <div class="header-tabs-wrapper" v-else>
|
|
|
+ <el-tabs v-model="activeTab" @tab-change="handleTabChange">
|
|
|
+ <template v-if="showAllTabs">
|
|
|
+ <el-tab-pane label="全部" name="ALL" />
|
|
|
+ <el-tab-pane
|
|
|
+ v-for="item in EVALUATION_SYSTEM_STATUS_OPTIONS"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :name="String(item.value)"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <el-tab-pane :label="singleTabLabel" :name="singleStatus" />
|
|
|
+ </template>
|
|
|
+ </el-tabs>
|
|
|
+ </div>
|
|
|
|
|
|
+ <header>
|
|
|
<div class="act-search">
|
|
|
<section class="select-box">
|
|
|
- <div class="select-box--item">
|
|
|
- <span>状态:</span>
|
|
|
- <el-select
|
|
|
- v-if="activeTab === 'ALL'"
|
|
|
- v-model="tableQuery.queryParam.status"
|
|
|
- placeholder="请选择状态"
|
|
|
- clearable
|
|
|
+ <!-- 部门考核结果视图:显示部门和部门负责人输入框 -->
|
|
|
+ <template v-if="viewTab === 'dept' && operate === 'evaluationSystem-advanced-group'">
|
|
|
+ <div class="select-box--item">
|
|
|
+ <span>部门:</span>
|
|
|
+ <el-input
|
|
|
+ v-model="tableQuery.queryParam.deptName"
|
|
|
+ placeholder="请输入部门名称"
|
|
|
+ clearable
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="select-box--item">
|
|
|
+ <span>部门负责人:</span>
|
|
|
+ <el-input
|
|
|
+ v-model="tableQuery.queryParam.userName"
|
|
|
+ placeholder="请输入部门负责人"
|
|
|
+ clearable
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <!-- <div class="select-box--item">
|
|
|
+ <span>时间范围:</span>
|
|
|
+ <el-date-picker
|
|
|
+ v-model="tableQuery.queryParam.dateRange"
|
|
|
+ type="daterange"
|
|
|
+ range-separator="至"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ format="YYYY-MM-DD"
|
|
|
+ />
|
|
|
+ </div> -->
|
|
|
+ </template>
|
|
|
+ <!-- 其他视图:显示原有搜索条件 -->
|
|
|
+ <template v-else>
|
|
|
+ <!-- 状态筛选仅在"全部"tab 下显示(包含文字和下拉框) -->
|
|
|
+ <div
|
|
|
+ class="select-box--item"
|
|
|
+ v-if="(showViewTab && viewTab === 'status' && activeTab === 'ALL') || (!showViewTab && activeTab === 'ALL')"
|
|
|
>
|
|
|
- <el-option
|
|
|
- v-for="item in EVALUATION_SYSTEM_STATUS_OPTIONS"
|
|
|
- :key="item.value"
|
|
|
- :label="item.label"
|
|
|
- :value="item.value"
|
|
|
+ <span>状态:</span>
|
|
|
+ <el-select
|
|
|
+ v-model="tableQuery.queryParam.status"
|
|
|
+ placeholder="请选择状态"
|
|
|
+ clearable
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="item in EVALUATION_SYSTEM_STATUS_OPTIONS"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :value="item.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="select-box--item">
|
|
|
+ <span>考核对象:</span>
|
|
|
+ <el-cascader
|
|
|
+ ref="targetDeptCascaderRef"
|
|
|
+ v-model="targetDeptId"
|
|
|
+ :options="deptTree"
|
|
|
+ :props="cascaderDeptProp"
|
|
|
+ :show-all-levels="false"
|
|
|
+ placeholder="请选择考核对象部门"
|
|
|
+ filterable
|
|
|
+ @change="handleTargetDeptChange"
|
|
|
/>
|
|
|
- </el-select>
|
|
|
- </div>
|
|
|
- <div class="select-box--item">
|
|
|
- <span>考核对象:</span>
|
|
|
- <el-input
|
|
|
- v-model="tableQuery.queryParam.target"
|
|
|
- placeholder="请输入考核对象"
|
|
|
- class="act-search-input"
|
|
|
- />
|
|
|
- </div>
|
|
|
- <div class="select-box--item">
|
|
|
- <span>时间范围:</span>
|
|
|
- <el-date-picker
|
|
|
- v-model="tableQuery.queryParam.dateRange"
|
|
|
- type="daterange"
|
|
|
- range-separator="至"
|
|
|
- start-placeholder="开始日期"
|
|
|
- end-placeholder="结束日期"
|
|
|
- value-format="YYYY-MM-DD"
|
|
|
- format="YYYY-MM-DD"
|
|
|
- />
|
|
|
- </div>
|
|
|
- <div class="select-box--item">
|
|
|
- <span>搜索关键词:</span>
|
|
|
- <el-input
|
|
|
- v-model="tableQuery.queryParam.keyword"
|
|
|
- placeholder="请输入关键字"
|
|
|
- class="act-search-input"
|
|
|
- />
|
|
|
- </div>
|
|
|
+ </div>
|
|
|
+ <div class="select-box--item">
|
|
|
+ <span>时间范围:</span>
|
|
|
+ <el-date-picker
|
|
|
+ v-model="tableQuery.queryParam.dateRange"
|
|
|
+ type="daterange"
|
|
|
+ range-separator="至"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ format="YYYY-MM-DD"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
</section>
|
|
|
<section class="search-btn">
|
|
|
<el-button type="primary" @click="handleSearch">查询</el-button>
|
|
|
<el-button @click="handleReset">重置</el-button>
|
|
|
+ <el-button plain class="search-table-container--button" @click="handleExport">
|
|
|
+ 导出
|
|
|
+ </el-button>
|
|
|
+ <!-- 先进集体排名 / 先进个人模式下,顶部按钮只保留“导出” -->
|
|
|
+ <!-- <el-button
|
|
|
+ v-if="viewTab === 'status'"
|
|
|
+ plain
|
|
|
+ class="search-table-container--button"
|
|
|
+ @click="handleBatchDelete"
|
|
|
+ >
|
|
|
+ 删除
|
|
|
+ </el-button> -->
|
|
|
</section>
|
|
|
</div>
|
|
|
</header>
|
|
|
@@ -91,10 +172,40 @@
|
|
|
{{ EVALUATION_SYSTEM_STATUS_LABEL[String(scope.row.status)] || '-' }}
|
|
|
</span>
|
|
|
</template>
|
|
|
+ <template #isAdvancedGroup="scope">
|
|
|
+ <span>{{ scope.row.isAdvancedGroup ? '是' : '否' }}</span>
|
|
|
+ </template>
|
|
|
+ <template #evaluationDocument="scope">
|
|
|
+ <div
|
|
|
+ class="file-container--div"
|
|
|
+ v-for="item in parseAttachments(scope.row.evaluationDocument)"
|
|
|
+ :key="item.fileUrl"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="file-container--div__icon"
|
|
|
+ @click="previewOnline(item.fileUrl, item.fileType as keyof typeof FILE_TYPE_ICON)"
|
|
|
+ :src="FILE_TYPE_ICON[item.fileType]"
|
|
|
+ />
|
|
|
+ <span
|
|
|
+ class="file-container--div__name"
|
|
|
+ @click="previewOnline(item.fileUrl, item.fileType as keyof typeof FILE_TYPE_ICON)"
|
|
|
+ >{{ item.fileName }}</span
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="file-container--div__download"
|
|
|
+ :src="DownloadIcon"
|
|
|
+ @click="downloadFile(item.fileUrl, item.fileName)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
<template #action="scope">
|
|
|
<div class="action-container--div" style="justify-content: left">
|
|
|
+ <!-- 先进集体视图:只显示详情 -->
|
|
|
+ <template v-if="viewTab === 'dept' && operate === 'evaluationSystem-advanced-group'">
|
|
|
+ <ActionButton text="详情" @click="handleViewDetail(scope.row.id)" />
|
|
|
+ </template>
|
|
|
<!-- 待反馈:删除 / 作废 -->
|
|
|
- <template v-if="Number(scope.row.status) === 2">
|
|
|
+ <template v-else-if="Number(scope.row.status) === 2">
|
|
|
<ActionButton
|
|
|
text="删除"
|
|
|
:popconfirm="{
|
|
|
@@ -176,21 +287,78 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</main>
|
|
|
+ <PreviewOnline ref="previewOnlineRef" />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
- import { onMounted, reactive, ref } from 'vue';
|
|
|
+ import { computed, onMounted, reactive, ref, watch } from 'vue';
|
|
|
+ import { useRoute, useRouter } from 'vue-router';
|
|
|
import BasicTable from '@/components/BasicTable.vue';
|
|
|
import useTableConfig from '@/hooks/useTableConfigHook';
|
|
|
import ActionButton from '@/components/ActionButton.vue';
|
|
|
import { TABLE_OPTIONS } from '../configs/tables';
|
|
|
- import { EVALUATION_TARGET_TABLE_COLUMNS } from '../configs/targetTables';
|
|
|
+ import {
|
|
|
+ EVALUATION_TARGET_TABLE_COLUMNS,
|
|
|
+ EVALUATION_ADVANCED_GROUP_TABLE_COLUMNS,
|
|
|
+ EVALUATION_ADVANCED_PERSON_TABLE_COLUMNS,
|
|
|
+ } from '../configs/targetTables';
|
|
|
import { EVALUATION_SYSTEM_STATUS_OPTIONS, EVALUATION_SYSTEM_STATUS_LABEL } from '../configs/status';
|
|
|
import type { QueryPageRequest } from '@/types/basic-query';
|
|
|
+ import { getAllDepartments } from '@/api/auth/dept';
|
|
|
+ import type { DeptTree } from '@/types/dept/type';
|
|
|
+ import {
|
|
|
+ querySecurityExamineIssue,
|
|
|
+ querySecurityExamineDetail,
|
|
|
+ updateSecurityExamineIssueRepeal,
|
|
|
+ deleteSecurityExamineIssue,
|
|
|
+ querySecurityExamineIssueAdvanced,
|
|
|
+ } from '@/api/evaluationSystem';
|
|
|
+ import type { QuerySecurityExamineIssueParams, EvaluationSystemItem } from '@/api/evaluationSystem';
|
|
|
+ import { ElMessage } from 'element-plus';
|
|
|
+ import DownloadIcon from '@/views/disaster/disaster-control/src/svg/download.svg';
|
|
|
+ import { downloadFile } from '@/views/disaster/utils';
|
|
|
+ import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
|
|
|
+ import { FILE_TYPE_ICON } from '@/components/UploadFiles/constants';
|
|
|
+
|
|
|
+ const route = useRoute();
|
|
|
+ const router = useRouter();
|
|
|
+ const operate = route.query.operate as string | undefined;
|
|
|
+
|
|
|
+ // 考核表详情
|
|
|
+ const evaluationDetail = ref<Partial<EvaluationSystemItem>>({});
|
|
|
+
|
|
|
+ // 是否展示“状态 / 部门考核结果 / 先进个人”顶层 tabs
|
|
|
+ const showViewTab = computed(
|
|
|
+ () =>
|
|
|
+ operate === 'evaluationSystem-advanced-group' ||
|
|
|
+ operate === 'evaluationSystem-advanced-person',
|
|
|
+ );
|
|
|
+
|
|
|
+ // 顶部 tabs:按状态 / 按部门考核结果(先进集体排名)/ 先进个人
|
|
|
+ const viewTab = ref<'status' | 'dept' | 'person'>(
|
|
|
+ operate === 'evaluationSystem-advanced-group'
|
|
|
+ ? 'dept'
|
|
|
+ : operate === 'evaluationSystem-advanced-person'
|
|
|
+ ? 'person'
|
|
|
+ : 'status',
|
|
|
+ );
|
|
|
+ // 如果从上级页传入 singleStatus(例如 3:待评分),则只展示对应状态的 tab
|
|
|
+ const singleStatus = (route.query.singleStatus as string | undefined) || '';
|
|
|
+ const showAllTabs = computed(() => !singleStatus);
|
|
|
+
|
|
|
+ const singleTabLabel = computed(() => {
|
|
|
+ if (!singleStatus) return '全部';
|
|
|
+ const found = EVALUATION_SYSTEM_STATUS_OPTIONS.find(
|
|
|
+ (item) => String(item.value) === String(singleStatus),
|
|
|
+ );
|
|
|
+ return found?.label || '全部';
|
|
|
+ });
|
|
|
|
|
|
// tabs(ALL:全部,其它为对应状态码字符串)
|
|
|
- const activeTab = ref<'ALL' | '0' | '2' | '3' | '4' | '5' | '1'>('ALL');
|
|
|
+ const activeTab = ref<'ALL' | '0' | '2' | '3' | '4' | '5' | '1'>(
|
|
|
+ (singleStatus as any) || 'ALL',
|
|
|
+ );
|
|
|
|
|
|
// 表格
|
|
|
const basicTableRef = ref<InstanceType<typeof BasicTable>>();
|
|
|
@@ -199,19 +367,60 @@
|
|
|
|
|
|
const tableData = ref<any[]>([]);
|
|
|
|
|
|
+ // 部门树(复用下发考核表的部门下拉逻辑)
|
|
|
+ const targetDeptCascaderRef = ref();
|
|
|
+ const deptTree = ref<DeptTree[]>([]);
|
|
|
+ const targetDeptId = ref<number | null>(null);
|
|
|
+ const cascaderDeptProp = {
|
|
|
+ checkStrictly: true,
|
|
|
+ expandTrigger: 'hover' as const,
|
|
|
+ value: 'id',
|
|
|
+ label: 'deptName',
|
|
|
+ emitPath: false,
|
|
|
+ };
|
|
|
+
|
|
|
const tableQuery = reactive<QueryPageRequest<any>>({
|
|
|
pageNumber: pagination.pageNumber,
|
|
|
pageSize: pagination.pageSize,
|
|
|
queryParam: {
|
|
|
status: '',
|
|
|
target: '',
|
|
|
- keyword: '',
|
|
|
+ deptName: '', // 部门名称(用于部门考核结果视图)
|
|
|
+ userName: '', // 部门负责人(用于部门考核结果视图)
|
|
|
dateRange: null as any,
|
|
|
startTime: '',
|
|
|
endTime: '',
|
|
|
},
|
|
|
});
|
|
|
|
|
|
+ // 从路由获取考核表ID(如果有)
|
|
|
+ const evaluationId = computed(() => {
|
|
|
+ const id = route.query.id;
|
|
|
+ return id ? Number(id) : undefined;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 如果是单状态模式(例如待评分),初始化筛选条件
|
|
|
+ if (singleStatus) {
|
|
|
+ tableQuery.queryParam.status = Number(singleStatus);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根据顶部 tabs 切换表格列配置
|
|
|
+ watch(
|
|
|
+ viewTab,
|
|
|
+ (val) => {
|
|
|
+ if (val === 'status') {
|
|
|
+ tableConfig.columns = EVALUATION_TARGET_TABLE_COLUMNS;
|
|
|
+ } else if (val === 'dept') {
|
|
|
+ tableConfig.columns = EVALUATION_ADVANCED_GROUP_TABLE_COLUMNS;
|
|
|
+ } else {
|
|
|
+ tableConfig.columns = EVALUATION_ADVANCED_PERSON_TABLE_COLUMNS;
|
|
|
+ }
|
|
|
+ // 切换视图时重查
|
|
|
+ handleSearch();
|
|
|
+ },
|
|
|
+ { immediate: true },
|
|
|
+ );
|
|
|
+
|
|
|
const handleSizeChange = (value: number) => {
|
|
|
pagination.pageSize = value;
|
|
|
tableQuery.pageSize = value;
|
|
|
@@ -226,16 +435,127 @@
|
|
|
|
|
|
async function getTableData() {
|
|
|
tableConfig.loading = true;
|
|
|
- // TODO: 调用考核对象列表查询接口
|
|
|
- // const res = await getEvaluationTargetList(tableQuery);
|
|
|
- // tableData.value = res.records;
|
|
|
- // pagination.total = res.totalRow;
|
|
|
- tableData.value = [];
|
|
|
- pagination.total = 0;
|
|
|
- tableConfig.loading = false;
|
|
|
+ try {
|
|
|
+ // 如果是先进集体(部门考核结果视图),调用先进集体接口
|
|
|
+ if (viewTab.value === 'dept' && operate === 'evaluationSystem-advanced-group') {
|
|
|
+ const params = {
|
|
|
+ pageNumber: tableQuery.pageNumber,
|
|
|
+ pageSize: tableQuery.pageSize,
|
|
|
+ queryParam: {
|
|
|
+ psemId: evaluationId.value, // 考核表ID(从路由参数获取)
|
|
|
+ planStartTime: tableQuery.queryParam.startTime || undefined,
|
|
|
+ planEndTime: tableQuery.queryParam.endTime || undefined,
|
|
|
+ deptName: tableQuery.queryParam.deptName || undefined, // 部门名称
|
|
|
+ userName: tableQuery.queryParam.userName || undefined, // 部门负责人
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ const res = await querySecurityExamineIssueAdvanced(params);
|
|
|
+ if (res) {
|
|
|
+ // 映射返回数据字段到表格字段(先进集体排名表格)
|
|
|
+ tableData.value = res.records.map((item) => {
|
|
|
+ // 计算总分数、加分项分数、减分项分数
|
|
|
+ let totalScore = 0;
|
|
|
+ let addScore = 0;
|
|
|
+ let subtractScore = 0;
|
|
|
+
|
|
|
+ if (item.scores && item.scores.length > 0) {
|
|
|
+ item.scores.forEach((score: any) => {
|
|
|
+ const scoreValue = Number(score.reviewScore) || 0;
|
|
|
+ totalScore += scoreValue;
|
|
|
+ if (scoreValue >= 0) {
|
|
|
+ addScore += scoreValue;
|
|
|
+ } else {
|
|
|
+ subtractScore += Math.abs(scoreValue);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ id: item.id,
|
|
|
+ departmentName: item.deptName, // 部门考核结果
|
|
|
+ isAdvancedGroup: item.isAdvancedGroup || false, // 是否先进集体(需要接口返回,暂时使用 false)
|
|
|
+ departmentSort: item.scoreRank || 0, // 部门排序(使用排名)
|
|
|
+ departmentLeader: item.deptUserName || '-', // 部门负责人
|
|
|
+ totalScore, // 总分数
|
|
|
+ addScore, // 加分项分数
|
|
|
+ subtractScore, // 减分项分数
|
|
|
+ // 保留原始数据
|
|
|
+ psemId: item.psemId,
|
|
|
+ deptId: item.deptId,
|
|
|
+ scores: item.scores,
|
|
|
+ scoreRank: item.scoreRank,
|
|
|
+ };
|
|
|
+ });
|
|
|
+ pagination.total = res.totalRow;
|
|
|
+ }
|
|
|
+ } else if (viewTab.value === 'status') {
|
|
|
+ // 状态视图下调用原有接口
|
|
|
+ const params: QuerySecurityExamineIssueParams = {
|
|
|
+ pageNumber: tableQuery.pageNumber,
|
|
|
+ pageSize: tableQuery.pageSize,
|
|
|
+ queryParam: {
|
|
|
+ psemId: evaluationId.value, // 考核表ID(从路由参数获取)
|
|
|
+ planStartTime: tableQuery.queryParam.startTime || undefined,
|
|
|
+ planEndTime: tableQuery.queryParam.endTime || undefined,
|
|
|
+ deptName: tableQuery.queryParam.target || undefined,
|
|
|
+ status:
|
|
|
+ tableQuery.queryParam.status !== '' && tableQuery.queryParam.status !== null
|
|
|
+ ? Number(tableQuery.queryParam.status)
|
|
|
+ : undefined,
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ const res = await querySecurityExamineIssue(params);
|
|
|
+ if (res) {
|
|
|
+ // 映射返回数据字段到表格字段
|
|
|
+ tableData.value = res.records.map((item) => ({
|
|
|
+ id: item.id,
|
|
|
+ evaluationTableName: item.exName, // 考核表名称
|
|
|
+ status: item.status, // 状态
|
|
|
+ statusName: item.statusName, // 状态名称
|
|
|
+ issueDepartment: item.deptName, // 下发部门(部门考核结果)
|
|
|
+ departmentLeader: item.deptUserName || '-', // 部门负责人
|
|
|
+ contactPhone: item.deptUserLink || '-', // 联系方式
|
|
|
+ evaluationDocument: item.attachments, // 考核文档
|
|
|
+ plannedCompletionTime: item.planEndTime || '-', // 计划完成时间(使用计划结束时间)
|
|
|
+ // 保留原始数据,供其他操作使用
|
|
|
+ psemId: item.psemId,
|
|
|
+ deptId: item.deptId,
|
|
|
+ scores: item.scores,
|
|
|
+ scoreRank: item.scoreRank,
|
|
|
+ }));
|
|
|
+ pagination.total = res.totalRow;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 其他视图(如先进个人)暂时为空
|
|
|
+ tableData.value = [];
|
|
|
+ pagination.total = 0;
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('获取列表失败:', e);
|
|
|
+ tableData.value = [];
|
|
|
+ pagination.total = 0;
|
|
|
+ } finally {
|
|
|
+ tableConfig.loading = false;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- const handleSearch = () => {
|
|
|
+ const getDeptTreeData = async () => {
|
|
|
+ try {
|
|
|
+ const res = await getAllDepartments();
|
|
|
+ deptTree.value = res?.[0]?.children ?? [];
|
|
|
+ } catch (e) {
|
|
|
+ console.error('获取部门树失败:', e);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleTargetDeptChange = () => {
|
|
|
+ const nodes = targetDeptCascaderRef.value?.getCheckedNodes?.();
|
|
|
+ tableQuery.queryParam.target = nodes?.[0]?.label ?? '';
|
|
|
+ };
|
|
|
+
|
|
|
+ function handleSearch() {
|
|
|
if (tableQuery.queryParam.dateRange && tableQuery.queryParam.dateRange.length === 2) {
|
|
|
tableQuery.queryParam.startTime = tableQuery.queryParam.dateRange[0];
|
|
|
tableQuery.queryParam.endTime = tableQuery.queryParam.dateRange[1];
|
|
|
@@ -246,13 +566,15 @@
|
|
|
pagination.pageNumber = 1;
|
|
|
tableQuery.pageNumber = 1;
|
|
|
getTableData();
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
const handleReset = () => {
|
|
|
tableQuery.queryParam.status = '';
|
|
|
tableQuery.queryParam.target = '';
|
|
|
- tableQuery.queryParam.keyword = '';
|
|
|
+ tableQuery.queryParam.deptName = '';
|
|
|
+ tableQuery.queryParam.userName = '';
|
|
|
tableQuery.queryParam.dateRange = null;
|
|
|
+ targetDeptId.value = null;
|
|
|
handleSearch();
|
|
|
};
|
|
|
|
|
|
@@ -275,28 +597,142 @@
|
|
|
console.log('batch delete evaluation targets');
|
|
|
};
|
|
|
|
|
|
- const handleDelete = (id: number) => {
|
|
|
- // TODO: 单条删除
|
|
|
- console.log('delete evaluation target', id);
|
|
|
+ const handleDelete = async (id: number) => {
|
|
|
+ try {
|
|
|
+ await deleteSecurityExamineIssue(id);
|
|
|
+ ElMessage.success('删除成功');
|
|
|
+ getTableData();
|
|
|
+ } catch (e: any) {
|
|
|
+ console.error('删除失败:', e);
|
|
|
+ ElMessage.error(e?.message || '删除失败,请重试');
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
- const handleCancel = (id: number) => {
|
|
|
- // TODO: 作废
|
|
|
- console.log('cancel evaluation target', id);
|
|
|
+ const handleCancel = async (id: number) => {
|
|
|
+ try {
|
|
|
+ await updateSecurityExamineIssueRepeal(id);
|
|
|
+ ElMessage.success('作废成功');
|
|
|
+ getTableData();
|
|
|
+ } catch (e: any) {
|
|
|
+ console.error('作废失败:', e);
|
|
|
+ ElMessage.error(e?.message || '作废失败,请重试');
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
const handleScore = (id: number) => {
|
|
|
- // TODO: 评分
|
|
|
- console.log('score evaluation target', id);
|
|
|
+ router.push({
|
|
|
+ name: 'EvaluationSystemItem',
|
|
|
+ query: {
|
|
|
+ id,
|
|
|
+ operate: 'evaluationSystem-feedback',
|
|
|
+ },
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
const handleAudit = (id: number) => {
|
|
|
- // TODO: 审核
|
|
|
- console.log('audit evaluation target', id);
|
|
|
+ router.push({
|
|
|
+ name: 'EvaluationSystemItem',
|
|
|
+ query: {
|
|
|
+ id,
|
|
|
+ operate: 'evaluationSystem-audit',
|
|
|
+ },
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleViewDetail = (id: number) => {
|
|
|
+ router.push({
|
|
|
+ name: 'EvaluationSystemItem',
|
|
|
+ query: {
|
|
|
+ id,
|
|
|
+ operate: 'evaluationSystem-feedback-view',
|
|
|
+ },
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ // 预览
|
|
|
+ const previewOnlineRef = ref<InstanceType<typeof PreviewOnline>>();
|
|
|
+ const previewOnline = (url: string | undefined, type: keyof typeof FILE_TYPE_ICON) => {
|
|
|
+ if (url) {
|
|
|
+ previewOnlineRef.value?.open(url, type);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 解析逗号分隔的URL字符串为文件列表
|
|
|
+ const parseAttachments = (attachmentsStr: string | undefined): Array<{
|
|
|
+ fileUrl: string;
|
|
|
+ fileName: string;
|
|
|
+ fileType: string;
|
|
|
+ }> => {
|
|
|
+ if (!attachmentsStr || !attachmentsStr.trim()) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按逗号分割URL
|
|
|
+ const urls = attachmentsStr.split(',').map(url => url.trim()).filter(url => url);
|
|
|
+
|
|
|
+ return urls.map((url) => {
|
|
|
+ // 从URL中提取文件名
|
|
|
+ const urlParts = url.split('/');
|
|
|
+ const fileName = urlParts[urlParts.length - 1] || '未知文件';
|
|
|
+
|
|
|
+ // 根据文件扩展名判断文件类型
|
|
|
+ const extension = fileName.split('.').pop()?.toLowerCase() || '';
|
|
|
+ let fileType = 'pdf';
|
|
|
+ if (extension === 'doc' || extension === 'docx') {
|
|
|
+ fileType = 'word';
|
|
|
+ } else if (extension === 'xls' || extension === 'xlsx') {
|
|
|
+ fileType = 'excel';
|
|
|
+ } else if (extension === 'ppt' || extension === 'pptx') {
|
|
|
+ fileType = 'ppt';
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ fileUrl: url,
|
|
|
+ fileName,
|
|
|
+ fileType,
|
|
|
+ };
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ // 格式化日期时间
|
|
|
+ const formatDateTime = (dateTimeStr: string | undefined): string => {
|
|
|
+ if (!dateTimeStr) return '';
|
|
|
+ try {
|
|
|
+ const date = new Date(dateTimeStr);
|
|
|
+ const year = date.getFullYear();
|
|
|
+ const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
|
+ const day = String(date.getDate()).padStart(2, '0');
|
|
|
+ const hours = String(date.getHours()).padStart(2, '0');
|
|
|
+ const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
|
+ const seconds = String(date.getSeconds()).padStart(2, '0');
|
|
|
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
|
+ } catch (e) {
|
|
|
+ return dateTimeStr;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 获取考核表详情
|
|
|
+ const getEvaluationDetail = async () => {
|
|
|
+ if (!evaluationId.value) return;
|
|
|
+ try {
|
|
|
+ const res = await querySecurityExamineDetail(evaluationId.value);
|
|
|
+ if (res) {
|
|
|
+ evaluationDetail.value = {
|
|
|
+ exName: res.exName,
|
|
|
+ deptNames: res.deptNames,
|
|
|
+ createdUserName: res.createdUserName,
|
|
|
+ createdAt: res.createdAt,
|
|
|
+ };
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('获取考核表详情失败:', e);
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
onMounted(() => {
|
|
|
+ getDeptTreeData();
|
|
|
getTableData();
|
|
|
+ getEvaluationDetail();
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
@@ -304,10 +740,34 @@
|
|
|
@use '@/styles/page-details-layout.scss' as *;
|
|
|
@use '@/styles/page-main-layout.scss' as *;
|
|
|
@use '@/styles/basic-table-action.scss' as *;
|
|
|
+ @use '@/styles/basic-table-file.scss' as *;
|
|
|
@use '@/views/traffic/violation/style/act-search-table.scss' as *;
|
|
|
|
|
|
.safety-platform-container__header {
|
|
|
padding-bottom: 0 !important;
|
|
|
}
|
|
|
+
|
|
|
+ .evaluation-header {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .evaluation-title {
|
|
|
+ font-size: 20px;
|
|
|
+ font-weight: bold;
|
|
|
+ margin: 0 0 12px 0;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+
|
|
|
+ .evaluation-meta {
|
|
|
+ margin-bottom: 12px;
|
|
|
+ display: flex;
|
|
|
+ gap: 24px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #666;
|
|
|
+ }
|
|
|
+
|
|
|
+ .evaluation-meta span {
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
</style>
|
|
|
|