|
|
@@ -1,148 +1,19 @@
|
|
|
<template>
|
|
|
<div class="shift-schedule-container">
|
|
|
- <!-- 搜索栏 -->
|
|
|
<ContentWrap>
|
|
|
- <el-form
|
|
|
- class="-mb-15px"
|
|
|
- :model="queryParams"
|
|
|
- ref="queryFormRef"
|
|
|
- :inline="true"
|
|
|
- label-width="70px"
|
|
|
- >
|
|
|
- <el-form-item label="起" prop="startDate">
|
|
|
- <el-date-picker
|
|
|
- v-model="queryParams.startDate"
|
|
|
- type="date"
|
|
|
- value-format="YYYY-MM-DD"
|
|
|
- placeholder="开始日期"
|
|
|
- class="!w-150px"
|
|
|
- />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="止" prop="endDate">
|
|
|
- <el-date-picker
|
|
|
- v-model="queryParams.endDate"
|
|
|
- type="date"
|
|
|
- value-format="YYYY-MM-DD"
|
|
|
- placeholder="结束日期"
|
|
|
- class="!w-150px"
|
|
|
- />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="类型" prop="checkType">
|
|
|
- <el-select
|
|
|
- v-model="queryParams.checkType"
|
|
|
- placeholder="全部"
|
|
|
- clearable
|
|
|
- class="!w-150px"
|
|
|
- >
|
|
|
- <el-option label="全部" value=""/>
|
|
|
- <el-option label="年度检查" value="100"/>
|
|
|
- <el-option label="定期检验" value="200"/>
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="单位" prop="unitName">
|
|
|
- <el-input
|
|
|
- v-model="queryParams.unitName"
|
|
|
- placeholder="输入关键字"
|
|
|
- clearable
|
|
|
- class="!w-150px"
|
|
|
- />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="状态" prop="status">
|
|
|
- <el-select
|
|
|
- v-model="queryParams.status"
|
|
|
- placeholder="全部"
|
|
|
- clearable
|
|
|
- class="!w-120px"
|
|
|
- >
|
|
|
- <el-option label="全部" value="">
|
|
|
- <span class="flex items-center gap-6px">
|
|
|
- <span class="inline-block w-10px h-10px rounded-full bg-gray-400"></span>
|
|
|
- <span>全部</span>
|
|
|
- </span>
|
|
|
- </el-option>
|
|
|
- <el-option label="已排期" value="100">
|
|
|
- <span class="flex items-center gap-6px">
|
|
|
- <span class="inline-block w-10px h-10px rounded-full"
|
|
|
- style="background-color: #409eff;"></span>
|
|
|
- <span>已排期</span>
|
|
|
- </span>
|
|
|
- </el-option>
|
|
|
- <el-option label="待约检" value="200">
|
|
|
- <span class="flex items-center gap-6px">
|
|
|
- <span class="inline-block w-10px h-10px rounded-full"
|
|
|
- style="background-color: #e6a23c;"></span>
|
|
|
- <span>待约检</span>
|
|
|
- </span>
|
|
|
- </el-option>
|
|
|
- <el-option label="已受理" value="300">
|
|
|
- <span class="flex items-center gap-6px">
|
|
|
- <span class="inline-block w-10px h-10px rounded-full"
|
|
|
- style="background-color: #67c23a;"></span>
|
|
|
- <span>已受理</span>
|
|
|
- </span>
|
|
|
- </el-option>
|
|
|
- <el-option label="检测中" value="400">
|
|
|
- <span class="flex items-center gap-6px">
|
|
|
- <span class="inline-block w-10px h-10px rounded-full"
|
|
|
- style="background-color: #f56c6c;"></span>
|
|
|
- <span>检测中</span>
|
|
|
- </span>
|
|
|
- </el-option>
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item>
|
|
|
- <el-button @click="handleQuery">
|
|
|
- <Icon icon="ep:search" class="mr-5px"/>
|
|
|
- 查询
|
|
|
- </el-button>
|
|
|
- <el-button @click="resetQuery">
|
|
|
- <Icon icon="ep:refresh" class="mr-5px"/>
|
|
|
- 重置
|
|
|
- </el-button>
|
|
|
-
|
|
|
- <el-button type="success" @click="handleSubmit" :disabled="!hasModifiedRows && !hasCopiedRows">
|
|
|
- <Icon icon="ep:upload" class="mr-5px"/>
|
|
|
- 提交修改
|
|
|
- </el-button>
|
|
|
- <el-button type="success" @click="handleExport" :loading="exportLoading">
|
|
|
- <Icon icon="ep:download" class="mr-5px"/>
|
|
|
- 导出
|
|
|
- </el-button>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- </ContentWrap>
|
|
|
- <ContentWrap>
|
|
|
- <el-table
|
|
|
- v-loading="loading"
|
|
|
- :data="tableData"
|
|
|
- border
|
|
|
- @current-change="handleCurrentChange"
|
|
|
- @row-click="handleRowClick"
|
|
|
- @sort-change="handleSortChange"
|
|
|
- class="shift-schedule-table"
|
|
|
- ref="tableRef"
|
|
|
- :row-class-name="getRowClassName"
|
|
|
- highlight-current-row
|
|
|
- >
|
|
|
- <el-table-column type="selection" width="55" fixed="left" />
|
|
|
+ <el-table v-loading="loading" :data="tableData" border @selection-change="handleSelectionChange"
|
|
|
+ @sort-change="handleSortChange" class="shift-schedule-table" ref="tableRef" :row-class-name="getRowClassName">
|
|
|
+ <el-table-column type="selection" width="55" fixed="left" :selectable="isSelectable" />
|
|
|
<el-table-column label="日期" prop="date" width="170" align="center" fixed="left" sortable>
|
|
|
<template #default="{ row }">
|
|
|
<div class="date-cell">
|
|
|
- <el-date-picker
|
|
|
- v-model="row.date"
|
|
|
- type="date"
|
|
|
- value-format="YYYY-MM-DD"
|
|
|
- placeholder="选择日期"
|
|
|
- :clearable="false"
|
|
|
- class="!w-120px"
|
|
|
- :disabled="!canEdit(row)"
|
|
|
- @change="handleDateChange(row)"
|
|
|
- />
|
|
|
+ <el-date-picker v-model="row.date" type="date" value-format="YYYY-MM-DD" placeholder="选择日期"
|
|
|
+ :clearable="false" class="!w-120px" :disabled="!canEdit(row)" @change="handleDateChange(row)" />
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
|
|
|
- <el-table-column label="星期" prop="week" width="80" align="center"/>
|
|
|
+ <el-table-column label="星期" prop="week" width="80" align="center" />
|
|
|
|
|
|
<!-- 检验员 -->
|
|
|
<el-table-column label="检验员" prop="checkers" width="300" align="center">
|
|
|
@@ -154,35 +25,21 @@
|
|
|
</div>
|
|
|
|
|
|
<!-- 可编辑状态:使用Popover -->
|
|
|
- <el-popover
|
|
|
- v-else
|
|
|
- placement="bottom-start"
|
|
|
- :width="600"
|
|
|
- trigger="click"
|
|
|
- popper-class="checker-select-popover"
|
|
|
- @show="() => handlePopoverShow(row)"
|
|
|
- >
|
|
|
+ <el-popover v-else placement="bottom-start" :width="600" trigger="click"
|
|
|
+ popper-class="checker-select-popover" @show="() => handlePopoverShow(row)">
|
|
|
<template #reference>
|
|
|
- <div
|
|
|
- class="checker-trigger"
|
|
|
- :class="{ 'has-checkers': getCheckerNames(row) }"
|
|
|
- @click.stop
|
|
|
- >
|
|
|
+ <div class="checker-trigger" :class="{ 'has-checkers': getCheckerNames(row) }" @click.stop>
|
|
|
<span class="checker-text">{{ getCheckerNames(row) || '请选择检验员' }}</span>
|
|
|
- <Icon icon="ep:edit" class="edit-icon ml-5px"/>
|
|
|
+ <Icon icon="ep:edit" class="edit-icon ml-5px" />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<!-- Popover内容 -->
|
|
|
<div class="popover-content" @click.stop>
|
|
|
- <CheckerSelect
|
|
|
- :ref="(el) => setCheckerSelectRef(el, row.id)"
|
|
|
- :dept-id="userStore.getUser.deptId?.toString() || props.relateDepartment"
|
|
|
- v-model="row.teamList"
|
|
|
- :multiple="true"
|
|
|
- :has-data="true"
|
|
|
- @change="(checkers) => handleCheckerSelectChange(checkers, row)"
|
|
|
- />
|
|
|
+ <CheckerSelect :ref="(el) => setCheckerSelectRef(el, row.id)"
|
|
|
+ :dept-id="userStore.getUser.deptId?.toString() || props.relateDepartment" v-model="inspectors"
|
|
|
+ :multiple="true" :has-data="true"
|
|
|
+ @change="(checkers) => handleCheckerSelectChange(checkers, row)" />
|
|
|
</div>
|
|
|
</el-popover>
|
|
|
</div>
|
|
|
@@ -194,24 +51,16 @@
|
|
|
{{ row.checkType === '100' ? '定期检验' : '年度检查' }}
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column label="使用单位" prop="unitName" width="150" align="center"
|
|
|
- show-overflow-tooltip sortable/>
|
|
|
- <el-table-column label="管道使用地址" prop="pipeAddress" width="200" align="center"
|
|
|
- show-overflow-tooltip/>
|
|
|
- <el-table-column label="联系人" prop="contact" width="100" align="center"/>
|
|
|
- <el-table-column label="电话" prop="contactPhone" width="130" align="center"/>
|
|
|
+ <el-table-column label="使用单位" prop="unitName" width="150" align="center" show-overflow-tooltip sortable />
|
|
|
+ <el-table-column label="管道使用地址" prop="pipeAddress" width="200" align="center" show-overflow-tooltip />
|
|
|
+ <el-table-column label="联系人" prop="contact" width="100" align="center" />
|
|
|
+ <el-table-column label="电话" prop="contactPhone" width="130" align="center" />
|
|
|
|
|
|
<!-- 管道介质 -->
|
|
|
<el-table-column label="管道介质" prop="pipeMedium" width="150" align="center">
|
|
|
<template #default="{ row }">
|
|
|
<div>
|
|
|
- <el-tag
|
|
|
- v-for="m in (row.pipeMedium || [])"
|
|
|
- :key="m"
|
|
|
- size="small"
|
|
|
- class="mr-5px mb-5px"
|
|
|
- type="primary"
|
|
|
- >
|
|
|
+ <el-tag v-for="m in (row.pipeMedium || [])" :key="m" size="small" class="mr-5px mb-5px" type="primary">
|
|
|
{{ m }}
|
|
|
</el-tag>
|
|
|
<span v-if="!row.pipeMedium || row.pipeMedium.length === 0">-</span>
|
|
|
@@ -223,7 +72,7 @@
|
|
|
<el-table-column label="管线长度 (m)" prop="pipeLengthTotal" width="120" align="center">
|
|
|
<template #default="{ row }">
|
|
|
<span class="font-mono font-semibold text-blue-800">
|
|
|
- {{ row.pipeLengthTotal || '-' }}
|
|
|
+ {{ formatPipeLength(row.pipeLengthTotal) }}
|
|
|
</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
@@ -235,9 +84,8 @@
|
|
|
</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column label="上次报告编号" prop="lastLegalPeriodicalInspectionReportNo" width="150" align="center"/>
|
|
|
- <el-table-column label="监督报告编号" prop="lastMaintenanceReportNo" width="150"
|
|
|
- align="center"/>
|
|
|
+ <el-table-column label="上次报告编号" prop="lastLegalPeriodicalInspectionReportNo" width="150" align="center" />
|
|
|
+ <el-table-column label="监督报告编号" prop="lastMaintenanceReportNo" width="150" align="center" />
|
|
|
|
|
|
<!-- 状态 -->
|
|
|
<el-table-column label="状态" prop="status" width="100" align="center" fixed="right">
|
|
|
@@ -265,20 +113,28 @@
|
|
|
</template>
|
|
|
<div class="flex items-center justify-center gap-6px cursor-help">
|
|
|
<span>状态</span>
|
|
|
- <Icon icon="ep:question-filled" class="text-gray-400" :size="14"/>
|
|
|
+ <Icon icon="ep:question-filled" class="text-gray-400" :size="14" />
|
|
|
</div>
|
|
|
</el-tooltip>
|
|
|
</template>
|
|
|
<template #default="{ row }">
|
|
|
<div class="inline-flex items-center gap-6px">
|
|
|
- <span
|
|
|
- class="inline-block w-10px h-10px rounded-full"
|
|
|
- :class="getStatusClass(row.status)"
|
|
|
- ></span>
|
|
|
+ <span class="inline-block w-10px h-10px rounded-full" :class="getStatusClass(row.status)"></span>
|
|
|
<span>{{ getStatusText(row.status) }}</span>
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
+
|
|
|
+ <!-- 操作 -->
|
|
|
+ <el-table-column label="操作" width="120" align="center" fixed="right">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-tag v-if="row.isCopied && !row.submitted" type="warning" size="small">已复制</el-tag>
|
|
|
+ <el-button v-else size="small" :type="row.modified ? 'success' : 'primary'"
|
|
|
+ :disabled="row.status === 100 || !canEdit(row)" @click="handleCopy(row)">
|
|
|
+ 复制
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
</el-table>
|
|
|
|
|
|
</ContentWrap>
|
|
|
@@ -287,22 +143,23 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
<script setup lang="ts">
|
|
|
-import {ref, reactive, onMounted, defineProps, watch, nextTick, computed} from 'vue'
|
|
|
-import {ElMessage, ElMessageBox} from 'element-plus'
|
|
|
-import {Icon} from '@/components/Icon'
|
|
|
-import {UserQualificationsApi} from "@/api/pressure2/userQualifications";
|
|
|
-import {Edit} from '@element-plus/icons-vue'
|
|
|
-import {EquipPipeSchedulingApi} from "@/api/pressure2/pipescheduling";
|
|
|
-import download from '@/utils/download'
|
|
|
+import { ref, onMounted, defineProps, nextTick, computed } from 'vue'
|
|
|
+import { ElMessage } from 'element-plus'
|
|
|
+import { Icon } from '@/components/Icon'
|
|
|
+import { EquipPipeSchedulingApi } from "@/api/pressure2/pipescheduling";
|
|
|
import dayjs from 'dayjs'
|
|
|
import 'dayjs/locale/zh-cn'
|
|
|
-import {formatArrayDate} from "@/utils/formatTime";
|
|
|
import CheckerSelect from '@/views/pressure2/components/CheckerSelect/index.vue'
|
|
|
-import type {CheckerItem} from '@/views/pressure2/components/CheckerSelect/index.vue'
|
|
|
-import {useUserStoreWithOut} from '@/store/modules/user'
|
|
|
+import type { CheckerItem } from '@/views/pressure2/components/CheckerSelect/index.vue'
|
|
|
+import { useUserStoreWithOut } from '@/store/modules/user'
|
|
|
|
|
|
const props = defineProps<{
|
|
|
- month, relateDepartment
|
|
|
+ relateDepartment: string
|
|
|
+ startDate?: string
|
|
|
+ endDate?: string
|
|
|
+ checkType?: string
|
|
|
+ unitName?: string
|
|
|
+ status?: string
|
|
|
}>()
|
|
|
|
|
|
|
|
|
@@ -337,7 +194,6 @@ interface ScheduleRow {
|
|
|
|
|
|
const loading = ref(false)
|
|
|
const exportLoading = ref(false)
|
|
|
-const queryFormRef = ref()
|
|
|
const tableData = ref<ScheduleRow[]>([])
|
|
|
const selectedRows = ref<ScheduleRow[]>([])
|
|
|
const tableRef = ref()
|
|
|
@@ -347,6 +203,11 @@ const handleSelectionChange = (val: ScheduleRow[]) => {
|
|
|
selectedRows.value = val
|
|
|
}
|
|
|
|
|
|
+// 只有已排期状态才能勾选
|
|
|
+const isSelectable = (row: ScheduleRow): boolean => {
|
|
|
+ return row.status === 100
|
|
|
+}
|
|
|
+
|
|
|
// 用户store
|
|
|
const userStore = useUserStoreWithOut()
|
|
|
|
|
|
@@ -354,17 +215,21 @@ const userStore = useUserStoreWithOut()
|
|
|
const currentEditingRow = ref<ScheduleRow | null>(null)
|
|
|
const checkerSelectRefs = ref<Record<string, any>>({})
|
|
|
|
|
|
-// 查询参数
|
|
|
-const queryParams = reactive({
|
|
|
- startDate: '',
|
|
|
- endDate: '',
|
|
|
- checkType: '',
|
|
|
- unitName: '',
|
|
|
- status: '',
|
|
|
- orderBy: '', // 排序字段
|
|
|
- orderType: '', // 排序类型:asc-升序,desc-降序
|
|
|
- relateDepartment: '' // 关联部门
|
|
|
-})
|
|
|
+// 查询参数 - 从 props 计算
|
|
|
+const queryParams = computed(() => ({
|
|
|
+ startDate: props.startDate || '',
|
|
|
+ endDate: props.endDate || '',
|
|
|
+ checkType: props.checkType || '',
|
|
|
+ unitName: props.unitName || '',
|
|
|
+ status: props.status || '',
|
|
|
+ orderBy: sortOrderBy.value,
|
|
|
+ orderType: sortOrderType.value,
|
|
|
+ relateDepartment: props.relateDepartment || ''
|
|
|
+}))
|
|
|
+
|
|
|
+// 排序参数
|
|
|
+const sortOrderBy = ref('')
|
|
|
+const sortOrderType = ref('')
|
|
|
|
|
|
|
|
|
// ==================== 方法 ====================
|
|
|
@@ -411,13 +276,14 @@ const setCheckerSelectRef = (el: any, rowId: string) => {
|
|
|
checkerSelectRefs.value[rowId] = el
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+const inspectors = ref()
|
|
|
// 处理 Popover 显示
|
|
|
const handlePopoverShow = async (row: ScheduleRow) => {
|
|
|
if (!canEdit(row)) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+ inspectors.value = row.inspectors
|
|
|
currentEditingRow.value = row
|
|
|
|
|
|
const checkerSelectRef = checkerSelectRefs.value[row.id]
|
|
|
@@ -425,8 +291,7 @@ const handlePopoverShow = async (row: ScheduleRow) => {
|
|
|
// 加载检验员列表
|
|
|
const deptId = userStore.getUser.deptId?.toString() || props.relateDepartment
|
|
|
await checkerSelectRef.getCheckerList(deptId)
|
|
|
- console.log(row.teamList)
|
|
|
- row.teamList = row.teamList || []
|
|
|
+ console.log(row.inspectors)
|
|
|
}
|
|
|
|
|
|
// 关闭Popover
|
|
|
@@ -441,7 +306,7 @@ const handleCheckerSelectChange = (selectedCheckers: CheckerItem[], row: Schedul
|
|
|
}
|
|
|
// 同步更新checkers数组(用于提交)- 只需要memberId
|
|
|
row.checkers = selectedCheckers.map(c => c.memberId.toString())
|
|
|
-
|
|
|
+
|
|
|
// 构建 teamList
|
|
|
const teamMap = new Map<string, any>()
|
|
|
selectedCheckers.forEach(item => {
|
|
|
@@ -504,6 +369,14 @@ const getStatusText = (status: number | string | null | undefined): string => {
|
|
|
return statusMap[Number(status)] || '未知'
|
|
|
}
|
|
|
|
|
|
+// 格式化管线长度,去掉小数点后无效的0
|
|
|
+const formatPipeLength = (val: string | undefined): string => {
|
|
|
+ if (!val) return '-'
|
|
|
+ const num = parseFloat(val)
|
|
|
+ if (isNaN(num)) return '-'
|
|
|
+ return String(num)
|
|
|
+}
|
|
|
+
|
|
|
// 获取状态样式类
|
|
|
const getStatusClass = (status: number | string | null | undefined): string => {
|
|
|
if (status === null || status === undefined) {
|
|
|
@@ -533,13 +406,8 @@ const hasCopiedRows = computed(() => {
|
|
|
return tableData.value.some(row => row.isCopied && !row.submitted)
|
|
|
})
|
|
|
|
|
|
-// 是否有修改的行
|
|
|
-const hasModifiedRows = computed(() => {
|
|
|
- return tableData.value.some(row => row.modified)
|
|
|
-})
|
|
|
-
|
|
|
// 获取行类名
|
|
|
-const getRowClassName = ({row}: { row: ScheduleRow }): string => {
|
|
|
+const getRowClassName = ({ row }: { row: ScheduleRow }): string => {
|
|
|
if (row.isCopied && !row.submitted) {
|
|
|
return 'copied-row'
|
|
|
}
|
|
|
@@ -577,6 +445,7 @@ const handleCopy = (row: ScheduleRow) => {
|
|
|
// 清空检验员相关数据
|
|
|
checkers: [],
|
|
|
teamList: [],
|
|
|
+ inspectors: [],
|
|
|
// 深拷贝其他数组类型字段
|
|
|
pipeMedium: row.pipeMedium ? [...row.pipeMedium] : []
|
|
|
}
|
|
|
@@ -601,12 +470,84 @@ const handleCopy = (row: ScheduleRow) => {
|
|
|
|
|
|
ElMessage.success('复制成功,日期已自动设为下一天,请修改检验员后提交')
|
|
|
}
|
|
|
-// 提交
|
|
|
+
|
|
|
+const handleQuery = async () => {
|
|
|
+ loading.value = true
|
|
|
+
|
|
|
+ const res = await EquipPipeSchedulingApi.planSchedulingShiftSchedule(queryParams.value)
|
|
|
+
|
|
|
+ // 处理后端返回的null值
|
|
|
+ tableData.value = (res || []).map((item, index) => ({
|
|
|
+ ...item,
|
|
|
+ index,
|
|
|
+ date: item.date ? dayjs(item.date).format('YYYY-MM-DD') : '',
|
|
|
+ week: item.week || '',
|
|
|
+ checkers: item.checkers || [],
|
|
|
+ teamList: item.teamList || [],
|
|
|
+ checkType: item.checkType || '',
|
|
|
+ unitName: item.unitName || '',
|
|
|
+ pipeAddress: item.pipeAddress || '',
|
|
|
+ contact: item.contact || '',
|
|
|
+ contactPhone: item.contactPhone || '',
|
|
|
+ pipeMedium: item.pipeMedium || [],
|
|
|
+ pipeLengthTotal: item.pipeLengthTotal || '',
|
|
|
+ equipDistrictName: item.equipDistrictName || '',
|
|
|
+ equipStreetName: item.equipStreetName || '',
|
|
|
+ lastLegalPeriodicalInspectionReportNo: item.lastLegalPeriodicalInspectionReportNo || '',
|
|
|
+ lastYearReportNo: item.lastYearReportNo || '',
|
|
|
+ lastMaintenanceReportNo: item.lastMaintenanceReportNo || '',
|
|
|
+ confirmOrderId: item.confirmOrderId || '',
|
|
|
+ status: item.status,
|
|
|
+ isCopied: false,
|
|
|
+ submitted: true
|
|
|
+ }))
|
|
|
+ tableData.value.forEach((row, index) => {
|
|
|
+ const inspectors = row.teamList?.flatMap(team => {
|
|
|
+ const teamMembers = []
|
|
|
+
|
|
|
+ // 处理组长
|
|
|
+ if (team.leaders && team.leaders.length > 0) {
|
|
|
+ team.leaders.forEach(leader => {
|
|
|
+ if (leader) {
|
|
|
+ teamMembers.push({
|
|
|
+ memberId: leader.id,
|
|
|
+ groupTeamId: team.groupTeamId,
|
|
|
+ leaderId: leader.id,
|
|
|
+ member: leader,
|
|
|
+ isLeader: true
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理组员
|
|
|
+ if (team.members && team.members.length > 0) {
|
|
|
+ team.members.forEach(member => {
|
|
|
+ if (member) {
|
|
|
+ teamMembers.push({
|
|
|
+ memberId: member.id,
|
|
|
+ groupTeamId: team.groupTeamId,
|
|
|
+ leaderId: team.leaders?.[0]?.id || '',
|
|
|
+ member: member,
|
|
|
+ isLeader: false
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ return teamMembers
|
|
|
+ }) || []
|
|
|
+ row.inspectors = inspectors
|
|
|
+ console.log('inspectors', inspectors)
|
|
|
+ })
|
|
|
+ loading.value = false
|
|
|
+}
|
|
|
+// 提交 - 提交全部修改和复制的行
|
|
|
const handleSubmit = async () => {
|
|
|
// 获取所有需要提交的行:复制的行和修改的行
|
|
|
const copiedRows = tableData.value.filter(row => row.isCopied && !row.submitted)
|
|
|
const modifiedRows = tableData.value.filter(row => row.modified && !row.isCopied)
|
|
|
-
|
|
|
+
|
|
|
if (copiedRows.length === 0 && modifiedRows.length === 0) {
|
|
|
ElMessage.warning('没有需要提交的行')
|
|
|
return
|
|
|
@@ -614,21 +555,18 @@ const handleSubmit = async () => {
|
|
|
|
|
|
// 校验复制的行
|
|
|
if (copiedRows.length > 0) {
|
|
|
- // 校验1:检查是否都填写了日期
|
|
|
const rowsWithoutDate = copiedRows.filter(row => !row.date || row.date.trim() === '')
|
|
|
if (rowsWithoutDate.length > 0) {
|
|
|
ElMessage.warning('请为所有复制的行选择日期')
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
- // 校验日期是否重复
|
|
|
+
|
|
|
let isDuplicate = false
|
|
|
copiedRows.forEach(row => {
|
|
|
- let id = row.id
|
|
|
- let rows = tableData.value.filter(row => row.id === id)
|
|
|
- // 增加行应该和其他行日期不相同
|
|
|
+ let confirmOrderId = row.confirmOrderId
|
|
|
+ let rows = tableData.value.filter(r => r.confirmOrderId === confirmOrderId)
|
|
|
rows.forEach(item => {
|
|
|
- if (item.date === row.date && row!==item) {
|
|
|
+ if (item.date === row.date && row !== item) {
|
|
|
isDuplicate = true
|
|
|
}
|
|
|
})
|
|
|
@@ -638,7 +576,6 @@ const handleSubmit = async () => {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- // 校验2:检查是否有检验员
|
|
|
const rowsWithoutCheckers = copiedRows.filter(row => !row.checkers || row.checkers.length === 0)
|
|
|
if (rowsWithoutCheckers.length > 0) {
|
|
|
ElMessage.warning('请为所有复制的行选择检验员')
|
|
|
@@ -648,14 +585,12 @@ const handleSubmit = async () => {
|
|
|
|
|
|
// 校验修改的行
|
|
|
if (modifiedRows.length > 0) {
|
|
|
- // 校验1:检查是否都填写了日期
|
|
|
const rowsWithoutDate = modifiedRows.filter(row => !row.date || row.date.trim() === '')
|
|
|
if (rowsWithoutDate.length > 0) {
|
|
|
ElMessage.warning('请为所有修改的行选择日期')
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- // 校验2:检查是否有检验员
|
|
|
const rowsWithoutCheckers = modifiedRows.filter(row => !row.checkers || row.checkers.length === 0)
|
|
|
if (rowsWithoutCheckers.length > 0) {
|
|
|
ElMessage.warning('请为所有修改的行选择检验员')
|
|
|
@@ -664,59 +599,42 @@ const handleSubmit = async () => {
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
- ElMessage({ message: '提交中...', type: 'info', duration: 0 })
|
|
|
-
|
|
|
- // 处理复制的行
|
|
|
- const copyPromises = copiedRows.map(async (row) => {
|
|
|
- // 从 teamList 构建提交数据
|
|
|
+ const allSubmitData: any[] = []
|
|
|
+
|
|
|
+ copiedRows.forEach(row => {
|
|
|
const teamList = (row.teamList || []).map(team => ({
|
|
|
groupTeamId: team.groupTeamId,
|
|
|
leaderId: team.leaders?.[0]?.id || '',
|
|
|
memberIdList: team.members?.map(member => member.id) || []
|
|
|
}))
|
|
|
-
|
|
|
- const copyData = {
|
|
|
+ allSubmitData.push({
|
|
|
+ isCopy: true,
|
|
|
sourceId: row.id,
|
|
|
- newDate: row.date,
|
|
|
+ date: row.date,
|
|
|
teamList: teamList
|
|
|
- }
|
|
|
-
|
|
|
- console.log('复制数据:', copyData)
|
|
|
-
|
|
|
- // 调用复制接口
|
|
|
- const res = await EquipPipeSchedulingApi.copyEquipPipeScheduling(copyData)
|
|
|
- return res
|
|
|
+ })
|
|
|
})
|
|
|
|
|
|
- // 处理修改的行
|
|
|
- const updatePromises = modifiedRows.map(async (row) => {
|
|
|
- // 从 teamList 构建提交数据
|
|
|
+ modifiedRows.forEach(row => {
|
|
|
const teamList = (row.teamList || []).map(team => ({
|
|
|
groupTeamId: team.groupTeamId,
|
|
|
leaderId: team.leaders?.[0]?.id || '',
|
|
|
memberIdList: team.members?.map(member => member.id) || []
|
|
|
}))
|
|
|
-
|
|
|
- const updateData = {
|
|
|
+ allSubmitData.push({
|
|
|
+ isCopy: false,
|
|
|
id: row.id,
|
|
|
date: row.date,
|
|
|
teamList: teamList
|
|
|
- }
|
|
|
-
|
|
|
- console.log('更新数据:', updateData)
|
|
|
-
|
|
|
- // 调用更新接口
|
|
|
- const res = await EquipPipeSchedulingApi.setShiftSchedule([updateData])
|
|
|
- return res
|
|
|
+ })
|
|
|
})
|
|
|
|
|
|
- // 执行所有操作
|
|
|
- await Promise.all([...copyPromises, ...updatePromises])
|
|
|
+ console.log('提交数据:', allSubmitData)
|
|
|
+ await EquipPipeSchedulingApi.setShiftSchedule(allSubmitData)
|
|
|
|
|
|
const totalCount = copiedRows.length + modifiedRows.length
|
|
|
ElMessage.success(`成功提交 ${totalCount} 条数据`)
|
|
|
-
|
|
|
- // 刷新数据
|
|
|
+
|
|
|
await handleQuery()
|
|
|
} catch (error) {
|
|
|
console.error('提交失败:', error)
|
|
|
@@ -724,74 +642,48 @@ const handleSubmit = async () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 查询
|
|
|
-const handleQuery = async () => {
|
|
|
- loading.value = true
|
|
|
-
|
|
|
- // 清除单选状态
|
|
|
- if (tableRef.value) {
|
|
|
- tableRef.value.setCurrentRow(null)
|
|
|
+// 提交计划 - 提交勾选的行
|
|
|
+const handleSubmitSelected = async () => {
|
|
|
+ if (selectedRows.value.length === 0) {
|
|
|
+ ElMessage.warning('请先勾选需要提交的计划')
|
|
|
+ return
|
|
|
}
|
|
|
+ const taskIdsToSubmit: any[] = []
|
|
|
|
|
|
- queryParams.relateDepartment = props.relateDepartment
|
|
|
- const res = await EquipPipeSchedulingApi.planSchedulingShiftSchedule(queryParams)
|
|
|
+ selectedRows.value.forEach(row => {
|
|
|
+ taskIdsToSubmit.push(
|
|
|
+ row.id
|
|
|
+ )
|
|
|
+ })
|
|
|
|
|
|
- // 处理后端返回的null值
|
|
|
- tableData.value = (res || []).map((item, index) => ({
|
|
|
- ...item,
|
|
|
- index,
|
|
|
- date: item.date ? dayjs(item.date).format('YYYY-MM-DD') : '',
|
|
|
- week: item.week || '',
|
|
|
- checkers: item.checkers || [],
|
|
|
- teamList: item.teamList || [],
|
|
|
- checkType: item.checkType || '',
|
|
|
- unitName: item.unitName || '',
|
|
|
- pipeAddress: item.pipeAddress || '',
|
|
|
- contact: item.contact || '',
|
|
|
- contactPhone: item.contactPhone || '',
|
|
|
- pipeMedium: item.pipeMedium || [],
|
|
|
- pipeLengthTotal: item.pipeLengthTotal || '',
|
|
|
- equipDistrictName: item.equipDistrictName || '',
|
|
|
- equipStreetName: item.equipStreetName || '',
|
|
|
- lastLegalPeriodicalInspectionReportNo: item.lastLegalPeriodicalInspectionReportNo || '',
|
|
|
- lastYearReportNo: item.lastYearReportNo || '',
|
|
|
- lastMaintenanceReportNo: item.lastMaintenanceReportNo || '',
|
|
|
- confirmOrderId: item.confirmOrderId || '',
|
|
|
- status: item.status,
|
|
|
- isCopied: false,
|
|
|
- submitted: true
|
|
|
- }))
|
|
|
- loading.value = false
|
|
|
-}
|
|
|
+ try {
|
|
|
+ await ElMessageBox.confirm(
|
|
|
+ `是否确认提交选中的这${taskIdsToSubmit.length} 个计划?`,
|
|
|
+ '提示',
|
|
|
+ {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }
|
|
|
+ )
|
|
|
|
|
|
-// 重置查询
|
|
|
-const resetQuery = async () => {
|
|
|
- queryParams.checkType = ''
|
|
|
- queryParams.unitName = ''
|
|
|
- queryParams.status = ''
|
|
|
- queryParams.orderBy = '' // 重置排序字段
|
|
|
- queryParams.orderType = '' // 重置排序类型
|
|
|
- if (props.month) {
|
|
|
- // month 格式:2026-02
|
|
|
- const [year, month] = props.month.split('-').map(Number)
|
|
|
-
|
|
|
- // 计算当月第一天
|
|
|
- const startDate = `${year}-${String(month).padStart(2, '0')}-01`
|
|
|
-
|
|
|
- // 计算当月最后一天
|
|
|
- const lastDay = new Date(year, month, 0).getDate()
|
|
|
- const endDate = `${year}-${String(month).padStart(2, '0')}-${String(lastDay).padStart(2, '0')}`
|
|
|
-
|
|
|
- // 设置日期范围
|
|
|
- queryParams.startDate = startDate
|
|
|
- queryParams.endDate = endDate
|
|
|
- } else {
|
|
|
- // 如果没有 month,则清空日期
|
|
|
- queryParams.startDate = ''
|
|
|
- queryParams.endDate = ''
|
|
|
+ await EquipPipeSchedulingApi.planSchedulingConfirm({
|
|
|
+ ids: taskIdsToSubmit
|
|
|
+ })
|
|
|
+ ElMessage.success('提交计划成功')
|
|
|
+
|
|
|
+ // 提交成功后清空选中状态
|
|
|
+ selectedRows.value = []
|
|
|
+ // 重新加载数据
|
|
|
+ handleQuery()
|
|
|
+ } catch (error) {
|
|
|
+ console.error('提交计划失败:', error)
|
|
|
+ ElMessage.error('提交计划失败')
|
|
|
}
|
|
|
- await handleQuery()
|
|
|
+
|
|
|
}
|
|
|
+// 查询
|
|
|
+
|
|
|
|
|
|
// 当前行变化(单选)
|
|
|
const handleCurrentChange = (currentRow: ScheduleRow | null) => {
|
|
|
@@ -802,35 +694,32 @@ const handleCurrentChange = (currentRow: ScheduleRow | null) => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 点击行自动勾选(单选)
|
|
|
-const handleRowClick = (row: ScheduleRow) => {
|
|
|
- if (tableRef.value) {
|
|
|
- tableRef.value.setCurrentRow(row)
|
|
|
- }
|
|
|
-}
|
|
|
|
|
|
// 排序变化
|
|
|
-const handleSortChange = ({column, prop, order}: { column: any; prop: string; order: string }) => {
|
|
|
+const handleSortChange = ({ column, prop, order }: { column: any; prop: string; order: string }) => {
|
|
|
if (order) {
|
|
|
- // 设置排序参数
|
|
|
- queryParams.orderBy = prop
|
|
|
- queryParams.orderType = order === 'ascending' ? 'asc' : 'desc'
|
|
|
+ sortOrderBy.value = prop
|
|
|
+ sortOrderType.value = order === 'ascending' ? 'asc' : 'desc'
|
|
|
} else {
|
|
|
- // 取消排序
|
|
|
- queryParams.orderBy = ''
|
|
|
- queryParams.orderType = ''
|
|
|
+ sortOrderBy.value = ''
|
|
|
+ sortOrderType.value = ''
|
|
|
}
|
|
|
-
|
|
|
- // 重新查询
|
|
|
handleQuery()
|
|
|
}
|
|
|
|
|
|
-// 导出排班表
|
|
|
+// 导出排班表 - 导出和列表看到的数据一模一样
|
|
|
const handleExport = async () => {
|
|
|
try {
|
|
|
exportLoading.value = true
|
|
|
- const data = await EquipPipeSchedulingApi.exportShiftSchedule(queryParams)
|
|
|
- download.excel(data, '排班表')
|
|
|
+ const data = await EquipPipeSchedulingApi.exportShiftSchedule(queryParams.value)
|
|
|
+ // 使用 Blob 方式下载
|
|
|
+ const blob = new Blob([data], { type: 'application/vnd.ms-excel' })
|
|
|
+ const href = URL.createObjectURL(blob)
|
|
|
+ const downA = document.createElement('a')
|
|
|
+ downA.href = href
|
|
|
+ downA.download = '排班表'
|
|
|
+ downA.click()
|
|
|
+ URL.revokeObjectURL(href)
|
|
|
ElMessage.success('导出成功')
|
|
|
} catch (error) {
|
|
|
console.error('导出失败:', error)
|
|
|
@@ -840,16 +729,18 @@ const handleExport = async () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// 暴露方法给父组件
|
|
|
+defineExpose({
|
|
|
+ handleQuery,
|
|
|
+ handleSubmit,
|
|
|
+ handleSubmitSelected,
|
|
|
+ handleExport
|
|
|
+})
|
|
|
+
|
|
|
// ==================== 生命周期 ====================
|
|
|
onMounted(async () => {
|
|
|
- await resetQuery()
|
|
|
+ await handleQuery()
|
|
|
})
|
|
|
-
|
|
|
-watch(() => props.month, async (newMonth, oldMonth) => {
|
|
|
- if (newMonth && newMonth !== oldMonth) {
|
|
|
- await resetQuery()
|
|
|
- }
|
|
|
-}, {immediate: false})
|
|
|
</script>
|
|
|
<style scoped lang="scss">
|
|
|
.shift-schedule-container {
|
|
|
@@ -865,6 +756,13 @@ watch(() => props.month, async (newMonth, oldMonth) => {
|
|
|
letter-spacing: 0.3px;
|
|
|
}
|
|
|
|
|
|
+ :deep(.el-table__header th:first-child) {
|
|
|
+ font-weight: 600;
|
|
|
+ color: #113355;
|
|
|
+ border-left: 3px solid #3f78b3;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
:deep(.el-table__row td) {
|
|
|
padding: 10px 6px;
|
|
|
font-size: 13px;
|