| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338 |
- <template>
- <ContentWrap>
- <!-- 搜索工作栏 -->
- <el-form
- class="-mb-15px"
- :model="queryParams"
- ref="queryFormRef"
- :inline="true"
- label-width="100px"
- >
- <!-- 基本信息查询部分 -->
- <div class="flex flex-wrap items-start gap-x-2">
- <el-form-item label="单位名称" prop="unitName">
- <el-input
- v-model="queryParams.unitName"
- placeholder="请输入单位名称"
- clearable
- @keyup.enter="getList"
- class="!w-240px"
- />
- </el-form-item>
- <el-form-item label="管道使用地址" prop="pipeAddress">
- <el-input
- v-model="queryParams.pipeAddress"
- placeholder="请输入管道使用地址"
- clearable
- @keyup.enter="getList"
- class="!w-240px"
- />
- </el-form-item>
- <el-form-item label="工程号" prop="projectNo">
- <el-input
- v-model="queryParams.projectNo"
- placeholder="请输入工程号"
- clearable
- @keyup.enter="getList"
- class="!w-240px"
- />
- </el-form-item>
- <el-form-item label="工程名称" prop="projectName">
- <el-input
- v-model="queryParams.projectName"
- placeholder="请输入工程名称"
- clearable
- @keyup.enter="getList"
- class="!w-240px"
- />
- </el-form-item>
- <el-form-item label="部门" prop="relateDepartment">
- <DeptSelect
- v-model="queryParams.relateDepartment"
- placeholder="请选择部门"
- clearable
- class="!w-240px"
- />
- </el-form-item>
- <!-- </div>
- <!– 区域和时间查询部分 –>
- <div class="flex flex-wrap items-start gap-x-2">-->
- <el-form-item label="区域" prop="equipDistrict">
- <AreaSelect
- v-model="queryParams.equipDistrict"
- placeholder="请选择区域"
- class="!w-[240px]"
- multiple
- collapse-tags
- collapse-tags-tooltip
- :clearable="true"
- @clear="handleAreaClear"
- @change="handleAreaChange"
- @area-type-change="handleAreaTypeChange"
- />
- </el-form-item>
- <el-form-item label="街道" prop="equipStreet">
- <StreetSelect
- v-model="queryParams.equipStreet"
- :district-ids="queryParams.equipDistrict"
- placeholder="请选择街道"
- class="!w-[240px]"
- multiple
- collapse-tags
- collapse-tags-tooltip
- :clearable="true"
- @clear="handleStreetClear"
- @change="handleStreetChange"
- />
- </el-form-item>
- <el-form-item label="使用状态" prop="useStatus">
- <el-select
- v-model="queryParams.useStatus"
- placeholder="选择使用状态"
- clearable
- multiple
- collapse-tags
- collapse-tags-tooltip
- class="!w-240px"
- >
- <el-option
- v-for="dict in getStrDictOptions(DICT_TYPE.PIPE_USE_STATUS)"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="临检时间" prop="checkDate">
- <div class="flex items-center gap-x-2">
- <el-select v-model="datePickerType" class="!w-[90px]">
- <el-option label="时间段" value="daterange" />
- <el-option label="月份" value="month" />
- </el-select>
- <el-date-picker
- v-if="datePickerType === 'daterange'"
- v-model="daterange"
- type="daterange"
- value-format="YYYY-MM-DD"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- class="!w-[220px]"
- @change="handleDateChange"
- />
- <el-date-picker
- v-else
- v-model="month"
- type="month"
- value-format="YYYY-MM"
- placeholder="选择月份"
- class="!w-[150px]"
- @change="handleMonthChange"
- />
- </div>
- </el-form-item>
- </div>
- <!-- 锅炉相关查询条件 -->
- <div class="bg-gray-50 p-3 rounded mt-2">
- <el-form-item label="管道归类" prop="typeList" class="mb-2">
- <div class="flex items-center flex-1">
- <el-checkbox-group
- v-model="queryParams.typeList"
- class="flex flex-wrap gap-2"
- @change="handleTypeListChange"
- >
- <el-checkbox
- v-for="dict in containerTypeOptions"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- </el-checkbox-group>
- </div>
- </el-form-item>
- </div>
- <!-- 操作按钮 -->
- <div class="flex justify-between mt-3">
- <el-form-item class="mb-0">
- <el-button type="primary" @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-form-item>
- <el-form-item class="mb-0">
- <el-button
- type="primary"
- plain
- v-if="source === 'pressure'"
- @click="handleBatchSchedule"
- :disabled="selectedRows.length === 0"
- >
- <Icon icon="ep:calendar" class="mr-5px" /> 排期约检
- </el-button>
- <el-button type="success" @click="handleExport">
- <Icon icon="ep:download" class="mr-5px" /> 导出
- </el-button>
- </el-form-item>
- </div>
- </el-form>
- </ContentWrap>
- <!-- 列表 -->
- <ContentWrap>
- <!-- <el-table
- v-loading="loading"
- :data="list"
- stripe
- @selection-change="handleSelectionChange"
- @sort-change="handleSortChange"
- @expand-change="handleExpandChange"
- ref="mainTableRef"
- border
- >
- <el-table-column type="expand">
- <template #default="props">
- <PipelineDetailList :row="props.row" @selection-change="handleChildSelectionChange"/>
- </template>
- </el-table-column>
- <!– <el-table-column v-if="source === 'pressure'" type="selection" width="30" />–>
- <el-table-column
- label="区域"
- align="center"
- prop="equipDistrictName"
- min-width="80"
- sortable="custom"
- />
- <el-table-column
- label="街道"
- align="center"
- prop="equipStreetName"
- min-width="100"
- sortable="custom"
- />
- <el-table-column label="使用单位名称 " align="center" prop="unitName" min-width="150" />
- <el-table-column label="使用管道使用地址" align="center" prop="pipeAddress" min-width="150" />
- <!– 法定检验 –>
- <el-table-column
- label="定期检验"
- align="center"
- prop="nextLegalCheckDate"
- min-width="140"
- sortable="custom"
- >
- <template #default="{ row }">
- <div class="check-number regular-check">{{ row.countLegal }}</div>
- <div v-if="row.nextLegalCheckDate !== null && row.countLegal > 0" class="text-xs text-gray-500">
- 最近临期时间:{{ dayjs(row.nextLegalCheckDate).format('YYYY-MM-DD') }}
- </div>
- </template>
- </el-table-column>
- <!– 年度检查 –>
- <el-table-column
- label="年度检查"
- align="center"
- prop="nextYearCheckDate"
- min-width="140"
- sortable="custom"
- >
- <template #default="{ row }">
- <div class="check-number year-check">{{ row.countYear }}</div>
- <div
- v-if="row.nextYearCheckDate !== null && row.countYear > 0"
- class="text-xs text-gray-500"
- >
- 最近临期时间:{{ dayjs(row.nextYearCheckDate).format('YYYY-MM-DD') }}
- </div>
- </template>
- </el-table-column>
- <!– 使用单位联系人 –>
- <el-table-column label="约检联系人" align="center" prop="contactPerson" min-width="140">
- <template #default="{ row }">
- <div>{{ row.contact || '无' }}</div>
- </template>
- </el-table-column>
- <!– 使用单位联系电话 –>
- <el-table-column label="约检联系电话" align="center" prop="contactPhone" min-width="140">
- <template #default="{ row }">
- <div>{{ row.contactPhone || '无' }}</div>
- </template>
- </el-table-column>
- <!– 操作 –>
- <el-table-column label="操作" align="center" width="150" fixed="right">
- <template #default="scope">
- <el-button link type="primary" size="small" @click="handleSchedule(scope.row)">
- 计划排期
- </el-button>
- <el-button link type="primary" size="small" @click="handleEdit(scope.row)">
- 编辑
- </el-button>
- </template>
- </el-table-column>
- </el-table>-->
- <el-table
- v-loading="loading"
- ref="mainTableRef"
- :data="list"
- border
- @selection-change="handleSelectionChange"
- @sort-change="handleSortChange"
- :row-key="(row) => row.id"
- :row-class-name="getMainRowClassName"
- @row-click="handleMainRowClick"
- @expand-change="handleExpandChange"
- :expand-row-keys="expandRowKeys"
- >
- <el-table-column type="selection" width="40"/>
- <el-table-column type="expand">
- <template #default="props">
- <el-table
- :data="props.row.pipes" border
- :header-cell-style="{background: '#f5f7fa', color: '#606266'}"
- :ref="(el) => setDetailTableRef(el, props.row.id)"
- @selection-change="(selection) => handleDetailSelectionChange(selection, props.row)"
- :row-class-name="getRowClassName"
- :cell-class-name="(params) => getDetailCellClassName(params, props.row)"
- class="inner-table"
- @row-click="handleRowClick"
- >
- <el-table-column type="selection" width="40"/>
- <el-table-column type="index" label="序号" width="60" align="center"/>
- <el-table-column label="工程号" prop="projectNo" align="center" min-width="150"/>
- <el-table-column label="管道编号" prop="pipeNo" align="center" min-width="150"/>
- <el-table-column label="注册代码" prop="pipeRegCode" align="center" min-width="150"/>
- <el-table-column label="管道名称" prop="pipeName" align="center" min-width="150"/>
- <el-table-column label="最近定期检查" prop="nextLegalCheckDateDetail" align="center" min-width="150" sortable>
- <template #default="{ row }">
- <div class="text-xs text-gray-500">
- {{ formatDate(row.nextLegalCheckDateDetail, 'YYYY-MM-DD') }}
- <div v-if="row.planLegalCheckDate" class="text-xs text-[#2D5FBD]">
- (排期时间:{{ formatDate(row.planLegalCheckDate, 'YYYY-MM-DD') }})
- </div>
- </div>
- </template>
- </el-table-column>
- <!-- 最近年度检查-->
- <el-table-column label="最近年度检查" prop="nextYearCheckDateDetail" align="center" min-width="150" sortable>
- <template #default="{ row }">
- <div class="text-xs text-gray-500">
- {{ formatDate(row.nextYearCheckDateDetail, 'YYYY-MM-DD') }}
- <div v-if="row.planYearCheckDate" class="text-xs text-[#2D5FBD]">
- (排期时间:{{ formatDate(row.planYearCheckDate, 'YYYY-MM-DD') }})
- </div>
- </div>
- </template>
- </el-table-column>
- <el-table-column label="状态" prop="useStatus" align="center" min-width="50">
- <template #default="{ row }">
- <dict-tag :type="DICT_TYPE.PIPE_USE_STATUS" :value="row.useStatus" />
- </template>
- </el-table-column>
- </el-table>
- </template>
- </el-table-column>
- <el-table-column type="index" label="序号" width="60" align="center"/>
- <el-table-column
- label="区域"
- align="center"
- prop="equipDistrictName"
- min-width="80"
- />
- <el-table-column
- label="街道"
- align="center"
- prop="equipStreetName"
- min-width="100"
- />
- <el-table-column label="使用单位名称 " align="center" prop="unitName" min-width="180">
- <template #default="{ row }">
- <el-link
- type="primary"
- :underline="false"
- @click.stop="handleEdit(row)"
- style="cursor: pointer"
- >
- {{ row.unitName }}
- </el-link>
- </template>
- </el-table-column>
- <el-table-column label="管道使用地址" align="center" prop="pipeAddress" min-width="150" />
- <el-table-column label="工程号" prop="projectNo" align="center" min-width="150"/>
- <el-table-column label="工程名称" prop="projectName" align="center" min-width="150"/>
- <el-table-column label="定期检验" prop="nextLegalCheckDate" align="center" min-width="150" sortable="custom">
- <template #default="{ row }">
- <div class="schedule-cell">
- <span class="schedule-date">
- <span class="schedule-date-link" @click.stop="handleSchedule(row,'100')">
- {{formatDate(row.nextLegalCheckDate, 'YYYY-MM-DD') || '-'}}
- </span>
- </span>
- <span
- class="schedule-count"
- :class="{ 'schedule-count-completed': row.legalScheduledCount === row.legalTotalCount && row.legalTotalCount > 0 }"
- v-if="row.legalScheduledCount > 0"
- >
- ({{ row.legalScheduledCount || 0 }}/{{ row.legalTotalCount || 0 }})
- </span>
- <span v-else class="schedule-count-placeholder"></span>
- </div>
- </template>
- </el-table-column>
- <el-table-column label="年度检查" prop="nextYearCheckDate" align="center" min-width="150" sortable="custom">
- <template #default="{ row }">
- <div class="schedule-cell">
- <span class="schedule-date">
- <span class="schedule-date-link" @click.stop="handleSchedule(row,'200')">
- {{formatDate(row.nextYearCheckDate, 'YYYY-MM-DD') || '-'}}
- </span>
- </span>
- <span
- class="schedule-count"
- :class="{ 'schedule-count-completed': row.yearScheduledCount === row.yearTotalCount && row.yearTotalCount > 0 }"
- v-if="row.yearScheduledCount > 0"
- >
- ({{ row.yearScheduledCount || 0 }}/{{ row.yearTotalCount || 0 }})
- </span>
- <span v-else class="schedule-count-placeholder"></span>
- </div>
- </template>
- </el-table-column>
- <el-table-column label="管道数量" prop="pipeCount" align="center" min-width="100"/>
- <el-table-column label="操作" align="center" width="150" fixed="right">
- <template #default="scope">
- <el-button link type="primary" size="small" @click.stop="handleSchedule(scope.row)">
- 计划排期
- </el-button>
- <el-button link type="primary" size="small" @click.stop="handleEdit(scope.row)">
- 编辑
- </el-button>
- </template>
- </el-table-column>
- </el-table>
- <!-- 分页 -->
- <Pagination
- :total="total"
- v-model:page="queryParams.pageNo"
- v-model:limit="queryParams.pageSize"
- @pagination="handleQuery"
- />
- </ContentWrap>
- <!-- 计划排期弹窗 -->
- <PipePlanScheduleDialog
- ref="scheduleDialogRef"
- :selected-rows="selectedRows"
- :selected-pipe-rows="selectedDetailRows"
- :selected-legal-list="selectedLegalList"
- :selected-year-list="selectedYearList"
- :source="source"
- @success="handleScheduleSuccess"
- />
- <!-- 详情弹窗 -->
- <Detail :source="source" ref="detailDialogRef" />
- </template>
- <script setup lang="ts">
- import {useUserStore} from "@/store/modules/user";
- import {
- EquipPipeSchedulingApi,
- EquipPipeSchedulingDetailVO,
- EquipPipeSchedulingVO,
- PipePlanSchedulingDetailVO
- } from '@/api/pressure2/pipescheduling'
- import {DICT_TYPE, getStrDictOptions, StringDictDataType} from "@/utils/dict";
- import DeptSelect from "@/views/pressure2/pipescheduling/components/DeptSelect.vue";
- import AreaSelect from "@/views/system/equipcontainer/components/AreaSelect.vue";
- import StreetSelect from "@/views/system/equipcontainer/components/StreetSelect.vue";
- import dayjs from "dayjs";
- import PipePlanScheduleDialog from "@/views/pressure2/pipescheduling/components/PipePlanScheduleDialog.vue";
- import Detail from "@/views/pressure2/pipescheduling/detail.vue";
- import PipelineDetailList from "@/views/pressure2/pipescheduling/components/PipelineDetailList.vue";
- import {formatDate} from "@/utils/formatTime";
- import {ref} from "vue";
- import {PipeEquipmentDetailVO, PipeEquipmentVO} from "@/api/pressure2/pipeequipment";
- import {EquipBoilerSchedulingVO} from "@/api/pressure2/equipboilerscheduling";
- import download from "@/utils/download";
- /** 锅炉计划排期 列表 */
- defineOptions({ name: 'EquipPipeScheduling' })
- const message = useMessage() // 消息弹窗
- const userStore = useUserStore()
- const loading = ref(true) // 列表的加载中
- const list = ref<EquipPipeSchedulingVO[]>([]) // 列表的数据
- const total = ref(0) // 列表的总页数
- const queryParams = ref({
- pageNo: 1,
- pageSize: 10,
- unitName: undefined as string | undefined,
- pipeAddress: undefined as string | undefined,
- projectNo: undefined as string | undefined,
- relateDepartment: userStore.user.deptId,
- equipDistrict: undefined as number[] | undefined,
- equipStreet: undefined as number[] | undefined,
- typeList: [] as string[],
- nextDate: [
- dayjs('1900-01-01').startOf('day').format('YYYY-MM-DD HH:mm:ss'),
- dayjs().add(1, 'month').endOf('month').endOf('day').format('YYYY-MM-DD HH:mm:ss')
- ] as string[],
- useStatus: [] as string[],
- areaType: 'gz',
- sort:undefined,
- order:undefined,
- })
- const queryFormRef = ref() // 搜索的表单
- const source = ref<string>('pressure') // 来源:计划约检、前台约检
- const selectedRows = ref<EquipPipeSchedulingVO[]>([]) // 选中的行
- const selectedPipeRows = ref<EquipPipeSchedulingVO[]>([]) // 选中的设备行
- const scheduleDialogRef = ref() // 计划排期弹窗引用
- const datePickerType = ref<'daterange' | 'month'>('month') // 修改时间选择类型定义
- const daterange = ref<string[]>([]) // 日期选择值
- const month = ref<string>(dayjs().add(1, 'month').endOf('month').endOf('day').format('YYYY-MM-DD')) // 月份选择值
- const detailDialogRef = ref() // 详情弹窗引用
- // 添加锅炉类型字典选项变量
- const containerTypeOptions = getStrDictOptions(DICT_TYPE.PIPE_TYPE)
- const selectedTypeList = ref<StringDictDataType[]>([]) // 选中的锅炉归类
- const selectedLegalList = ref([])
- const selectedYearList = ref([])
- const mainTableRef = ref() // 主表格引用
- const selectedDetailRows = ref<any[]>([]) // 选中的行
- /** 查询列表 */
- const getList = async () => {
- loading.value = true
- try {
- const data = await EquipPipeSchedulingApi.getEquipPipeSchedulingPagePipe(queryParams.value)
- list.value = data.list
- total.value = data.total
- // 重置展开状态、选中状态和缓存
- expandRowKeys.value = []
- selectedDetailRows.value = []
- selectedRows.value = []
- selectedLegalList.value = []
- selectedYearList.value = []
- expandedRowsCache.value.clear()
- } finally {
- loading.value = false
- }
- }
- /** 搜索按钮操作 */
- const handleQuery = () => {
- //queryParams.value.pageNo = 1
- getList()
- }
- /** 重置按钮操作 */
- const resetQuery = () => {
- queryFormRef.value.resetFields()
- // 重置日期相关的所有值
- daterange.value = []
- month.value = ''
- datePickerType.value = 'month' // 重置为默认的月份选择
- queryParams.value.nextDate = [
- dayjs('1900-01-01').startOf('day').format('YYYY-MM-DD HH:mm:ss'),
- dayjs().add(1, 'month').endOf('month').endOf('day').format('YYYY-MM-DD HH:mm:ss')
- ] // 重置nextDate参数
- // 重置区域和街道的选择
- queryParams.value.equipDistrict = undefined
- queryParams.value.equipStreet = undefined
- areaStreetMap.value.clear()
- queryParams.value.sort = undefined
- queryParams.value.order = undefined
- // 重置页码
- queryParams.value.pageNo = 1
- // 清空选中的容器归类对象
- selectedTypeList.value = []
- // 清除表格排序
- mainTableRef.value?.clearSort()
- handleQuery()
- }
- /** 处理日期变化 */
- const handleDateChange = (val: [string, string] | null) => {
- daterange.value = val || []
- queryParams.value.nextDate = val
- ? [
- dayjs(val[0]).startOf('day').format('YYYY-MM-DD HH:mm:ss'),
- dayjs(val[1]).endOf('day').format('YYYY-MM-DD HH:mm:ss')
- ]
- : []
- }
- /** 处理月份变化 */
- const handleMonthChange = (val: string | null) => {
- if (!val) {
- queryParams.value.nextDate = []
- return
- }
- const date = dayjs(val)
- queryParams.value.nextDate = [
- date.startOf('month').format('YYYY-MM-DD HH:mm:ss'),
- date.endOf('month').format('YYYY-MM-DD HH:mm:ss')
- ]
- month.value = val
- }
- // 记录每个区域下已选择的街道
- const areaStreetMap = ref(new Map<number, number[]>())
- /** 处理区域变化 */
- const handleAreaChange = (areas: number[]) => {
- // 获取移除的区域(通过比较之前的区域列表和现在的区域列表)
- const prevAreas = Array.from(areaStreetMap.value.keys())
- const removedAreas = prevAreas.filter((area) => !areas.includes(area))
- // 移除取消选择的区域下的街道
- if (removedAreas.length > 0) {
- const currentStreets = queryParams.value.equipDistrict || []
- removedAreas.forEach((areaId) => {
- const streetsToRemove = areaStreetMap.value.get(areaId) || []
- // 从当前选中的街道中移除这些街道
- queryParams.value.equipDistrict = currentStreets.filter(
- (streetId) => !streetsToRemove.includes(streetId)
- )
- // 从映射中移除该区域
- areaStreetMap.value.delete(areaId)
- })
- }
- }
- /** 处理区域清空 */
- const handleAreaClear = () => {
- // 清空所有选中的街道
- queryParams.value.equipDistrict = []
- // 清空区域-街道映射
- areaStreetMap.value.clear()
- }
- /** 区域类型的变化 */
- const handleAreaTypeChange = (areaType) => {
- queryParams.value.areaType = areaType
- }
- /** 处理街道变化 */
- const handleStreetChange = (streets: number[], areaId: number) => {
- // 更新区域-街道映射
- if (queryParams.value.equipDistrict?.includes(areaId)) {
- areaStreetMap.value.set(areaId, streets)
- }
- }
- /** 处理街道清空 */
- const handleStreetClear = () => {
- // 清空所有区域下的街道选择
- areaStreetMap.value.clear()
- }
- /** 处理锅炉归类变化 */
- const handleTypeListChange = (values: string[]) => {
- selectedTypeList.value = containerTypeOptions.filter((dict) => values.includes(dict.value))
- }
- /*
- /!** 表格选择框变化 *!/
- const handleSelectionChange = (selection: EquipPipeSchedulingVO[]) => {
- selectedRows.value = selection
- }
- /!** 处理表格排序 *!/
- const handleSortChange = ({ prop, order }) => {
- if (!prop || !order) {
- list.value.sort(() => 0) // 重置排序
- return
- }
- list.value.sort((a, b) => {
- const aValue = a[prop] || ''
- const bValue = b[prop] || ''
- if (order === 'ascending') {
- return aValue > bValue ? 1 : -1
- } else {
- return aValue < bValue ? 1 : -1
- }
- })
- }
- /!** 处理单条记录排期 *!/
- const handleSchedule = async (row: EquipPipeSchedulingVO) => {
- let rowSelections = selectedRows.value.filter(item => item.unitId === row.unitId);
- // if (rowSelections.length === 0){
- // message.warning('请至少选择一条明细记录')
- // return
- // }
- // 如果没有选中明细记录,则获取该主表下的所有子表数据
- if (rowSelections.length === 0) {
- // 从列表中找到对应的主表行
- const mainRow = list.value.find(item => item.id === row.id);
- if (mainRow) {
- // 获取该主表行的所有子表数据
- const params = {
- legalEquipIds: mainRow.legalEquipIds,
- yearEquipIds: mainRow.yearEquipIds,
- };
- try {
- const response = await EquipPipeSchedulingApi.getDetailByProject(params);
- rowSelections = response || [];
- if (rowSelections.length === 0) {
- message.warning('该工程下没有可排期的管道数据');
- return;
- }
- // 展开该主表行以显示子表
- if (mainTableRef.value) {
- mainTableRef.value.toggleRowExpansion(row, true);
- }
- } catch (error) {
- console.log(error)
- message.error('获取管道详情失败');
- return;
- }
- } else {
- message.warning('请至少选择一条明细记录');
- return;
- }
- }
- //按定检和年检分组
- selectedLegalList.value = []
- selectedYearList.value = []
- rowSelections.forEach(item => {
- if (!item.hasLegalScheduling && item.planLegalCheckDate == null){
- selectedLegalList.value.push(item)
- }
- if (!item.hasYearScheduling && item.planYearCheckDate == null){
- selectedYearList.value.push(item)
- }
- })
- //selectedPipeRows.value = [row];
- scheduleDialogRef.value?.open(selectedLegalList.value,selectedYearList.value)
- //console.log(selectedPipeRows.value)
- }
- /!** 处理编辑操作 *!/
- const handleEdit = (row: EquipPipeSchedulingVO) => {
- // 传递当前的查询条件,处理 relateDepartment 类型
- const currentQueryParams = {
- ...queryParams.value,
- relateDepartment: queryParams.value.relateDepartment?.toString(),
- datePickerType: datePickerType.value,
- month: month.value,
- nextDate: queryParams.value.nextDate
- }
- //console.log(currentQueryParams)
- detailDialogRef.value?.open(row, currentQueryParams)
- }
- */
- /** 处理批量排期 */
- const handleBatchSchedule = () => {
- if (selectedDetailRows.value.length === 0 && selectedRows.value.length === 0) {
- message.warning('请至少选择一条记录')
- return
- }
- // 遍历选中的子表行,找到主表行
- // selectedPipeRows.value = list.value.filter(item => selectedRows.value.some(row => {
- // if (item.legalEquipIds && item.legalEquipIds.includes(row.equipPipeId)) {
- // return true
- // }
- // return !!(item.yearEquipIds && item.yearEquipIds.includes(row.equipPipeId));
- //
- // }
- // ))
- //按定检和年检分组
- selectedLegalList.value = []
- selectedYearList.value = []
- // 选择了主表但是没有选子表,则获取该主表下的所有子表数据
- let ids = selectedDetailRows.value.map(item => item.equipPipeId)
- selectedRows.value.forEach(item => {
- if (!ids.includes(item.id)) {
- item.pipes.forEach(pipe => {
- if (!pipe.hasLegalScheduling && pipe.planLegalCheckDate == null) {
- selectedLegalList.value.push(pipe)
- }
- if (!pipe.hasYearScheduling && pipe.planYearCheckDate == null) {
- selectedYearList.value.push(pipe)
- }
- })
- }
- })
- selectedDetailRows.value.forEach(item => {
- if (!item.hasLegalScheduling && item.planLegalCheckDate == null){
- selectedLegalList.value.push(item)
- }
- if (!item.hasYearScheduling && item.planYearCheckDate == null){
- selectedYearList.value.push(item)
- }
- })
- //console.log("selectedRows.value",selectedRows.value)
- //console.log(selectedLegalList.value,selectedYearList.value)
- //scheduleDialogRef.value?.open(selectedPipeRows.value,selectedRows.value)
- //selectedPipeRows.value = [row];
- console.log('selectedLegalList.value',selectedLegalList.value,selectedYearList.value)
- scheduleDialogRef.value?.open(selectedLegalList.value,selectedYearList.value)
- }
- /** 排期成功处理 */
- const handleScheduleSuccess = () => {
- selectedRows.value = []
- getList()
- }
- /** 处理子组件选择变化 */
- /*const childSelectionsMap = ref<Record<string | number, PipePlanSchedulingDetailVO[]>>({}); // 新增: 存储子组件的选中项
- const handleChildSelectionChange = (selection: EquipPipeSchedulingDetailVO[], parentId: string | number) => {
- if (!parentId) {
- // 如果父ID无效,则不处理,或者记录一个警告
- console.warn('Received selection change from child with invalid parentId');
- return;
- }
- selectedRows.value = [...selection]
- if (selection && selection.length > 0) {
- childSelectionsMap.value[parentId] = [...selection];
- } else {
- //delete childSelectionsMap.value[parentId]; // 如果子列表选择为空,则移除其记录
- childSelectionsMap.value[parentId] = [];
- }
- // 重新计算 selectedRows,合并所有子列表的选中项,并基于 detail 项的 id 去重
- const allSelections = Object.values(childSelectionsMap.value).flat();
- if (allSelections.length > 0 && allSelections[0].id !== undefined) {
- selectedRows.value = Array.from(new Map(allSelections.map(item => [item.id, item])).values());
- } else {
- // 如果没有 id 字段或者 allSelections 为空,直接赋值(或根据实际情况处理)
- selectedRows.value = allSelections;
- }
- //console.log('Updated selectedRows:', selectedRows.value);
- }
- const handleExpandChange = (row,expandedRows) => {
- if (expandedRows.includes(row)) {
- //console.log(`展开行`,row);
- } else {
- //console.log(`收起行`,row);
- childSelectionsMap.value[row.id] = [];
- // 重新计算 selectedRows,合并所有子列表的选中项,并基于 detail 项的 id 去重
- const allSelections = Object.values(childSelectionsMap.value).flat();
- if (allSelections.length > 0 && allSelections[0].id !== undefined) {
- selectedRows.value = Array.from(new Map(allSelections.map(item => [item.id, item])).values());
- } else {
- // 如果没有 id 字段或者 allSelections 为空,直接赋值(或根据实际情况处理)
- selectedRows.value = allSelections;
- }
- }
- //console.log('Updated selectedRows:', selectedRows.value);
- }
- const handleChildExpandChange = (row,expandedRows,id) => {
- // if (expandedRows.includes(row)) {
- // //console.log(`展开行`,row);
- // } else {
- // //console.log(`收起行`,row);
- // childSelectionsMap.value[id] = [];
- // //console.log(`childSelectionsMap.value child`,childSelectionsMap.value);
- // // 重新计算 selectedRows,合并所有子列表的选中项,并基于 detail 项的 id 去重
- // const allSelections = Object.values(childSelectionsMap.value).flat();
- // //console.log('allSelections:', allSelections);
- // if (allSelections.length > 0 && allSelections[0].id !== undefined) {
- // selectedRows.value = Array.from(new Map(allSelections.map(item => [item.id, item])).values());
- // } else {
- // // 如果没有 id 字段或者 allSelections 为空,直接赋值(或根据实际情况处理)
- // selectedRows.value = allSelections;
- // }
- // }
- console.log('Updated selectedRows:', childSelectionsMap.value);
- }
- //保存查询参数
- const QUERY_PARAMS_CACHE_KEY = 'equip_pipe_scheduling_query_params'
- // 保存查询参数到缓存
- const saveQueryParamsToCache = () => {
- const cacheData = {
- queryParams: unref(queryParams),
- datePickerType: unref(datePickerType),
- dateRange: unref(daterange),
- month: unref(month),
- selectedTypeList: unref(selectedTypeList),
- }
- localStorage.setItem(QUERY_PARAMS_CACHE_KEY, JSON.stringify(cacheData))
- }
- // 从缓存恢复查询参数
- const loadQueryParamsFromCache = () => {
- const cacheData = localStorage.getItem(QUERY_PARAMS_CACHE_KEY)
- if (cacheData) {
- try {
- const parsedData = JSON.parse(cacheData)
- // 排除 useStatus和relateDepartment、pageNo、pageSize 字段
- const { useStatus,relateDepartment, pageNo, pageSize, ...queryParamsWithoutStatus } = parsedData.queryParams
- queryParams.value = {
- ...queryParams.value,
- ...queryParamsWithoutStatus
- }
- datePickerType.value = parsedData.datePickerType
- daterange.value = parsedData.dateRange
- month.value = parsedData.month
- selectedTypeList.value = parsedData.selectedTypeList
- } catch (error) {
- console.error('解析缓存数据失败:', error)
- }
- }
- }*/
- /** 判断是否有已排期的时间 */
- const hasPlanSchedule = (row: any, type: 'legal' | 'year') => {
- if (type === 'legal') {
- return row.planLegalCheckDate != null && row.planLegalCheckDate !== '' && row.planLegalCheckDate !== 'null'
- } else {
- return row.planYearCheckDate != null && row.planYearCheckDate !== '' && row.planYearCheckDate !== 'null'
- }
- }
- /** 获取子表单元格类名 */
- const getDetailCellClassName = ({ row, column }, mainRow) => {
- // 检查列是否为检验日期列,只有当有有效排期时间时才添加黄色背景类
- if (column.property === 'nextLegalCheckDateDetail') {
- if (row.planLegalCheckDate != null && row.planLegalCheckDate !== '' && row.planLegalCheckDate !== 'null') {
- return 'cell-scheduled'
- }
- }
- if (column.property === 'nextYearCheckDateDetail') {
- if (row.planYearCheckDate != null && row.planYearCheckDate !== '' && row.planYearCheckDate !== 'null') {
- return 'cell-scheduled'
- }
- }
- return ''
- }
- const detailTableRefs = ref<Record<string, any>>({})
- const setDetailTableRef = (el: any, parentId: string) => {
- if (el) {
- detailTableRefs.value[parentId] = el;
- }
- }
- const getDetailTableRef = (parentId: string) => {
- return detailTableRefs.value[parentId];
- }
- // 标志位:防止展开时恢复选中状态触发 handleDetailSelectionChange 覆盖缓存
- const isRestoringSelection = ref(false)
- /** 处理表格排序 */
- const handleSortChange = ({ prop, order }) => {
- queryParams.value.sort = prop
- queryParams.value.order = order
- handleQuery()
- }
- const getMainRowClassName = ({ row }) => {
- const isSelected = mainTableRef.value?.getSelectionRows().some((item) =>
- item.id === row.id
- )
- return isSelected ? 'selected-row' : ''
- }
- const getRowClassName = ({row}) => {
- // 找到当前行所在的分组,从 Map 中获取对应的表格实例
- const tableRef = getDetailTableRef(row.equipPipeId)
- if (tableRef) {
- const isSelected = tableRef.getSelectionRows().some((item) =>
- item.id === row.id
- )
- return isSelected ? 'selected-row' : ''
- }
- return ''
- }
- const handleExpandChange = (row, expandedRows: any[]) => {
- const rowId = row.id
- const isExpanded = expandedRows.some((r) => r.id === rowId)
-
- if (isExpanded) {
- // 展开时,从缓存中恢复或初始化
- if (!expandedRowsCache.value.has(rowId)) {
- // 首次展开,初始化缓存
- expandedRowsCache.value.set(rowId, {
- pipes: row.pipes || [],
- selectedIds: new Set<string>()
- })
- }
- // 恢复选中状态
- nextTick(() => {
- const cache = expandedRowsCache.value.get(rowId)
- const tableRef = getDetailTableRef(rowId)
- if (cache && tableRef && cache.pipes.length > 0) {
- // 设置标志位,防止触发 handleDetailSelectionChange
- isRestoringSelection.value = true
-
- cache.pipes.forEach((pipe) => {
- if (cache.selectedIds.has(pipe.id)) {
- tableRef.toggleRowSelection(pipe, true)
- }
- })
-
- // 恢复完成后,延迟重置标志位
- nextTick(() => {
- isRestoringSelection.value = false
- })
- }
- })
- } else {
- // 收起时,保存当前选中状态
- const tableRef = getDetailTableRef(rowId)
- if (tableRef) {
- const currentSelection = tableRef.getSelectionRows()
- const selectedIds = new Set(currentSelection.map((item: any) => item.id))
- expandedRowsCache.value.set(rowId, {
- pipes: row.pipes || [],
- selectedIds: selectedIds
- })
- }
- }
-
- // 更新展开的行 key 列表
- expandRowKeys.value = expandedRows.map((r) => r.id)
- }
- /** 处理行点击勾选 */
- const handleMainRowClick = (row, _event,_column) => {
- mainTableRef.value?.toggleRowSelection(row)
- }
- const handleRowClick = (row, _event, column) => {
- // 如果点击的是选择列,不处理
- if (column.type === 'selection') {
- return
- }
- // 找到当前行所在的分组,从 Map 中获取对应的表格实例
- const tableRef = getDetailTableRef(row.equipPipeId)
- if (tableRef && tableRef.toggleRowSelection) {
- tableRef.toggleRowSelection(row)
- }
- }
- // 已展开行的 key 列表
- const expandRowKeys = ref<string[]>([])
- // 缓存展开行的子表数据和选中状态
- const expandedRowsCache = ref<Map<string, { pipes: any[], selectedIds: Set<string> }>>(new Map())
- /** 表格选择框变化 */
- const handleSelectionChange = async (selection: any[]) => {
- // 计算取消选择的行
- const deselectedRows = selectedRows.value.filter(
- item => !selection.includes(item)
- );
- selectedRows.value = selection
-
- // 清除取消选中行的子表选择(包括展开的和收起的)
- deselectedRows.forEach(item => {
- const rowId = item.id
- // 如果该行是展开状态,直接清除表格选中
- const tableRef = getDetailTableRef(rowId)
- if (tableRef) {
- tableRef.clearSelection()
- }
-
- // 无论是否展开,都清除缓存中的选中状态
- if (expandedRowsCache.value.has(rowId)) {
- expandedRowsCache.value.get(rowId)!.selectedIds.clear()
- }
-
- // 从全局选中的子表数据中移除
- selectedDetailRows.value = selectedDetailRows.value.filter(
- detailRow => detailRow.equipPipeId !== rowId
- )
- })
- }
- /** 处理子表选择变化 */
- const handleDetailSelectionChange = (selection: any[], mainRow: any) => {
- // 如果正在恢复选中状态,不更新缓存(避免展开时 toggleRowSelection 触发此函数覆盖缓存)
- if (isRestoringSelection.value) {
- return
- }
-
- const rowId = mainRow.id
-
- // 更新缓存中的选中状态(如果缓存不存在则创建)
- if (!expandedRowsCache.value.has(rowId)) {
- // 如果该行还未展开,初始化缓存
- expandedRowsCache.value.set(rowId, {
- pipes: mainRow.pipes || [],
- selectedIds: new Set<string>()
- })
- }
- const cache = expandedRowsCache.value.get(rowId)!
- cache.selectedIds = new Set(selection.map((item: any) => item.id))
-
- // 更新全局选中的子表数据
- selectedDetailRows.value = selectedDetailRows.value.filter((item) => item.equipPipeId !== mainRow.id)
- selectedDetailRows.value = [...selectedDetailRows.value.filter(row => !selection.some(sel => sel.id === row.id)), ...selection]
-
- // 如果子表有选中项,则自动选中主表行;否则取消选中主表行
- nextTick(() => {
- if (selection.length > 0) {
- // 子表有选中项,选中主表行
- mainTableRef.value.toggleRowSelection(mainRow, true);
- } else if (!selectedDetailRows.value.map(row => row.equipPipeId).includes(mainRow.id)) {
- const currentlySelected = selectedRows.value.some(row => row.id === mainRow.id);
- if (currentlySelected && selection.length === 0) {
- // 只有当主行当前是选中状态且子表没有任何选中项时才取消主行选择
- mainTableRef.value.toggleRowSelection(mainRow, false);
- }
- }
- });
- }
- /** 处理编辑操作 */
- const handleEdit = (row: any) => {
- // 传递当前的查询条件,处理 relateDepartment 类型
- const currentQueryParams = {
- ...queryParams.value,
- relateDepartment: queryParams.value.relateDepartment?.toString(),
- datePickerType: datePickerType.value,
- month: month.value,
- nextDate: queryParams.value.nextDate
- }
- //console.log(currentQueryParams)
- detailDialogRef.value?.open(row, currentQueryParams)
- }
- const handleSchedule = async (row: any,checkType?: string) => {
- selectedRows.value = [row]
- //按定检和年检分组
- selectedLegalList.value = []
- selectedYearList.value = []
- row.pipes.forEach(item => {
- if (selectedDetailRows.value.includes(item)) {
- if (!item.hasLegalScheduling && item.planLegalCheckDate == null) {
- selectedLegalList.value.push(item)
- }
- if (!item.hasYearScheduling && item.planYearCheckDate == null) {
- selectedYearList.value.push(item)
- }
- }
- })
- if (selectedLegalList.value.length == 0 && selectedYearList.value.length == 0) {
- // 默认带出全部
- row.pipes.forEach(item => {
- if (!item.hasLegalScheduling && item.planLegalCheckDate == null) {
- selectedLegalList.value.push(item)
- }
- if (!item.hasYearScheduling && item.planYearCheckDate == null) {
- selectedYearList.value.push(item)
- }
- })
- }
- scheduleDialogRef.value?.open(selectedLegalList.value, selectedYearList.value,checkType)
- }
- const handleExport = async () => {
- try {
- const data = await EquipPipeSchedulingApi.exportEquipPipeScheduling(queryParams.value)
- download.excel(data, '管道计划排期表单.xls')
- message.success('导出成功')
- } catch (error) {
- console.error(error)
- message.error('导出失败')
- }
- }
- /** 初始化 **/
- onMounted(() => {
- //loadQueryParamsFromCache()
- getList()
- })
- onUnmounted(()=>{
- //saveQueryParamsToCache()
- })
- </script>
- <style lang="scss" scoped>
- .check-number {
- font-size: 18px;
- font-weight: bold;
- }
- .regular-check {
- color: var(--el-color-primary);
- }
- .year-check {
- color: var(--el-color-success);
- }
- .expired-check {
- color: var(--el-color-danger);
- }
- .containerView {
- padding: 10px;
- }
- ::v-deep .el-select__selection.is-near {
- max-height: 200px;
- overflow-y: scroll;
- scrollbar-width: none;
- -ms-overflow-style: none;
- }
- ::v-deep .containerView .el-select__wrapper {
- min-width: 200px;
- }
- // 外层表格复选框样式
- ::v-deep .outer-table .el-checkbox__input.is-checked .el-checkbox__inner,
- ::v-deep .outer-table .el-checkbox__input.is-indeterminate .el-checkbox__inner {
- }
- ::v-deep .outer-table .el-checkbox__input.is-checked .el-checkbox__inner::after {
- border-color: #fff;
- }
- // 内层表格复选框样式
- ::v-deep .inner-table .el-checkbox__input.is-checked .el-checkbox__inner,
- ::v-deep .inner-table .el-checkbox__input.is-indeterminate .el-checkbox__inner {
- background-color: #67c23a; // 绿色
- border-color: #67c23a;
- }
- ::v-deep .inner-table .el-checkbox__input.is-checked .el-checkbox__inner::after {
- border-color: #fff;
- }
- // 外层表格选中行背景色
- ::v-deep .outer-table .el-table__body tr.current-row > td {
- background-color: #ecf5ff;
- }
- // 内层表格选中行背景色
- ::v-deep .inner-table .el-table__body tr.current-row > td {
- background-color: #f0f9eb;
- }
- :deep(.selected-row){
- background-color: #ecf5ff !important;
- }
- // 子表选中行特殊背景色(浅绿色)
- :deep(.inner-table .selected-row) {
- background-color: #e8f5e9 !important;
- }
- // 排期日期链接样式
- .schedule-date-link {
- cursor: pointer;
- color: var(--el-color-primary);
- transition: all 0.2s;
-
- &:hover {
- color: var(--el-color-primary-light-3);
- text-decoration: underline;
- }
- }
- // 排期统计分数样式
- .schedule-count {
- font-size: 12px;
- color: var(--el-color-info);
- font-weight: 500;
- background-color: #FFFF99;
- }
- // 已完成排期的样式
- .schedule-count-completed {
- color: var(--el-color-info);
- background-color: #C5F1C1;
- }
- // 分数占位符,用于对齐
- .schedule-count-placeholder {
- width: 26.91px;
- flex-shrink: 0;
- }
- // 排期单元格样式
- .schedule-cell {
- display: flex;
- align-items: center;
- justify-content: center;
- min-height: 24px;
- gap: 5px;
- position: relative;
- }
- // 日期文本容器
- .schedule-date {
- min-width: 80px;
- text-align: center;
- flex-shrink: 0;
- line-height: 24px;
- }
- // 已排期的单元格黄色背景
- :deep(.cell-scheduled) {
- background-color: #FFFF99 !important;
- }
- .schedule-link {
- color: var(--el-color-primary);
- &:hover {
- color: var(--el-color-primary-light-3);
- }
- }
- </style>
|