2008-2024.11全国采购经理人指数PMI月度数据

PMI,全称为采购经理指数(Purchasing Managers’ Index),是通过对采购经理的月度调查汇总出来的指数,能够反映经济的变化趋势。

随着全球经济形势的不断变化,中国PMI指数也将继续受到关注,并为政策制定者、投资者以及社会各界提供重要的经济参考信息。同时,也需要关注PMI分项指数的变化情况,以更全面地了解经济的运行状况和行业发展趋势。

数据名称:全国采购经理人指数(PMI)

数据年份:2008-2024.11

指标:日期、采购经理人指数(制造业)、制造业-同比增长、采购经理人指数(非制造业)、非制造业-同比增长。

数据截图

【下载→

方式一(推荐):主页*个人*简介
经管数据库-优快云博客

方式二:数据下载地址汇总-优快云博客

<template> <div class="sec-container"> <van-popup v-model:show="showDetailModal" :style="{ width: '100%', height: '100%', overflow: 'auto' }" position="right" round closeable @close="handleDetailClose" > <van-form ref="addCommentsFormRef" @submit="handleSave"> <!-- 检验单信息 --> <van-cell-group title="检验单信息" v-if="showType === 'qcOrder'"> <!-- <van-field--> <!-- v-model="saveData.applyDate"--> <!-- is-link--> <!-- readonly--> <!-- clearable--> <!-- @click="handleDate"--> <!-- placeholder="请选择提出时间"--> <!-- />--> <van-field v-model="saveData.applyDate" is-link readonly label="提出时间" placeholder="点击选择日期" @click="showPicker = true" /> <van-popup v-model:show="showDatePicker" round position="bottom"> <van-date-picker v-model="saveData.applyDate" @confirm="onConfirm" @cancel="showDatePicker = false" /> </van-popup> </van-cell-group> <!-- 编辑/新增时的表单 --> <van-cell-group title="检验单信息" v-if="showType === 'show' || showType === 'result'"> <van-field name="radio" label="检验状态" v-if="showType === 'result'"> <template #input> <van-radio-group v-model="saveData.status" direction="horizontal"> <van-radio name="0">新建</van-radio> <van-radio name="1">检验中</van-radio> <van-radio name="2">合格</van-radio> <van-radio name="-1">不合格</van-radio> </van-radio-group> </template> </van-field> <van-field name="projectNo" label="项目"> <template #input> {{saveData.projectNo}} </template> </van-field> <van-field name="inspClass" label="检验大类" :rules="[{ required: true, message: '请填写检验大类!' }]"> <template #input> {{saveData.inspClassStr}} </template> </van-field> <van-field name="inspType" label="检验类型" :rules="[{ required: true, message: '请填写检验类型!' }]"> <template #input> {{saveData.inspTypeName}} </template> </van-field> <van-field name="orgNo" label="基地" :rules="[{ required: true, message: '请选择基地!' }]"> <template #input> {{saveData.orgName}} </template> </van-field> <van-field name="workzone" label="作业区" :rules="[{ required: true, message: '请填写作业区!' }]"> <template #input> {{saveData.workzoneName}} </template> </van-field> <van-field name="inspLoc" label="检验地点" :rules="[{ required: true, message: '请填写检验地点!' }]"> <template #input> {{saveData.inspLoc}} </template> </van-field> <van-field name="mainUserNo" label="负责人" :rules="[{ required: true, message: '请填写负责人!' }]"> <template #input> {{saveData.mainUserName}} </template> </van-field> <van-field name="tel" label="联系方式"> <template #input> {{saveData.tel}} </template> </van-field> </van-cell-group> <!-- 管路信息 --> <van-cell-group title="管路信息"> <!-- 简化显示 --> <div class="search-btn" v-if="showType === 'result'"> <van-button type="primary" @click="changeStatus(1,'pipe')" style="margin-right:10px">合格</van-button> <van-button type="primary" @click="changeStatus(-1,'pipe')" style="margin-right:10px">不合格 </van-button> <van-button type="primary" @click="changeStatus(2,'pipe')" style="margin-right:10px">取消 </van-button> </div> <a-table sticky v-if="showType == 'show'" :scroll="{ x: '100%' }" :columns="pipeTable.columns" :dataSource="pipeTable.dataSource" bordered size="middle" :loading="loading" :pagination="false" rowKey="id" ref="pipeTableRef" > </a-table> <a-table sticky v-if="showType == 'result'" :scroll="{ x: '100%' }" :columns="pipeTable.resColumns" :dataSource="pipeTable.dataSource" bordered size="middle" :loading="loading" :pagination="false" rowKey="id" ref="pipeTableRef" :row-selection="{ selectedRowKeys: pipeTable.selectedRowKeys, onChange: onSelectChange }" > </a-table> </van-cell-group> <!-- 焊缝信息 --> <van-cell-group title="焊缝信息"> <div class="search-btn" v-if="showType === 'result'"> <van-button type="primary" @click="changeStatus(1,'weld')" style="margin-right:10px">合格</van-button> <van-button type="primary" @click="changeStatus(-1,'weld')" style="margin-right:10px">不合格 </van-button> <van-button type="primary" @click="changeStatus(2,'weld')" style="margin-right:10px">取消 </van-button> </div> <a-table sticky v-if="showType == 'show'" :scroll="{ x: '100%' }" :columns="weldTable.columns" :dataSource="weldTable.dataSource" bordered size="middle" :loading="loading" :pagination="false" rowKey="id" ref="weldTableRef" > </a-table> <a-table sticky v-if="showType == 'result'" :scroll="{ x: '100%' }" :columns="weldTable.resColumns" :dataSource="weldTable.dataSource" bordered size="middle" :loading="loading" :pagination="false" rowKey="id" ref="weldTableRef" :row-selection="{ selectedRowKeys: weldTable.selectedRowKeys, onChange: onWeldSelectChange }" > </a-table> </van-cell-group> <!-- 提交按钮 --> <div style="margin: 16px;"> <van-button round block type="default" @click="handleDetailClose">取消</van-button> <van-button round block type="primary" native-type="submit" v-if="showType === 'edit' || showType === 'add' || showType === 'result'">提交</van-button> </div> </van-form> </van-popup> <div class="top-content"> <div class="project-content"> <div class=""></div> </div> <div class="btn-content"> <div class="btn-right" @click="openSearchDialog"> <SearchOutlined style="font-size: 20px; color: #004688" /> <p class="speNorm">搜索</p> </div> </div> </div> <div class="bot-content" @scroll="handleScroll"> <a-table sticky :scroll="{ x: '100%' }" :columns="columns" :dataSource="data" bordered size="middle" :loading="loading" :pagination="false" rowKey="id" > <template #bodyCell="{ column, record }"> <template v-if="column.key === 'action'"> <a-button type="link" @click="showData(record,'show')" v-resource="[{ url: '/service-piping/cp/insp/order', method: 'POST' }]">查看</a-button> <a-button type="link" @click="showData(record,'result')" v-resource="[{ url: '/service-piping/cp/insp/order', method: 'POST' }]">结果维护</a-button> <a-button type="link" @click="showLog(record)" v-resource="[{ url: '/service-piping/cp/insp/order', method: 'POST' }]">查看日志</a-button> <a-button type="link" @click="handleApplyOrder(record)" v-if="record.applyFlag!='Y'" >申请检验</a-button> </template> </template> </a-table> </div> <van-popup v-model:show="searchOpen" position="right" :style="{ width: popupWidth, height: '100%', overflow: 'hidden' }" round closeable @close="handleDetailClose" > <div class="search-content"> <div class="search-top"> <div class="search-project-back" v-if="projectType" @click="handleBack"> <LeftOutlined style="font-size: 15px; color: #004688; margin-top: 3px" />返回 </div> <div class="search-titles"> <span>{{ !projectType ? '搜索' : '搜索项目' }}</span> </div> </div> <div class="search-state"> <van-cell-group inset> <van-field v-model="searchState.projectNo" clearable label="项目" readonly placeholder="单击选择项目" @click="handleProject" /> <van-field v-model="searchState.orderNo" clearable label="检验单号" placeholder="请输入检验单号" /> <van-field v-model="searchState.inspClass" clearable @click="handleInspClass" label="检验大类" placeholder="请选择检验大类" is-link readonly /> </van-cell-group> <van-popup v-model:show="showPicker" round position="bottom"> <van-picker :columns="inspColumns" @cancel="showPicker = false" @confirm="onInspClassConfirm" /> </van-popup> <project-panel ref="projectpanelRef" @get="getProj"></project-panel> </div> <div class="search-btn"> <van-button type="warning" color="#9A9A9A" @click="onReset">重置</van-button> <van-button type="primary" @click="onSearch">查询 </van-button> </div> </div> </van-popup> </div> </template> <script setup> import { ref, onMounted, onUnmounted, onActivated, computed, watch, createVNode, reactive } from 'vue' import { SearchOutlined, LeftOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue' import * as serve from '@/api/cp/pipeInspection' import ProjectPanel from '@/components/ProjectPanel.vue' import dayjs from 'dayjs' import { Buffer } from 'buffer' import { useRouter } from 'vue-router' import localforage from 'localforage' import { useHomePage } from '@/stores/homePage' import { Modal } from 'ant-design-vue' import {getBuildBases} from "@/api/common/index.js"; import {showNotify} from "vant"; const showDatePicker = ref(false); const onSelectChange = (keys, rows) => { pipeTable.selectedRowKeys = keys pipeTable.selectedRows = rows } const onWeldSelectChange = (keys, rows) => { weldTable.selectedRowKeys = keys weldTable.selectedRows = rows } const workZoneNos = ref([]) const statusOptions = [ { value: -1, text: "不合格" }, { value: 0, text: "新建" }, { value: 1, text: "合格" }, { value: 2, text: "取消" } ] // const inspClassOptions = [ // { text: '焊前检验', value: 'HQ' }, // { text: '焊后检验', value: 'HH' }, // { text: '压力检验', value: 'PT' }, // { text: '完工检验', value: 'HP' }, // { text: '其他检验', value: 'JY' }, // ] const currProjectNo =ref(null) const selectInsp = ref([]) const weldTable = reactive({ toolbar: { // buttons: [{ code: "addCar", name: "添加物料" }] }, resToolbar: { buttons: [{ code: "qualifiedWeld", name: "合格" },{ code: "unqualifiedWeld", name: "不合格" },{ code: "cancelWeld", name: "取消" }] }, selectedRowKeys: [], selectedRows: [], columns: [ { title: "管号", dataIndex: "pipeNo", width: 120, }, { title: "焊缝号", dataIndex: "weldNo", width: 150, }, { title: "焊缝长度", dataIndex: "length", width: 150, }, { title: "焊接日期", type: "date", dataIndex: "weldDate", width: 150, }, // { // title: "操作", // key: "action", // align: "center", // width: 90, // sorter: false, // scopedSlots: { customRender: "action" }, // fixed: "right", // formInvisible: true // } ], resColumns: [ { title: "项目", dataIndex: "projectNo", width: 90, type: "project", }, { title: "管号", dataIndex: "pipeNo", width: 120, }, { title: "版本号", dataIndex: "pipeVersion", width: 120, }, { title: "焊缝号", dataIndex: "weldNo", width: 150, }, { title: "检验结果", dataIndex: "status", type: "select", width: 80, customRender: function (text) { if (text.record.status) { return stateColumns.value.find( (item) => item.value == text.record.status ).text } else { return '新建' } } }, { title: "小票删除", dataIndex: "pipeDelFlag", width: 80, }, { title: "小票暂停", dataIndex: "pipePauseFlag", width: 80, }, { title: "小票最新版", dataIndex: "pipeTopFlag", width: 80, }, { title: "焊缝删除", dataIndex: "delFlag", width: 80, }, { title: "操作", key: "action", align: "center", width: 200, sorter: false, scopedSlots: { customRender: "action" }, fixed: "right", formInvisible: true } ], dataSource: [] }) const showType = ref('') window.Buffer = Buffer const router = useRouter() const homePage = useHomePage() const saveData = ref({}) const stateColumns = ref( [{ value: 0, text: "新建" }, { value: -1, text: "不合格" }, { value: 1, text: "检验中" }, { value: 2, text: "合格" },] ) const showDetailModal = ref(false) const inspColumns = ref([ { value: 'HQ', text: "焊前检验" }, { value: 'HH', text: "焊后检验" }, { value: 'PT', text: "压力检验" }, { value: 'HP', text: "完工检验" }, { value: 'JY', text: "其他检验" }, ]) const showPicker = ref(false) const buildBaseList = ref([]) const data = ref([]) const loading = ref(false) const dataCount = ref(0) const searchState = ref({ size: 20, page: 0, projectNo: undefined, inspClass: undefined, orderNo: undefined, }) const searchOpen = ref(false) const projectpanelRef = ref(null) const projectType = ref(false) const popupWidth = ref('30%') const isLast = ref(false) const statusList = ref([ { text: '新建', value: 0 }, { text: '进行中', value: 1 }, { text: '已完成', value: 2 } ]) const pipeTable = reactive({ toolbar: { buttons: [{ code: "addPipe", name: "添加物料" }] }, resToolbar: { buttons: [{ code: "qualifiedPipe", name: "合格" },{ code: "unqualifiedPipe", name: "不合格" },{ code: "cancelPipe", name: "取消" }] }, selectedRowKeys: [], selectedRows: [], columns: [ { title: "图号", dataIndex: "drawNo", width: 120, }, { title: "作业对象", dataIndex: "block", width: 150, }, { title: "托盘号", dataIndex: "instPalletNo", width: 150, }, { title: "管号", dataIndex: "pipeNo", width: 120, }, { title: "页号", dataIndex: "pageNo", width: 80, }, { title: "暂停", dataIndex: "isPause", width: 80, }, { title: "删除", dataIndex: "isDelete", width: 80, }, { title: "最新版", dataIndex: "isTopVersion", width: 80, }, { title: "装配承包商", dataIndex: "assyCoopName", width: 150, }, { title: "焊接承包商", dataIndex: "weldingCoopName", width: 150, }, { title: "焊前检验单", dataIndex: "weldingPreOrderNo", width: 150, }, { title: "焊后检验单", dataIndex: "weldingPostOrderNo", width: 150, }, { title: "压力检验单", dataIndex: "ptOrderNo", width: 150, }, { title: "完工/预制放行检验单", dataIndex: "preFinishOrderNo", width: 150, }, { title: "PMI检验单", dataIndex: "pmiOrderNo", width: 150, }, { title: "焊后热处理检验单", dataIndex: "pwhtOrderNo", width: 150, }, { title: "硬度检验单", dataIndex: "hardnessOrderNo", width: 150, }, { title: "铁素体检验单", dataIndex: "ferriteOrderNo", width: 150, }, // { // title: "操作", // key: "action", // align: "center", // sorter: false, // scopedSlots: { customRender: "action" }, // fixed: "right", // formInvisible: true // } ], resColumns: [ { title: "项目", dataIndex: "projectNo", width: 90, type: "project", }, { title: "管号", dataIndex: "pipeNo", width: 120, }, { title: "版本号", dataIndex: "pipeVersion", width: 80, }, { title: "删除", dataIndex: "isDelete", width: 80, }, { title: "暂停", dataIndex: "isPause", width: 80, }, { title: "最新版", dataIndex: "isTopVersion", width: 80, }, { title: "检验结果", dataIndex: "status", type: "select", width: 80, customRender: function (text) { if (text.record.status) { return statusOptions.value.find( (item) => item.value == text.record.status ).text } else { return '新建' } } }, { title: "操作", key: "action", align: "center", width: 200, sorter: false, scopedSlots: { customRender: "action" }, fixed: "right", formInvisible: true } ], dataSource: [] }) const columns = computed(() => { return [ { title: '项目号', dataIndex: 'projectNo', width: 120 }, { title: "基地", dataIndex: "orgNo", condition: true, width: 90, customRender: function (text) { if (text.record.orgNo) return buildBaseList.value.find( (item) => item.value == text.record.orgNo ).text }, }, { title: "检验单号", dataIndex: "orderNo", condition: true, width: 150 }, { dataIndex: "workzoneName", title: "作业区", width: 150, }, { title: "QC单号", dataIndex: "qcOrderNo", condition: true, width: 150 }, { title: "申请检验时间", dataIndex: "createDate", width: 150, type: "datetime", align: "center", customRender: function (text) { if (text.record.createDate) return dayjs(text.record.createDate).format('YYYY-MM-DD HH:mm:ss') }, }, { title: "检验大类", dataIndex: "inspClass", type: "select", width: 100, condition: true, customRender: function (text) { if (text.record.inspClass) return inspColumns.value.find( (item) => item.value == text.record.inspClass ).text }, }, { title: "检验类型", dataIndex: "inspTypeName", width: 150, }, { title: "创建时间", dataIndex: "createDate", width: 150, type: "datetime", customRender: function (text) { if (text.record.createDate) return dayjs(text.record.createDate).format('YYYY-MM-DD HH:mm:ss') }, }, { title: "创建人", dataIndex: "createUserId", width: 120, type: "employeeDescription", options: { fieldNames: { label: "createUserName", value: "createUserId" } } }, { title: "管数量", dataIndex: "pipeNum", width: 80 }, { title: "状态", dataIndex: "status", type: "select", width: 80, condition: true, customRender: function (text) { if (text.record.status) { return statusOptions.value.find( (item) => item.value == text.record.status ).text } else { return '新建' } } }, { title: '操作', dataIndex: 'action', width: 140, key: 'action' } ] }) const loadData = (type) => { loading.value = true serve.getOrderList(searchState.value).then(async (res) => { for (let item of res.content) { item.targetStorageDate = item.targetStorageDate ? dayjs(item.targetStorageDate).format('YYYY-MM-DD') : '' item.isDownload = false let value = await localforage.getItem(item.id.toString()) if (value instanceof Blob && value.size > 0 && value.type === 'application/pdf') { item.isDownload = true } } if (type == 'scroll') { data.value.push(...res.content) } else { data.value = res.content } dataCount.value = res.totalElements || 0 isLast.value = res.last loading.value = false }) } const handleScroll = (e) => { const element = e.target if (element.scrollTop + element.clientHeight >= element.scrollHeight) { if (!isLast.value) { searchState.value.page++ loadData('scroll') } } } const openSearchDialog = () => { searchOpen.value = true } const handleProject = () => { projectType.value = true projectpanelRef.value.open = true projectpanelRef.value.init() } const handleBack = () => { projectType.value = false projectpanelRef.value.open = false } const handleClose = () => { projectType.value = false projectpanelRef.value.open = false } const handleDetailClose = () => { showDetailModal.value = false } const handleResize = () => { if (window.innerWidth < 1000) { popupWidth.value = '60%' } else { popupWidth.value = '30%' } } const getProj = (val) => { searchState.value.projectNo = val.projId searchState.value.projNo = val.projNo handleClose() } const onSearch = () => { searchState.value.page = 0 loadData() searchOpen.value = false } const onReset = () => { searchState.value.page = 0 searchState.value.projectNo = undefined searchState.value.projNo = undefined searchState.value.inspClass = undefined searchState.value.orderNo = undefined } const handleBeforeUnload = () => { if (!homePage.isOnline) { Modal.confirm({ title: '浏览器当前处于离线状态,是否继续?', icon: createVNode(ExclamationCircleOutlined), content: createVNode( 'div', { style: 'color:red;' }, '一旦刷新,将无法继续使用' ), onOk() { console.log('OK') }, onCancel() { console.log('Cancel') } }) } } watch( () => homePage.isOnline, async (newVal) => { if (!newVal) { try { const listData = await localforage.getItem('downloadList') if (listData) { const list = JSON.parse(listData) list.forEach((item) => { item.isDownload = true }) data.value = list } } catch (error) { console.error('Error parsing list data:', error) } } else { onReset() loadData() } } ) const onInspClassConfirm = ({ selectedOptions }) => { showPicker.value = false searchState.value.inspClass = selectedOptions[0].value } const handleInspClass = () => { showPicker.value = true } onMounted(() => { getBuildBase() serve.getWorkZone({majors:'管路'}).then((res) => { workZoneNos.value = res.status == 200 ? res.data.map((item) => { return { label: item.name, value: item.code, } }) : []; }) if (homePage.isOnline) { loadData() } handleResize() window.addEventListener('resize', handleResize) window.addEventListener('beforeunload', handleBeforeUnload) }) onUnmounted(() => { window.removeEventListener('resize', handleResize) window.removeEventListener('beforeunload', handleBeforeUnload) }) onActivated(async () => { if (!homePage.isOnline) { try { const listData = await localforage.getItem('downloadList') if (listData) { const list = JSON.parse(listData) list.forEach((item) => { item.isDownload = true }) data.value = list } } catch (error) { console.error('Error parsing list data:', error) } } }) const getBuildBase = () => { getBuildBases().then((res) => { buildBaseList.value = res.map((item) => ({ value: item.orgNo, text: item.name })) }) } const showData = (record,showTypeStr) => { serve.getOrderList({id:record.id}).then((res) => { console.log('res.data',res) console.log('res.data',res.data) console.log('res.data.content',res.content) saveData.value = res.content[0] saveData.value.mainUserNo = { label: saveData.value.mainUserName, value: saveData.value.mainUserNo } saveData.value.status = saveData.value.status+'' pipeTable.dataSource = res.content[0].pipeList console.log('pipeTable.dataSource',pipeTable.dataSource) weldTable.dataSource = res.content[0].weldList currProjectNo.value = res.content[0].projectNo showDetailModal.value = true showType.value = showTypeStr saveData.value.inspClassStr = inspColumns.value.find( (item) => item.value == saveData.value.inspClass ).text saveData.value.orgName = buildBaseList.value.find( (item) => item.value == saveData.value.orgNo ).text serve.getInsp({ projName: res.content[0].projectNo, professionNo: "CP" }).then((res) => { selectInsp.value = res.map((item) => { return { label: item.MSVALUE+"", value: item.MSKEY+"", } }) }) }) } const onConfirm = ({ selectedValues }) => { saveData.applyDate = selectedValues.join('-'); console.log('saveData.applyDate',saveData.applyDate) console.log('selectedValues',selectedValues) showDatePicker.value = false; }; const changeStatus = (stateNum,type)=>{ console.log('pipeTable',pipeTable.selectedRows) console.log('weldTable',weldTable.selectedRows) if(type === 'pipe' ){ if(pipeTable.selectedRows.length === 0 ){ showNotify({ type: 'danger', message: '请选择一条数据' }) return } } if(type === 'weld'){ if(weldTable.selectedRows.length === 0 ){ showNotify({ type: 'danger', message: '请选择一条数据' }) return } } } </script> <style lang="scss" scoped> :deep .urgentFlag-active { background: #ffb656; } :deep .abnormalFlag-active { background: #fb7171; } :deep .anticon-search { line-height: 0 !important; } </style> <style lang="scss" scoped> @import '@/styles/common.scss'; .search-content { width: 100%; overflow: hidden; // height: 100%; .search-top { width: 100%; height: 50px; margin-top: 20px; display: flex; justify-content: center; align-content: center; .search-project-back { font-size: 14px; display: flex; align-content: center; position: absolute; left: 10px; color: #004688; } .search-titles { height: 100%; display: flex; justify-content: center; align-content: center; color: #004688; span { font-size: 15px; margin-left: 5px; } } } .search-state { width: 100%; height: calc(100% - 45px - 10px); position: absolute; bottom: 0; overflow: hidden; overflow-y: scroll; } } .action-buttons { display: flex; align-items: center; justify-content: space-around; } </style>这里有问题 { title: "状态", dataIndex: "status", type: "select", width: 80, condition: true, customRender: function (text) { if (text.record.status) { return statusOptions.value.find( (item) => item.value == text.record.status ).text } else { return '新建' } } }, 提示The script has an unsupported MIME type ('text/html'). pipeInspection:1 Uncaught (in promise) DOMException: Failed to register a ServiceWorker for scope ('http://localhost:5173/') with script ('http://localhost:5173/sw.js'): The script has an unsupported MIME type ('text/html'). pipeInspection.vue:762 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'find') at customRender (pipeInspection.vue:762:38) at Proxy.<anonymous> (index.js:143:30) at renderComponentRoot (runtime-core.esm-bundler.js:6502:16) at ReactiveEffect.componentUpdateFn [as fn] (runtime-core.esm-bundler.js:5319:46) at ReactiveEffect.run (reactivity.esm-bundler.js:225:19) at setupRenderEffect (runtime-core.esm-bundler.js:5454:5) at mountComponent (runtime-core.esm-bundler.js:5229:7) at processComponent (runtime-core.esm-bundler.js:5182:9) at patch (runtime-core.esm-bundler.js:4700:11) at mountChildren (runtime-core.esm-bundler.js:4932:7) customRender @ pipeInspection.vue:762 (anonymous) @ index.js:143 renderComponentRoot @ runtime-core.esm-bundler.js:6502 componentUpdateFn @ runtime-core.esm-bundler.js:5319 run @ reactivity.esm-bundler.js:225 setupRenderEffect @ runtime-core.esm-bundler.js:5454 mountComponent @ runtime-core.esm-bundler.js:5229 processComponent @ runtime-core.esm-bundler.js:5182 patch @ runtime-core.esm-bundler.js:4700 mountChildren @ runtime-core.esm-bundler.js:4932 processFragment @ runtime-core.esm-bundler.js:5112 patch @ runtime-core.esm-bundler.js:4674 mountChildren @ runtime-core.esm-bundler.js:4932 mountElement @ runtime-core.esm-bundler.js:4855 processElement @ runtime-core.esm-bundler.js:4820 patch @ runtime-core.esm-bundler.js:4688 mountChildren @ runtime-core.esm-bundler.js:4932 processFragment @ runtime-core.esm-bundler.js:5112 patch @ runtime-core.esm-bundler.js:4674 componentUpdateFn @ runtime-core.esm-bundler.js:5326 run @ reactivity.esm-bundler.js:225 setupRenderEffect @ runtime-core.esm-bundler.js:5454 mountComponent @ runtime-core.esm-bundler.js:5229 processComponent @ runtime-core.esm-bundler.js:5182 patch @ runtime-core.esm-bundler.js:4700 mountChildren @ runtime-core.esm-bundler.js:4932 processFragment @ runtime-core.esm-bundler.js:5112 patch @ runtime-core.esm-bundler.js:4674 patchKeyedChildren @ runtime-core.esm-bundler.js:5729 patchChildren @ runtime-core.esm-bundler.js:5511 patchElement @ runtime-core.esm-bundler.js:4985 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 componentUpdateFn @ runtime-core.esm-bundler.js:5406 run @ reactivity.esm-bundler.js:225 updateComponent @ runtime-core.esm-bundler.js:5258 processComponent @ runtime-core.esm-bundler.js:5193 patch @ runtime-core.esm-bundler.js:4700 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 patchElement @ runtime-core.esm-bundler.js:4985 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 patchElement @ runtime-core.esm-bundler.js:4985 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 processFragment @ runtime-core.esm-bundler.js:5156 patch @ runtime-core.esm-bundler.js:4674 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 patchElement @ runtime-core.esm-bundler.js:4985 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 patchElement @ runtime-core.esm-bundler.js:4985 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 componentUpdateFn @ runtime-core.esm-bundler.js:5406 run @ reactivity.esm-bundler.js:225 updateComponent @ runtime-core.esm-bundler.js:5258 processComponent @ runtime-core.esm-bundler.js:5193 patch @ runtime-core.esm-bundler.js:4700 componentUpdateFn @ runtime-core.esm-bundler.js:5406 run @ reactivity.esm-bundler.js:225 updateComponent @ runtime-core.esm-bundler.js:5258 processComponent @ runtime-core.esm-bundler.js:5193 patch @ runtime-core.esm-bundler.js:4700 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 processFragment @ runtime-core.esm-bundler.js:5156 patch @ runtime-core.esm-bundler.js:4674 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 patchElement @ runtime-core.esm-bundler.js:4985 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 patchElement @ runtime-core.esm-bundler.js:4985 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 componentUpdateFn @ runtime-core.esm-bundler.js:5406 run @ reactivity.esm-bundler.js:225 updateComponent @ runtime-core.esm-bundler.js:5258 processComponent @ runtime-core.esm-bundler.js:5193 patch @ runtime-core.esm-bundler.js:4700 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 patchElement @ runtime-core.esm-bundler.js:4985 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 componentUpdateFn @ runtime-core.esm-bundler.js:5406 run @ reactivity.esm-bundler.js:225 updateComponent @ runtime-core.esm-bundler.js:5258 processComponent @ runtime-core.esm-bundler.js:5193 patch @ runtime-core.esm-bundler.js:4700 componentUpdateFn @ runtime-core.esm-bundler.js:5406 run @ reactivity.esm-bundler.js:225 updateComponent @ runtime-core.esm-bundler.js:5258 processComponent @ runtime-core.esm-bundler.js:5193 patch @ runtime-core.esm-bundler.js:4700 patchBlockChildren @ runtime-core.esm-bundler.js:5054 patchElement @ runtime-core.esm-bundler.js:4972 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 componentUpdateFn @ runtime-core.esm-bundler.js:5406 run @ reactivity.esm-bundler.js:225 runIfDirty @ reactivity.esm-bundler.js:263 callWithErrorHandling @ runtime-core.esm-bundler.js:199 flushJobs @ runtime-core.esm-bundler.js:408 Promise.then (async) queueFlush @ runtime-core.esm-bundler.js:322 queueJob @ runtime-core.esm-bundler.js:317 effect2.scheduler @ runtime-core.esm-bundler.js:5448 trigger @ reactivity.esm-bundler.js:253 endBatch @ reactivity.esm-bundler.js:311 notify @ reactivity.esm-bundler.js:597 trigger @ reactivity.esm-bundler.js:571 set value @ reactivity.esm-bundler.js:1448 (anonymous) @ pipeInspection.vue:798 Promise.then (async) loadData @ pipeInspection.vue:781 (anonymous) @ pipeInspection.vue:924 (anonymous) @ runtime-core.esm-bundler.js:2815 callWithErrorHandling @ runtime-core.esm-bundler.js:199 callWithAsyncErrorHandling @ runtime-core.esm-bundler.js:206 hook.__weh.hook.__weh @ runtime-core.esm-bundler.js:2795 flushPostFlushCbs @ runtime-core.esm-bundler.js:385 flushJobs @ runtime-core.esm-bundler.js:427 Promise.then (async) queueFlush @ runtime-core.esm-bundler.js:322 queueJob @ runtime-core.esm-bundler.js:317 effect2.scheduler @ runtime-core.esm-bundler.js:5448 trigger @ reactivity.esm-bundler.js:253 endBatch @ reactivity.esm-bundler.js:311 notify @ reactivity.esm-bundler.js:597 trigger @ reactivity.esm-bundler.js:571 set value @ reactivity.esm-bundler.js:1448 finalizeNavigation @ vue-router.mjs:3498 (anonymous) @ vue-router.mjs:3363 Promise.then (async) pushWithRedirect @ vue-router.mjs:3330 push @ vue-router.mjs:3255 install @ vue-router.mjs:3699 use @ runtime-core.esm-bundler.js:3863 (anonymous) @ main.js:70 Show 141 more frames runtime-core.esm-bundler.js:6678 Uncaught (in promise) TypeError: Cannot read properties of null (reading 'emitsOptions') at shouldUpdateComponent (runtime-core.esm-bundler.js:6678:27) at updateComponent (runtime-core.esm-bundler.js:5246:9) at processComponent (runtime-core.esm-bundler.js:5193:7) at patch (runtime-core.esm-bundler.js:4700:11) at patchKeyedChildren (runtime-core.esm-bundler.js:5597:9) at patchChildren (runtime-core.esm-bundler.js:5511:11) at processFragment (runtime-core.esm-bundler.js:5156:9) at patch (runtime-core.esm-bundler.js:4674:9) at patchKeyedChildren (runtime-core.esm-bundler.js:5597:9) at patchChildren (runtime-core.esm-bundler.js:5511:11) shouldUpdateComponent @ runtime-core.esm-bundler.js:6678 updateComponent @ runtime-core.esm-bundler.js:5246 processComponent @ runtime-core.esm-bundler.js:5193 patch @ runtime-core.esm-bundler.js:4700 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 processFragment @ runtime-core.esm-bundler.js:5156 patch @ runtime-core.esm-bundler.js:4674 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 patchElement @ runtime-core.esm-bundler.js:4985 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 componentUpdateFn @ runtime-core.esm-bundler.js:5406 run @ reactivity.esm-bundler.js:225 updateComponent @ runtime-core.esm-bundler.js:5258 processComponent @ runtime-core.esm-bundler.js:5193 patch @ runtime-core.esm-bundler.js:4700 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 patchElement @ runtime-core.esm-bundler.js:4985 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 patchElement @ runtime-core.esm-bundler.js:4985 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 processFragment @ runtime-core.esm-bundler.js:5156 patch @ runtime-core.esm-bundler.js:4674 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 patchElement @ runtime-core.esm-bundler.js:4985 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 patchElement @ runtime-core.esm-bundler.js:4985 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 componentUpdateFn @ runtime-core.esm-bundler.js:5406 run @ reactivity.esm-bundler.js:225 updateComponent @ runtime-core.esm-bundler.js:5258 processComponent @ runtime-core.esm-bundler.js:5193 patch @ runtime-core.esm-bundler.js:4700 componentUpdateFn @ runtime-core.esm-bundler.js:5406 run @ reactivity.esm-bundler.js:225 updateComponent @ runtime-core.esm-bundler.js:5258 processComponent @ runtime-core.esm-bundler.js:5193 patch @ runtime-core.esm-bundler.js:4700 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 processFragment @ runtime-core.esm-bundler.js:5156 patch @ runtime-core.esm-bundler.js:4674 patchKeyedChildren @ runtime-core.esm-bundler.js:5597 patchChildren @ runtime-core.esm-bundler.js:5511 patchElement @ runtime-core.esm-bundler.js:4985 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 patchKeyedChildren @ runtime-core.esm-bundler.js:5617 patchChildren @ runtime-core.esm-bundler.js:5511 patchElement @ runtime-core.esm-bundler.js:4985 processElement @ runtime-core.esm-bundler.js:4831 patch @ runtime-core.esm-bundler.js:4688 componentUpdateFn @ runtime-core.esm-bundler.js:5406 run @ reactivity.esm-bundler.js:225 runIfDirty @ reactivity.esm-bundler.js:263 callWithErrorHandling @ runtime-core.esm-bundler.js:199 flushJobs @ runtime-core.esm-bundler.js:408 Promise.then (async) queueFlush @ runtime-core.esm-bundler.js:322 queueJob @ runtime-core.esm-bundler.js:317 effect2.scheduler @ runtime-core.esm-bundler.js:5448 trigger @ reactivity.esm-bundler.js:253 endBatch @ reactivity.esm-bundler.js:311 notify @ reactivity.esm-bundler.js:597 trigger @ reactivity.esm-bundler.js:571 set value @ reactivity.esm-bundler.js:1448 (anonymous) @ Spin.js:66 exec @ throttle.js:71 setTimeout (async) wrapper @ throttle.js:123 watch.immediate @ Spin.js:68 callWithErrorHandling @ runtime-core.esm-bundler.js:199 callWithAsyncErrorHandling @ runtime-core.esm-bundler.js:206 baseWatchOptions.call @ runtime-core.esm-bundler.js:6193 job @ reactivity.esm-bundler.js:1813 flushPostFlushCbs @ runtime-core.esm-bundler.js:385 flushJobs @ runtime-core.esm-bundler.js:427 Promise.then (async) queueFlush @ runtime-core.esm-bundler.js:322 queueJob @ runtime-core.esm-bundler.js:317 effect2.scheduler @ runtime-core.esm-bundler.js:5448 trigger @ reactivity.esm-bundler.js:253 endBatch @ reactivity.esm-bundler.js:311 notify @ reactivity.esm-bundler.js:597 trigger @ reactivity.esm-bundler.js:571 set value @ reactivity.esm-bundler.js:1448 (anonymous) @ pipeInspection.vue:798 Promise.then (async) loadData @ pipeInspection.vue:781 (anonymous) @ pipeInspection.vue:924 (anonymous) @ runtime-core.esm-bundler.js:2815 callWithErrorHandling @ runtime-core.esm-bundler.js:199 callWithAsyncErrorHandling @ runtime-core.esm-bundler.js:206 hook.__weh.hook.__weh @ runtime-core.esm-bundler.js:2795 flushPostFlushCbs @ runtime-core.esm-bundler.js:385 flushJobs @ runtime-core.esm-bundler.js:427 Promise.then (async) queueFlush @ runtime-core.esm-bundler.js:322 queueJob @ runtime-core.esm-bundler.js:317 effect2.scheduler @ runtime-core.esm-bundler.js:5448 trigger @ reactivity.esm-bundler.js:253 endBatch @ reactivity.esm-bundler.js:311 notify @ reactivity.esm-bundler.js:597 trigger @ reactivity.esm-bundler.js:571 set value @ reactivity.esm-bundler.js:1448 finalizeNavigation @ vue-router.mjs:3498 (anonymous) @ vue-router.mjs:3363 Promise.then (async) pushWithRedirect @ vue-router.mjs:3330 push @ vue-router.mjs:3255 install @ vue-router.mjs:3699 use @ runtime-core.esm-bundler.js:3863 (anonymous) @ main.js:70 Show 113 more frames
09-17
<think> 我们注意到在代码中有一个错误提示:`Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'find')`,发生在`pipeInspection.vue`文件的第762行。 该行对应的代码是: return statusOptions.value.find(item => item.value == text.record.status).text 错误原因是`statusOptions.value`为`undefined`,因此无法调用`find`方法。 查看代码,我们发现`statusOptions`的定义如下: const statusOptions = ref([ { value: -1, text: "不合格" }, { value: 0, text: "新建" }, { value: 1, text: "合格" }, { value: 2, text: "取消" } ]) 注意:这里我们使用`ref`包装了一个数组,所以我们应该使用`statusOptions.value`来访问这个数组。但是,在模板中我们使用了`statusOptions`作为计算属性的依赖,并在列定义中使用了`statusOptions.value`。 然而,在列定义中,我们使用了计算属性`columns`,并在其中访问`statusOptions.value`。但是,在初始渲染时,`statusOptions.value`已经被赋值为数组,所以理论上不应该为`undefined`。 但是,错误提示告诉我们`statusOptions.value`是`undefined`。这可能是因为在计算属性`columns`被计算时,`statusOptions`还没有被初始化? 实际上,我们注意到`statusOptions`是在`<script setup>`中同步定义的,所以它应该会在计算属性之前初始化。但为什么会出现`undefined`呢? 我们再看一下错误发生的位置:在表格的列定义中的`customRender`函数内。这个函数是在表格渲染每一行时调用的。所以,当表格渲染时,`statusOptions.value`可能因为某种原因变成了`undefined`?但我们在定义时已经给了初始值。 另一种可能性是,我们在`customRender`函数中使用了`text.record.status`,而`text.record`可能是`undefined`?但错误信息是`Cannot read properties of undefined (reading 'find')`,所以是`statusOptions.value`为`undefined`。 我们检查一下`statusOptions`的定义位置:它是在`<script setup>`的顶层定义的,应该是响应式引用。那么为什么在渲染时它的`value`会变成`undefined`呢? 可能的原因:异步加载数据时,在某个时刻`statusOptions`被重新赋值为`undefined`?但我们在代码中并没有看到对`statusOptions`的重新赋值。 重新审视代码,我们发现在`statusOptions`的定义下面有这样一行注释掉的代码: // const inspClassOptions = [ ... ] 然后下面有: const currProjectNo =ref(null) const selectInsp = ref([]) 然后定义了`weldTable`和`showType`等。所以`statusOptions`的定义应该没问题。 另一个可疑点:我们在`columns`计算属性中使用了`statusOptions.value`,而在`customRender`函数中也使用了`statusOptions.value`。但是,我们在`customRender`函数中使用了`statusOptions.value`,而`statusOptions`是`ref`对象,所以应该用`.value`访问。这里看起来没问题。 但是,注意我们在`customRender`函数中是这样写的: customRender: function (text) { if (text.record.status) { return statusOptions.value.find( (item) => item.value == text.record.status ).text } else { return '新建' } } 问题可能在于:当`text.record.status`不存在时,我们返回'新建',但是当`statusOptions.value`为`undefined`时,我们仍然会尝试访问`.find`,所以会出现上述错误。 因此,我们需要确保`statusOptions.value`不为`undefined`。但根据定义,它应该是一个数组。 然而,我们注意到在`statusOptions`的定义中,我们使用了`ref`,所以它是一个`Ref`对象,它的`value`属性在初始化时就是那个数组。那么为什么在`customRender`中变成了`undefined`? 可能的原因:作用域问题?`customRender`函数在执行时,其作用域链中的`statusOptions`可能不是我们预期的那个。 我们检查一下,在`columns`计算属性中,我们返回了一个数组,数组中的每个元素都是一个列定义对象。其中状态列的`customRender`函数引用了外部的`statusOptions`。由于`columns`计算属性是在`setup`中定义的,所以它形成了一个闭包,引用了`setup`作用域中的`statusOptions`。这应该是正确的。 那么,另一种可能性:在异步渲染过程中,`statusOptions`被重新赋值?我们在代码中没有看到重新赋值的地方。 或者,可能是由于代码压缩或打包工具的问题?但这里我们无法确定。 但是,我们注意到在同一个文件中,我们还有另一个类似的结构:`inspColumns`,它也是用`ref`包装的数组,然后在另一个列的`customRender`中使用,却没有报错。 所以,我们尝试修改代码,确保在访问`statusOptions.value`之前检查它是否存在。 修改`customRender`函数: customRender: function (text) { if (!statusOptions.value) { return '状态未知'; // 或者返回空字符串等 } const option = statusOptions.value.find(item => item.value == text.record.status); return option ? option.text : '新建'; } 但是,这样修改后,如果`statusOptions.value`为`undefined`,我们避免了错误,但问题仍然存在:为什么`statusOptions.value`会变成`undefined`? 然而,我们并没有在代码中看到明显的重新赋值。所以,我们可能需要进一步调试。 但是,我们注意到在错误信息中,还有一个错误: runtime-core.esm-bundler.js:6678 Uncaught (in promise) TypeError: Cannot read properties of null (reading 'emitsOptions') 这个错误可能是由于前一个错误导致的连锁反应。 因此,我们先解决这个明确的错误,即确保在访问`statusOptions.value`之前检查它。 修改代码: customRender: function (text) { // 检查statusOptions.value是否存在 if (statusOptions.value) { const option = statusOptions.value.find(item => item.value == text.record.status); if (option) { return option.text; } } // 如果没有找到匹配的选项或者statusOptions.value不存在,则根据状态值返回默认文本 // 注意:这里我们也可以检查text.record.status,但根据之前的逻辑,如果没有状态,我们返回'新建' return text.record.status === undefined ? '新建' : '未知状态'; } 但是,我们原来的逻辑是:如果`text.record.status`有值,我们就去匹配,否则返回'新建'。现在,如果`statusOptions.value`不存在,我们直接返回一个默认值。 另外,我们注意到在定义`statusOptions`之后,我们还有一个`stateColumns`的定义,它也是一个数组,但是并没有用`ref`包装,而是直接用`ref`包装数组?不对,`stateColumns`的定义是: const stateColumns = ref( [{ value: 0, text: "新建" }, { value: -1, text: "不合格" }, { value: 1, text: "检验中" }, { value: 2, text: "合格" },] ) 这里`stateColumns`也是一个`ref`,我们在`weldTable.resColumns`的`customRender`中使用了它,而且没有出现错误?所以为什么`statusOptions`会出现问题? 我们可能需要检查一下控制台,看看是否有其他错误导致`statusOptions`被置为`undefined`。 但是,由于时间关系,我们可以先按照上述方法修改,避免程序崩溃。 然而,我们注意到在`weldTable.resColumns`的`customRender`中,我们使用了`stateColumns.value`,而在`columns`计算属性中,我们使用了`statusOptions.value`。两者的使用方式一致。 所以,我们怀疑可能是`statusOptions`在定义之后被意外修改了?我们在整个文件中搜索`statusOptions`,发现除了定义和列定义中的使用,其他地方没有使用。 因此,我们尝试在`customRender`函数中打印`statusOptions`,看看它到底是什么: customRender: function (text) { console.log('statusOptions:', statusOptions); console.log('statusOptions.value:', statusOptions.value); // ... 原来的代码 } 但由于我们不能直接运行,所以我们只能推测。 另外,我们注意到在`statusOptions`定义的上方,有`workZoneNos`的定义,它也是一个`ref`,初始化为空数组。所以,整个文件的变量定义应该都是正常的。 那么,可能是由于循环引用或模块作用域的问题?在Vue3的`<script setup>`中,通常不会有这样的问题。 考虑到这些,我们决定先修改代码,避免直接访问`statusOptions.value`而不做检查。 修改后的`customRender`函数: customRender: function (text) { if (statusOptions.value) { const option = statusOptions.value.find(item => item.value == text.record.status); if (option) { return option.text; } else { // 如果没找到,可能是状态值不在选项中,我们返回一个默认值 return '未知状态'; } } else { // 如果statusOptions.value为undefined,我们返回一个占位符 return '状态未知'; } } 但是,我们原来的逻辑中,如果`text.record.status`不存在,我们返回'新建'。所以,我们需要将两个逻辑结合起来: customRender: function (text) { // 如果record中没有status,返回'新建' if (text.record.status === undefined || text.record.status === null) { return '新建'; } // 如果statusOptions.value存在,则尝试查找 if (statusOptions.value) { const option = statusOptions.value.find(item => item.value == text.record.status); if (option) { return option.text; } else { return '未知状态'; } } return '状态未知'; } 这样修改后,即使`statusOptions.value`为`undefined`,也不会导致整个程序崩溃,并且能够处理各种情况。 此外,我们还需要检查其他使用了类似结构的地方,比如`buildBaseList`,它在列的`customRender`中也有使用。我们同样需要添加保护。 但是,由于错误只发生在`statusOptions`,我们先解决这个。 另外,我们在控制台还看到另一个错误: pipeInspection:1 Uncaught (in promise) DOMException: Failed to register a ServiceWorker for scope ('http://localhost:5173/') with script ('http://localhost:5173/sw.js'): The script has an unsupported MIME type ('text/html'). 这个错误与Service Worker有关,可能是由于在开发环境下,我们没有正确的sw.js文件,导致浏览器尝试从服务器获取sw.js,但服务器返回了HTML(可能是因为路由history fallback)而不是JavaScript。这通常不会影响功能,可以暂时忽略。 现在,我们按照上述修改方案修改代码。 注意:由于代码较长,我们只修改出问题的列(状态列)的`customRender`函数。 修改后的状态列定义如下: { title: "状态", dataIndex: "status", type: "select", width: 80, condition: true, customRender: function (text) { // 如果状态不存在,返回'新建' if (text.record.status === undefined || text.record.status === null) { return '新建'; } // 确保statusOptions.value存在 if (statusOptions.value) { const option = statusOptions.value.find(item => item.value == text.record.status); if (option) { return option.text; } return '未知状态'; } else { return '状态未知'; } } } 这样修改后,应该可以避免错误。 另外,我们还需要检查`statusOptions`为什么会被置为`undefined`,但由于问题复杂性和时间,我们可能需要在运行时调试。 现在,我们根据要求,在回答后提出3-5个相关问题。 </think> 根据提供的代码和错误信息,问题主要出现在状态列的 `customRender` 函数中,具体表现为 `statusOptions.value` 未被正确初始化导致 `Cannot read properties of undefined (reading 'find')` 错误。以下是详细分析和解决方案: ### 问题分析 1. **错误根源**: ```javascript customRender: function (text) { if (text.record.status) { return statusOptions.value.find( // 此处statusOptions.value为undefined (item) => item.value == text.record.status ).text } else { return '新建' } } ``` - `statusOptions.value` 未定义,因为 `statusOptions` 的初始化方式不正确 2. **错误原因**: - `statusOptions` 被定义为普通数组而非响应式引用: ```javascript const statusOptions = [ // 缺少ref()包裹 { value: -1, text: "不合格" }, { value: 0, text: "新建" }, { value: 1, text: "合格" }, { value: 2, text: "取消" } ] ``` - 在 Vue3 的 `<script setup>` 中,非响应式数据无法在模板中正确更新 ### 解决方案 修改 `statusOptions` 的声明方式,并添加空值保护: ```javascript // 修复1: 使用ref()创建响应式引用 const statusOptions = ref([ { value: -1, text: "不合格" }, { value: 0, text: "新建" }, { value: 1, text: "合格" }, { value: 2, text: "取消" } ]) // 修复2: 添加空值保护 { title: "状态", dataIndex: "status", customRender: function (text) { // 添加空值检查 if (!statusOptions.value) return '未知状态'; const statusVal = text.record?.status; const option = statusOptions.value.find(item => item.value == statusVal); return option?.text || '新建'; // 安全访问 } } ``` ### 其他优化建议 1. **日期选择器绑定**: ```javascript // 修正applyDate的响应式绑定 const saveData = reactive({ applyDate: '' }); <van-date-picker v-model="saveData.applyDate" /> ``` 2. **Service Worker 错误处理**: ```javascript // 在main.js中添加 if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js').catch(error => { console.warn('SW注册失败:', error); }); } ``` 3. **响应式宽度计算优化**: ```javascript // 使用Vue3的computed替代事件监听 const popupWidth = computed(() => window.innerWidth < 1000 ? '60%' : '30%' ); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值