Error in event handler for “click“ (Promise/async): “cancel“

在进行Vue后台项目开发时遇到一个问题,当尝试使用Element-UI的弹框组件删除用户时,触发了一个错误,导致Promise结果打印出错。错误信息表明问题出在弹框组件上。为了解决这个问题,采用了try-catch来捕获并处理可能出现的错误,简单地通过.catch方法避免了弹框组件的错误,确保了逻辑的正常执行。

在做vue后台项目时,使用element-ui在删除用户弹出确认框时,打印promise结果报错了

错误信息如下:

原因是触发了弹框组件的一个错误,

解决办法:.用try catch捕获错误

逻辑比较简单我就直接.catch

<c-search-panel :columns="columns" @search="search" ref="searchForm"> <template #projSlot> <v-project-select :disabled="disabled" v-decorator="[ 'projNo', { rules: [ { required: true, message: $t('maintenance.common.selectValidator'), }, ], }, ]" @change="changeProj" /> </template> </c-search-panel> <v-table filled :dataSource="this.dataList" :columns="columns" :pagination="pagination" :toolbar="toolbar" @toolbar-button-click="onToolbarClick" :proxy-config="proxyConfig" :sort-congfig="sortConfig" ref="vtable" > <template slot="action" slot-scope="{ record }"> <a @click="edit(record)" v-resource="[{ url: '/service-pipeline/cp/mc/package', method: 'POST' }]">{{ $t("pipeControll.mc.edit") }}</a> <a-divider type="vertical" /> <a v-if="record.version != null && record.version >= 0 && record.pageCount != null && record.pageCount > 0" @click="viewPdf(record)">{{ $t("pipeControll.mc.viewPdf") }}</a> <a-divider type="vertical" /> <a @click="handleSign(record)" v-resource="[{ url: '/service-pipeline/cp/mc/package/sign', method: 'POST' }]">{{ $t("pipeControll.mc.signature") }}</a> <a-divider type="vertical" /> <a @click="handleLog(record)">{{ $t("pipeControll.mc.log") }}</a> </template> <template #viewSlot="{ text }"> <div> {{ text }} </div> </template> <template #pressureDesc="{ record }"> <a-input v-model="record.pressureDesc" @blur="pressureDescChange(record)"></a-input> </template> <template #testSlot="{ record }"> <a-input-number v-model="record.testPressure" @blur="testChange(record)"></a-input-number> </template> </v-table> <a-modal :visible="progressModal" @cancel="modalCancel" @ok="modalSubmit" title="关联四级计划" width="1300px" > <c-search-panel :columns="modalTable.columns" @search="modalSearch" ref="modalForm"> <template #projSlot> <v-project-select :disabled="disabled" v-decorator="['projId']" /> </template> </c-search-panel> <v-table :columns="modalTable.columns" :pagination="modalTable.pagination" :proxy-config="modalTable.proxyConfig" :toolbar="false" ref="vtable1" > </v-table> </a-modal> <a-modal :title="this.action === 'add' ? '新增' : '编辑'" v-model="formVisible" :disabled="isSubmitting" @cancel="cancelModal" @ok="submitModal" width="40%"> <a-form :form="saveForm"> <a-row :gutter="24"> <a-col :span="12" :push="1"> <a-form-item label="id" v-show="false" :label-col="{ span: 8 }" :wrapper-col="{ span: 14 }"> <a-input v-decorator="['id']" /> </a-form-item> </a-col> </a-row> <a-row :gutter="24"> <a-col :span="12" :push="1"> <a-form-item :label="$t('pipeControll.mc.project')" :label-col="{ span: 8 }" :wrapper-col="{ span: 14 }"> <v-project-select showSearch optionFilterProp="children" allowClear :disabled="disabled" v-decorator="['projNo', { rules: [{ required: true, message: '请选择项目' }] }]" @change="changeProj" /> </a-form-item> </a-col> <a-col :span="12" :push="1"> <a-form-item :label="$t('pipeControll.mc.sysCode')" :label-col="{ span: 8 }" :wrapper-col="{ span: 14 }"> <a-select v-decorator="['system', { rules: [{ required: true, message: '请选择系统号' }] }]" showSearch allowClear :disabled="disabled" optionFilterProp="children" @change="changeSystem"> <a-select-option v-for="item in systemList" :key="item.sysCode" :value="item.sysCode"> {{ item.sysCode }} </a-select-option> </a-select> </a-form-item> </a-col> </a-row> <a-row :gutter="24"> <a-col :span="12" :push="1"> <a-form-item :label="$t('pipeControll.mc.subSystemNo')" :label-col="{ span: 8 }" :wrapper-col="{ span: 14 }"> <a-select v-decorator="['subSystem', { rules: [{ required: true, message: '请选择子系统号' }] }]" showSearch allowClear :disabled="disabled" optionFilterProp="children"> <a-select-option v-for="item in subSystemList" :key="item.subsysCode" :value="item.subsysCode"> {{ item.subsysName }} </a-select-option> </a-select> </a-form-item> </a-col> <a-col :span="12" :push="1"> <a-form-item :label="$t('pipeControll.mc.packageNo')" :label-col="{ span: 8 }" :wrapper-col="{ span: 14 }"> <a-input :disabled="disabled" v-decorator="['packageNo', { rules: [{ required: true, message: '请输入MC包号' }] }]" /> </a-form-item> </a-col> </a-row> <a-row :gutter="24"> <a-col :span="12" :push="1"> <a-form-item :label="$t('pipeControll.mc.pressDesc')" :label-col="{ span: 8 }" :wrapper-col="{ span: 14 }"> <a-input v-decorator="['pressureDesc']" /> </a-form-item> </a-col> <a-col :span="12" :push="1"> <a-form-item :label="$t('pipeControll.mc.testPressure')" :label-col="{ span: 8 }" :wrapper-col="{ span: 14 }"> <a-input v-decorator="['testPressure']" /> </a-form-item> </a-col> </a-row> <a-row :gutter="24"> <a-col :span="12" :push="1"> <a-form-item :label="$t('pipeControll.mc.pidNo')" :label-col="{ span: 8 }" :wrapper-col="{ span: 14 }"> <a-select v-decorator="['pidNo']" showSearch allowClear mode="multiple" optionFilterProp="children"> <a-select-option v-for="item in pidList" :key="item.pidNo" :value="item.pidNo"> {{ item.pidNo }} </a-select-option> </a-select> </a-form-item> </a-col> <a-col :span="12" :push="1"> <a-form-item :label="$t('pipeControll.mc.isoDrawNo')" :label-col="{ span: 8 }" :wrapper-col="{ span: 14 }"> <a-select v-decorator="['isoDrawNo']" showSearch allowClear mode="multiple" optionFilterProp="children"> <a-select-option v-for="item in isoDrawList" :key="item.isoDrawNo" :value="item.isoDrawNo"> {{ item.isoDrawNo }} </a-select-option> </a-select> </a-form-item> </a-col> </a-row> </a-form> </a-modal> <a-modal :title="pdfModalTitle" v-model="pdfModalVisible" :footer="null" width="50%"> <div> <p><strong>{{ $t("pipeControll.mc.project") }}: {{ selectedRecord.projId }}</strong></p> <p><strong>{{ $t("pipeControll.mc.mcPackageNo") }}: {{ selectedRecord.packageNo }}</strong></p> <p><strong>{{ $t("pipeControll.mc.version") }}: {{ selectedRecord.version }}</strong></p> <div style="margin-top: 10px;"> <a-button @click="downloadPdf" style="margin-right: 10px;">{{ $t("pipeControll.mc.downloadPdf") }}</a-button> <a-button @click="viewPdfContent" style="margin-right: 10px;">{{ $t("pipeControll.mc.view") }}</a-button> <a-button @click="viewHistoryVersions" style="margin-right: 10px;">{{ $t("pipeControll.mc.historyView") }}</a-button> <a-button @click="viewChangeLogs">{{ $t("pipeControll.mc.log") }}</a-button> </div> </div> <v-table :columns="pdfTableColumns" :dataSource="pdfTableData" :pagination="false" height="500" ref="pdfTable"> <template slot="action" slot-scope="{ record }"> <a @click="maintain(record)">{{ $t("pipeControll.mc.maintain") }}</a> <a-divider type="vertical" /> <a @click="viewLog(record)">{{ $t("pipeControll.mc.log") }}</a> <a-divider type="vertical" /> <a v-if="record.createType && record.createType == '系统生成'" @click="updateMcPdf(record)">{{ $t("pipeControll.mc.update") }}</a> <a-divider type="vertical" /> <a v-if="record.nameKey && record.nameKey == 'catalog'" @click="updateIndexRemark(record)">{{ $t("pipeControll.mc.editRemark") }}</a> </template> </v-table> </a-modal> <a-modal :title="pdfModalLogTitle" v-model="pdfModalLogVisible" @cancel="pdfModalLogCancel" width="40%"> <v-table :columns="pdfModalLogColumns" :dataSource="pdfModalLogData" :pagination="false" :height="600" ref="pdfModalLogTable"> </v-table> </a-modal> <a-modal title="查看历史版本" v-model="historyModalVisible" @ok="handleHistoryVersionOk" @cancel="handleHistoryVersionCancel" width="400px"> <a-form-item :label="$t('pipeControll.mc.version')" :label-col="{ span: 8 }" :wrapper-col="{ span: 14 }"> <a-input placeholder="请输入版本号" v-model="historyVersion" /> </a-form-item> </a-modal> <a-modal :title="`维护 - ${selectedSection.name}`" v-model="maintainModalVisible" :footer="null" width="50%"> <div> <p><strong>{{ $t("pipeControll.mc.project") }}: {{ selectedRecord.projId }}</strong></p> <p><strong>{{ $t("pipeControll.mc.mcPackageNo") }}: {{ selectedRecord.packageNo }}</strong></p> <p><strong>{{ $t("pipeControll.mc.catalog") }}: {{ selectedSection.name }}</strong></p> <div style="margin-top: 10px;"> <a-button @click="handleAddContent" style="margin-right: 10px;">{{ $t("pipeControll.mc.addContent") }}</a-button> </div> </div> <v-table :columns="maintainTableColumns" :dataSource="maintainTableData" :pagination="false" ref="maintainTable"> <template slot="action" slot-scope="{ record }"> <a @click="handleViewAttachment(record)">{{ $t("pipeControll.mc.view") }}</a> <a-divider type="vertical" /> <a @click="handleDelete(record)">{{ $t("pipeControll.mc.delete") }}</a> <a-divider type="vertical" /> <a @click="handleReplace(record)">{{ $t("pipeControll.mc.replace") }}</a> <a-divider type="vertical" /> <a @click="handleAdjustPage(record)">{{ $t("pipeControll.mc.adjustPage") }}</a> </template> </v-table> </a-modal> <a-modal title="新增/调整" v-model="addContentModalVisible" @ok="handleInsertPage" @cancel="addContentModalVisible = false" width="20%"> <a-form :form="contentForm" :label-col="{ span: 5 }" :wrapper-col="{ span: 12 }"> <a-form-item v-if="isUpload" label="上传文件"> <a-upload class="common-upload-icontop" action="/api/service-file/files" :headers="Headers" :file-list="fileList" list-type="pdf" :showUploadList="true" :max-count="1" accept=".pdf,application/pdf" @change="handleUpload" > <a-button> <a-icon type="upload" /> {{ $t("pipeControll.mc.upload") }} </a-button> </a-upload> </a-form-item> <a-form-item v-if="isPage" label="页数"> <a-input v-model="insertPageNumber" style="margin-top: 10px; width: 60%;" /> </a-form-item> </a-form> </a-modal> <a-modal :title="$t('pipeControll.mc.signature')" :okText="$t('pipeControll.mc.signature')" v-model="signModalVisible" @ok="handleSignSubmit" @cancel="handleSignCancel" width="20%"> <a-form :form="signForm"> <a-row :gutter="16"> <a-col :span="10" style="text-align: right;"> <p><strong>{{ $t("pipeControll.mc.project") }}:</strong></p> </a-col> <a-col :span="12"> <p>{{ selectedRecord.projId }}</p> </a-col> </a-row> <a-row :gutter="16"> <a-col :span="10" style="text-align: right;"> <p><strong>{{ $t("pipeControll.mc.mcPackageNo") }}:</strong></p> </a-col> <a-col :span="12"> <p>{{ selectedRecord.packageNo }}</p> </a-col> </a-row> <a-form-item :label="$t('pipeControll.mc.signRole')" :label-col="{ span: 8 }" :wrapper-col="{ span: 14 }"> <a-select v-decorator="['role', { rules: [{ required: true, message: '请选择签名角色' }] }]"> <a-select-option v-for="item in signRoleList" :key="item.name" :value="item.name"> {{ item.name }} </a-select-option> </a-select> </a-form-item> <a-form-item :label="$t('pipeControll.mc.signNode')" :label-col="{ span: 8 }" :wrapper-col="{ span: 14 }"> <a-select v-decorator="['node', { rules: [{ required: true, message: '请选择签名节点' }] }]"> <a-select-option v-for="item in signNodeList" :key="item.name" :value="item.name"> {{ item.name }} </a-select-option> </a-select> </a-form-item> </a-form> </a-modal> <a-modal :title="logModalTitle" v-model="logModalVisible" @cancel="logModalCancel" width="40%"> <v-table :columns="logTableColumns" :dataSource="logTableData" :pagination="false" :height="400" ref="logTable"> </v-table> </a-modal> <a-modal title="维护备注" v-model="remarkModalVisible" @ok="saveRemarks" @cancel="remarkModalVisible = false" width="50%"> <v-table :columns="remarkModalColumns" :dataSource="remarkModalData" :pagination="false"> <template #remark="{ record }"> <a-input v-model="record.remark" placeholder="请输入备注" /> </template> </v-table> </a-modal> </section> </template> <script> import { floatObj, toLine } from "~/utils/dataUtils"; import moment from "moment"; import * as Serve from "~/api/modules/Pipe/mc/cpMcPackage"; import { adjustPage, generatePdf, getMcPackageLogList, getPackageIsoList, getPackagePidList, getPidDropList, getTemplateSectionList, updateMcPackageData, } from "~/api/modules/Pipe/mc/cpMcPackage"; import { findDataByName as cByName, getDropList as cDeopList } from "~/api/modules/Pipe/mc/cpMcCleanFactor"; import ImportDataModal from "@/components/mc/ImportDataModal"; import { getDictionary, majorAll } from "~api/modules/common"; import { fileSaver } from "@/utils"; import { preview } from "~api/modules/CommissioningManagement/RecordSave/CheckRecord"; import { Modal } from "ant-design-vue"; // 类型详情 export default { components: { ImportDataModal, }, data() { return { Headers: { authorization: `Bearer${localStorage.getItem("token")}`, }, isGeneratingPdf: false, isSubmittingSign: false, fileList: [], fileId: "", isSubmitting: false, test: Serve.imp, pdfUrl: "", isPage: true, isUpload: true, insertPageNumber: "", originPageNumber: "", version: "", pageNum: "", dataPageId: "", historyModalVisible: false, historyVersion: '', disabled: false, systemList: [], subSystemList: [], pipeLineList: [], isoDrawList: [], pidList: [], majorList: [], flushingTypeList: [], projectId: null, packageNo: "", isoDrawNo: "", action: "", visible: false, formVisible: false, columns: [ {type: "checkbox", width: 50 }, { //title: "项目号", title: this.$t("pipeControll.mc.project"), align: "left", width: 110, visible: false, scopedSlots: { customRender: "projSlot" }, condition: true, }, { //title: "项目号", title: this.$t("pipeControll.mc.project"), align: "left", dataIndex: "projNo", rules: [{ required: true }], sorter: false, type: "project", verification: true, width: 120, }, { //title: "系统号", title: this.$t("pipeControll.mc.sysCode"), align: "left", dataIndex: "system", condition: true, rules: [{ required: true }], verification: true, width: 120, }, { //title: "子系统号", title: this.$t("pipeControll.mc.subSystemNo"), align: "left", width: 120, condition: true, rules: [{ required: true }], verification: true, dataIndex: "subSystem", }, { // title: "MC包号", title: this.$t("pipeControll.mc.mcPackageNo"), align: "left", width: 120, condition: true, rules: [{ required: true }], verification: true, dataIndex: "packageNo", }, { // title: "介质", title: this.$t("pipeControll.mc.medium"), align: "left", width: 120, rules: [{ required: true }], verification: true, dataIndex: "testMedium", }, { // title: "压力描述", title: this.$t("pipeControll.mc.pressDesc"), align: "left", width: 120, scopedSlots: { customRender: "viewSlot", customEditorRender: "pressureDesc", }, dataIndex: "pressureDesc", }, { // title: "试验压力", title: this.$t("pipeControll.mc.testPressure"), align: "left", width: 120, scopedSlots: { customRender: "viewSlot", customEditorRender: "testSlot", }, dataIndex: "testPressure", }, { // title: "压力系数", title: this.$t("pipeControll.mc.pressureFactor"), align: "left", width: 120, verification: true, dataIndex: "testPressureFactor", }, { // title: "清洗内容", title: this.$t("pipeControll.mc.cleanContent"), align: "left", width: 120, rules: [{ required: true }], type: "select", options: { options: [], fieldNames: { label: "name", value: "name" }, ajax: cDeopList(), }, verification: true, dataIndex: "flushingType", }, { // title: "清洗系数", title: this.$t("pipeControll.mc.cleanFactor"), align: "left", width: 120, verification: true, dataIndex: "flushingFactor", }, { // title: "外观权重", title: this.$t("pipeControll.mc.appearWeight"), align: "left", width: 120, rules: [{ required: true }], type: "number", options: { min: 0, }, formatter: v => (v.cellValue ? `${v.cellValue}%` : ""), verification: true, dataIndex: "appearWeight", }, { // title: "压力权重", title: this.$t("pipeControll.mc.pressureWeight"), align: "left", width: 120, rules: [{ required: true }], type: "number", options: { min: 0, }, formatter: v => (v.cellValue ? `${v.cellValue}%` : ""), verification: true, dataIndex: "pressureWeight", }, { // title: "串洗权重", title: this.$t("pipeControll.mc.washWeight"), align: "left", width: 120, rules: [{ required: true }], type: "number", options: { min: 0, }, formatter: v => (v.cellValue ? `${v.cellValue}%` : ""), verification: true, dataIndex: "flushingWeight", }, { // title: "复位权重", title: this.$t("pipeControll.mc.resetWeight"), align: "left", width: 120, rules: [{ required: true }], type: "number", options: { min: 0, }, formatter: v => (v.cellValue ? `${v.cellValue}%` : ""), verification: true, dataIndex: "reinstatementWeight", }, { // title: "配合调试权重", title: this.$t("pipeControll.mc.matchDebugWeight"), align: "left", width: 160, rules: [{ required: false }], type: "number", options: { min: 0, }, formatter: v => (v.cellValue ? `${v.cellValue}%` : ""), verification: true, dataIndex: "commissionWeight", }, { // title: "总定额", title: this.$t("pipeControll.mc.totalQuota"), align: "left", width: 120, dataIndex: "quotaMh", }, { // title: "外观定额", title: this.$t("pipeControll.mc.appearQuota"), align: "left", width: 120, dataIndex: "appearQuotaMh", }, { // title: "压力定额", title: this.$t("pipeControll.mc.pressureQuota"), align: "left", width: 120, dataIndex: "pressureQuotaMh", }, { // title: "串洗定额", title: this.$t("pipeControll.mc.washQuota"), align: "left", width: 120, dataIndex: "flushingQuotaMh", }, { // title: "复位定额", title: this.$t("pipeControll.mc.resetQuota"), align: "left", width: 120, dataIndex: "reinstatementQuotaMh", }, { // title: "配合调试定额", title: this.$t("pipeControll.mc.matchDebugQuota"), align: "left", width: 160, dataIndex: "commissionQuotaMh", }, { // title: "汇总实动工时", title: this.$t("pipeControll.mc.sumActualWorkHour"), align: "left", width: 160, dataIndex: "hzHours", }, { // title: "外观实动工时", title: this.$t("pipeControll.mc.appearActualWorkHour"), align: "left", width: 120, dataIndex: "appearHours", }, { // title: "压力实动工时", title: this.$t("pipeControll.mc.pressureActualWorkHour"), align: "left", width: 120, dataIndex: "pressureHours", }, { // title: "串洗实动工时", title: this.$t("pipeControll.mc.washActualWorkHour"), align: "left", width: 120, dataIndex: "flushingHours", }, { // title: "复位实动工时", title: this.$t("pipeControll.mc.resetActualWorkHour"), align: "left", width: 120, dataIndex: "reinstatementHours", }, { // title: "配合调试实动工时", title: this.$t("pipeControll.mc.matchDebugActualWorkHour"), align: "left", width: 160, dataIndex: "commissionHours", }, { // title: "外观状态", title: this.$t("pipeControll.mc.appearStatus"), align: "left", width: 120, formatter: ({ cellValue }) => { let obj = { 0: "新建", 1: "进行中", 2: "已完成", }; return obj[cellValue]; }, verification: true, dataIndex: "appearDispatchStatus", }, { // title: "压力状态", title: this.$t("pipeControll.mc.pressureStatus"), align: "left", width: 120, formatter: ({ cellValue }) => { let obj = { 0: "新建", 1: "进行中", 2: "已完成", }; return obj[cellValue]; }, verification: true, dataIndex: "pressureDispatchStatus", }, { // title: "串洗状态", title: this.$t("pipeControll.mc.washStatus"), align: "left", width: 120, formatter: ({ cellValue }) => { let obj = { 0: "新建", 1: "进行中", 2: "已完成", }; return obj[cellValue]; }, verification: true, dataIndex: "flushingDispatchStatus", }, { // title: "复位状态", title: this.$t("pipeControll.mc.resetStatus"), align: "left", width: 120, formatter: ({ cellValue }) => { let obj = { 0: "新建", 1: "进行中", 2: "已完成", }; return obj[cellValue]; }, verification: true, dataIndex: "reinstatementDispatchStatus", }, { // title: "配合调试状态", title: this.$t("pipeControll.mc.matchDebugStatus"), align: "left", width: 160, formatter: ({ cellValue }) => { let obj = { 0: "新建", 1: "进行中", 2: "已完成", }; return obj[cellValue]; }, verification: true, dataIndex: "commissionDispatchStatus", }, { // title: "MC包状态", title: this.$t("pipeControll.mc.mcStatus"), align: "left", width: 120, formatter: ({ cellValue }) => { let obj = { 0: "新建", 1: "进行中", 2: "已完成", }; return obj[cellValue]; }, verification: true, dataIndex: "status", }, { // title: "创建时间", title: this.$t("pipeControll.mc.createDate"), align: "left", width: 180, verification: true, dataIndex: "createDate", formatter: data => (data.cellValue ? moment(data.cellValue).format("YYYY-MM-DD") : ""), }, { // title: "创建人", title: this.$t("pipeControll.mc.creator"), align: "left", width: 100, dataIndex: "createUserName", }, { // title: "修改时间", title: this.$t("pipeControll.mc.updateDate"), align: "left", width: 180, dataIndex: "updateDate", formatter: data => (data.cellValue ? moment(data.cellValue).format("YYYY-MM-DD") : ""), }, { //title: "更新人", title: this.$t("pipeControll.mc.updater"), align: "left", width: 100, dataIndex: "updateUserName", }, { //title: "专业", title: this.$t("pipeControll.mc.major"), align: "left", width: 100, dataIndex: "majorCode", type: "select", options: { options: [], fieldNames: { label: "name", value: "code" }, ajax: majorAll(), }, }, { //title: "PID图号", title: this.$t("pipeControll.mc.pidNo"), align: "left", width: 100, dataIndex: "pidNo", }, { //title: "ISO图号", title: this.$t("pipeControll.mc.isoDrawNo"), align: "left", width: 100, dataIndex: "isoDrawNo", }, { //title: "操作", title: this.$t("column.operation"), scopedSlots: { customRender: "action" }, width: 210, fixed: "right", sortable: false, }, { // title: "MC包状态", title: this.$t("pipeControll.mc.mcStatus"), dataIndex: "planStatus", condition: true, type: "select", visible: false, options: { options: [ { label: "新建", value: "0" }, { label: "进行中", value: "1" }, { label: "已完成", value: "2" }, ], fieldNames: { label: "label", value: "value" }, }, decorator: [ "planStatus", { initialValue: "0", }, ], }, ], toolbar: { buttons: [ { code: "insertData", //name: "新增", name: this.$t("pipeControll.mc.add"), resource: [{ url: "/service-pipeline/cp/mc/package", method: "POST" }], }, { code: "delete", //name: "删除", name: this.$t("pipeControll.mc.delete"), resource: [{ url: "/service-pipeline/cp/mc/clean/factor", method: "DELETE" }], }, // { // code: "check", // //name: "保存", // name: this.$t("crud.save"), // resource: [{ url: "/service-pipeline/cp/mc/clean/factor", method: "POST" }], // }, { code: "template", // name: "下载导入模板", name: this.$t("pipeControll.mc.importTemplate"), }, { code: "importData", //name: '导入', name: this.$t("pipeControll.mc.import"), }, { code: "exp", // name: "导出", name: this.$t("pipeControll.mc.export"), resource: [ { url: "/service-pipeline/cp/mc/clean/factor/excels", method: "GET", }, ], }, { code: "generatePdf", // name: "生成/更新pdf", name: this.$t("pipeControll.mc.generatePdf"), resource: [ { url: "/service-pipeline/cp/mc/package/generatePdf", method: "POST", }, ], }, ], }, pagination: { total: 0, }, dataList: [], sortConfig: { default: "id", sort: "asc" }, proxyConfig: { autoLoad: false, ajax: { query: ({ page, sort, filters }, ...args) => { let sorter = ""; if (sort && sort.field && sort.order) { sorter = toLine(sort.field) + "," + sort.order; } return Serve.page({ ...this.conditionData, ...this.$vtable.pagination(page), sort: sorter, }); }, // save: ({ body }) => Serve.save(this.$vtable.updateRecords(body, "id")), delete: ({ body }) => { return Serve.del({ ids: this.$vtable.removeRecords(body, "id").join(","), }); }, }, }, modalTable: { columns: [ { type: "radio", width: 50 }, { //title: "项目号", title: this.$t("pipeControll.common.projectNumber"), align: "left", width: 110, visible: false, scopedSlots: { customRender: "projSlot" }, condition: true, }, { //title: "项目号", title: this.$t("pipeControll.common.projectNumber"), align: "left", dataIndex: "projId", }, { //title: '建造地', title: this.$t("pipeControll.common.builtPlace"), align: "left", dataIndex: "orgName", }, { title: "任务ID", align: "left", condition: true, dataIndex: "wbsCode", }, { title: "任务描述", align: "left", condition: true, dataIndex: "wbsName", }, { title: "任务对象", align: "left", condition: true, dataIndex: "objectCode", }, ], pagination: { pageSize: 10, total: 0, }, proxyConfig: { autoLoad: false, ajax: { query: ({ page, sort, filters }, ...args) => { let sorter = ""; if (sort && sort.field && sort.order) { sorter = toLine(sort.field) + "," + sort.order; } return Serve.getProjectCyc({ ...this.conditionData1, ...this.$vtable.pagination(page), sort: sorter, }); }, }, }, }, progressModal: false, pdfModalVisible: false, pdfModalTitle: '', selectedRecord: {}, pdfTableColumns: [ { // title: '目录名称', title: this.$t("pipeControll.mc.catalogName"), dataIndex: 'name' }, { // title: '维护方式', title: this.$t("pipeControll.mc.maintainMethod"), dataIndex: 'createType' }, { // title: '最后维护时间', title: this.$t("pipeControll.mc.lastMaintainDate"), dataIndex: 'updateDate' }, { // title: '最后维护人', title: this.$t("pipeControll.mc.lastMaintainPerson"), dataIndex: "updateUserName", type: "employeeDescription", options: { fieldNames: { label: "updateUserName", value: "updateUserId", }, }, }, { // title: '操作', title: this.$t("pipeControll.mc.operation"), width: 200, scopedSlots: { customRender: 'action' } }, ], pdfTableData: [], pdfModalLogVisible: false, pdfModalLogTitle: '', pdfModalLogColumns: [ { // title: '操作时间', title: this.$t("pipeControll.mc.operateDate"), dataIndex: 'operateDate' }, { // title: '操作类型', title: this.$t("pipeControll.mc.operateType"), dataIndex: 'operateType' }, { // title: '操作人', title: this.$t("pipeControll.mc.operator"), dataIndex: 'operatorName', type: "employeeDescription", options: { fieldNames: { label: "operatorName", value: "operatorCode", }, }}, { // title: '操作详情', title: this.$t("pipeControll.mc.operateDetail"), dataIndex: 'operateDetail' } ], pdfModalLogData: [], maintainModalVisible: false, addContentModalVisible: false, selectedSection: {}, maintainTableColumns: [ { // title: '描述', title: this.$t("pipeControll.mc.desc"), dataIndex: 'linkObject' }, { // title: '页数', title: this.$t("pipeControll.mc.pageNum"), dataIndex: 'pageNum' }, { // title: '操作', title: this.$t("pipeControll.mc.operation"), scopedSlots: { customRender: 'action' } } ], maintainTableData: [], signModalVisible: false, signRoleList: [], signNodeList: [], signRole: '', signNode: '', logModalVisible: false, logModalTitle: '', logTableColumns: [ { title: "操作类型", dataIndex: "operateType", sorter: false }, { title: "操作详情", dataIndex: "operateDetail", sorter: false }, { title: "操作时间", dataIndex: "operateDate", type: "datetime", sorter: false }, { title: "操作人", dataIndex: "operateUserName", type: "employeeDescription", sorter: false, options: { fieldNames: { label: "operateUserName", value: "operateUserId" } } } ], logTableData: [], remarkModalVisible: false, remarkModalData: [], mcPackageDataId: '', templateNameKey: '', remarkModalColumns: [ { title: '目录Key', dataIndex: 'nameKey', visible: false, }, { // title: '目录名称', title: this.$t("pipeControll.mc.catalogName"), dataIndex: 'name', }, { // title: '备注', title: this.$t("pipeControll.mc.remark"), dataIndex: 'remark', scopedSlots: { customRender: 'remark' }, }, ], }; }, beforeCreate() { this.contentForm = this.$form.createForm(this); this.saveForm = this.$form.createForm(this); this.signForm = this.$form.createForm(this); }, computed: { table() { return this.$refs.vtable.getTable(); }, form() { return this.$refs.searchForm.getForm(); }, table1() { return this.$refs.vtable1.getTable(); }, cycForm() { return this.$refs.modalForm.getForm(); }, }, mounted() { // this.form.setFieldsValue({ cycStatus: "0" }) this.$refs.searchForm.toggle(); this.getMajorList(); this.getFlushingTypeList(); }, methods: { onToolbarClick(target) { switch (target.code) { case "insertData": this.insert(); break; case "exp": this.exp(); break; case "relevance": this.relevance(); break case "template": this.template(); break; case "importData": this.importData(); break; case "asyncData": this.asyncData(); break; case "generatePdf": this.generatePdf(); // case "check": // this.check(); // break; default: break; } }, search(values) { this.conditionData = values; this.table.commitProxy("reload", { page: 0 }); }, modalSearch(values) { this.conditionData1 = values; this.table1.commitProxy("reload", { page: 0 }); }, getMajorList() { majorAll().then(res => { this.majorList = res.data; }); }, getFlushingTypeList() { cDeopList().then(res => { this.flushingTypeList = res.data; }); }, changeProj(val) { this.projectId = val; this.saveForm.setFieldsValue({ system: '' }); this.saveForm.setFieldsValue({ subSystem: '' }); this.saveForm.setFieldsValue({ isoDrawNo: [] }); this.saveForm.setFieldsValue({ pidNo: [] }); this.subSystemList = [] Serve.getSystemDropList({projectId: val}).then(res => { this.systemList = res.status == 200 ? res.data : []; }); Serve.getIsoDrawDropList({projectId: val, topVersionFlag: "Y"}).then(res => { this.isoDrawList = res.status == 200 ? res.data : []; }); Serve.getPidDropList({projectId: val, topVersionFlag: "Y"}).then(res => { this.pidList = res.status == 200 ? res.data : []; }); }, changeSystem(val) { Serve.getSubSystemDropList({projectId: this.projectId, sysCode: val}).then(res => { this.subSystemList = res.status == 200 ? res.data : []; }); }, insert() { this.action = "add"; this.disabled = false; this.formVisible = true; this.saveForm.resetFields(); }, edit(record) { Serve.getPackageIsoList({projectId: record.projNo, packageNo: record.packageNo}).then(res => { const isoValues = res.data.map(item => item.isoDrawNo); this.saveForm.setFieldsValue({ isoDrawNo: isoValues }); }); Serve.getPackagePidList({projectId: record.projNo, packageNo: record.packageNo}).then(res => { const pidValues = res.data.map(item => item.pidNo); this.saveForm.setFieldsValue({ pidNo: pidValues }); }); this.action = "edit"; this.disabled = true; this.saveForm.resetFields(); setTimeout(() => { this.saveForm.setFieldsValue({ id: record.id }); this.saveForm.setFieldsValue({ projNo: record.projNo }); this.saveForm.setFieldsValue({ system: record.system }); this.saveForm.setFieldsValue({ subSystem: record.subSystem }); this.saveForm.setFieldsValue({ majorCode: record.majorCode }); this.saveForm.setFieldsValue({ packageNo: record.packageNo }); this.saveForm.setFieldsValue({ pidNo: record.pidNo }); this.saveForm.setFieldsValue({ isoDrawNo: record.isoDrawNo }); this.saveForm.setFieldsValue({ testMedium: record.testMedium }); this.saveForm.setFieldsValue({ pressureDesc: record.pressureDesc }); this.saveForm.setFieldsValue({ testPressure: record.testPressure }); this.saveForm.setFieldsValue({ flushingType: record.flushingType }); this.saveForm.setFieldsValue({ appearWeight: record.appearWeight }); this.saveForm.setFieldsValue({ pressureWeight: record.pressureWeight }); this.saveForm.setFieldsValue({ flushingWeight: record.flushingWeight }); this.saveForm.setFieldsValue({ reinstatementWeight: record.reinstatementWeight }); this.saveForm.setFieldsValue({ commissionWeight: record.commissionWeight }); }, 0); this.formVisible = true; }, submitModal() { if (this.isSubmitting) return; this.isSubmitting = true; this.saveForm.validateFields((err, values) => { if (!err) { if (values.isoDrawNo) { values.isoDrawNos = values.isoDrawNo.join(',') delete values.isoDrawNo; } if(values.pidNo) { values.pidNos = values.pidNo.join(',') delete values.pidNo; } Serve.savePdcsOrUpdate(values).then(res => { this.$message.success(this.$t("basedata.cecable.saveSuccess")); this.form.validateFields((err, values) => { if (!err) { this.table.commitProxy("reload", { page: 0 }); } }); this.cancelModal(); this.isSubmitting = false; }).catch(() => { this.isSubmitting = false; }); } }) }, cancelModal() { this.disabled = false; this.formVisible = false; this.saveForm.resetFields(); }, //删除数据确认 dataDelete() { if (this.selectedCheck() == false) { //this.$message.error("请选择需要删除的行!"); this.$message.error(this.$t("pipeControll.common.selectRemoveRow")); return; } this.$confirm({ title: this.$t("maintenance.common.SureToDelete"), //title: '确定删除?', onOk: () => { this.del(this.selectedCheck()); }, onCancel() {}, }); }, // 导出 exp() { this.form.validateFields((err, values) => { if (!err) { Serve.exp(values); } }); }, generatePdf() { if (this.isGeneratingPdf) { this.$message.warning("正在生成PDF,请稍候..."); return; } let rows = this.table.getCheckboxRecords(); if (rows.length !== 1) { this.$message.error("请选择一行数据!"); return; } this.isGeneratingPdf = true; this.projectId = rows[0].projNo; this.packageNo = rows[0].packageNo; this.isoDrawNo = rows[0].isoDrawNo; this.signFilePath = rows[0].signFilePath; try { Serve.generatePdf({ projNo: this.projectId, packageNo: this.packageNo, isoDrawNo: this.isoDrawNo, signFilePath: this.signFilePath }).then(res => { this.$message.success('生成成功!'); this.table.commitProxy("reload", { page: 0 }); }).catch(err => { this.$message.error('生成失败: ' + err.message); }).finally(() => { this.isGeneratingPdf = false; }); } catch (err) { this.$message.error('生成失败: ' + err.message); // 异常时也需重置状态 this.isGeneratingPdf = false; } }, // 项目号选择匹配默认权重 projChange(event, value) { Serve.findDataByProjNo({ projNo: value }).then(res => { let { commissionWeight, pressureWeight, flushingWeight, reinstatementWeight,appearWeight } = res.data; event.row.commissionWeight = commissionWeight; event.row.pressureWeight = pressureWeight; event.row.flushingWeight = flushingWeight; event.row.reinstatementWeight = reinstatementWeight; event.row.appearWeight = appearWeight; }); }, // 清洗内容系数匹配 flushChange(event, value) { cByName({ name: value }).then(res => { event.row.flushingFactor = res.data.factor; event.row.flushingType = res.data.name; }); }, //测试压力系数匹配 testChange(record) { let { testPressure } = record; Serve.findTestPressureFactor({ testPressure }).then(res => { record.testPressureFactor = res.data; }); }, pressureDescChange(record) { Serve.findTestPressureFactor({ desc: record.pressureDesc }).then(res => { record.testPressureFactor = res.data; }); }, // 关联四级计划 relevance() { let selectIds = this.getCheckboxIds(); let projNo = this.form.getFieldValue("projNo"); if (!projNo || selectIds.length === 0) { this.$message.error("请勾选要处理的数据"); return; } this.progressModal = true; this.$nextTick(() => { this.cycForm.setFieldsValue({ projId: projNo }); }); }, // 同步MC包数据 asyncData() { let params = {}; let projNo = this.form.getFieldValue("projNo"); let system = this.form.getFieldValue("system"); let subSystem = this.form.getFieldValue("subSystem"); if (!projNo) { this.$message.error(this.$t("pipeControll.common.selectProjectNumber")); return; } else { params.projectNumber = projNo; } if (system) { params.tmSycode = system; } if (subSystem) { params.tmSscode = subSystem; } Serve.asyncData(params).then(res => { this.$message.success("同步数据成功!"); }); }, // 模态框取消 modalCancel() { this.progressModal = false; }, getCheckboxIds() { let selected = this.table.getCheckboxRecords(); let arr = selected.map(e => e.id); return arr; }, // 模态框提交更改四级计划 modalSubmit() { let packageIds = this.getCheckboxIds(); let radioRecord = this.table1.getRadioRecord(); if (!radioRecord) { return; } let taskId = radioRecord.id; Serve.relevance({ taskId, packageIds }).then(res => { this.$message.success("关联成功!"); this.modalCancel(); this.search(this.conditionData); }); }, template() { Serve.pdcsMcTemplate(); }, importData() { this.table.readFile({ types: ["xlsx", "xls"] }).then(response => { const { files } = response; if (files.length < 1) return; let params = { file: files[0] }; Serve.importData(params).then(response => { if (response.data.size > 0) { this.$message.error("上传失败,请查看错误文件"); fileSaver.saveAs(response.data, "导入提示.xlsx"); } else { this.$message.success("导入成功"); this.form.validateFields((err, values) => { if (!err) { this.table.commitProxy("reload", { page: 0 }); } }); } }); }); }, getImportColumns() { let arr = this.columns.filter(res => { return res.verification == true; }); return arr; }, check() { let updateRecords = this.table.getUpdateRecords(); let insertRecords = this.table.getInsertRecords(); let records = [...updateRecords, ...insertRecords]; let flag = true; records.forEach(element => { let a = floatObj.add(element.commissionWeight * 1, element.reinstatementWeight * 1); let b = floatObj.add(element.pressureWeight * 1, element.flushingWeight * 1); let c =floatObj.add(a, b); if (floatObj.add(c, element.appearWeight * 1) != 100) { this.$XModal.message({ status: "error", message: "校验不通过!权重比之和必须为100%", }); flag = false; } if (!element.testPressureFactor) { this.$XModal.message({ status: "error", message: "压力系数不可为空,更改实验压力计算压力系数", }); flag = false; } }); if (flag) { this.table.commitProxy("save"); } }, viewPdf(record) { this.selectedRecord = record; this.pdfModalTitle = `查看PDF`; this.fetchPdfTableData(record.projNo); this.pdfModalVisible = true; }, // 新增签名弹窗 handleSign(record) { this.signForm.resetFields(); this.signModalVisible = true; this.selectedRecord = record; this.getSignRoleList(); this.getSignNodeList(); this.isSubmittingSign = false; }, // 获取签名角色列表 getSignRoleList() { getDictionary({code: "mcTemplateSignRole", state: "1"}).then((res) => { this.signRoleList = res.data; }); }, // 获取签名节点列表 getSignNodeList() { getDictionary({code: "mcTemplateSignNode", state: "1"}).then((res) => { this.signNodeList = res.data; }); }, handleSignSubmit() { if (this.isSubmittingSign) { this.$message.warning("正在提交签名,请稍候..."); return; } this.signForm.validateFields((err, values) => { if (!err) { this.isSubmittingSign = true; const params = { id: this.selectedRecord.id, projNo: this.selectedRecord.projNo, packageNo: this.selectedRecord.packageNo, version: this.selectedRecord.version, ...values }; Serve.submitSign(params) .then(res => { this.$message.success('签名成功!'); this.signModalVisible = false; this.table.commitProxy("reload", { page: 0 }); }) .catch(err => { this.$message.error('签名失败: ' + (err.message || '未知错误')); }) .finally(() => { this.isSubmittingSign = false; }); } }); }, // 签名弹窗取消 handleSignCancel() { this.signModalVisible = false; }, fetchPdfTableData(projectId) { // 调用接口获取表格数据 Serve.getTemplateSectionList({ projectId: projectId }).then(res => { this.pdfTableData = res.data; }); }, downloadPdf() { Serve.downloadPdf({ projNo: this.selectedRecord.projNo, packageNo: this.selectedRecord.packageNo, version: this.selectedRecord.version }).then(res => { const blob = new Blob([res.data], { type: 'application/pdf' }); const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.setAttribute('download', `${this.selectedRecord.packageNo}_${this.selectedRecord.version}.pdf`); document.body.appendChild(link); link.click(); document.body.removeChild(link); window.URL.revokeObjectURL(url); }).catch(err => { this.$message.error('下载PDF失败: ' + err.message); }); }, viewPdfContent() { Serve.viewPdf({ projNo: this.selectedRecord.projNo, packageNo: this.selectedRecord.packageNo, version: this.selectedRecord.version }).then(res => { const blob = new Blob([res.data], { type: 'application/pdf' }); this.pdfUrl = window.URL.createObjectURL(blob); window.open(this.pdfUrl, '_blank'); }).catch(err => { this.$message.error('预览失败: ' + err.message); }); }, viewHistoryVersions() { this.historyModalVisible = true; this.historyVersion = ''; }, handleHistoryVersionOk() { if (!this.historyVersion) { this.$message.error('请输入版本号'); return; } Serve.viewPdf({ projNo: this.selectedRecord.projNo, packageNo: this.selectedRecord.packageNo, version: this.historyVersion, isHistoryVersion: 1 }).then(res => { if (!res.data || res.data.size == 0) { this.$message.error("没有该版本的PDF"); return; } const blob = new Blob([res.data], { type: 'application/pdf' }); this.pdfUrl = window.URL.createObjectURL(blob); window.open(this.pdfUrl, '_blank'); this.historyModalVisible = false; }).catch(err => { this.$message.error('预览失败: ' + err.message); }); }, handleHistoryVersionCancel() { this.historyModalVisible = false; }, viewChangeLogs() { Serve.getMcPackageDataLog({ projectId: this.selectedRecord.projNo, packageNo: this.selectedRecord.packageNo }).then(res => { this.pdfModalLogData = res.data; this.pdfModalLogTitle = '日志详情'; this.pdfModalLogVisible = true; }); }, viewLog(record) { Serve.getMcPackageDataLog({ projectId: this.selectedRecord.projNo, packageNo: this.selectedRecord.packageNo, sectionId: record.id }).then(res => { this.pdfModalLogData = res.data; this.pdfModalLogVisible = true; this.pdfModalLogTitle = '日志详情'; }); }, pdfModalLogCancel() { this.pdfModalLogVisible = false; }, maintain(record) { this.selectedSection = record; this.maintainModalVisible = true; Serve.getMcPackageDataPageList({ projectId: this.selectedRecord.projNo, packageNo: this.selectedRecord.packageNo, version: this.selectedRecord.version, sectionId: record.id }).then(res => { this.maintainTableData = res.data; }); }, handleAddContent() { this.fileList = []; this.insertPageNumber = ''; this.isUpload = true; this.isPage = true; this.addContentModalVisible = true; }, handleUpload({ fileList }) { this.fileList = fileList; this.fileList.forEach(file => { if (file.status === "done") { if (file.response && file.response.id) { this.fileId = file.response.id; } else if (file.id) { this.fileId = file.id; } } }); }, handleInsertPage() { const projectId = this.selectedRecord.projNo; const packageNo = this.selectedRecord.packageNo; const sectionId = this.selectedSection.id; if (this.isUpload == true && this.isPage == true) { const filePath = this.fileId; const pageNum = this.insertPageNumber; if (!filePath) { this.$message.error('请选择要插入的PDF!'); return; } if (!pageNum) { this.$message.error('请输入要插入的页数!'); return; } Serve.add({ projectId, packageNo, sectionId, filePath, pageNum }) .then(res => { this.$message.success('插入页数成功!'); this.addContentModalVisible = false; this.maintain(this.selectedSection); }) } if (this.isUpload == true && this.isPage == false) { const filePath = this.fileId; const version = this.version; const pageNum = this.pageNum; if (!filePath) { this.$message.error('请选择要替换的PDF!'); return; } Serve.replacePage({ projectId, packageNo, sectionId, filePath, version, pageNum }).then(res => { this.$message.success('替换成功!'); this.addContentModalVisible = false; this.maintain(this.selectedSection); }) } if (this.isUpload == false && this.isPage == true){ const pageNum = this.insertPageNumber; const version = this.version; const id = this.dataPageId; const originPageNum = this.originPageNumber; if (!this.insertPageNumber) { this.$message.error('请输入要插入的页数!'); return; } if(this.originPageNumber == this.insertPageNumber) { this.$message.warn('页数相同,无需调整!'); return; } Serve.adjustPage({ projectId, packageNo, sectionId, version, pageNum, id, originPageNum }).then(res => { this.$message.success('成功!'); this.addContentModalVisible = false; this.maintain(this.selectedSection); }) } }, handleViewAttachment(record) { preview(record.filePath).then(res => { if (!res.error) { let fileName = ""; let tmp = res.headers["content-disposition"]; if (tmp != null && tmp != "" && tmp != "undefined") { let startIndex = tmp.indexOf('filename="') + 10; let endIndex = tmp.indexOf('"', startIndex); fileName = tmp.substring(startIndex, endIndex); } let puffix = fileName.split(".")[0]; let suffix = fileName.split(".")[1]; if (suffix == "pdf") { let blob = new Blob([res.data], { type: 'application/pdf' }); let fileUrl = URL.createObjectURL(blob); window.open(fileUrl, '_blank'); } else { fileSaver.saveAs(res.data, puffix + "preview" + suffix); } } }); }, handleDelete(record) { Modal.confirm({ title: '确认框', content: '确定要删除?', okText: '确认', cancelText: '取消', onOk: () => { const projectId = this.selectedRecord.projNo; const packageNo = this.selectedRecord.packageNo; const sectionId = this.selectedSection.id; const pageNum = record.pageNum; const version = record.version; Serve.deletePage({ projectId, packageNo, sectionId, version, pageNum }).then(res => { this.$message.success('删除成功!'); this.maintain(this.selectedSection); }) } }) }, handleReplace(record) { this.isPage = false; this.isUpload = true; this.fileList = []; this.insertPageNumber = ''; this.addContentModalVisible = true; this.version = record.version; this.pageNum = record.pageNum; }, handleAdjustPage(record) { this.isPage = true; this.isUpload = false; this.fileList = []; this.insertPageNumber = ''; this.addContentModalVisible = true; this.version = record.version; this.dataPageId = record.id; this.originPageNumber = record.pageNum }, pdfModalCancel() { this.pdfModalVisible = false; }, handleLog(record) { this.logModalTitle = `日志 - ${record.packageNo}`; this.fetchLogTableData(record.id); this.logModalVisible = true; }, fetchLogTableData(mcPackageId) { Serve.getMcPackageLogList({ mcPackageId: mcPackageId }).then(res => { this.logTableData = res.data; }); }, logModalCancel() { this.logModalVisible = false; }, updateMcPdf(record) { const projectId = this.selectedRecord.projNo; const packageNo = this.selectedRecord.packageNo; const mcPackageId = this.selectedRecord.id; const params = { ...record, projectId, packageNo, mcPackageId }; Serve.updateMcPdf(params).then(res => { this.$message.success('更新成功!'); }); }, updateIndexRemark(record) { this.templateNameKey = record.nameKey; const { projNo, packageNo } = this.selectedRecord; try { // 调用接口获取备注数据 Serve.getMcPackageData({ projNo, packageNo }).then(res => { const indexRemark = res.data.indexRemark; this.mcPackageDataId = res.data?.id || null; const remarkMap = {}; if (indexRemark && indexRemark != "") { JSON.parse(indexRemark).forEach(item => { const key = Object.keys(item)[0]; remarkMap[key] = item[key]; }); } this.remarkModalData = this.pdfTableData.map(item => ({ ...item, remark: item.nameKey ? remarkMap[item.nameKey] || "" : "", })); this.remarkModalVisible = true; }); } catch (error) { console.error("获取备注失败:", error); this.$message.error("获取备注失败"); } }, saveRemarks() { try { const indexRemark = this.remarkModalData.reduce((acc, item) => { if (item.nameKey) { acc.push({ [item.nameKey]: item.remark }); } return acc; }, []); const indexRemarkStr = JSON.stringify(indexRemark); Serve.updateMcPackageData({ id: this.mcPackageDataId, indexRemark: indexRemarkStr, projectId: this.selectedRecord.projNo, packageNo: this.selectedRecord.packageNo,templateNameKey: this.templateNameKey }).then(res => { if (!res.error) { this.$message.success('更新备注成功'); this.remarkModalVisible = false; } }); } catch (error) { console.error('更新备注失败:', error); this.$message.error('更新备注失败'); } }, }, }; </script> vue2示例如上,需要转换成vue3 vue3示例如下 <c-search-panel ref=“searchPanelRef” :columns=“tableState.columns” @search=“onSearch” </c-search-panel> <c-table :columns=“tableState.columns” :proxy-config=“tableState.proxyConfig” :toolbar=“tableState.toolbar” @toolbar-button-click=“onToolbarClick:pagination=“tableState.pagination” :sortConfig=“{ showIcon: false }” :row-selection=“rowSelection” ref=“tableRef” <template #action="{ record }"> <a-button type="link" @click="editRow(record)">{{ t("pipeControll.mc.edit") }}</a-button> </template> </c-table> <c-modal :title="action === 'add' ? '新增系统' : '编辑系统'" destroyOnClose v-model:open="open" okText="确认" cancelText="取消" @ok="handleOk" width="650px" > <a-form :model="formState" name="basic" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }" ref="formRef" > <a-row> <a-col> <a-input v-model:value="formState.id" v-if="false"/> </a-col> <a-col span="12"> <a-form-item :label="t('ptwSystem.system.projectId')" name="projectNo" :rules="[{ required: true, message: 'Please Select Project!' }]" > <c-project-select v-model:value="formState.projectNo" :field-names="{ value: 'projId' }" :disabled="isDisabledComputed" /> </a-form-item> </a-col> <a-col span="12"> <a-form-item :label="t('pipeControll.mc.sysCode')" name="sysNo" :rules="[{ required: true, message: 'Please Input!' }]" > <a-input v-model:value="formState.sysNo" :disabled="isDisabledComputed"/> </a-form-item> </a-col> </a-row> <a-row> <a-col :span="colSpan"> <a-form-item :label-col="{ span: 4 }" :wrapper-col="{ span: 19 }" :label="t('pipeControll.mc.systemName')" name="sysName" :rules="[{ required: true, message: 'Please Input!' }]" > <a-input v-model:value="formState.sysName"/> </a-form-item> </a-col> </a-row> <a-card :title="t('pipeControll.mc.subsysInfo')"> <c-table :columns="subTableState.columns" :pagination="false" :dataSource="subTableState.dataSource" height="250" :toolbar="subTableState.toolbar" @toolbar-button-click="onSubToolbarClick" :sortConfig="{ showIcon: false }" :rowSelection="{ selectedRowKeys: subTableState.selectedRowKeys, onChange: onSelectChange }" ref="subTableRef" > </c-table> </a-card> </a-form> </c-modal> </template> <script setup> import * as server from "@/packages/piping/api/cpmc/index" import {computed, createVNode, reactive, ref} from "vue" import {useI18n} from "vue-i18n" import {message, Modal} from "ant-design-vue" import {ExclamationCircleOutlined} from "@ant-design/icons-vue" import {saveAs} from "file-saver" const {t} = useI18n() const action = ref(null) const searchPanelRef = ref(null) const isDisabledComputed = computed(() => { if (action.value == "add") { return false } else { return true } }) const searchForm = computed(() => { if (searchPanelRef.value) { return searchPanelRef.value.getForm() } return null }) const tableState = reactive({ toolbar: { buttons: [ { code: "insert", status: 'primary', icon: 'PlusOutlined', // name: "新增", name: t("pipeControll.mc.add"), resource: [{url: "/service-piping/cp/mc/system", method: "POST"}] }, { code: "deleteData", status: 'danger', icon: 'DeleteOutlined', // name: "删除", name: t("pipeControll.mc.delete"), resource: [{url: "/service-piping/cp/pipe/mc/system/delete", method: "POST"}] }, { name: '模板导入', dropdowns: [ { code: "downloadModal", status: 'warning', icon: 'DownloadOutlined', // name: "下载导入模板", name: t("pipeControll.mc.importTemplate"), resource: [{url: "/service-piping/cp/pipe/mc/system/exportTemplate", method: "GET"}] }, { code: "importModal", status: 'success', icon: 'UploadOutlined', // name: "导入", name: t("pipeControll.mc.import"), resource: [{url: "/service-piping/pipe/cp/mc/system/importData", method: "POST"}] }, ] }, { code: "exportExcel", status: 'warning', icon: 'DownloadOutlined', // name: "导出", name: t("pipeControll.mc.export"), resource: [{url: "/service-piping/cp/mc/system/export", method: "GET"}] } ], }, selectedRowKeys: [], pagination: {pageSize: 20}, proxyConfig: { autoLoad: false, ajax: { query: (pagination) => server.systemPage({...pagination, ...conditionData.value}) } }, columns: [ { // title: "项目", title: t("ptwSystem.system.projectNo"), dataIndex: "projectNo", width: 60, type: "project", condition: true, options: { options: [], fieldNames: {label: "projId", value: "projId"} }, }, { // title: "系统号", title: t("ptwSystem.system.sysCode"), dataIndex: "sysNo", width: 100, condition: true }, { // title: "系统名称", title: t("pipeControll.mc.systemName"), dataIndex: "sysName", width: 180, condition: true }, { // title: "子系统数量", title: t("pipeControll.mc.subSystemQuantity"), dataIndex: "subSysQuantity", width: 130 }, { // title: "创建人", title: t("pipeControll.mc.creator"), dataIndex: "createUserNo", type: "employeeDescription", options: { fieldNames: { label: "createUserName", value: "createUserNo" } } }, { // title: "创建时间", title: t("pipeControll.mc.createDate"), dataIndex: "createDate", width: 100, type: "datetime" }, { // title: "更新人", title: t("pipeControll.mc.updater"), dataIndex: "updateUserNo", type: "employeeDescription", options: { fieldNames: { label: "updateUserName", value: "updateUserNo" } } }, { // title: "更新时间", title: t("pipeControll.mc.updateDate"), dataIndex: "updateDate", width: 100, type: "datetime" }, { // title: "操作", title: t("pipeControll.mc.operation"), key: "action", scopedSlots: {customRender: "action"}, width: 80, fixed: "right", formInvisible: true } ] }) const subTableState = reactive({ selectedRowKeys: [], toolbar: { buttons: [ { code: "insertInfo", status: "primary", icon: "PlusOutlined", // name: "新增" name: t("pipeControll.mc.add") }, { code: "deleteInfo", status: "danger", icon: "DeleteOutlined", // name: "删除" name: t("pipeControll.mc.delete") } ], showFilter: false }, columns: [ { // title: "子系统号", title: t("pipeControll.mc.subSystemNo"), dataIndex: "subsysNo", width: 100, condition: true, editable: true, rules: [{required: true, message: "必填项!"}] }, { // title: "子系统名称", title: t("pipeControll.mc.subSystemName"), dataIndex: "subsysName", width: 200, condition: true, editable: true, rules: [{required: true, message: "必填项!"}] } ], dataSource: [] }) const tableRef = ref(null) const ctable = computed(() => tableRef.value?.getTable()) const subTableRef = ref(null) const cSubTable = computed(() => subTableRef.value?.getTable()) const conditionData = ref() const formState = ref({projectNo: undefined, sysNo: undefined, sysName: undefined}) const colSpan = ref(24) const open = ref(false) const formRef = ref() const selectedRow = ref([]) const deletedRows = ref([]) //搜索 const onSearch = (values) => { conditionData.value = values ctable.value.commitProxy("query", values) } const onToolbarClick = (target) => { switch (target.code) { case "insert": funInsertModal() break case "deleteData": fundeleteModal() break case "downloadModal": funDownloadModal() break case "importModal": funImportModal() break case "exportExcel": funExportModal() break default: break } } const onSubToolbarClick = (target) => { switch (target.code) { case "insertInfo": insertInfo() break case "deleteInfo": deleteInfo() break default: break } } const rowSelection = computed(() => { return { selectedRowKeys: tableState.selectedRowKeys, onChange: (selectedRowKeys, selectedRows) => { tableState.selectedRowKeys = selectedRowKeys selectedRow.value = selectedRows } } }) const onSelectChange = (selectedRowKeys) => { subTableState.selectedRowKeys = selectedRowKeys } const insertInfo = () => { cSubTable.value.insert({ id: undefined, projectNo: undefined, sysNo: undefined, sysName: undefined }) } const deleteInfo = () => { subTableState.selectedRowKeys.forEach((rowKey) => { const row = cSubTable.value.getRowById(rowKey) if (row) { row.status = 0 deletedRows.value.push({...row}) cSubTable.value.deleteRowByRowKey(rowKey) } }) subTableState.selectedRowKeys = [] } const funInsertModal = () => { action.value = "add" open.value = true formState.value = {} subTableState.dataSource = [] } const editRow = (record) => { action.value = "edit" open.value = true formState.value = record subTableState.selectedRowKeys = [] server.getSubsystemDropList({projectNo: record.projectNo, sysNo: record.sysNo}).then((res) => { subTableState.dataSource = res.data }) } const fundeleteModal = () => { if (tableState.selectedRowKeys.length == 0) { message.error("请选择至少一条需要删除的数据") return } Modal.confirm({ title: "请确认是否要进行删除?", icon: createVNode(ExclamationCircleOutlined), content: "该操作一旦执行无法撤回", okText: "确认", okType: "danger", cancelText: "取消", onOk() { let param = tableState.selectedRowKeys.map((item) => { return {id: item} }) server.systemDelete(param).then(() => { message.success("删除成功") ctable.value.commitProxy("query") }) }, onCancel() { console.log("Cancel") } }) } const funDownloadModal = () => { server.systemTemplate() } const funImportModal = () => { ctable.value.readFile({types: ["xlsx", "xls"]}).then((response) => { const {file} = response handleFileChange(file) }) } const handleFileChange = (event) => { const selectedFile = event let param = { file: selectedFile } server.systemImportData(param).then((res) => { const contentType = res.headers["content-type"] if (!contentType) { // 处理数组对象 message.success("导入成功") ctable.value.commitProxy("query") } else if (contentType.includes("application/vnd.ms-excel;charset=utf-8")) { message.error("上传失败,请查看错误文件") saveAs(res.data, "导入提示.xlsx") } }) } const funExportModal = () => { searchForm.value.validateFields().then((values) => { server.systemExport({...values}) }) } const handleOk = () => { formRef.value .validate() .then(() => { let param = { id: formState.value.id, projectNo: formState.value.projectNo, sysNo: formState.value.sysNo, sysName: formState.value.sysName } cSubTable.value.validateEditFields().then(() => { param.mcSubsystemList = [...cSubTable.value.getUpdateRecords(), ...deletedRows.value] server.systemSave(param).then(() => { message.success("保存成功") open.value = false ctable.value.commitProxy("query") }) }) }) .catch((error) => { console.log("error", error) }) } </script>
最新发布
09-11
/*-----------弹窗模块管理------------------- */ <template> <el-dialog :title="dialogMode === 'create' ? '新建' : dialogMode === 'edit' ? '修改' : '查看'" :visible.sync="dialogVisible" :modal-append-to-body="true" append-to-body :close-on-click-modal="false" custom-class="fixed-height-dialog" width="60%" top="5vh"> <el-form label-width="80px" ref="formRef" :model="currentForm" style="height: 100%; display: flex; flex-direction: column;" :rules="rules"> <!-- 项目信息区域 --> <div class="formBorder"> <el-row :gutter="10"> <el-col :span="6"> <el-form-item size="mini" label="项目名称" prop="projectName"> <el-input v-model="currentForm.projectName" clearable style="width:100%" size="mini" :disabled="dialogMode === 'view'"> </el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item size="mini" label="项目编号" prop="projectCode"> <el-input v-model="currentForm.projectCode" clearable style="width:100%" size="mini" :disabled="dialogMode === 'view'"> </el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item size="mini" label="项目周期" prop="projectDate"> <el-date-picker v-model="projectDate" range-separator="→" start-placeholder="请选择开始日期" end-placeholder="请选择结束日期" type="daterange" size="mini" style="width: 100%;" unlink-panels :disabled="dialogMode === 'view'"> </el-date-picker> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="6"> <el-form-item label="负责人" size="mini" style="width: fit-content;"> <el-input v-model="currentForm.projectUser" clearable style="width:100%" size="mini" :disabled="dialogMode === 'view'"> </el-input> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="项目概述"> <el-input v-model="currentForm.remark" :rows="2" :disabled="dialogMode === 'view'"> </el-input> </el-form-item> </el-col> </el-row> </div> <div class="formBorder2"> <el-container style="height: 100%;"> <el-header style="height: auto; flex-shrink: 0; padding-bottom: 10px;"> <el-row :gutter="10" type="flex" class="searchDialog"> <el-col :span="5"> <el-select v-model="filterForm.maintenanceCompanyName" placeholder="请选择管养单位" size="mini" clearable filterable @clear="resetSearch" :disabled="dialogMode === 'view'"> <el-option v-for="item in MaintenanceUnitoptions" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-col> <el-col :span="5"> <el-select v-model="filterForm.routeCode" placeholder="请选择路线编号" size="mini" clearable filterable @clear="resetSearch" :disabled="dialogMode === 'view'"> <el-option v-for="item in routeCodeOptions" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-col> <el-col :span="5"> <el-input v-model="filterForm.searchKey" placeholder="请输入边坡编号或名称" size="mini" clearable @keyup.enter.native="searchForm" @clear="resetSearch" :disabled="dialogMode === 'view'"> <i slot="suffix" class="el-input__icon el-icon-search"></i> </el-input> </el-col> <el-col :span="5"> <el-select v-model="filterForm.evaluateLevel" placeholder="请选择技术状态等级" size="mini" clearable @clear="resetSearch" :disabled="dialogMode === 'view'"> <el-option v-for="item in evaluateLeveloptions" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-col> <el-col :span="2" :offset="4"> <el-button type="primary" size="mini" style="width:100%" icon="el-icon-search" @click="searchForm" :loading="loading" :disabled="dialogMode === 'view'">搜索 </el-button> </el-col> </el-row> </el-header> <el-main style="overflow-y: hidden;"> <el-table ref="scrollTable" v-loading="loading" style="width: 100%;" border :data="formTabledata" :row-style="{ height: '36px' }" :cell-style="{ padding: '4px 0', textAlign: 'center' }" :header-cell-style="{ height: '36px', padding: '4px 0', lineHeight: '36px', textAlign: 'center' }" @selection-change="handleSelectionChange" :row-key="getRowkey"> <el-table-column type="selection" width="55" :selectable="isRowSelectable" :reserve-selection="true"> </el-table-column> <el-table-column label="管养单位" prop="maintenanceCompanyName" width="290" show-overflow-tooltip> </el-table-column> <el-table-column label="路线编号" prop="routeCode" width="100"> </el-table-column> <el-table-column label="边坡编号" prop="sideSlopeCode" width="240" show-overflow-tooltip> </el-table-column> <el-table-column label="边坡名称" prop="sideSlopeName" width="267" show-overflow-tooltip> </el-table-column> <el-table-column label="技术状态等级" width="137"> <template slot-scope="scope"> {{ mapEvaluateLevel(scope.row.evaluateLevel) }} </template> </el-table-column> </el-table> </el-main> <!-- 分页区域 --> <el-footer style="flex-shrink: 0; padding-top: 10px;"> <el-pagination background @current-change="handleCurrentChange" :current-page="pageParams.pageNo" :page-size="pageParams.pageSize" layout="total, prev, pager, next" :total="total"> </el-pagination> </el-footer> </el-container> </div> </el-form> <!-- 弹窗底部按钮 --> <div slot="footer" class="dialog-footer" v-if="dialogMode === 'create' || dialogMode === 'edit'"> <el-button @click="dialogVisible = false">取消 </el-button> <el-button type="primary" @click="submitForm">提交 </el-button> </div> </el-dialog> </template> <script> import { mapCfg } from "@/utils"; import { getPeriodicInspectionSideSlopePageList, addPeriodicInspection, modifyPeriodicInspection, getSelectedPeriodicInspectionSideSlopeList } from "../../api/testProject"; import { getMaintenanceCompanyList, getRouteList } from "../../api/basicInformation"; export default { name: "SideSlopeDialog", props: { visible: Boolean, // 控制弹窗显示 mode: String, // 模式:create/edit/view initialForm: Object, // 初始表单数据 }, data() { return { isInitializingSelection: false, // 初始化状态标志 dialogVisible: this.visible, // 弹窗显示状态 dialogMode: this.mode, // 当前模式 currentForm: { projectCode: '', // 项目编号 projectName: '', // 项目名称 projectStartDate: '', // 开始日期 projectEndDate: '', // 结束日期 projectUser: '', // 项目负责人 remark: '', // 备注 sideSlopeDetailList: [] // 边坡详情列表 }, projectDate: [], // 项目日期范围 total: 0, // 总数据量 loading: false, // 加载状态 pageParams: { // 分页参数 pageNo: 1, pageSize: 10, }, filterForm: { // 搜索条件 maintenanceCompanyName: "", routeCode: "", searchKey: "", evaluateLevel: "", }, mulitipleSelection: [], allSelection: new Map(), MaintenanceUnitoptions: [], // 管养单位选项 routeCodeOptions: [], // 路线编号选项 formTabledata: [], // 表格数据 evaluateLeveloptions: [], // 技术状态等级选项 rules: { // 表单验证规则 projectName: [ { required: true, message: "项目名称不能为空", trigger: "blur" }, ], projectCode: [ { required: true, message: "项目编码不能为空", trigger: "blur" }, ], }, }; }, watch: { // 修复1:监听visible变化时确保加载数据 async visible(val) { this.dialogVisible = val; if (val) { // 打开对话框时重置状态 this.resetAllData(); // 关键修复:确保在创建模式外加载数据 if (this.dialogMode !== 'create' && this.currentForm.id) { // 确保在DOM更新后加载数据 await this.$nextTick(); await this.LoadListData(); } } else { // 关闭对话框时重置数据 this.resetAllData(); } }, // 修复2:监听模式变化 mode(val) { this.dialogMode = val; // 当模式从创建变为编辑/查看时,确保加载数据 if (this.dialogVisible && val !== 'create' && this.currentForm.id) { this.LoadListData(); } }, // 修复3:监听初始表单数据变化 initialForm: { deep: true, immediate: true, // 添加立即执行 async handler(val) { this.currentForm = { ...val }; this.projectDate = [val.projectStartDate, val.projectEndDate]; // 关键修复:当初始表单有ID时立即加载数据 if (this.dialogVisible && val.id && this.dialogMode !== 'create') { await this.$nextTick(); await this.LoadListData(); } } }, // 同步弹窗显示状态到父组件 dialogVisible(val) { this.$emit("update:visible", val); }, projectDate: { deep: true, handler(value) { if (value && value.length === 2) { this.currentForm.projectStartDate = value[0]; this.currentForm.projectEndDate = value[1]; } }, }, }, async created() { // 初始化数据 this.getRouteList(); await this.getEvaluateLevel(); this.getMaintenanceCompanyList(); }, methods: { handleSelectionChange(selection) { // 跳过初始化阶段的选中状态变更 if (this.isInitializingSelection) return; // 获取当前页选中项的key集合 const currentPageKeys = new Set( selection.map(row => row.sideSlopeUniqueCode) ); // 处理当前页的取消选中操作 this.formTabledata.forEach(row => { const key = row.sideSlopeUniqueCode; // 仅当行在全局选中池中但不在当前页选中集合时删除 if (this.allSelection.has(key) && !currentPageKeys.has(key)) { this.allSelection.delete(key); } }); // 添加新选中的项到全局池 selection.forEach(row => { const key = row.sideSlopeUniqueCode; if (!this.allSelection.has(key)) { this.allSelection.set(key, row); } }); // 更新当前页选中引用 this.mulitipleSelection = selection; }, getRowkey(row) { return row.sideSlopeUniqueCode; }, // 判断行是否可选(查看模式禁用选择) isRowSelectable(row, index) { return this.dialogMode !== "view"; }, // 获取管养单位列表 async getMaintenanceCompanyList() { const res = await getMaintenanceCompanyList(); this.MaintenanceUnitoptions = res.map((item) => ({ value: item, label: item, })); }, // 获取路线列表 async getRouteList() { const res = await getRouteList(); this.routeCodeOptions = res.map((item) => ({ value: item.id, label: item.routeCode, })); }, // 搜索方法 searchForm() { // this.showSelectedOnly = false, this.pageParams.pageNo = 1; this.LoadListData(); }, // 重置搜索条件 resetSearch() { // this.showSelectedOnly = true, this.filterForm = { maintenanceCompanyName: "", routeCode: "", searchKey: "", evaluateLevel: "", }; this.pageParams.pageNo = 1; this.LoadListData(); }, // 重置组件状态 resetAllData() { this.resetSelection(); this.formTabledata = []; // 清空表格数据 this.total = 0; // 重置总条数 this.pageParams = { // 重置分页 pageNo: 1, pageSize: 10 }; // 重置搜索条件(可选) this.filterForm = { maintenanceCompanyName: "", routeCode: "", searchKey: "", evaluateLevel: "" }; }, // 修改原有方法 resetSelection() { this.allSelection.clear(); this.allSelection = new Map(); if (this.$refs.scrollTable) { this.$refs.scrollTable.clearSelection(); } }, // 映射技术状态等级 mapEvaluateLevel(level) { const option = this.evaluateLeveloptions.find( (item) => item.value === level ); return option.label; }, // 加载表格数据 async LoadListData() { this.loading = true; try { const params = { orgId: this.filterForm.maintenanceCompanyName, routeId: this.filterForm.routeCode, searchKey: this.filterForm.searchKey, evaluateLevel: this.filterForm.evaluateLevel, pageSize: this.pageParams.pageSize, pageNo: this.pageParams.pageNo, }; // 获取表格数据 const res = await getPeriodicInspectionSideSlopePageList(params); this.formTabledata = res.entities; this.total = res.entityCount; // 处理非创建模式的数据加载 if (this.dialogMode !== 'create' && this.currentForm.id) { // 首次加载时获取所有选中项 if (this.pageParams.pageNo === 1) { const selected = await getSelectedPeriodicInspectionSideSlopeList({ periodicId: this.currentForm.id, pageSize: 10000, // 获取所有选中项 pageNo: 1 }); // 重置全局选中池 this.allSelection.clear(); this.mulitipleSelection = selected.entities; // 存储全局选中状态 this.mulitipleSelection.forEach(item => { this.allSelection.set(item.sideSlopeUniqueCode, item); }); } // 设置当前页选中状态 this.isInitializingSelection = true; this.$nextTick(() => { this.formTabledata.forEach(row => { if (this.allSelection.has(row.sideSlopeUniqueCode)) { this.$refs.scrollTable.toggleRowSelection(row, true); } }); this.isInitializingSelection = false; }); } } catch (error) { console.error("加载数据失败:", error); this.$message.error("加载数据失败"); } finally { this.loading = false; } }, // 当前页码变化 handleCurrentChange(val) { this.pageParams.pageNo = val; this.LoadListData(); }, // 获取技术状态等级选项 async getEvaluateLevel() { const levelList = await mapCfg("Inspection.Regular.RegularEvaluateLevel")(); this.evaluateLeveloptions = levelList.map((item) => ({ value: item.key, label: item.value, })); }, // 提交表单 async submitForm() { this.$refs.formRef.validate(async (valid) => { if (valid) { // 验证是否选择了边坡 const selectedItems = Array.from(this.allSelection.values()); if (this.allSelection.size === 0) { this.$message.warning("请至少选择一个边坡"); return; } // 构造提交参数 const params = { ...this.currentForm, sideSlopeDetailList: selectedItems.map(item => ({ sideSlopeUniqueCode: item.sideSlopeUniqueCode, evaluateLevel: item.evaluateLevel, evaluateDate: item.evaluateDate || undefined })), }; // 根据模式选择操作 const action = this.dialogMode === "create" ? addPeriodicInspection : modifyPeriodicInspection; // 执行操作 try { const success = await action(params); if (success) { this.$message.success( this.dialogMode === "create" ? "新建成功" : "修改成功" ); this.$refs.scrollTable.clearSelection(); this.$emit("success"); this.dialogVisible = false; } else { this.$message.error("操作失败"); } } catch (error) { this.$message.error(error.message || "操作失败"); } } }); } }, }; </script> <style lang="scss" scoped> /* 修复1:弹性容器最小高度约束 */ :deep(.fixed-height-dialog), .formBorder2, .formBorder2 .el-container, .formBorder2 .el-main { min-height: 0 !important; } /* 表格行高优化 */ :deep(.el-table) { .el-table__row { height: 36px !important; td { padding: 4px 0 !important; } } .el-table__header { th { padding: 4px 0 !important; .cell { line-height: 28px !important; } } } /* 确保内部滚动 */ .el-table__body-wrapper { overflow-y: auto !important; max-height: calc(100vh - 400px) !important; } } /* 表单区域固定 */ .formBorder { position: relative; ///为伪元素提供定位上下文 border: thin dotted black !important; padding: 10px !important; margin-top: 15px !important; flex-shrink: 0 !important; height: auto !important; overflow: visible !important; margin-bottom: 15px !important; /* 边框的文字 */ &::before { content: "项目信息"; position: absolute; top: -8px; //调整到更合适的位置 left: 15px; //向右移动避免遮挡 background-color: #fff; //背景色需与页面背景一致 padding: 0 8px; font-size: 13px; color: #606266; z-index: 10; //提高层级确保显示 font-weight: 500; //加粗文字 pointer-events: none; //防止点击穿透 } } .formBorder2 { position: relative; border: thin dotted black; padding: 10px; flex: 1; min-height: 0; overflow: hidden; // 保留 display: flex; flex-direction: column; padding-top: 25px; // 新增 &::before { content: "待检边坡"; position: absolute; top: 5px; // 调整到新增的padding区域内部 left: 15px; background-color: #fff; padding: 0 8px; font-size: 13px; color: #606266; z-index: 1000; font-weight: 500; pointer-events: none; } .el-container { height: auto !important; // 覆盖行内样式 flex: 1; // 填满剩余空间 display: flex; flex-direction: column; min-height: 0; .el-header { flex-shrink: 0; height: auto !important; padding-bottom: 10px; } .el-main { flex: 1; overflow: hidden; position: relative; padding: 0; } .el-footer { flex-shrink: 0; padding-top: 10px; } } } // 弹窗底部按钮区域 .dialog-footer { padding: 10px 20px; border-top: 1px solid #ebeef5; text-align: center; } // 搜索区域样式 .searchDialog { margin-top: 5px; } // 空数据样式 :deep(.el-table__empty-block) { min-height: 200px; display: flex; justify-content: center; align-items: center; } // 分页样式 :deep(.el-pagination) { padding: 5px 0; } // 表格高度控制 :deep(.el-table) { height: 100% !important; .el-table__body-wrapper { overflow-y: auto !important; } } </style><template> <div class="project-management-block"> <!-- 弹窗组件 --> <side-slope-dialog :visible="dialogVisible" :mode="currentMode" :initial-form="currentForm" @update:visible="dialogVisible = $event" @success="handleDialogSuccess" /> <div class="project-management-block--header"> <el-form size="mini" :inline="true" class="fr ml10" align="left"> <el-input v-model="searchParams.projectName" placeholder="项目名称或编号" size="mini" clearable @clear="resetSearch" style="width: 140px;" class="mr10" /> <el-select v-model="searchParams.status" placeholder="项目状态" size="mini" clearable @clear="resetSearch" style="width: 140px;" class="mr10"> <el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" filterable /> </el-select> <el-date-picker v-model="searchProjectDate" value-format="timestamp" size="mini" class="mr10" type="datetimerange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker> <el-button type="primary" size="mini" style="width: 80px;" @click="handleSearch" class="mr10" >查询 </el-button> <el-button type="success" size="mini" style="width: 80px;" @click="openCreateDialog" class="mr10" >新建 </el-button> </el-form> </div> <div class="project-management-block--content" > <!-- 项目数据表格 --> <el-table :data="tableData" border style="width: 100%; flex: 1;" height="100%" > <el-table-column label="序号" type="index" width="120"> </el-table-column> <el-table-column label="项目名称" prop="projectName" width="250"> </el-table-column> <el-table-column label="项目编号" prop="projectCode" width="220"> </el-table-column> <el-table-column label="项目周期" width="250"> <template slot-scope="scope"> {{ scope.row.projectStartDate ? formatDateRange(scope.row.projectStartDate, scope.row.projectEndDate) : '' }} </template> </el-table-column> <el-table-column label="项目状态" width="150"> <template slot-scope="scope"> {{ scope.row.status ? getStatusText(scope.row.status) : '' }} </template> </el-table-column> <el-table-column label="边坡总数" prop="sideSlopeTotalCount" width="150"> </el-table-column> <el-table-column label="已完成边坡数" prop="sideSlopeCompleteCount" width="194"> </el-table-column> <el-table-column label="完成率" width="150"> <template slot-scope="scope"> {{ scope.row.sideSlopeTotalCount ? calculateCompletionRate( scope.row.sideSlopeCompleteCount, scope.row.sideSlopeTotalCount ) : '' }} </template> </el-table-column> <el-table-column label="操作" width="195"> <template slot-scope="scope"> <div v-if="scope.row.id" style="display: flex; justify-content: center;"> <el-button size="mini" type="primary" @click="openViewDialog(scope.row)" style="padding: 4px 8px; font-size: 12px" >查看 </el-button> <el-button size="mini" type="info" @click="openEditDialog(scope.row)" style="padding: 4px 8px; font-size: 12px" >编辑 </el-button> <el-button size="mini" type="danger" @click="deleteItem(scope.row)" style="padding: 4px 8px; font-size: 12px" >删除 </el-button> </div> </template> </el-table-column> </el-table> </div> <div class="project-management-block--footer"> <el-pagination background layout="total,prev, pager, next,jumper" :current-page.sync="pageParams.pageNo" :page-size="pageParams.pageSize" :total="pageParams.total"/> </div> </div> </template> <script> // 导入模块 import SideSlopeDialog from './SideSlopeDialog.vue' // 项目详情弹窗组件 import { mapCfg } from '@/utils' // 字典配置映射工具 //接口 import { getPeriodicInspectionPageList, deletePeriodicInspection } from '../../api/testProject' // 组件定义 export default { name: 'ProjectManagement', // 组件名称 components: { SideSlopeDialog // 注册弹窗组件 }, // 数据模型 data() { return { // 搜索参数对象 searchParams: { projectName: '', // 项目名称/编号搜索词 status: '', // 项目状态筛选值 projectStartDate: '', // 项目开始日期 projectEndDate: '' // 项目结束日期 }, // 日期范围选择器绑定值 searchProjectDate: [], // 项目状态下拉选项 statusOptions: [], // 表格数据源 tableData: [], // 分页参数 pageParams: { pageNo: 1, // 当前页码 pageSize: 10, // 每页条数 total: 0 // 总数据量 }, // 弹窗控制参数 dialogVisible: false, // 弹窗显示状态 currentMode: '', // 弹窗模式: 'create'/'edit'/'view' currentForm: null // 当前表单数据 } }, // 监听器 watch: { //监听日期范围选择器变化:将选择器值同步到搜索参数对象 searchProjectDate(newVal) { if (newVal && newVal.length === 2) { this.searchParams.projectStartDate = newVal[0] this.searchParams.projectEndDate = newVal[1] } else { this.searchParams.projectStartDate = '' this.searchParams.projectEndDate = '' } } }, // 生命周期钩子 async created() { // 初始化状态选项 this.getStatus() // 加载表格数据 this.loadTableData() }, // 方法/函数 methods: { // 工具方法 //根据状态值获取状态文本 getStatusText(statusValue) { const option = this.statusOptions.find((opt) => opt.value === statusValue) return option ? option.label : '' }, //格式化日期范围 formatDateRange(start, end) { if (!start || !end) return '' // 截取日期部分(去除时间) const format = (dateStr) => dateStr.substring(0, 10) return `${format(start)} 至 ${format(end)}` }, //计算完成率 calculateCompletionRate(completed, total) { if (!total || isNaN(total) || total <= 0) return '0%' return `${((completed / total) * 100).toFixed(1)}%` }, // 弹窗操作方法 //创建项目弹窗 openCreateDialog() { this.currentMode = 'create' // 重置表单数据 this.currentForm = { projectCode: '', projectName: '', projectStartDate: '', projectEndDate: '', projectUser: '', remark: '', sideSlopeDetailList: [] } this.dialogVisible = true }, //编辑项目弹窗 openEditDialog(row) { this.currentMode = 'edit' // 复制当前行数据到表单 this.currentForm = { ...row, projectStartDate: row.projectStartDate, projectEndDate: row.projectEndDate } this.dialogVisible = true }, //查看项目弹窗 openViewDialog(row) { this.currentMode = 'view' // 复制当前行数据到表单 this.currentForm = { ...row, projectStartDate: row.projectStartDate, projectEndDate: row.projectEndDate } this.dialogVisible = true }, // 弹窗操作成功回调,刷新表格数据(返回第一页) handleDialogSuccess() { this.pageParams.pageNo = 1 this.loadTableData() }, // 数据操作方法 //加载表格数据,根据搜索参数和分页设置获取项目数据 async loadTableData() { // 转换日期为时间戳格式 const startTime = this.searchParams.projectStartDate ? new Date(this.searchParams.projectStartDate).getTime() : null const endTime = this.searchParams.projectEndDate ? new Date(this.searchParams.projectEndDate).getTime() : null // 构造API参数 const params = { pageNo: this.pageParams.pageNo, pageSize: this.pageParams.pageSize, searchKey: this.searchParams.projectName, status: this.searchParams.status, startTime, endTime } try { // 调用API获取项目数据 const res = await getPeriodicInspectionPageList(params) this.tableData = res.entities || [] this.pageParams.total = res.entityCount || 0 } catch (error) { console.error('加载项目列表失败', error) this.tableData = [] this.pageParams.total = 0 } }, //搜索方法重置到第一页并重新加载数据 handleSearch() { this.pageParams.pageNo = 1 this.loadTableData() }, //重置搜索条件,清空所有搜索参数并重新加载数据 resetSearch() { this.searchParams = { projectName: '', status: '', projectStartDate: '', projectEndDate: '' } this.searchProjectDate = [] this.handleSearch() }, //删除项目 async deleteItem(row) { try { // 显示确认对话框 await this.$confirm('确定要删除该项目吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }) // 调用删除API await deletePeriodicInspection({ periodicId: row.id }) this.$message.success('删除成功') // 如果删除的是最后一页的最后一条,返回上一页 if (this.tableData.length === 1 && this.pageParams.pageNo > 1) { this.pageParams.pageNo -= 1 } // 重新加载数据 this.loadTableData() } catch (error) { // 用户取消删除时不显示错误 if (error !== 'cancel') { this.$message.error('删除失败') } } }, //从字典配置加载状态选项 getStatus() { try { // 获取字典配置 const dictList = mapCfg('Inspection.Periodic.PeriodicInspectionStatus')() // 转换为Element-UI需要的格式 this.statusOptions = dictList.map((item) => ({ value: item.key, label: item.value })) } catch (e) { console.error("获取状态失败", e); this.statusOptions = []; } } } } </script> <style lang="scss" scoped> .project-management-block { width: 100%; height: 100%; position: relative; background-color: #fff; &--header { height: 50px; box-sizing: border-box; padding: 10px; border-bottom: 1px solid #ebeef5; } &--content { display: block; padding: 10px; height: calc(100% - 90px); position: relative; z-index: 10; } &--footer { border-top: 1px solid #ebeef5; padding: 4px 10px 0 10px; position: relative; z-index: 11; text-align: center; } } /* 优化表格样式 */ ::v-deep .el-table { flex: 1; min-height: 0; // 防止flex布局溢出 /* 单元格样式 */ th, td { padding: 4px 0; } /* 表头样式 */ .el-table__header-wrapper { line-height: 1; th { .cell { line-height: 1.2; } } } } /* 分页组件样式优化,确保在不同缩放比例下可见 */ ::v-deep .el-pagination { padding: 4px 5px; .btn-prev, .btn-next, .el-pager li, .el-pagination__jump { min-width: 28px; height: 28px; line-height: 28px; margin: 0 2px; } .el-pagination__total, .el-pagination__jump { font-size: 12px; } } /* 响应式调整 */ @media screen and (max-width: 1200px) { .project-management-block--header .el-col { margin-bottom: 8px; } ::v-deep .el-pagination { display: flex; flex-wrap: wrap; justify-content: center; &>* { margin-bottom: 5px; } } } </style>vue.runtime.esm.js:4662 [Vue warn]: Error in callback for immediate watcher "initialForm" (Promise/async): "TypeError: Cannot read properties of null (reading 'projectStartDate')" found in ---> <SideSlopeDialog> at src/pages/conservation-management/SideSlopeDialog.vue <ProjectManagement> at src/pages/conservation-management/_ProjectManagement.vue <TabPage> at src/pages/base/components/TabPage.vue <ElTabPane> at packages/tabs/src/tab-pane.vue <ElTabs> at packages/tabs/src/tabs.vue <ElMain> at packages/main/src/main.vue <ElContainer> at packages/container/src/main.vue... (1 recursive calls) <AppMain> at src/pages/base/AppMain.vue <Backend> at src/pages/common/Backend.vue <App> at src/App.vue <Root>这是怎么回事
09-04
/* * @Author: liuhm * @Date: 2024-9-26 14:43:05 * @Last Modified by: liuhm * @Last Modified time: 2024-9-26 14:43:09 */ /** |-------------------------------------------------- | | 任务管理 | |-------------------------------------------------- */ <template> <el-card class="custom"> <!-- 头部 START --> <div slot="header" class="plr10 clearfix"> <div class="fl header-seach-box"> <el-form :model="searchFormData" class="fl mr5"> <el-cascader style="width: 200px" v-model="searchFormData.orgId" clearable class="ml10" filterable :options="maintenanceCompanyList" :props="{ value: 'id', label: 'name', emitPath: false, checkStrictly: true, children: 'childrenList' }" size="mini" placeholder="请选择管养单位" ></el-cascader> <el-select style="width: 200px" v-model="searchFormData.routeId" clearable class="ml10" filterable size="mini" placeholder="请选择巡查路线" > <el-option v-for="item in routerList" :key="item.id" :label="item.routeCode" :value="item.id" > </el-option> </el-select> <div v-if="hasFunctionCode(functionList, 'PERM_10244')" class="fr ml5"> <el-button size="mini" icon="el-icon-search " @click="searchTable" /> </div> </el-form> </div> </div> <!-- 头部 END --> <!-- 内容 START --> <el-table v-loading="tableLoading" size="mini" :data="dataSource" :height="`${cardContentHeight + 35}px`" row-key="id" style="width: 100%" border stripe :cell-class-name="cellClass" > <el-table-column label="序号" width="50" type="index" align="left" /> <el-table-column label="管养单位" prop="orgName" width="230" align="left" /> <el-table-column label="巡查时间" align="center" width="200" show-overflow-tooltip> <template slot-scope="scope"> <span>{{ `${formatDate(scope.row.inspectStartDate)} -${formatDate(scope.row.inspectEndDate)}` }}</span> </template> </el-table-column> <el-table-column label="巡查路线" prop="routeName" width="280" align="center" show-overflow-tooltip > <template slot-scope="scope"> <span>{{ scope.row.routeCode +scope.row.routeName }}</span> </template> </el-table-column> <el-table-column label="巡查状态" prop="status" width="100" align="center" show-overflow-tooltip > <template slot-scope="scope"> <span>{{ scope.row.status | DailyInspectionStatusMap }}</span> </template> </el-table-column> <el-table-column label="巡检人" prop="inspectUser" align="center" show-overflow-tooltip /> <el-table-column label="记录人" prop="recorder" align="center" show-overflow-tooltip > </el-table-column> <el-table-column label="操作" fixed="right" width="140" align="center"> <template slot-scope="scope"> <ul class="table-button-list"> <!-- <template v-if="hasFunctionCode(functionList, 'PERM_10249')"> <li @click="detailDailyInspection(scope.row)"> <img src="@/assets/images/table/chakan.png" />详情 </li> </template> --> <template v-if="hasFunctionCode(functionList, 'PERM_10246')"> <li @click="modifyDailyInspection(scope.row)"> <img src="@/assets/images/table/bianji.png" />编辑 </li> </template> <!-- <template v-if="hasFunctionCode(functionList, 'PERM_10247')"> <li @click="deleteDailyInspection(scope.row)"> <img src="@/assets/images/table/shanchu.png" />删除 </li> </template> --> </ul> <!-- <el-button-group> <template v-if="hasFunctionCode(functionList, 'PERM_10249')"> <el-button size="mini" type="primary" icon="el-icon-view" @click="detailDailyInspection(scope.row)" ></el-button> </template> <template v-if="hasFunctionCode(functionList, 'PERM_10246')"> <el-button size="mini" type="primary" icon="el-icon-edit-outline" @click="modifyDailyInspection(scope.row)" ></el-button> </template> <template v-if="hasFunctionCode(functionList, 'PERM_10247')"> <el-button size="mini" type="danger" icon="el-icon-delete" @click="deleteDailyInspection(scope.row)" ></el-button> </template> <template v-if="hasFunctionCode(functionList, 'PERM_10248')"> <el-button size="mini" icon="el-icon-document-checked" @click="completeDailyInspection(scope.row)" ></el-button> </template> </el-button-group> --> </template> </el-table-column> </el-table> <el-pagination class="mt10" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page.pageNo" :page-sizes="[10, 20, 30, 40, 50]" :page-size="page.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="entityCount" > </el-pagination> <!-- 内容 END --> <!-- 组件 START --> <template> <InspectionDialog ref="InspectionDialog" /> </template> <!-- 组件 END --> </el-card> </template> <script> // 接口 import { getDailyInspectionList, deleteDailyInspection, completeDailyInspection, getDailyDiseaseDetailPageList } from "@/api/dailyInspection"; import { getMaintenanceCompanyList, getRouteList } from "@/api/commonAnalysis" // 组件 import InspectionDialog from "./inspection-dialog/InspectionDialog"; // mixin import autoHeight from "@/mixin/autoHeight"; import { CONFIRM as CONF } from "@/optionsCfg/Message.js"; import { DIALOG_CLOSED_TYPE as DIALOG } from "@/optionsCfg/Constants"; import moment from "moment"; import { mapCfg } from "@/utils"; export default { name: "DailyInspection", components: { InspectionDialog, }, mixins: [autoHeight], data() { return { searchFormData: { orgId: "", // 管养单位id routeId: "", // 巡查路线id status: "", // 巡查状态 }, tableLoading: false, dataSource: [], page: { pageSize: 20, pageNo: 1, }, searchTime:[], entityCount: 0, routerList: [], maintenanceCompanyList:[], functionList: this.$store.getters.getFunction, deviceTypeOpt: [], // 设备类型配置 bridgeMonitorTypeOpt: [], // 监测类型列表 isFirstLoad: false, }; }, created() { this.isFirstLoad = true; this.getRouteList(); this.getMaintenanceCompanyList(); this.loadTableData(); }, filters: { //边坡与路线位置关系 DailyInspectionStatusMap(key) { const config = mapCfg("Inspection.Daliy.DailyInspectionStatus")(); let name = ""; config.forEach((item) => { if (item.key === key) { name = item.value; } }); return name; }, }, computed: { dailyInspectionStatusConfig() { const DailyInspectionStatus = mapCfg("Inspection.Daliy.DailyInspectionStatus")().map((item) => { return { value: item.key, label: item.value, }; }); return DailyInspectionStatus; }, }, methods: { // 加载表格数据 loadTableData() { this.tableLoading = true; const params = { pageSize: this.page.pageSize, pageNo: this.page.pageNo, status: this.searchFormData.status, routeId: this.searchFormData.routeId, orgId: this.searchFormData.orgId, startTime: this.searchTime && this.searchTime[0], endTime: this.searchTime && this.searchTime[1], }; getDailyInspectionList(params) .then((res) => { if (res) { this.dataSource = res.entities || []; this.entityCount = res.entityCount; if (res.pageCount < this.page.pageNo) { this.page.pageNo = res.pageCount; this.loadTableData(); } } }) .catch((e) => { this.$message.error(e && e.message); console.warn(e); }) .finally((_) => { this.tableLoading = false; }); }, // 搜索 searchTable() { this.page.pageNo = 1; this.loadTableData(); }, // 格式化时间 formatDate(date) { if (!date) return ""; return moment(date).format(`YYYY-MM-DD`); }, // 更改一页显示数量时 handleSizeChange(pageSize) { this.page.pageNo = 1; this.page.pageSize = pageSize; this.loadTableData(); }, // 分页改变时 handleCurrentChange(page) { this.page.pageNo = page; this.loadTableData(); }, // 获取养护单位列表 async getMaintenanceCompanyList() { try { const res = await getMaintenanceCompanyList(); if (res) { this.maintenanceCompanyList = res; } } catch (err) { console.log(err); } }, // 获取巡查路线列表编号 async getRouteList() { try { const res = await getRouteList(); if (res) { this.routerList = res; } } catch (err) { console.log(err); } }, // 添加边坡基本信息 addDailyInspection() { this.$refs["InspectionDialog"].open(); this.$refs["InspectionDialog"].onClosed = (args) => { if (DIALOG.CONFIRM === args.option) { this.page.pageNo = 1; this.loadTableData(); } }; }, //查看边坡基本信息 async detailDailyInspection(row) { try { // this.$store.commit("SHOW_WAITING"); this.$refs["InspectionDialog"].open(row); this.$refs["InspectionDialog"].onClosed = (args) => { if (DIALOG.CONFIRM === args.option) { // this.page.pageNo = 1 this.loadTableData(); } }; } catch (e) { console.warn(e); this.$store.commit("CLOSE_WAITING"); } }, // 修改边坡基本信息 async modifyDailyInspection(row) { try { this.$store.commit("SHOW_WAITING"); this.$refs["InspectionDialog"].open(row); this.$refs["InspectionDialog"].onClosed = (args) => { if (DIALOG.CONFIRM === args.option) { // this.page.pageNo = 1 this.loadTableData(); } }; } catch (e) { console.warn(e); this.$store.commit("CLOSE_WAITING"); }finally { this.$store.commit("CLOSE_WAITING"); } }, // 删除项目 async deleteDailyInspection(row) { try { await this.$confirm(CONF.DELETE, CONF.TITLE, { closeOnClickModal: false, confirmButtonText: CONF.YES, cancelButtonText: CONF.NO, type: "warning", }); } catch (e) { return; } // eslint-disable-line try { await this.deleteSideSlopeInfo({ dailyId : row.id }); } catch (e) { console.warn(e); this.$message.error(e && e.message); } }, // 删除项目接口 async deleteSideSlopeInfo(id) { try { this.$store.commit("SHOW_WAITING"); const res = await deleteDailyInspection(id); if (res) { this.page.pageNo = 1; this.loadTableData(); this.$message.success("删除成功"); } } catch (e) { console.warn(e); this.$message.error(e && e.message); } finally { this.$store.commit("CLOSE_WAITING"); } }, cellClass({ row, column, rowIndex, columnIndex }) { if (columnIndex === 3) return "table-align"; }, async uploadBridgeDeviceInfo(file) { // 设备导入 this.$store.commit("SHOW_WAITING"); try { const formData = new FormData(); formData.append("file", file.file); const res = await importBridgeDeviceInfo(formData); if (res) { this.$message.success("导入成功"); this.page.pageNo = 1; this.loadTableData(); } } catch (e) { console.warn(e); this.$message.error(e && e.message); } finally { this.$store.commit("CLOSE_WAITING"); } }, downLoadFile() { if (!this.searchFormData.bridgeId) { this.$message.warning("请选择桥梁"); return; } const bridgeList = this.$store.state.bridge.bridgeList.filter( (item) => item.id === this.searchFormData.bridgeId ); if (bridgeList[0] && bridgeList[0].hasOwnProperty("bridgeNo")) { const bridgeCode = bridgeList[0].bridgeNo; downloadMonitorDeviceInfo(bridgeCode) .then((res) => { if (res && res.message) { console.warn(res); this.$message.error(res && res.message); } }) .catch((e) => { this.$message.error(e && e.message); console.warn(e); }); } else { this.$message.warning("暂无桥梁"); } }, }, }; </script> <style lang="scss" scoped> ::v-deep .el-button-group > .el-button:not(:last-child) { margin-right: 0; } .header-seach-box { height: 46px; box-sizing: border-box; padding: 9px 0; } ::v-deep .table-align .el-tooltip { padding-left: 28%; text-align: left; } ::v-deep .el-table th > .cell { color: #000; } ::v-deep .el-table th { background-color: #eff3f8; } ::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td { background-color: rgb(239, 243, 248, 0.6); } .table-button-list{ grid-template-columns: repeat(1, 1fr); } </style>// 巡查任务弹窗 <template> <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="600px" :close-on-click-modal="false" @closed="handleClosed" > <el-form ref="inspectionForm" :model="formData" :rules="formRules" label-width="100px" size="mini" :disabled="viewMode" > <el-row> <el-col :span="12"> <el-form-item label="管养单位" prop="orgId"> <el-cascader v-model="formData.orgId" :options="maintenanceCompanyList" :props="{ value: 'id', label: 'name', checkStrictly: true, children: 'childrenList', emitPath: false }" placeholder="请选择管养单位" style="width: 100%" clearable ></el-cascader> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="任务名称" prop="taskName"> <el-input v-model="formData.taskName" placeholder="请输入任务名称"></el-input> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="巡检路线" prop="routeId"> <el-select v-model="formData.routeId" placeholder="请选择巡检路线" style="width: 100%"> <el-option v-for="item in routeList" :key="item.id" :label="item.name" :value="item.id" ></el-option> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="状态" prop="status"> <el-radio-group v-model="formData.status" placeholder="请选择状态" style="width: 100%"> <el-radio label="启用" :value="true"></el-radio> <el-radio label="禁用" :value="false"></el-radio> </el-radio-group> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="巡检周期" prop="inspectionPeriod"> <el-date-picker v-model="formData.inspectionPeriod" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd" style="width: 100%" ></el-date-picker> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="巡检频次" prop="frequency"> <el-select v-model="formData.frequency" placeholder="请选择巡检频次" style="width: 100%"> <el-option v-for="item in frequencyOptions" :key="item.value" :label="item.label" :value="item.value" ></el-option> </el-select> </el-form-item> </el-col> </el-row> <el-form-item label="备注"> <el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请输入备注信息" ></el-input> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button size="mini" @click="dialogVisible = false">取 消</el-button> <el-button v-if="!viewMode" type="primary" size="mini" @click="submitForm">确 定</el-button> </div> </el-dialog> </template> <script> import { getMaintenanceCompanyList } from '@/api/commonAnalysis'; import { getRouteList } from '@/api/basicInformation'; // import { addInspectionTask, updateInspectionTask, getInspectionTaskDetail } from '@/api/conservation'; // 假设这些API已存在 export default { name: 'InspectionDialog', data() { return { dialogVisible: false, dialogType: 'add', // add, edit, view formData: { id: '', orgId: null, taskName: '', routeId: '', frequency: '', inspectionPeriod: [], remark: '' }, formRules: { orgId: [{ required: true, message: '请选择管养单位', trigger: 'change' }], taskName: [{ required: true, message: '请输入任务名称', trigger: 'blur' }], routeId: [{ required: true, message: '请选择巡检路线', trigger: 'change' }], frequency: [{ required: true, message: '请选择巡检频次', trigger: 'change' }], inspectionPeriod: [{ required: true, message: '请选择巡检周期', trigger: 'change' }] }, maintenanceCompanyList: [], routeList: [], frequencyOptions: [ { label: '每日', value: 'daily' }, { label: '每周', value: 'weekly' }, { label: '每月', value: 'monthly' }, { label: '每季度', value: 'quarterly' }, { label: '每半年', value: 'semiannually' }, { label: '每年', value: 'annually' } ], onClosed: null }; }, computed: { dialogTitle() { const titleMap = { add: '新建巡查任务', edit: '修改巡查任务', view: '巡查任务详情' }; return titleMap[this.dialogType] || '巡查任务'; }, viewMode() { return this.dialogType === 'view'; } }, created() { this.getMaintenanceCompanyList(); this.getRouteList(); }, methods: { // 打开弹窗 open(type = 'add', data = null) { this.dialogType = type; this.dialogVisible = true; this.resetForm(); if (data && (type === 'edit' || type === 'view')) { this.loadTaskDetail(data.id); } return new Promise((resolve) => { this.onClosed = resolve; }); }, // 重置表单 resetForm() { this.formData = { id: '', orgId: null, taskName: '', routeId: '', frequency: '', inspectionPeriod: [], remark: '' }; // 如果表单已经被渲染,则重置校验结果 this.$nextTick(() => { this.$refs.inspectionForm && this.$refs.inspectionForm.clearValidate(); }); }, // 加载任务详情 async loadTaskDetail(id) { try { this.$store.commit('SHOW_WAITING'); const res = await getInspectionTaskDetail({ id }); if (res) { // 假设API返回的数据结构与表单一致 this.formData = { ...res, inspectionPeriod: [res.startDate, res.endDate] }; } } catch (e) { console.warn(e); this.$message.error(e && e.message); } finally { this.$store.commit('CLOSE_WAITING'); } }, // 提交表单 submitForm() { this.$refs.inspectionForm.validate(async (valid) => { if (!valid) return; try { this.$store.commit('SHOW_WAITING'); // 处理日期范围 const params = { ...this.formData, startDate: this.formData.inspectionPeriod[0], endDate: this.formData.inspectionPeriod[1] }; delete params.inspectionPeriod; let res; if (this.dialogType === 'add') { res = await addInspectionTask(params); } else { res = await updateInspectionTask(params); } if (res) { this.$message.success(`${this.dialogType === 'add' ? '新增' : '修改'}成功`); this.dialogVisible = false; this.onClosed && this.onClosed({ option: 'confirm', data: res }); } } catch (e) { console.warn(e); this.$message.error(e && e.message); } finally { this.$store.commit('CLOSE_WAITING'); } }); }, // 弹窗关闭回调 handleClosed() { this.onClosed && this.onClosed({ option: 'cancel' }); }, // 获取管养单位列表 async getMaintenanceCompanyList() { try { const res = await getMaintenanceCompanyList(); if (res) { this.maintenanceCompanyList = res; } } catch (e) { console.warn(e); this.$message.error(e && e.message); } }, // 获取路线列表 async getRouteList() { try { const res = await getRouteList(); if (res) { this.routeList = res; } } catch (e) { console.warn(e); this.$message.error(e && e.message); } } } }; </script> <style lang="scss" scoped> .dialog-footer { text-align: right; } </style> <template> <div class="project-management-block"> <!-- 弹窗组件 --> <side-slope-dialog :visible="dialogVisible" :mode="currentMode" :initial-form="currentForm" @update:visible="dialogVisible = $event" @success="handleDialogSuccess" /> <div class="project-management-block--header"> <el-form size="mini" :inline="true" class="fr ml10" align="left"> <el-input v-model="searchParams.projectName" placeholder="项目名称或编号" size="mini" clearable @clear="resetSearch" style="width: 140px;" class="mr10" /> <el-select v-model="searchParams.status" placeholder="项目状态" size="mini" clearable @clear="resetSearch" style="width: 140px;" class="mr10"> <el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" filterable /> </el-select> <el-date-picker v-model="searchProjectDate" value-format="timestamp" size="mini" class="mr10" type="datetimerange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker> <el-button type="primary" size="mini" style="width: 80px;" @click="handleSearch" class="mr10" >查询 </el-button> <el-button type="success" size="mini" style="width: 80px;" @click="handleAction('create')" class="mr10" >新建 </el-button> </el-form> </div> <div class="project-management-block--content" > <!-- 项目数据表格 --> <el-table :data="tableData" border stripe style="width: 100%; flex: 1;" height="100%" row-key="id" > <el-table-column label="序号" type="index" width="120"> </el-table-column> <el-table-column label="项目名称" prop="projectName" width="250"> </el-table-column> <el-table-column label="项目编号" prop="projectCode" width="220"> </el-table-column> <el-table-column label="项目周期" width="250"> <template slot-scope="scope"> <span v-if="scope.row">{{ `${formatDate(scope.row.projectStartDate)} 至 ${formatDate(scope.row.projectEndDate)}` }}</span> </template> </el-table-column> <el-table-column label="项目状态" width="150"> <template slot-scope="scope"> {{ getStatusText(scope.row.status)}} </template> </el-table-column> <el-table-column label="边坡总数" prop="sideSlopeTotalCount" width="150"> </el-table-column> <el-table-column label="已完成边坡数" prop="sideSlopeCompleteCount" width="194"> </el-table-column> <el-table-column label="完成率" width="150"> <template slot-scope="scope"> {{ `${((scope.row.sideSlopeCompleteCount / scope.row.sideSlopeTotalCount) * 100).toFixed(1)}%` }} </template> </el-table-column> <el-table-column label="操作" width="195"> <template slot-scope="scope"> <div v-if="scope.row.id" style="display: flex; justify-content: center;"> <el-button size="mini" type="primary" @click="handleAction('view', scope.row)" style="padding: 4px 8px; font-size: 12px" >查看 </el-button> <el-button size="mini" type="info" @click="handleAction('edit', scope.row)" style="padding: 4px 8px; font-size: 12px" >编辑 </el-button> <el-button size="mini" type="danger" @click="handleAction('delete', scope.row)" style="padding: 4px 8px; font-size: 12px" >删除 </el-button> </div> </template> </el-table-column> </el-table> </div> <div class="project-management-block--footer"> <el-pagination background layout="total,prev, pager, next,jumper" :current-page.sync="pageParams.pageNo" :page-size="pageParams.pageSize" :total="pageParams.total"/> </div> </div> </template> <script> // 导入模块 import SideSlopeDialog from './SideSlopeDialog.vue' // 项目详情弹窗组件 import { mapCfg } from '@/utils' // 字典配置映射工具 //接口 import { getPeriodicInspectionPageList, deletePeriodicInspection } from '../../api/testProject' import moment from 'moment' // 组件定义 export default { name: 'ProjectManagement', // 组件名称 components: { SideSlopeDialog // 注册弹窗组件 }, // 数据模型 data() { return { // 搜索参数对象 searchParams: { projectName: '', // 项目名称/编号搜索词 status: '', // 项目状态筛选值 projectStartDate: '', // 项目开始日期 projectEndDate: '' // 项目结束日期 }, // 日期范围选择器绑定值 searchProjectDate: [], // 表格数据源 tableData: [], // 分页参数 pageParams: { pageNo: 1, // 当前页码 pageSize: 10, // 每页条数 total: 0 // 总数据量 }, // 弹窗控制参数 dialogVisible: false, // 弹窗显示状态 currentMode: '', // 弹窗模式: 'create'/'edit'/'view' currentForm: null // 当前表单数据 } }, // 监听器 watch: { //监听日期范围选择器变化:将选择器值同步到搜索参数对象 searchProjectDate(newVal) { if (newVal && newVal.length === 2) { this.searchParams.projectStartDate = newVal[0] this.searchParams.projectEndDate = newVal[1] } else { this.searchParams.projectStartDate = '' this.searchParams.projectEndDate = '' } } }, // 生命周期钩子 async created() { // 加载表格数据 this.loadTableData() }, computed:{ statusOptions() { const dictList = mapCfg('Inspection.Periodic.PeriodicInspectionStatus')() return dictList.map(item => ({ value: item.key, label: item.value })) }, }, // 方法/函数 methods: { // 工具方法 //根据状态值获取状态文本 getStatusText(statusValue) { const option = this.statusOptions.find((opt) => opt.value === statusValue) return option.label }, // 格式化时间 formatDate(date) { if (!date) return ""; return moment(date).format(`YYYY-MM-DD`); }, // 弹窗操作方法 handleAction(action, row = null) { if (action === 'create') { // 新建操作 this.currentMode = 'create' this.currentForm = { projectCode: '', projectName: '', projectStartDate: '', projectEndDate: '', projectUser: '', remark: '', sideSlopeDetailList: [] } this.dialogVisible = true } else if (action === 'edit') { // 编辑操作 this.currentMode = 'edit' this.currentForm = { ...row, projectStartDate: row.projectStartDate, projectEndDate: row.projectEndDate } this.dialogVisible = true } else if (action === 'view') { // 查看操作 this.currentMode = 'view' this.currentForm = { ...row, projectStartDate: row.projectStartDate, projectEndDate: row.projectEndDate } this.dialogVisible = true } else if (action === 'delete') { // 删除操作 this.deleteItem(row) } }, //删除方法 async deleteItem(row) { try { // 显示确认对话框 await this.$confirm('确定要删除该项目吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }) // 调用删除API await deletePeriodicInspection({ periodicId: row.id }) this.$message.success('删除成功') // 如果删除的是最后一页的最后一条,返回上一页 if (this.tableData.length === 1 && this.pageParams.pageNo > 1) { this.pageParams.pageNo -= 1 } // 重新加载数据 this.loadTableData() } catch (error) { // 用户取消删除时不显示错误 if (error !== 'cancel') { this.$message.error('删除失败') }} }, // 弹窗操作成功回调,刷新表格数据(返回第一页) handleDialogSuccess() { this.pageParams.pageNo = 1 this.loadTableData() }, // 数据操作方法 //加载表格数据,根据搜索参数和分页设置获取项目数据 async loadTableData() { // 转换日期为时间戳格式 const startTime = this.searchParams.projectStartDate ? new Date(this.searchParams.projectStartDate).getTime() : null const endTime = this.searchParams.projectEndDate ? new Date(this.searchParams.projectEndDate).getTime() : null // 构造API参数 const params = { pageNo: this.pageParams.pageNo, pageSize: this.pageParams.pageSize, searchKey: this.searchParams.projectName, status: this.searchParams.status, startTime, endTime } try { // 调用API获取项目数据 const res = await getPeriodicInspectionPageList(params) this.tableData = res.entities || [] this.pageParams.total = res.entityCount || 0 } catch (error) { console.error('加载项目列表失败', error) this.tableData = [] this.pageParams.total = 0 } }, //搜索方法重置到第一页并重新加载数据 handleSearch() { this.pageParams.pageNo = 1 this.loadTableData() }, //重置搜索条件,清空所有搜索参数并重新加载数据 resetSearch() { this.searchParams = { projectName: '', status: '', projectStartDate: '', projectEndDate: '' } this.searchProjectDate = [] this.handleSearch() }, } } </script> <style lang="scss" scoped> .project-management-block { width: 100%; height: 100%; position: relative; background-color: #fff; &--header { height: 50px; box-sizing: border-box; padding: 10px; border-bottom: 1px solid #ebeef5; } &--content { display: block; padding: 10px; height: calc(100% - 90px); position: relative; z-index: 10; } &--footer { border-top: 1px solid #ebeef5; padding: 4px 10px 0 10px; position: relative; z-index: 11; text-align: center; } } /* 优化表格样式 */ ::v-deep .el-table { flex: 1; min-height: 0; // 防止flex布局溢出 /* 单元格样式 */ th, td { padding: 4px 0; } /* 表头样式 */ .el-table__header-wrapper { line-height: 1; th { .cell { line-height: 1.2; } } } } /* 分页组件样式优化,确保在不同缩放比例下可见 */ ::v-deep .el-pagination { padding: 4px 5px; .btn-prev, .btn-next, .el-pager li, .el-pagination__jump { min-width: 28px; height: 28px; line-height: 28px; margin: 0 2px; } .el-pagination__total, .el-pagination__jump { font-size: 12px; } } /* 响应式调整 */ @media screen and (max-width: 1200px) { .project-management-block--header .el-col { margin-bottom: 8px; } ::v-deep .el-pagination { display: flex; flex-wrap: wrap; justify-content: center; &>* { margin-bottom: 5px; } } } </style>/*-----------弹窗模块管理------------------- */ <template> <el-dialog :title="dialogMode === 'create' ? '新建' : dialogMode === 'edit' ? '修改' : '查看'" :visible.sync="dialogVisible" :modal-append-to-body="true" append-to-body :close-on-click-modal="false" custom-class="fixed-height-dialog" width="60%" top="5vh"> <el-form label-width="80px" ref="formRef" :model="currentForm" style="height: 100%; display: flex; flex-direction: column;" :rules="rules"> <!-- 项目信息区域 --> <div class="formBorder"> <el-row :gutter="10"> <el-col :span="6"> <el-form-item size="mini" label="项目名称" prop="projectName"> <el-input v-model="currentForm.projectName" clearable style="width:100%" size="mini" :disabled="dialogMode === 'view'"> </el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item size="mini" label="项目编号" prop="projectCode"> <el-input v-model="currentForm.projectCode" clearable style="width:100%" size="mini" :disabled="dialogMode === 'view'"> </el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item size="mini" label="项目周期" prop="projectDate"> <el-date-picker v-model="projectDate" range-separator="→" start-placeholder="请选择开始日期" end-placeholder="请选择结束日期" type="daterange" size="mini" style="width: 100%;" unlink-panels :disabled="dialogMode === 'view'"> </el-date-picker> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="6"> <el-form-item label="负责人" size="mini" style="width: fit-content;"> <el-input v-model="currentForm.projectUser" clearable style="width:100%" size="mini" :disabled="dialogMode === 'view'"> </el-input> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="项目概述"> <el-input v-model="currentForm.remark" :rows="2" :disabled="dialogMode === 'view'"> </el-input> </el-form-item> </el-col> </el-row> </div> <div class="formBorder2"> <el-container style="height: 100%;"> <el-header style="height: auto; flex-shrink: 0; padding-bottom: 10px;"> <el-row :gutter="10" type="flex" class="searchDialog"> <el-col :span="5"> <el-select v-model="filterForm.maintenanceCompanyName" placeholder="请选择管养单位" size="mini" clearable filterable @clear="resetSearch" :disabled="dialogMode === 'view'"> <el-option v-for="item in MaintenanceUnitoptions" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-col> <el-col :span="5"> <el-select v-model="filterForm.routeCode" placeholder="请选择路线编号" size="mini" clearable filterable @clear="resetSearch" :disabled="dialogMode === 'view'"> <el-option v-for="item in routeCodeOptions" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-col> <el-col :span="5"> <el-input v-model="filterForm.searchKey" placeholder="请输入边坡编号或名称" size="mini" clearable @keyup.enter.native="searchForm" @clear="resetSearch" :disabled="dialogMode === 'view'"> <i slot="suffix" class="el-input__icon el-icon-search"></i> </el-input> </el-col> <el-col :span="5"> <el-select v-model="filterForm.evaluateLevel" placeholder="请选择技术状态等级" size="mini" clearable @clear="resetSearch" :disabled="dialogMode === 'view'"> <el-option v-for="item in getEvaluateLevel" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-col> <el-col :span="2" :offset="4"> <el-button type="primary" size="mini" style="width:100%" icon="el-icon-search" @click="searchForm" :loading="loading" :disabled="dialogMode === 'view'">搜索 </el-button> </el-col> </el-row> </el-header> <el-main style="overflow-y: hidden;"> <el-table ref="scrollTable" v-loading="loading" style="width: 100%;" border :data="formTabledata" :row-style="{ height: '36px' }" :cell-style="{ padding: '4px 0', textAlign: 'center' }" :header-cell-style="{ height: '36px', padding: '4px 0', lineHeight: '36px', textAlign: 'center' }" @selection-change="handleSelectionChange" :row-key="getRowkey"> <el-table-column type="selection" width="55" :selectable="isRowSelectable" :reserve-selection="true"> </el-table-column> <el-table-column label="管养单位" prop="maintenanceCompanyName" width="290" show-overflow-tooltip> </el-table-column> <el-table-column label="路线编号" prop="routeCode" width="100"> </el-table-column> <el-table-column label="边坡编号" prop="sideSlopeCode" width="240" show-overflow-tooltip> </el-table-column> <el-table-column label="边坡名称" prop="sideSlopeName" width="267" show-overflow-tooltip> </el-table-column> <el-table-column label="技术状态等级" width="137"> <template slot-scope="scope"> {{ mapEvaluateLevel(scope.row.evaluateLevel) }} </template> </el-table-column> </el-table> </el-main> <!-- 分页区域 --> <el-footer style="flex-shrink: 0; padding-top: 10px;"> <el-pagination background @current-change="handleCurrentChange" :current-page="pageParams.pageNo" :page-size="pageParams.pageSize" layout="total, prev, pager, next" :total="total"> </el-pagination> </el-footer> </el-container> </div> </el-form> <!-- 弹窗底部按钮 --> <div slot="footer" class="dialog-footer" v-if="dialogMode === 'create' || dialogMode === 'edit'"> <el-button @click="dialogVisible = false">取消 </el-button> <el-button type="primary" @click="submitForm">提交 </el-button> </div> </el-dialog> </template> <script> import { mapCfg } from "@/utils"; import { getPeriodicInspectionSideSlopePageList, addPeriodicInspection, modifyPeriodicInspection, getSelectedPeriodicInspectionSideSlopeList } from "../../api/testProject"; import { getMaintenanceCompanyList, getRouteList } from "../../api/basicInformation"; export default { name: "SideSlopeDialog", props: { visible: Boolean, // 控制弹窗显示 mode: String, // 模式:create/edit/view initialForm: Object, // 初始表单数据 }, data() { return { isInitializingSelection: false, // 初始化状态标志 dialogVisible: this.visible, // 弹窗显示状态 dialogMode: this.mode, // 当前模式 currentForm: { projectCode: '', // 项目编号 projectName: '', // 项目名称 projectStartDate: '', // 开始日期 projectEndDate: '', // 结束日期 projectUser: '', // 项目负责人 remark: '', // 备注 sideSlopeDetailList: [] // 边坡详情列表 }, projectDate: [], // 项目日期范围 total: 0, // 总数据量 loading: false, // 加载状态 pageParams: { // 分页参数 pageNo: 1, pageSize: 10, }, filterForm: { // 搜索条件 maintenanceCompanyName: "", routeCode: "", searchKey: "", evaluateLevel: "", }, mulitipleSelection: [], allSelection: new Map(), MaintenanceUnitoptions: [], // 管养单位选项 routeCodeOptions: [], // 路线编号选项 formTabledata: [], // 表格数据 rules: { // 表单验证规则 projectName: [ { required: true, message: "项目名称不能为空", trigger: "blur" }, ], projectCode: [ { required: true, message: "项目编码不能为空", trigger: "blur" }, ], }, }; }, watch: { //监听visible变化时确保加载数据 async visible(val) { this.dialogVisible = val; if (val) { // 打开对话框时重置状态 this.resetAllData(); if (this.dialogMode !== 'create' && this.currentForm.id) { // 确保在DOM更新后加载数据 await this.$nextTick(); await this.LoadListData(); } } else { // 关闭对话框时重置数据 this.resetAllData(); } }, //监听模式变化 mode(val) { this.dialogMode = val; // 当模式从创建变为编辑/查看时,确保加载数据 if (this.dialogVisible && val !== 'create' && this.currentForm.id) { this.LoadListData(); } }, // 修复3:监听初始表单数据变化 initialForm: { deep: true, immediate: true, async handler(val) { this.currentForm = { ...val }; // 安全处理日期(新增空值判断) this.projectDate = val.projectStartDate && val.projectEndDate // 关键修复:添加空值校验 if (this.dialogVisible && val.id && this.dialogMode !== 'create') { await this.$nextTick(); await this.LoadListData(); } } }, // 同步弹窗显示状态到父组件 dialogVisible(val) { this.$emit("update:visible", val); }, projectDate: { deep: true, handler(value) { if (value && value.length === 2) { this.currentForm.projectStartDate = value[0]; this.currentForm.projectEndDate = value[1]; } }, }, }, async created() { // 初始化数据 this.getRouteList(); this.getMaintenanceCompanyList(); }, computed:{ getEvaluateLevel() { const levelList = mapCfg("Inspection.Regular.RegularEvaluateLevel")(); return levelList.map((item) => ({ value: item.key, label: item.value, })) }, }, methods: { handleSelectionChange(selection) { // 跳过初始化阶段的选中状态变更 if (this.isInitializingSelection) return; // 获取当前页选中项的key集合 const currentPageKeys = new Set( selection.map(row => row.sideSlopeUniqueCode) ); // 处理当前页的取消选中操作 this.formTabledata.forEach(row => { const key = row.sideSlopeUniqueCode; // 仅当行在全局选中池中但不在当前页选中集合时删除 if (this.allSelection.has(key) && !currentPageKeys.has(key)) { this.allSelection.delete(key); } }); // 添加新选中的项到全局池 selection.forEach(row => { const key = row.sideSlopeUniqueCode; if (!this.allSelection.has(key)) { this.allSelection.set(key, row); } }); // 更新当前页选中引用 this.mulitipleSelection = selection; }, getRowkey(row) { return row.sideSlopeUniqueCode; }, // 判断行是否可选(查看模式禁用选择) isRowSelectable(row, index) { return this.dialogMode !== "view"; }, // 获取管养单位列表 async getMaintenanceCompanyList() { const res = await getMaintenanceCompanyList(); this.MaintenanceUnitoptions = res.map((item) => ({ value: item, label: item, })); }, // 获取路线列表 async getRouteList() { const res = await getRouteList(); this.routeCodeOptions = res.map((item) => ({ value: item.id, label: item.routeCode, })); }, // 搜索方法 searchForm() { this.pageParams.pageNo = 1; this.LoadListData(); }, // 重置搜索条件 resetSearch() { this.filterForm = { maintenanceCompanyName: "", routeCode: "", searchKey: "", evaluateLevel: "", }; this.pageParams.pageNo = 1; this.LoadListData(); }, // 重置组件状态 resetAllData() { this.resetSelection(); this.formTabledata = []; // 清空表格数据 this.total = 0; // 重置总条数 this.pageParams = { // 重置分页 pageNo: 1, pageSize: 10 }; // 重置搜索条件(可选) this.filterForm = { maintenanceCompanyName: "", routeCode: "", searchKey: "", evaluateLevel: "" }; }, // 修改原有方法 resetSelection() { this.allSelection.clear(); this.allSelection = new Map(); if (this.$refs.scrollTable) { this.$refs.scrollTable.clearSelection(); } }, // 映射技术状态等级 mapEvaluateLevel(level) { const option = this.getEvaluateLevel.find( (item) => item.value === level ); return option.label; }, // 加载表格数据 async LoadListData() { this.loading = true; try { const params = { orgId: this.filterForm.maintenanceCompanyName, routeId: this.filterForm.routeCode, searchKey: this.filterForm.searchKey, evaluateLevel: this.filterForm.evaluateLevel, pageSize: this.pageParams.pageSize, pageNo: this.pageParams.pageNo, }; // 获取表格数据 const res = await getPeriodicInspectionSideSlopePageList(params); this.formTabledata = res.entities; this.total = res.entityCount; // 处理非创建模式的数据加载 if (this.dialogMode !== 'create' && this.currentForm.id) { // 首次加载时获取所有选中项 if (this.pageParams.pageNo === 1) { const selected = await getSelectedPeriodicInspectionSideSlopeList({ periodicId: this.currentForm.id, pageSize: 10000, // 获取所有选中项 pageNo: 1 }); // 重置全局选中池 this.allSelection.clear(); this.mulitipleSelection = selected.entities; // 存储全局选中状态 this.mulitipleSelection.forEach(item => { this.allSelection.set(item.sideSlopeUniqueCode, item); }); } // 设置当前页选中状态 this.isInitializingSelection = true; this.$nextTick(() => { this.formTabledata.forEach(row => { if (this.allSelection.has(row.sideSlopeUniqueCode)) { this.$refs.scrollTable.toggleRowSelection(row, true); } }); this.isInitializingSelection = false; }); } } catch (error) { console.error("加载数据失败:", error); this.$message.error("加载数据失败"); } finally { this.loading = false; } }, // 当前页码变化 handleCurrentChange(val) { this.pageParams.pageNo = val; this.LoadListData(); }, // 提交表单 async submitForm() { this.$refs.formRef.validate(async (valid) => { if (valid) { // 验证是否选择了边坡 const selectedItems = Array.from(this.allSelection.values()); if (this.allSelection.size === 0) { this.$message.warning("请至少选择一个边坡"); return; } // 构造提交参数 const params = { ...this.currentForm, sideSlopeDetailList: selectedItems.map(item => ({ sideSlopeUniqueCode: item.sideSlopeUniqueCode, evaluateLevel: item.evaluateLevel, evaluateDate: item.evaluateDate || undefined })), }; // 根据模式选择操作 const action = this.dialogMode === "create" ? addPeriodicInspection : modifyPeriodicInspection; // 执行操作 try { const success = await action(params); if (success) { this.$message.success( this.dialogMode === "create" ? "新建成功" : "修改成功" ); this.$refs.scrollTable.clearSelection(); this.$emit("success"); this.dialogVisible = false; } else { this.$message.error("操作失败"); } } catch (error) { this.$message.error(error.message || "操作失败"); } } }); } }, }; </script> <style lang="scss" scoped> /* 修复1:弹性容器最小高度约束 */ :deep(.fixed-height-dialog), .formBorder2, .formBorder2 .el-container, .formBorder2 .el-main { min-height: 0 !important; } /* 表格行高优化 */ :deep(.el-table) { .el-table__row { height: 36px !important; td { padding: 4px 0 !important; } } .el-table__header { th { padding: 4px 0 !important; .cell { line-height: 28px !important; } } } /* 确保内部滚动 */ .el-table__body-wrapper { overflow-y: auto !important; max-height: calc(100vh - 400px) !important; } } /* 表单区域固定 */ .formBorder { position: relative; ///为伪元素提供定位上下文 border: thin dotted black !important; padding: 10px !important; margin-top: 15px !important; flex-shrink: 0 !important; height: auto !important; overflow: visible !important; margin-bottom: 15px !important; /* 边框的文字 */ &::before { content: "项目信息"; position: absolute; top: -8px; //调整到更合适的位置 left: 15px; //向右移动避免遮挡 background-color: #fff; //背景色需与页面背景一致 padding: 0 8px; font-size: 13px; color: #606266; z-index: 10; //提高层级确保显示 font-weight: 500; //加粗文字 pointer-events: none; //防止点击穿透 } } .formBorder2 { position: relative; border: thin dotted black; padding: 10px; flex: 1; min-height: 0; overflow: hidden; // 保留 display: flex; flex-direction: column; padding-top: 25px; // 新增 &::before { content: "待检边坡"; position: absolute; top: 5px; // 调整到新增的padding区域内部 left: 15px; background-color: #fff; padding: 0 8px; font-size: 13px; color: #606266; z-index: 1000; font-weight: 500; pointer-events: none; } .el-container { height: auto !important; // 覆盖行内样式 flex: 1; // 填满剩余空间 display: flex; flex-direction: column; min-height: 0; .el-header { flex-shrink: 0; height: auto !important; padding-bottom: 10px; } .el-main { flex: 1; overflow: hidden; position: relative; padding: 0; } .el-footer { flex-shrink: 0; padding-top: 10px; } } } // 弹窗底部按钮区域 .dialog-footer { padding: 10px 20px; border-top: 1px solid #ebeef5; text-align: center; } // 搜索区域样式 .searchDialog { margin-top: 5px; } // 空数据样式 :deep(.el-table__empty-block) { min-height: 200px; display: flex; justify-content: center; align-items: center; } // 分页样式 :deep(.el-pagination) { padding: 5px 0; } // 表格高度控制 :deep(.el-table) { height: 100% !important; .el-table__body-wrapper { overflow-y: auto !important; } } </style>结合前两段代码的组件方式 后两段代码应该如何修改
09-04
<template> <el-dialog :title="dialogMode === 'create' ? '新建' : dialogMode === 'edit' ? '修改' : '查看'" :visible.sync="dialogVisible" :modal-append-to-body="true" append-to-body :close-on-click-modal="false" custom-class="fixed-height-dialog" width="60%" top="5vh"> <el-form label-width="80px" ref="formRef" :model="currentForm" style="height: 100%; display: flex; flex-direction: column;" :rules="rules"> <!-- 项目信息区域 --> <div class="formBorder"> <el-row :gutter="10"> <el-col :span="6"> <el-form-item size="mini" label="项目名称" prop="projectName"> <el-input v-model="currentForm.projectName" clearable style="width:100%" size="mini" :disabled="dialogMode === 'view'"></el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item size="mini" label="项目编号" prop="projectCode"> <el-input v-model="currentForm.projectCode" clearable style="width:100%" size="mini" :disabled="dialogMode === 'view'"></el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item size="mini" label="项目周期" prop="projectDate"> <el-date-picker v-model="projectDate" range-separator="→" start-placeholder="请选择开始日期" end-placeholder="请选择结束日期" type="daterange" size="mini" style="width: 100%;" unlink-panels :disabled="dialogMode === 'view'"> </el-date-picker> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="6"> <el-form-item label="负责人" size="mini" style="width: fit-content;"> <el-input v-model="currentForm.projectUser" clearable style="width:100%" size="mini" :disabled="dialogMode === 'view'"></el-input> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="项目概述"> <el-input v-model="currentForm.remark" :rows="2" :disabled="dialogMode === 'view'"></el-input> </el-form-item> </el-col> </el-row> </div> <!-- 待检边坡区域 --> <div class="formBorder2" style="flex: 1; min-height: 0; display: flex; flex-direction: column;"> <el-container style="height: 100%; display: flex; flex-direction: column;"> <!-- 搜索区域 --> <el-header style="height: auto; flex-shrink: 0; padding-bottom: 10px;"> <el-row :gutter="10" type="flex" class="searchDialog"> <el-col :span="5"> <el-select v-model="filterForm.maintenanceCompanyName" placeholder="请选择管养单位" size="mini" clearable filterable @clear="resetSearch" :disabled="dialogMode === 'view'"> <el-option v-for="item in MaintenanceUnitoptions" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </el-col> <el-col :span="5"> <el-select v-model="filterForm.routeCode" placeholder="请选择路线编号" size="mini" clearable filterable @clear="resetSearch" :disabled="dialogMode === 'view'"> <el-option v-for="item in routeCodeOptions" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </el-col> <el-col :span="5"> <el-input v-model="filterForm.searchKey" placeholder="请输入边坡编号或名称" size="mini" clearable @keyup.enter.native="searchForm" @clear="resetSearch" :disabled="dialogMode === 'view'"> <i slot="suffix" class="el-input__icon el-icon-search"></i> </el-input> </el-col> <el-col :span="5"> <el-select v-model="filterForm.evaluateLevel" placeholder="请选择技术状态等级" size="mini" clearable @clear="resetSearch" :disabled="dialogMode === 'view'"> <el-option v-for="item in evaluateLeveloptions" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-col> <el-col :span="2" :offset="4"> <el-button type="primary" size="mini" style="width:100%" icon="el-icon-search" @click="searchForm" :loading="loading" :disabled="dialogMode === 'view'">搜索</el-button> </el-col> </el-row> </el-header> <!-- 边坡表格 --> <el-main style="flex: 1; overflow-y: auto; padding: 0;"> <el-table ref="scrollTable" v-loading="loading" style="width: 100%;" border :data="formTabledata" :height="tableHeight" :header-row-style="{ height: '40px' }" :header-cell-style="{ padding: '0', height: '40px', lineHeight: '40px', textAlign: 'center', }" :cell-style="{ textAlign: 'center' }" @selection-change="handleSelectionChange"> <!-- 选择列(查看模式禁用) --> <el-table-column type="selection" width="55" :selectable="isRowSelectable"> </el-table-column> <!-- 其他数据列 --> <el-table-column label="管养单位" prop="maintenanceCompanyName" width="290" show-overflow-tooltip></el-table-column> <el-table-column label="路线编号" prop="routeCode" width="100"></el-table-column> <el-table-column label="边坡编号" prop="sideSlopeCode" width="240" show-overflow-tooltip></el-table-column> <el-table-column label="边坡名称" prop="sideSlopeName" width="267" show-overflow-tooltip></el-table-column> <el-table-column label="技术状态等级" width="137"> <template slot-scope="scope"> {{ mapEvaluateLevel(scope.row.evaluateLevel) }} </template> </el-table-column> </el-table> </el-main> <!-- 分页区域 --> <el-footer style="flex-shrink: 0; padding-top: 10px;"> <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="pageParams.pageNo" :page-sizes="[10, 20, 50, 100]" :page-size="pageParams.pageSize" layout="total, sizes, prev, pager, next" :total="total" :disabled="dialogMode === 'view'"> </el-pagination> </el-footer> </el-container> </div> </el-form> <!-- 弹窗底部按钮 --> <div slot="footer" class="dialog-footer" v-if="dialogMode === 'create' || dialogMode === 'edit'"> <el-button @click="dialogVisible = false">取消</el-button> <el-button type="primary" @click="submitForm">提交</el-button> </div> </el-dialog> </template> <script> import { mapCfg } from "@/utils"; import { getPeriodicInspectionSideSlopePageList, addPeriodicInspection, modifyPeriodicInspection, getSelectedPeriodicInspectionSideSlopeList // 新增接口 } from "../../api/testProject"; import { getMaintenanceCompanyList, getRouteList } from "../../api/basicInformation"; export default { name: "SideSlopeDialog", props: { visible: Boolean, // 控制弹窗显示 mode: String, // 模式:create/edit/view initialForm: Object, // 初始表单数据 }, data() { return { mulitipleSelection: [], dialogVisible: this.visible, // 弹窗显示状态 dialogMode: this.mode, // 当前模式 currentForm: { ...this.initialForm }, // 当前表单数据 projectDate: [], // 项目日期范围 total: 0, // 总数据量 loading: false, // 加载状态 pageParams: { // 分页参数 pageNo: 1, pageSize: 10, }, filterForm: { // 搜索条件 maintenanceCompanyName: "", routeCode: "", searchKey: "", evaluateLevel: "", }, allSelection: [], // 存储所有选择的边坡 MaintenanceUnitoptions: [], // 管养单位选项 routeCodeOptions: [], // 路线编号选项 formTabledata: [], // 表格数据 evaluateLeveloptions: [], // 技术状态等级选项 tableHeight: 200, // 表格高度 rules: { // 表单验证规则 projectName: [ { required: true, message: "项目名称不能为空", trigger: "blur" }, ], projectCode: [ { required: true, message: "项目编码不能为空", trigger: "blur" }, ], }, selectedSideSlopes: [] // 存储已选择的边坡列表 }; }, watch: { // 监听模式变化 mode(val) { this.dialogMode = val; if (val === "edit" && this.dialogVisible) { this.resetSearch(); } }, // 监听弹窗显示状态变化 visible(val) { this.dialogVisible = val; if (val) { this.resetSearch(); // 编辑/查看模式时获取已选择边坡 if (this.dialogMode !== 'create' && this.currentForm.id) { this.getSelectedSlopes(); } this.$nextTick(() => { this.calculateTableHeight(); }); } else { // 关闭弹窗时重置选择状态 this.resetSelection(); } }, // 同步弹窗显示状态到父组件 dialogVisible(val) { this.$emit("update:visible", val); }, // 监听初始表单数据变化 initialForm: { deep: true, handler(val) { this.currentForm = { ...val }; this.projectDate = val.projectStartDate && val.projectEndDate ? [val.projectStartDate, val.projectEndDate] : []; } }, // 处理日期范围变化 projectDate: { deep: true, handler(value) { if (value && value.length === 2) { this.currentForm.projectStartDate = value[0]; this.currentForm.projectEndDate = value[1]; } }, }, }, async created() { // 初始化数据 this.getRouteList(); await this.getEvaluateLevel(); this.getMaintenanceCompanyList(); this.LoadListData(); }, mounted() { // 计算表格高度并监听窗口变化 this.calculateTableHeight(); window.addEventListener("resize", this.calculateTableHeight); }, beforeDestroy() { // 移除事件监听 window.removeEventListener("resize", this.calculateTableHeight); }, methods: { // 获取已选择的边坡 async getSelectedSlopes() { try { const res = await getSelectedPeriodicInspectionSideSlopeList({ periodicId: this.currentForm.id }); this.selectedSideSlopes = res; this.$nextTick(() => { this.setSelectedRows(); }); } catch (error) { console.error('获取已选择边坡失败', error); } }, //设置选中 setSelectedRows() { if ( this.dialogMode === 'create') return; if (this.selectedSideSlopes.length > 0) { this.formTabledata.forEach(row => { this.selectedSideSlopes.forEach(item => { if (row.sideSlopeCode === item.sideSlopeUniqueCode) { this.$refs.scrollTable.toggleRowSelection(row, true); } }); }); } }, // 判断行是否可选(查看模式禁用选择) isRowSelectable(row, index) { return this.dialogMode !== "view"; }, // 获取管养单位列表 async getMaintenanceCompanyList() { const res = await getMaintenanceCompanyList(); this.MaintenanceUnitoptions = res.map((item) => ({ value: item, label: item, })); }, // 获取路线列表 async getRouteList() { const res = await getRouteList(); this.routeCodeOptions = res.map((item) => ({ value: item.id, label: item.routeCode, })); }, // 搜索方法 searchForm() { this.pageParams.pageNo = 1; this.LoadListData(); }, // 重置搜索条件 resetSearch() { this.filterForm = { maintenanceCompanyName: "", routeCode: "", searchKey: "", evaluateLevel: "", }; this.pageParams.pageNo = 1; this.LoadListData(); }, // 重置选择状态 resetSelection() { this.allSelection = []; this.selectedSideSlopes = []; if (this.$refs.scrollTable) { this.$refs.scrollTable.clearSelection(); } }, // 处理选择变化 handleSelectionChange(val) { // 查看模式不允许修改选择 if (this.dialogMode === 'view') return; this.mulitipleSelection = val; // 创建当前页选择的唯一标识集合 const currentPageSelections = new Set( val.map((item) => item.sideSlopeCode) ); // 更新全量选择:先移除当前页的数据,再添加新选择 this.allSelection = [ ...this.allSelection.filter( (item) => !currentPageSelections.has(item.sideSlopeCode) ), ...val, ]; }, // 映射技术状态等级 mapEvaluateLevel(level) { const option = this.evaluateLeveloptions.find( (item) => item.value === level ); return option ? option.label : ''; }, // 加载表格数据 async LoadListData() { this.loading = true; const params = { orgId: this.filterForm.maintenanceCompanyName, routeId: this.filterForm.routeCode, searchKey: this.filterForm.searchKey, evaluateLevel: this.filterForm.evaluateLevel, pageSize: this.pageParams.pageSize, pageNo: this.pageParams.pageNo, }; try { const res = await getPeriodicInspectionSideSlopePageList(params); this.formTabledata = res.entities; this.total = res.entityCount; // 加载数据后设置选中状态 this.$nextTick(() => { this.setSelectedRows(); }); } catch (error) { console.error("加载边坡列表失败", error); } finally { this.loading = false; } }, // 分页大小变化 handleSizeChange(val) { this.pageParams.pageSize = val; this.pageParams.pageNo = 1; this.LoadListData(); }, // 当前页码变化 handleCurrentChange(val) { this.pageParams.pageNo = val; this.LoadListData(); }, // 获取技术状态等级选项 async getEvaluateLevel() { const levelList = await mapCfg("Inspection.Regular.RegularEvaluateLevel")(); this.evaluateLeveloptions = levelList.map((item) => ({ value: item.key, label: item.value, })); }, // 提交表单 async submitForm() { this.$refs.formRef.validate(async (valid) => { if (valid) { // 验证是否选择了边坡 if (this.allSelection.length === 0) { this.$message.warning("请至少选择一个边坡"); return; } // 构造提交参数 const params = { ...this.currentForm, sideSlopeDetailList: this.allSelection.map((item) => ({ sideSlopeUniqueCode: item.sideSlopeCode, evaluateLevel: item.evaluateLevel, evaluateDate: item.evaluateDate ? item.evaluateDate : undefined, })), }; // 根据模式选择操作 const action = this.dialogMode === "create" ? addPeriodicInspection : modifyPeriodicInspection; // 执行操作 try { const success = await action(params); if (success) { this.$message.success( this.dialogMode === "create" ? "新建成功" : "修改成功" ); this.$emit("success"); this.dialogVisible = false; } else { this.$message.error("操作失败"); } } catch (error) { this.$message.error(error.message || "操作失败"); } } }); }, // 计算表格高度(自适应) calculateTableHeight() { this.$nextTick(() => { try { const dialogBody = document.querySelector( ".fixed-height-dialog .el-dialog__body" ); if (dialogBody) { const bodyHeight = dialogBody.clientHeight; const headerHeight = document.querySelector(".formBorder")?.offsetHeight || 0; const searchHeight = document.querySelector(".formBorder2 .el-header")?.offsetHeight || 0; const footerHeight = document.querySelector(".formBorder2 .el-footer")?.offsetHeight || 0; const padding = 30; // 安全边距 this.tableHeight = bodyHeight - headerHeight - searchHeight - footerHeight - padding; } } catch (e) { console.warn("高度计算错误", e); this.tableHeight = 300; // 默认高度 } }); }, }, }; </script> <style lang="scss" scoped> :deep(.fixed-height-dialog) { .el-dialog { display: flex; flex-direction: column; max-height: 80vh !important; height: 80vh !important; .el-dialog__body { flex: 1; overflow: hidden; padding: 15px 20px; display: flex; flex-direction: column; } } } // 项目信息区域样式 .formBorder { position: relative; border: thin dotted black; padding: 10px; flex-shrink: 0; &::before { content: "项目信息"; position: absolute; top: -10px; left: 40px; background-color: #fff; padding: 0 10px; font-size: 14px; color: #606266; } } // 待检边坡区域样式 .formBorder2 { margin-top: 15px; position: relative; border: thin dotted black; padding: 10px; flex: 1; min-height: 0; display: flex; flex-direction: column; &::before { content: "待检边坡"; position: absolute; top: -10px; left: 40px; background-color: #fff; padding: 0 10px; font-size: 14px; color: #606266; } } // 弹窗底部按钮区域 .dialog-footer { padding: 10px 20px; border-top: 1px solid #ebeef5; text-align: center; } // 搜索区域样式 .searchDialog { margin-top: 5px; } // 空数据样式 :deep(.el-table__empty-block) { min-height: 200px; display: flex; justify-content: center; align-items: center; } // 分页样式 :deep(.el-pagination) { padding: 5px 0; } </style> <template> <div style=" display: flex; justify-content: center; align-items: center; height: 100%; width: 100%; background-color: #fff; "> <!-- 封装后的弹窗组件 --> <side-slope-dialog :visible="dialogVisible" :mode="currentMode" :initial-form="currentForm" @update:visible="dialogVisible = $event" @success="handleDialogSuccess" /> <!-- 页面主体内容 --> <el-container style="height: 100%"> <el-header> <el-row :gutter="10" type="flex" justify="left"> <el-col :span="3"> <el-input v-model="searchParams.projectName" placeholder="项目名称或编号" size="mini" clearable @clear="resetSearch" /> </el-col> <el-col :span="3"> <el-select v-model="searchParams.status" placeholder="项目状态" size="mini" clearable @clear="resetSearch"> <el-option v-for="item in StatusOptions" :key="item.value" :label="item.label" :value="item.value" filterable /> </el-select> </el-col> <el-col :span="6"> <el-date-picker v-model="searchProjectDate" range-separator="→" start-placeholder="请选择开始日期" end-placeholder="请选择结束日期" type="daterange" size="mini" style="width: 100%" value-format="yyyy-MM-dd" @clear="resetSearch" /> </el-col> <el-col :span="1.5"> <el-button type="primary" size="mini" @click="handleSearch">查询</el-button> </el-col> <el-col :span="1.5"> <el-button type="success" size="mini" style="width: 100%" @click="openCreateDialog">新建</el-button> </el-col> </el-row> </el-header> <el-main> <el-table :data="tableData" border style="width: 100%" :main-height="400" :header-row-style="() => { return 'line-height:15px'; }" :cell-style="{ textAlign: 'center' }" :header-cell-style="{ textAlign: 'center' }"> <el-table-column label="序号" type="index" width="120"></el-table-column> <el-table-column label="项目名称" prop="projectName" width="250"></el-table-column> <el-table-column label="项目编号" prop="projectCode" width="150"></el-table-column> <el-table-column label="项目周期" width="250"> <template slot-scope="scope"> {{ formatDateRange(scope.row.projectStartDate, scope.row.projectEndDate) }} </template> </el-table-column> <el-table-column label="项目状态" width="200"> <template slot-scope="scope"> {{ getStatusText(scope.row.status) }} </template> </el-table-column> <el-table-column label="边坡总数" prop="sideSlopeTotalCount" width="150"></el-table-column> <el-table-column label="已完成边坡数" prop="sideSlopeCompleteCount" width="194"></el-table-column> <el-table-column label="完成率" width="150"> <template slot-scope="scope"> {{ calculateCompletionRate( scope.row.sideSlopeCompleteCount, scope.row.sideSlopeTotalCount ) }} </template> </el-table-column> <el-table-column label="操作" width="200"> <template slot-scope="scope"> <el-button @click="openViewDialog(scope.row)" type="text" size="small">查看</el-button> <el-button @click="openEditDialog(scope.row)" type="text" size="small">编辑</el-button> <el-button @click="deleteItem(scope.row)" type="text" size="small">删除</el-button> </template> </el-table-column> </el-table> </el-main> <el-footer> <!-- 分页 --> <div class="pagination" style="margin-top: 20px; text-align: center"> <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" layout="total,prev, sizes, pager, next,jumper" :current-page.sync="pageParams.pageNo" :page-size="pageParams.pageSize" :page-sizes="[10, 40, 60, 100]" :total="pageParams.total"> </el-pagination> </div> </el-footer> </el-container> </div> </template> <script> import sideSlopeDialog from './sideSlopeDialog.vue' import { mapCfg } from '@/utils' import { getPeriodicInspectionPageList, deletePeriodicInspection } from '../../api/testProject' export default { name: 'ProjectManagement', components: { sideSlopeDialog }, data() { return { searchParams: { projectName: '', status: '', projectStartDate: '', projectEndDate: '' }, searchProjectDate: [], StatusOptions: [], tableData: [], pageParams: { pageNo: 1, pageSize: 10, total: 0 }, dialogVisible: false, currentMode: '', currentForm: { projectCode: '', projectName: '', projectStartDate: '', projectEndDate: '', projectUser: '', remark: '', sideSlopeDetailList: [] } } }, watch: { searchProjectDate(newVal) { if (newVal && newVal.length === 2) { this.searchParams.projectStartDate = newVal[0] this.searchParams.projectEndDate = newVal[1] } else { this.searchParams.projectStartDate = '' this.searchParams.projectEndDate = '' } } }, async created() { await this.getStatus() this.loadTableData() }, methods: { getStatusText(statusValue) { const option = this.StatusOptions.find((opt) => opt.value === statusValue) return option ? option.label : '' }, openCreateDialog() { this.currentMode = 'create' this.currentForm = { projectCode: '', projectName: '', projectStartDate: '', projectEndDate: '', projectUser: '', remark: '', sideSlopeDetailList: [] } this.dialogVisible = true }, openEditDialog(row) { this.currentMode = 'edit' this.currentForm = { ...row, projectStartDate: row.projectStartDate, projectEndDate: row.projectEndDate } this.dialogVisible = true }, openViewDialog(row) { this.currentMode = 'view' this.currentForm = { ...row, projectStartDate: row.projectStartDate, projectEndDate: row.projectEndDate } this.dialogVisible = true }, handleDialogSuccess() { this.pageParams.pageNo = 1 this.loadTableData() }, async loadTableData() { const startTime = this.searchParams.projectStartDate ? new Date(this.searchParams.projectStartDate).getTime() : null const endTime = this.searchParams.projectEndDate ? new Date(this.searchParams.projectEndDate).getTime() : null const params = { pageNo: this.pageParams.pageNo, pageSize: this.pageParams.pageSize, searchKey: this.searchParams.projectName, status: this.searchParams.status, startTime, endTime } try { const res = await getPeriodicInspectionPageList(params) this.tableData = res.entities this.pageParams.total = res.entityCount } catch (error) { console.error('加载项目列表失败', error) } }, handleSearch() { this.pageParams.pageNo = 1 this.loadTableData() }, resetSearch() { this.searchParams = { projectName: '', status: '', projectStartDate: '', projectEndDate: '' } this.searchProjectDate = [] this.handleSearch() }, async deleteItem(row) { try { await this.$confirm('确定要删除该项目吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }) await deletePeriodicInspection({ periodicId: row.id }) this.$message.success('删除成功') if (this.tableData.length === 1 && this.pageParams.pageNo > 1) { this.pageParams.pageNo -= 1 } this.loadTableData() } catch (error) { if (error !== 'cancel') { this.$message.error('删除失败') } } }, async getStatus() { const dictList = await mapCfg('Inspection.Periodic.PeriodicInspectionStatus')() this.StatusOptions = dictList.map((item) => ({ value: item.key, label: item.value })) }, formatDateRange(start, end) { if (!start || !end) return '' const format = (dateStr) => dateStr.substring(0, 10) return `${format(start)} 至 ${format(end)}` }, calculateCompletionRate(completed, total) { if (!total) return '0%' return `${((completed / total) * 100).toFixed(1)}%` }, handleSizeChange(val) { this.pageParams.pageSize = val this.loadTableData() }, handleCurrentChange(val) { this.pageParams.pageNo = val this.loadTableData() } } } </script> <style lang="scss" scoped> .el-header { color: #333; text-align: center; line-height: 60px; } .el-main { color: #333; text-align: center; line-height: 100%; padding-left: 5px; padding-top: 0px; } .pagination { margin-top: 20px; text-align: center; } </style> /** * 测试项目api */ import request from "@/utils/request"; //取得定期检查边坡列表接口 export function getPeriodicInspectionSideSlopePageList(params){ return request({ url: "periodicInspection/getPeriodicInspectionSideSlopePageList", method: "GET", params, }); } //取得定期检查分页列表接口 export function getPeriodicInspectionPageList(params){ return request({ url: "periodicInspection/getPeriodicInspectionPageList", method: "GET", params }); } //新增定期检查接口 export function addPeriodicInspection(data) { return request({ url: "periodicInspection/addPeriodicInspection", method: "POST", data, }); } //修改定期检查接口 export function modifyPeriodicInspection(data) { return request({ url: "periodicInspection/modifyPeriodicInspection ", method: "POST", data, }); } //删除定期检查接口 export function deletePeriodicInspection(params) { return request({ url: "periodicInspection/deletePeriodicInspection", method: "GET", params, }) } //取得已选择的定期检查边坡列表接口 export function getSelectedPeriodicInspectionSideSlopeList(params) { return request({ url: "periodicInspection/getSelectedPeriodicInspectionSideSlopeList", method: "GET", params }) } //已完成定期检查接口 export function completePeriodicInspection(params){ return request({ url: "periodicInspection/completePeriodicInspection", method: "GET", params, }) }为什么查看和编辑的时候报错 VM83271 testProject.js:62 GET https://10.1.2.3:8080/sshm/rest/periodicInspection/getSelectedPeriodicInspectionSideSlopeList 404 (Not Found) dispatchXhrRequest @ xhr.js:187 xhrAdapter @ xhr.js:13 dispatchRequest @ dispatchRequest.js:53 Promise.then request @ Axios.js:88 wrap @ bind.js:9 getSelectedPeriodicInspectionSideSlopeList @ VM83271 testProject.js:62 getSelectedSlopes @ VM83270 sideSlopeDialog.vue:180 visible @ VM83270 sideSlopeDialog.vue:125 invokeWithErrorHandling @ vue.runtime.esm.js:3072 Watcher.run @ vue.runtime.esm.js:3589 flushSchedulerQueue @ vue.runtime.esm.js:4180 eval @ vue.runtime.esm.js:3198 flushCallbacks @ vue.runtime.esm.js:3120 Promise.then timerFunc @ vue.runtime.esm.js:3145 nextTick @ vue.runtime.esm.js:3210 queueWatcher @ vue.runtime.esm.js:4266 Watcher.update @ vue.runtime.esm.js:3568 Dep.notify @ vue.runtime.esm.js:790 reactiveSetter @ vue.runtime.esm.js:1021 proxySetter @ vue.runtime.esm.js:5413 openViewDialog @ VM83267 _Blank.vue:95 click @ cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"67c25b62-vue-loader-template"}!./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/pages/building/_Blank.vue?vue&type=template&id=eaaff1c8&scoped=true:236 invokeWithErrorHandling @ vue.runtime.esm.js:3072 invoker @ vue.runtime.esm.js:1874 invokeWithErrorHandling @ vue.runtime.esm.js:3072 Vue.$emit @ vue.runtime.esm.js:3771 handleClick @ element-ui.common.js:9465 invokeWithErrorHandling @ vue.runtime.esm.js:3072 invoker @ vue.runtime.esm.js:1874 original_1._wrapper @ vue.runtime.esm.js:7533 VM83270 sideSlopeDialog.vue:188 获取已选择边坡失败 Error: Request failed with status code 404 at createError (createError.js:16:15) at settle (settle.js:17:12) at XMLHttpRequest.onloadend (xhr.js:54:7
08-20
<template> <div style=" display: flex; justify-content: center; align-items: center; height: 100%; width: 100%; background-color: #fff; "> <!-- 封装后的弹窗组件 --> <side-slope-dialog :visible="dialogVisible" :mode="currentMode" :initial-form="currentForm" @update:visible="dialogVisible = $event" @success="handleDialogSuccess" /> <!-- 页面主体内容 --> <el-container style="height: 100%"> <el-header> <el-row :gutter="10" type="flex" justify="left"> <el-col :span="3"> <el-input v-model="searchParams.projectName" placeholder="项目名称或编号" size="mini" clearable @clear="resetSearch" /> </el-col> <el-col :span="3"> <el-select v-model="searchParams.status" placeholder="项目状态" size="mini" clearable @clear="resetSearch"> <el-option v-for="item in StatusOptions" :key="item.value" :label="item.label" :value="item.value" filterable /> </el-select> </el-col> <el-col :span="6"> <el-date-picker v-model="searchProjectDate" range-separator="→" start-placeholder="请选择开始日期" end-placeholder="请选择结束日期" type="daterange" size="mini" style="width: 100%" value-format="yyyy-MM-dd" @clear="resetSearch" /> </el-col> <el-col :span="1.5"> <el-button type="primary" size="mini" @click="handleSearch">查询</el-button> </el-col> <el-col :span="1.5"> <el-button type="success" size="mini" style="width: 100%" @click="openCreateDialog">新建</el-button> </el-col> </el-row> </el-header> <el-main> <el-table :data="tableData" border style="width: 100%" :main-height="400" :header-row-style="() => { return 'line-height:15px'; }" :cell-style="{ textAlign: 'center' }" :header-cell-style="{ textAlign: 'center' }"> <el-table-column label="序号" type="index" width="120"></el-table-column> <el-table-column label="项目名称" prop="projectName" width="250"></el-table-column> <el-table-column label="项目编号" prop="projectCode" width="150"></el-table-column> <el-table-column label="项目周期" width="250"> <template slot-scope="scope"> {{ formatDateRange(scope.row.projectStartDate, scope.row.projectEndDate) }} </template> </el-table-column> <el-table-column label="项目状态" width="200"> <template slot-scope="scope"> {{ getStatusText(scope.row.status) }} </template> </el-table-column> <el-table-column label="边坡总数" prop="sideSlopeTotalCount" width="150"></el-table-column> <el-table-column label="已完成边坡数" prop="sideSlopeCompleteCount" width="194"></el-table-column> <el-table-column label="完成率" width="150"> <template slot-scope="scope"> {{ calculateCompletionRate( scope.row.sideSlopeCompleteCount, scope.row.sideSlopeTotalCount ) }} </template> </el-table-column> <el-table-column label="操作" width="200"> <template slot-scope="scope"> <el-button @click="openViewDialog(scope.row)" type="text" size="small">查看</el-button> <el-button @click="openEditDialog(scope.row)" type="text" size="small">编辑</el-button> <el-button @click="deleteItem(scope.row)" type="text" size="small">删除</el-button> </template> </el-table-column> </el-table> </el-main> <el-footer> <!-- 分页 --> <div class="pagination" style="margin-top: 20px; text-align: center"> <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" layout="total,prev, sizes, pager, next,jumper" :current-page.sync="pageParams.pageNo" :page-size="pageParams.pageSize" :page-sizes="[10, 40, 60, 100]" :total="pageParams.total"> </el-pagination> </div> </el-footer> </el-container> </div> </template> <script> import sideSlopeDialog from './sideSlopeDialog.vue' import { mapCfg } from '@/utils' import { getPeriodicInspectionPageList, deletePeriodicInspection } from '../../api/testProject' export default { name: 'ProjectManagement', components: { sideSlopeDialog }, data() { return { searchParams: { projectName: '', status: '', projectStartDate: '', projectEndDate: '' }, searchProjectDate: [], StatusOptions: [], tableData: [], pageParams: { pageNo: 1, pageSize: 10, total: 0 }, dialogVisible: false, currentMode: '', currentForm: { projectCode: '', projectName: '', projectStartDate: '', projectEndDate: '', projectUser: '', remark: '', sideSlopeDetailList: [] } } }, watch: { searchProjectDate(newVal) { if (newVal && newVal.length === 2) { this.searchParams.projectStartDate = newVal[0] this.searchParams.projectEndDate = newVal[1] } else { this.searchParams.projectStartDate = '' this.searchParams.projectEndDate = '' } } }, async created() { await this.getStatus() this.loadTableData() }, methods: { getStatusText(statusValue) { const option = this.StatusOptions.find((opt) => opt.value === statusValue) return option ? option.label : '' }, openCreateDialog() { this.currentMode = 'create' this.currentForm = { projectCode: '', projectName: '', projectStartDate: '', projectEndDate: '', projectUser: '', remark: '', sideSlopeDetailList: [] } this.dialogVisible = true }, openEditDialog(row) { this.currentMode = 'edit' this.currentForm = { ...row, projectStartDate: row.projectStartDate, projectEndDate: row.projectEndDate } this.dialogVisible = true }, openViewDialog(row) { this.currentMode = 'view' this.currentForm = { ...row, projectStartDate: row.projectStartDate, projectEndDate: row.projectEndDate } this.dialogVisible = true }, handleDialogSuccess() { this.pageParams.pageNo = 1 this.loadTableData() }, async loadTableData() { const startTime = this.searchParams.projectStartDate ? new Date(this.searchParams.projectStartDate).getTime() : null const endTime = this.searchParams.projectEndDate ? new Date(this.searchParams.projectEndDate).getTime() : null const params = { pageNo: this.pageParams.pageNo, pageSize: this.pageParams.pageSize, searchKey: this.searchParams.projectName, status: this.searchParams.status, startTime, endTime } try { const res = await getPeriodicInspectionPageList(params) this.tableData = res.entities this.pageParams.total = res.entityCount } catch (error) { console.error('加载项目列表失败', error) } }, handleSearch() { this.pageParams.pageNo = 1 this.loadTableData() }, resetSearch() { this.searchParams = { projectName: '', status: '', projectStartDate: '', projectEndDate: '' } this.searchProjectDate = [] this.handleSearch() }, async deleteItem(row) { try { await this.$confirm('确定要删除该项目吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }) await deletePeriodicInspection({ periodicId: row.id }) this.$message.success('删除成功') if (this.tableData.length === 1 && this.pageParams.pageNo > 1) { this.pageParams.pageNo -= 1 } this.loadTableData() } catch (error) { if (error !== 'cancel') { this.$message.error('删除失败') } } }, async getStatus() { const dictList = await mapCfg('Inspection.Periodic.PeriodicInspectionStatus')() this.StatusOptions = dictList.map((item) => ({ value: item.key, label: item.value })) }, formatDateRange(start, end) { if (!start || !end) return '' const format = (dateStr) => dateStr.substring(0, 10) return `${format(start)} 至 ${format(end)}` }, calculateCompletionRate(completed, total) { if (!total) return '0%' return `${((completed / total) * 100).toFixed(1)}%` }, handleSizeChange(val) { this.pageParams.pageSize = val this.loadTableData() }, handleCurrentChange(val) { this.pageParams.pageNo = val this.loadTableData() } } } </script> <style lang="scss" scoped> .el-header { color: #333; text-align: center; line-height: 60px; } .el-main { color: #333; text-align: center; line-height: 100%; padding-left: 5px; padding-top: 0px; } .pagination { margin-top: 20px; text-align: center; } </style> <template> <el-dialog :title="dialogMode === 'create' ? '新建' : dialogMode === 'edit' ? '修改' : '查看'" :visible.sync="dialogVisible" :modal-append-to-body="true" append-to-body :close-on-click-modal="false" custom-class="fixed-height-dialog" width="60%" top="5vh"> <el-form label-width="80px" ref="formRef" :model="currentForm" style="height: 100%; display: flex; flex-direction: column;" :rules="rules"> <!-- 项目信息区域 --> <div class="formBorder"> <el-row :gutter="10"> <el-col :span="6"> <el-form-item size="mini" label="项目名称" prop="projectName"> <el-input v-model="currentForm.projectName" clearable style="width:100%" size="mini" :disabled="dialogMode === 'view'"></el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item size="mini" label="项目编号" prop="projectCode"> <el-input v-model="currentForm.projectCode" clearable style="width:100%" size="mini" :disabled="dialogMode === 'view'"></el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item size="mini" label="项目周期" prop="projectDate"> <el-date-picker v-model="projectDate" range-separator="→" start-placeholder="请选择开始日期" end-placeholder="请选择结束日期" type="daterange" size="mini" style="width: 100%;" unlink-panels :disabled="dialogMode === 'view'"> </el-date-picker> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="6"> <el-form-item label="负责人" size="mini" style="width: fit-content;"> <el-input v-model="currentForm.projectUser" clearable style="width:100%" size="mini" :disabled="dialogMode === 'view'"></el-input> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="项目概述"> <el-input v-model="currentForm.remark" :rows="2" :disabled="dialogMode === 'view'"></el-input> </el-form-item> </el-col> </el-row> </div> <!-- 待检边坡区域 --> <div class="formBorder2" style="flex: 1; min-height: 0; display: flex; flex-direction: column;"> <el-container style="height: 100%; display: flex; flex-direction: column;"> <!-- 搜索区域 --> <el-header style="height: auto; flex-shrink: 0; padding-bottom: 10px;"> <el-row :gutter="10" type="flex" class="searchDialog"> <el-col :span="5"> <el-select v-model="filterForm.maintenanceCompanyName" placeholder="请选择管养单位" size="mini" clearable filterable @clear="resetSearch" :disabled="dialogMode === 'view'"> <el-option v-for="item in MaintenanceUnitoptions" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </el-col> <el-col :span="5"> <el-select v-model="filterForm.routeCode" placeholder="请选择路线编号" size="mini" clearable filterable @clear="resetSearch" :disabled="dialogMode === 'view'"> <el-option v-for="item in routeCodeOptions" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </el-col> <el-col :span="5"> <el-input v-model="filterForm.searchKey" placeholder="请输入边坡编号或名称" size="mini" clearable @keyup.enter.native="searchForm" @clear="resetSearch" :disabled="dialogMode === 'view'"> <i slot="suffix" class="el-input__icon el-icon-search"></i> </el-input> </el-col> <el-col :span="5"> <el-select v-model="filterForm.evaluateLevel" placeholder="请选择技术状态等级" size="mini" clearable @clear="resetSearch" :disabled="dialogMode === 'view'"> <el-option v-for="item in evaluateLeveloptions" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-col> <el-col :span="2" :offset="4"> <el-button type="primary" size="mini" style="width:100%" icon="el-icon-search" @click="searchForm" :loading="loading" :disabled="dialogMode === 'view'">搜索</el-button> </el-col> </el-row> </el-header> <!-- 边坡表格 --> <el-main style="flex: 1; overflow-y: auto; padding: 0;"> <el-table ref="scrollTable" v-loading="loading" style="width: 100%;" border :data="formTabledata" :height="tableHeight" :header-row-style="{ height: '40px' }" :header-cell-style="{ padding: '0', height: '40px', lineHeight: '40px', textAlign: 'center', }" :cell-style="{ textAlign: 'center' }" @selection-change="handleSelectionChange"> <!-- 选择列(查看模式禁用) --> <el-table-column type="selection" width="55" :selectable="isRowSelectable"> </el-table-column> <!-- 其他数据列 --> <el-table-column label="管养单位" prop="maintenanceCompanyName" width="290" show-overflow-tooltip></el-table-column> <el-table-column label="路线编号" prop="routeCode" width="100"></el-table-column> <el-table-column label="边坡编号" prop="sideSlopeCode" width="240" show-overflow-tooltip></el-table-column> <el-table-column label="边坡名称" prop="sideSlopeName" width="267" show-overflow-tooltip></el-table-column> <el-table-column label="技术状态等级" width="137"> <template slot-scope="scope"> {{ mapEvaluateLevel(scope.row.evaluateLevel) }} </template> </el-table-column> </el-table> </el-main> <!-- 分页区域 --> <el-footer style="flex-shrink: 0; padding-top: 10px;"> <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="pageParams.pageNo" :page-sizes="[10, 20, 50, 100]" :page-size="pageParams.pageSize" layout="total, sizes, prev, pager, next" :total="total" > </el-pagination> </el-footer> </el-container> </div> </el-form> <!-- 弹窗底部按钮 --> <div slot="footer" class="dialog-footer" v-if="dialogMode === 'create' || dialogMode === 'edit'"> <el-button @click="dialogVisible = false">取消</el-button> <el-button type="primary" @click="submitForm">提交</el-button> </div> </el-dialog> </template> <script> import { mapCfg } from "@/utils"; import { getPeriodicInspectionSideSlopePageList, addPeriodicInspection, modifyPeriodicInspection, getSelectedPeriodicInspectionSideSlopeList } from "../../api/testProject"; import { getMaintenanceCompanyList, getRouteList } from "../../api/basicInformation"; export default { name: "SideSlopeDialog", props: { visible: Boolean, // 控制弹窗显示 mode: String, // 模式:create/edit/view initialForm: Object, // 初始表单数据 }, data() { return { mulitipleSelection: [], dialogVisible: this.visible, // 弹窗显示状态 dialogMode: this.mode, // 当前模式 currentForm: { ...this.initialForm }, // 当前表单数据 projectDate: [], // 项目日期范围 total: 0, // 总数据量 loading: false, // 加载状态 pageParams: { // 分页参数 pageNo: 1, pageSize: 10, }, filterForm: { // 搜索条件 maintenanceCompanyName: "", routeCode: "", searchKey: "", evaluateLevel: "", }, allSelection: [], // 存储所有选择的边坡 MaintenanceUnitoptions: [], // 管养单位选项 routeCodeOptions: [], // 路线编号选项 formTabledata: [], // 表格数据 evaluateLeveloptions: [], // 技术状态等级选项 tableHeight: 200, // 表格高度 rules: { // 表单验证规则 projectName: [ { required: true, message: "项目名称不能为空", trigger: "blur" }, ], projectCode: [ { required: true, message: "项目编码不能为空", trigger: "blur" }, ], }, selectedSideSlopes: [] // 存储已选择的边坡列表 }; }, watch: { // 监听模式变化 mode(val) { this.dialogMode = val; if (val === "edit" && this.dialogVisible) { this.resetSearch(); } }, // 监听弹窗显示状态变化 visible(val) { this.dialogVisible = val; if (val) { this.resetSearch(); // 编辑/查看模式时获取已选择边坡 if (this.dialogMode !== 'create' && this.currentForm.id) { this.getSelectedSlopes(); } this.$nextTick(() => { this.calculateTableHeight(); }); } else { // 关闭弹窗时重置选择状态 this.resetSelection(); } }, // 同步弹窗显示状态到父组件 dialogVisible(val) { this.$emit("update:visible", val); }, // 监听初始表单数据变化 initialForm: { deep: true, handler(val) { this.currentForm = { ...val }; this.projectDate = val.projectStartDate && val.projectEndDate ? [val.projectStartDate, val.projectEndDate] : []; } }, // 处理日期范围变化 projectDate: { deep: true, handler(value) { if (value && value.length === 2) { this.currentForm.projectStartDate = value[0]; this.currentForm.projectEndDate = value[1]; } }, }, }, async created() { // 初始化数据 this.getRouteList(); await this.getEvaluateLevel(); this.getMaintenanceCompanyList(); this.LoadListData(); }, mounted() { // 计算表格高度并监听窗口变化 this.calculateTableHeight(); window.addEventListener("resize", this.calculateTableHeight); }, beforeDestroy() { // 移除事件监听 window.removeEventListener("resize", this.calculateTableHeight); }, methods: { // 获取已选择的边坡 async getSelectedSlopes() { try { const res = await getSelectedPeriodicInspectionSideSlopeList({ periodicId: this.currentForm.id }); this.selectedSideSlopes = res; this.$nextTick(() => { this.setSelectedRows(); this.getCompletePeriodicInspection() }); } catch (error) { console.error('获取已选择边坡失败', error); } }, //设置选中 setSelectedRows() { if ( this.dialogMode === 'create') return; if (this.selectedSideSlopes.length > 0) { this.formTabledata.forEach(row => { this.selectedSideSlopes.forEach(item => { if (row.sideSlopeCode === item.sideSlopeUniqueCode) { this.$refs.scrollTable.toggleRowSelection(row, true); } }); }); } }, // 判断行是否可选(查看模式禁用选择) isRowSelectable(row, index) { return this.dialogMode !== "view"; }, // 获取管养单位列表 async getMaintenanceCompanyList() { const res = await getMaintenanceCompanyList(); this.MaintenanceUnitoptions = res.map((item) => ({ value: item, label: item, })); }, // 获取路线列表 async getRouteList() { const res = await getRouteList(); this.routeCodeOptions = res.map((item) => ({ value: item.id, label: item.routeCode, })); }, // 搜索方法 searchForm() { this.pageParams.pageNo = 1; this.LoadListData(); }, // 重置搜索条件 resetSearch() { this.filterForm = { maintenanceCompanyName: "", routeCode: "", searchKey: "", evaluateLevel: "", }; this.pageParams.pageNo = 1; this.LoadListData(); }, // 重置选择状态 resetSelection() { this.allSelection = []; this.selectedSideSlopes = []; if (this.$refs.scrollTable) { this.$refs.scrollTable.clearSelection(); } }, // 处理选择变化 handleSelectionChange(val) { // 查看模式不允许修改选择 if (this.dialogMode === 'view') return; this.mulitipleSelection = val; // 创建当前页选择的唯一标识集合 const currentPageSelections = new Set( val.map((item) => item.sideSlopeCode) ); // 更新全量选择:先移除当前页的数据,再添加新选择 this.allSelection = [ ...this.allSelection.filter( (item) => !currentPageSelections.has(item.sideSlopeCode) ), ...val, ]; }, // 映射技术状态等级 mapEvaluateLevel(level) { const option = this.evaluateLeveloptions.find( (item) => item.value === level ); return option ? option.label : ''; }, // 加载表格数据 async LoadListData() { this.loading = true; const params = { orgId: this.filterForm.maintenanceCompanyName, routeId: this.filterForm.routeCode, searchKey: this.filterForm.searchKey, evaluateLevel: this.filterForm.evaluateLevel, pageSize: this.pageParams.pageSize, pageNo: this.pageParams.pageNo, }; try { const res = await getPeriodicInspectionSideSlopePageList(params); this.formTabledata = res.entities; this.total = res.entityCount; // 加载数据后设置选中状态 this.$nextTick(() => { this.setSelectedRows(); }); } catch (error) { console.error("加载边坡列表失败", error); } finally { this.loading = false; } }, // 分页大小变化 handleSizeChange(val) { this.pageParams.pageSize = val; this.pageParams.pageNo = 1; this.LoadListData(); }, // 当前页码变化 handleCurrentChange(val) { this.pageParams.pageNo = val; this.LoadListData(); }, // 获取技术状态等级选项 async getEvaluateLevel() { const levelList = await mapCfg("Inspection.Regular.RegularEvaluateLevel")(); this.evaluateLeveloptions = levelList.map((item) => ({ value: item.key, label: item.value, })); }, // 提交表单 async submitForm() { this.$refs.formRef.validate(async (valid) => { if (valid) { // 验证是否选择了边坡 if (this.allSelection.length === 0) { this.$message.warning("请至少选择一个边坡"); return; } // 构造提交参数 const params = { ...this.currentForm, sideSlopeDetailList: this.allSelection.map((item) => ({ sideSlopeUniqueCode: item.sideSlopeCode, evaluateLevel: item.evaluateLevel, evaluateDate: item.evaluateDate ? item.evaluateDate : undefined, })), }; // 根据模式选择操作 const action = this.dialogMode === "create" ? addPeriodicInspection : modifyPeriodicInspection; // 执行操作 try { const success = await action(params); if (success) { this.$message.success( this.dialogMode === "create" ? "新建成功" : "修改成功" ); this.$emit("success"); this.dialogVisible = false; } else { this.$message.error("操作失败"); } } catch (error) { this.$message.error(error.message || "操作失败"); } } }); }, // 计算表格高度(自适应) calculateTableHeight() { this.$nextTick(() => { try { const dialogBody = document.querySelector( ".fixed-height-dialog .el-dialog__body" ); if (dialogBody) { const bodyHeight = dialogBody.clientHeight; const headerHeight = document.querySelector(".formBorder")?.offsetHeight || 0; const searchHeight = document.querySelector(".formBorder2 .el-header")?.offsetHeight || 0; const footerHeight = document.querySelector(".formBorder2 .el-footer")?.offsetHeight || 0; const padding = 30; // 安全边距 this.tableHeight = bodyHeight - headerHeight - searchHeight - footerHeight - padding; } } catch (e) { console.warn("高度计算错误", e); this.tableHeight = 300; // 默认高度 } }); }, }, }; </script> <style lang="scss" scoped> :deep(.fixed-height-dialog) { .el-dialog { display: flex; flex-direction: column; max-height: 80vh !important; height: 80vh !important; .el-dialog__body { flex: 1; overflow: hidden; padding: 15px 20px; display: flex; flex-direction: column; } } } // 项目信息区域样式 .formBorder { position: relative; border: thin dotted black; padding: 10px; flex-shrink: 0; &::before { content: "项目信息"; position: absolute; top: -10px; left: 40px; background-color: #fff; padding: 0 10px; font-size: 14px; color: #606266; } } // 待检边坡区域样式 .formBorder2 { margin-top: 15px; position: relative; border: thin dotted black; padding: 10px; flex: 1; min-height: 0; display: flex; flex-direction: column; &::before { content: "待检边坡"; position: absolute; top: -10px; left: 40px; background-color: #fff; padding: 0 10px; font-size: 14px; color: #606266; } } // 弹窗底部按钮区域 .dialog-footer { padding: 10px 20px; border-top: 1px solid #ebeef5; text-align: center; } // 搜索区域样式 .searchDialog { margin-top: 5px; } // 空数据样式 :deep(.el-table__empty-block) { min-height: 200px; display: flex; justify-content: center; align-items: center; } // 分页样式 :deep(.el-pagination) { padding: 5px 0; } </style> /** * 测试项目api */ import request from "@/utils/request"; //取得定期检查边坡列表接口 export function getPeriodicInspectionSideSlopePageList(params){ return request({ url: "periodicInspection/getPeriodicInspectionSideSlopePageList", method: "GET", params, }); } //取得定期检查分页列表接口 export function getPeriodicInspectionPageList(params){ return request({ url: "periodicInspection/getPeriodicInspectionPageList", method: "GET", params }); } //新增定期检查接口 export function addPeriodicInspection(data) { return request({ url: "periodicInspection/addPeriodicInspection", method: "POST", data, }); } //修改定期检查接口 export function modifyPeriodicInspection(data) { return request({ url: "periodicInspection/modifyPeriodicInspection ", method: "POST", data, }); } //删除定期检查接口 export function deletePeriodicInspection(params) { return request({ url: "periodicInspection/deletePeriodicInspection", method: "GET", params, }) } //取得已选择的定期检查边坡列表接口 export function getSelectedPeriodicInspectionSideSlopeList(params) { return request({ url: "periodicInspection/getSelectedPeriodicInspectionSideSlopeList", method: "GET", params }) } //已完成定期检查接口 export function completePeriodicInspection(params){ return request({ url: "periodicInspection/completePeriodicInspection", method: "GET", params, }) } 为什么打开查看和编辑dialog报错testProject.js:53 GET https://10.1.2.3:8080/sshm/rest/periodicInspection/getSelectedPeriodicInspectionSideSlopeList?periodicId=1957683347311169536 404 (Not Found) dispatchXhrRequest @ xhr.js:187 xhrAdapter @ xhr.js:13 dispatchRequest @ dispatchRequest.js:53 Promise.then request @ Axios.js:88 wrap @ bind.js:9 getSelectedPeriodicInspectionSideSlopeList @ testProject.js:53 getSelectedSlopes @ VM91943 sideSlopeDialog.vue:186 visible @ VM91943 sideSlopeDialog.vue:125 invokeWithErrorHandling @ vue.runtime.esm.js:3072 Watcher.run @ vue.runtime.esm.js:3589 flushSchedulerQueue @ vue.runtime.esm.js:4180 eval @ vue.runtime.esm.js:3198 flushCallbacks @ vue.runtime.esm.js:3120 Promise.then timerFunc @ vue.runtime.esm.js:3145 nextTick @ vue.runtime.esm.js:3210 queueWatcher @ vue.runtime.esm.js:4266 Watcher.update @ vue.runtime.esm.js:3568 Dep.notify @ vue.runtime.esm.js:790 reactiveSetter @ vue.runtime.esm.js:1021 proxySetter @ vue.runtime.esm.js:5413 openViewDialog @ cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/pages/building/_Blank.vue?vue&type=script&lang=js:94 click @ cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"67c25b62-vue-loader-template"}!./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/pages/building/_Blank.vue?vue&type=template&id=eaaff1c8&scoped=true:236 invokeWithErrorHandling @ vue.runtime.esm.js:3072 invoker @ vue.runtime.esm.js:1874 invokeWithErrorHandling @ vue.runtime.esm.js:3072 Vue.$emit @ vue.runtime.esm.js:3771 handleClick @ element-ui.common.js:9465 invokeWithErrorHandling @ vue.runtime.esm.js:3072 invoker @ vue.runtime.esm.js:1874 original_1._wrapper @ vue.runtime.esm.js:7533 VM91943 sideSlopeDialog.vue:195 获取已选择边坡失败 Error: Request failed with status code 404 at createError (createError.js:16:15) at settle (settle.js:17:12) at XMLHttpRequest.onloadend (xhr.js:54:7)需要根据sideSlopeUniqueCode来匹配表格行
08-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值