selector.js?type=script&index=0!./src/pages/Rescue...

Creato il: 24 marzo 2026

Risposto usando GPT-5.4 Thinking da Chat01

Domanda

selector.js?type=script&index=0!./src/pages/Rescuemodule/Rescueagencies/institutionalregistration.vue:219 undefined '99999999999999999999999999'
15:40:42.636 main.js:244 getOrganizationList error: Error: 又失败了
at VueComponent.normalizeAjaxResult (selector.js?type=script&index=0!./src/pages/Rescuemodule/Rescueagencies/institutionalregistration.vue:174:15)
at VueComponent._callee$ (selector.js?type=script&index=0!./src/pages/Rescuemodule/Rescueagencies/institutionalregistration.vue:221:29)
at tryCatch (runtime.js:62:40)
at Generator.invoke [as _invoke] (runtime.js:296:22)
at prototype.<computed> [as next] (runtime.js:114:21)
at step (asyncToGenerator.js:17:30)
at eval (asyncToGenerator.js:28:13) 什么情况啊写一个完整的页面修改过后的 <template>
<container-component
style="width: 100%; height: 100%"
type="col"
v-show="isReload"

<container-component type="row" y="center" style="width: 100%" wrap>
text
<div v-html="$store.getters.ottitle"></div> </container-component> <container-component type="row" style="width: 100%"> <container-component type="col" x="center" style="width: 100%" class="table-wrapper" > <el-table :data="organizationList" style="width: 100%" v-loading="tableLoading" > <el-table-column type="index" :label="messageCode('prompt.base.number')" min-width="6%" align="center" /> <el-table-column prop="organizationName" label="机构名" min-width="26%" align="center" show-overflow-tooltip > <template slot-scope="scope"> <span>{{ scope.row.organizationName || "-" }}</span> </template> </el-table-column> <el-table-column prop="state" label="状态" min-width="14%" align="center" > <template slot-scope="scope"> <span>{{ stateLabel(scope.row.state) }}</span> </template> </el-table-column> <el-table-column prop="createTime" label="创建时间" min-width="20%" align="center" show-overflow-tooltip > <template slot-scope="scope"> <span>{{ formatTime(scope.row.createTime) }}</span> </template> </el-table-column> <!-- 通过 --> <el-table-column v-if="showAuditAction" :label="messageCode('prompt.base.state.start')" min-width="10%" align="center" show-overflow-tooltip > <template slot-scope="scope"> <span class="linkStyle" @click="approve(scope.row)"> {{ messageCode("prompt.base.state.start") }} </span> </template> </el-table-column> <!-- 拒绝 --> <el-table-column v-if="showAuditAction" label="不通过" min-width="10%" align="center" show-overflow-tooltip > <template slot-scope="scope"> <span class="linkStyle" @click="reject(scope.row)">拒绝</span> </template> </el-table-column> <template slot="empty"> <img :src=" $baseURL + '/images/' + styleMap.folder + '/' + styleMap.noRecord " alt="empty" /> </template> </el-table> </container-component> </container-component>
</container-component> </template> <script> import util from "$static/javascript/util.js"; export default { inject: ["reload"], name: "organizationAuditList", data() { return { styleMap: this.$store.getters.styleMap, organizationList: [], tableLoading: false, // 分页递归加载 selectTime: 0, rowCount: 20, operateType: "", showAuditAction: true, isReload: false, }; }, created() { this.init(); }, beforeRouteUpdate(to, from, next) { next(); this.init(); }, methods: { init() { this.styleMap = this.$store.getters.styleMap; this.selectTime = 0; this.organizationList = []; this.operateType = util.getRouteParams(this.$route).operateType; this.showAuditAction = this.operateType !== "superEdit"; this.isReload = false; this.getOrganizationList(); }, // 统一兼容 $ajax 返回值(res / res.data / data) normalizeAjaxResult(res) { // 有的封装直接返回 data if (res && res.result) return res; // axios 标准:{data, status, ...} if (res && res.data) return res.data; // 最糟糕:封装吞了返回值 if (res === undefined) { throw new Error("又失败了"); } return res; }, // 24.organizationAuditList async getOrganizationList() { const self = this; self.tableLoading = true; // 防止后端一直返回满 rowCount 导致死递归(保险阈值) const maxPages = 200; try { for (let page = self.selectTime; page < maxPages; page++) { const res = await self.$ajax({ method: "post", url: "organizationAuditList", data: self.stringify({ rowStartIdx: page * self.rowCount, rowCount: self.rowCount, }), }); console.log(res, "99999999999999999999999999"); const data = self.normalizeAjaxResult(res); self.isReload = true; if (data && data.result === "success") { const arr = data.organizationArray && data.organizationArray.length ? data.organizationArray : []; self.organizationList = self.organizationList.concat(arr); // 本次不足 rowCount,结束 if (arr.length < self.rowCount) { self.selectTime = page; break; } } else { self.$Prompt({ content: data && data.result ? data.result : "加载失败", icoType: "error", }); break; } } } catch (e) { // 这里能把“封装吞返回值”的问题直接提示出来 console.error("getOrganizationList error:", e); self.$Prompt({ content: e && e.message ? e.message : self.messageCode("errors.failure"), icoType: "error", }); } finally { self.tableLoading = false; } }, approve(row) { this.doAudit(row, 2); }, reject(row) { this.doAudit(row, -1); }, async doAudit(row, state) { const self = this; const defaultReason = state === 2 ? "审核通过" : "审核拒绝"; try { let reason = defaultReason; if (self.$prompt) { const res = await self.$prompt("请输入审批理由", "机构审批", { confirmButtonText: "确定", cancelButtonText: "取消", inputPlaceholder: "请填写审批理由(confirmContent)", inputValue: defaultReason, inputType: "textarea", closeOnClickModal: false, }); reason = (res && res.value ? String(res.value).trim() : "") || defaultReason; } else { // 没有 $prompt 的项目:这里你也可以换成自定义弹窗 reason = defaultReason; } // 注意:这里“取消”会进入 catch,所以取消不提交更合理 await self.submitAudit(row.id, state, reason); } catch (e) { // 用户取消 or 异常:不提交 if (e !== "cancel") console.log("doAudit canceled/failed:", e); } }, async submitAudit(organizationId, state, confirmContent) { const self = this; self.$Loading(true); const param = { organizationId, state, confirmContent }; console.log("submitAudit param =>", param); try { const res = await self.$ajax({ method: "post", url: "newOrganizationAudit", data: self.stringify(param, { indices: false }), }); // ✅ 这句你原来想要的 log:现在一定能看到(除非 $ajax 吞返回值,会在 normalize 里报错) console.log("submitAudit raw response =>", res); const data = self.normalizeAjaxResult(res); if (data && data.result === "success") { await self.$Prompt({ content: self.messageCode("prompt.success"), icoType: "success", }); self.reload(); } else { self.$Prompt({ content: data && data.result ? data.result : "操作失败", icoType: "error", }); } } catch (e) { console.error("submitAudit error:", e); self.$Prompt({ content: e && e.message ? e.message : self.messageCode("errors.failure"), icoType: "error", }); } finally { self.$Loading(false); } }, stateLabel(state) { const s = Number(state); const map = { "-2": "删除", "-1": "拒绝/停用", 0: "维护", 1: "上报", 2: "有效", }; const key = String(s); if (Object.prototype.hasOwnProperty.call(map, key)) return map[key]; if (state === null || state === undefined) return "-"; return String(state); }, formatTime(t) { if (t === null || t === undefined || t === "" || t === "undefined") return "-"; let d = null; if (typeof t === "number" || /^\d+$/.test(String(t))) { const n = Number(t); d = String(n).length === 10 ? new Date(n * 1000) : new Date(n); } else { d = new Date(t); } if (!d || isNaN(d.getTime())) return "-"; const pad = (num) => (String(num).length === 1 ? "0" + num : String(num)); return ( d.getFullYear() + "-" + pad(d.getMonth() + 1) + "-" + pad(d.getDate()) + " " + pad(d.getHours()) + ":" + pad(d.getMinutes()) + ":" + pad(d.getSeconds()) ); }, }, }; </script> <style lang="less" scoped> @import "~$static/lesses/allImages/style.less"; .linkStyle { cursor: pointer; color: #409eff; } </style>

Pensiero

先给你结论:不是页面模板的问题,核心是 await self.$ajax(...) 拿到的就是 undefined,所以你打印才会出现 undefined '999999...',接着 normalizeAjaxResult 主动抛了“又失败了”。我先把原因说清,再给你一份可以直接替换的完整页面。

Thought for 1m 17s

Risposta

你这个报错本质上是:

js
const res = await self.$ajax(...) console.log(res, "99999999999999999999999999")

这里打印出来的是:

js
undefined '99999999999999999999999999'

说明 $ajax 这次请求没有返回值,不是模板报错,也不是 el-table 的问题。然后你下面这句:

js
const data = self.normalizeAjaxResult(res);

因为 res === undefined,就被你自己抛出了:

js
throw new Error("又失败了");

所以真实问题是这几个之一:

  1. 你的 $ajax 封装里没 return
  2. axios 响应拦截器里没 return responsereturn response.data
  3. $ajax(...).then(...) 写了,但外层没把 Promise return 出来
  4. catch 里把异常吞了,最后返回了 undefined

也就是说:页面能优化,但根因还是 $ajax 封装要查。

下面我先给你一份可以直接替换的完整页面,做了这些改动:

  • undefined 的报错提示写清楚
  • 兼容更多返回结构:res / res.data / res.data.data
  • 兼容成功标识:result === "success" / code === 200 / success === true
  • 审核时兼容 row.idrow.organizationId
  • 分页加载做了保险处理
  • 出错时不会只弹“又失败了”,而是告诉你真正该查哪里

vue
<template> <container-component style="width: 100%; height: 100%" type="col" v-show="isReload" > <container-component type="row" y="center" style="width: 100%" wrap> <div v-html="$store.getters.ottitle"></div> </container-component> <container-component type="row" style="width: 100%"> <container-component type="col" x="center" style="width: 100%" class="table-wrapper" > <el-table :data="organizationList" style="width: 100%" v-loading="tableLoading" > <el-table-column type="index" :label="messageCode('prompt.base.number')" min-width="6%" align="center" /> <el-table-column prop="organizationName" label="机构名" min-width="26%" align="center" show-overflow-tooltip > <template slot-scope="scope"> <span>{{ scope.row.organizationName || "-" }}</span> </template> </el-table-column> <el-table-column prop="state" label="状态" min-width="14%" align="center" > <template slot-scope="scope"> <span>{{ stateLabel(scope.row.state) }}</span> </template> </el-table-column> <el-table-column prop="createTime" label="创建时间" min-width="20%" align="center" show-overflow-tooltip > <template slot-scope="scope"> <span>{{ formatTime(scope.row.createTime) }}</span> </template> </el-table-column> <el-table-column v-if="showAuditAction" :label="messageCode('prompt.base.state.start')" min-width="10%" align="center" show-overflow-tooltip > <template slot-scope="scope"> <span class="linkStyle" @click="approve(scope.row)"> {{ messageCode("prompt.base.state.start") }} </span> </template> </el-table-column> <el-table-column v-if="showAuditAction" label="不通过" min-width="10%" align="center" show-overflow-tooltip > <template slot-scope="scope"> <span class="linkStyle" @click="reject(scope.row)">拒绝</span> </template> </el-table-column> <template slot="empty"> <img :src=" $baseURL + '/images/' + styleMap.folder + '/' + styleMap.noRecord " alt="empty" /> </template> </el-table> </container-component> </container-component> </container-component> </template> <script> import util from "$static/javascript/util.js"; export default { inject: ["reload"], name: "organizationAuditList", data() { return { styleMap: this.$store.getters.styleMap, organizationList: [], tableLoading: false, // 分页参数 selectTime: 0, rowCount: 20, maxPages: 200, operateType: "", showAuditAction: true, isReload: false, }; }, created() { this.init(); }, beforeRouteUpdate(to, from, next) { next(); this.init(); }, methods: { init() { this.styleMap = this.$store.getters.styleMap; this.selectTime = 0; this.organizationList = []; this.operateType = util.getRouteParams(this.$route).operateType; this.showAuditAction = this.operateType !== "superEdit"; this.isReload = false; this.getOrganizationList(); }, /** * 统一请求入口 * 这里最关键:如果 $ajax 没有 return,会直接抛出更明确的错误 */ async requestAjax(url, payload) { const res = await this.$ajax({ method: "post", url, data: this.stringify(payload, { indices: false }), }); console.log(`[${url}] raw response =>`, res); if (res === undefined) { throw new Error( "$ajax 返回了 undefined,请检查 $ajax 封装 / axios 拦截器是否缺少 return" ); } return this.normalizeAjaxResult(res); }, /** * 兼容后端常见返回结构: * 1. res * 2. res.data * 3. res.data.data * 4. 字符串 JSON */ normalizeAjaxResult(res) { let data = res; if (typeof data === "string") { try { data = JSON.parse(data); } catch (e) { return { result: "error", message: data }; } } // axios 标准结构 if (data && typeof data === "object" && data.data !== undefined) { data = data.data; } // 某些后端再包一层 data if ( data && typeof data === "object" && data.data !== undefined && ( data.result === undefined && data.code === undefined && data.success === undefined && data.organizationArray === undefined ) ) { data = data.data; } return data; }, /** * 兼容 success 判断 */ isSuccess(data) { if (!data || typeof data !== "object") return false; return ( data.result === "success" || data.result === true || data.code === 200 || data.code === "200" || data.success === true || data.status === 200 ); }, /** * 统一提取提示文案 */ getMessage(data, fallback) { if (!data) return fallback || "请求失败"; return ( data.message || data.msg || data.resultDesc || data.resultMsg || data.result || fallback || "请求失败" ); }, /** * 兼容多种列表字段 */ getOrganizationArray(data) { if (!data || typeof data !== "object") return []; if (Array.isArray(data.organizationArray)) return data.organizationArray; if (data.data && Array.isArray(data.data.organizationArray)) { return data.data.organizationArray; } if (Array.isArray(data.list)) return data.list; if (Array.isArray(data.rows)) return data.rows; return []; }, // 24.organizationAuditList async getOrganizationList() { this.tableLoading = true; this.isReload = true; try { let page = 0; let hasMore = true; let allList = []; while (hasMore && page < this.maxPages) { const data = await this.requestAjax("organizationAuditList", { rowStartIdx: page * this.rowCount, rowCount: this.rowCount, }); if (!this.isSuccess(data)) { throw new Error(this.getMessage(data, "机构列表加载失败")); } const arr = this.getOrganizationArray(data); allList = allList.concat(arr); if (arr.length < this.rowCount) { hasMore = false; } else { page += 1; } } this.organizationList = allList; this.selectTime = page; } catch (e) { console.error("getOrganizationList error:", e); this.organizationList = []; this.$Prompt({ content: (e && e.message) || this.messageCode("errors.failure") || "加载失败", icoType: "error", }); } finally { this.tableLoading = false; } }, approve(row) { this.doAudit(row, 2); }, reject(row) { this.doAudit(row, -1); }, async doAudit(row, state) { const defaultReason = state === 2 ? "审核通过" : "审核拒绝"; try { let reason = defaultReason; if (this.$prompt) { const res = await this.$prompt("请输入审批理由", "机构审批", { confirmButtonText: "确定", cancelButtonText: "取消", inputPlaceholder: "请填写审批理由(confirmContent)", inputValue: defaultReason, inputType: "textarea", closeOnClickModal: false, }); reason = (res && res.value ? String(res.value).trim() : "") || defaultReason; } const organizationId = row.organizationId || row.id || row.orgId || row.organizationCode; if (!organizationId) { throw new Error("当前行缺少 organizationId / id,无法提交审核"); } await this.submitAudit(organizationId, state, reason); } catch (e) { if (e !== "cancel") { console.error("doAudit error:", e); this.$Prompt({ content: (e && e.message) || this.messageCode("errors.failure") || "操作失败", icoType: "error", }); } } }, async submitAudit(organizationId, state, confirmContent) { this.$Loading(true); try { const data = await this.requestAjax("newOrganizationAudit", { organizationId, state, confirmContent, }); if (!this.isSuccess(data)) { throw new Error(this.getMessage(data, "审核操作失败")); } await this.$Prompt({ content: this.messageCode("prompt.success") || "操作成功", icoType: "success", }); this.reload(); } catch (e) { console.error("submitAudit error:", e); this.$Prompt({ content: (e && e.message) || this.messageCode("errors.failure") || "操作失败", icoType: "error", }); } finally { this.$Loading(false); } }, stateLabel(state) { const s = Number(state); const map = { "-2": "删除", "-1": "拒绝/停用", "0": "维护", "1": "上报", "2": "有效", }; const key = String(s); if (Object.prototype.hasOwnProperty.call(map, key)) { return map[key]; } if (state === null || state === undefined || state === "") { return "-"; } return String(state); }, formatTime(t) { if (t === null || t === undefined || t === "" || t === "undefined") { return "-"; } let d = null; if (typeof t === "number" || /^\d+$/.test(String(t))) { const n = Number(t); d = String(n).length === 10 ? new Date(n * 1000) : new Date(n); } else { d = new Date(t); } if (!d || isNaN(d.getTime())) { return "-"; } const pad = (num) => (String(num).length === 1 ? "0" + num : String(num)); return ( d.getFullYear() + "-" + pad(d.getMonth() + 1) + "-" + pad(d.getDate()) + " " + pad(d.getHours()) + ":" + pad(d.getMinutes()) + ":" + pad(d.getSeconds()) ); }, }, }; </script> <style lang="less" scoped> @import "~$static/lesses/allImages/style.less"; .linkStyle { cursor: pointer; color: #409eff; } </style>

但你要注意

上面这个页面能把错误提示变清楚,也能增强兼容性,但如果你的 $ajax 本身就是这样写的,那页面再怎么改也白搭:

js
// 错误示例 Vue.prototype.$ajax = function (config) { axios(config).then((res) => { return res.data; }); };

因为外层没 return,所以调用方拿到的一定是 undefined

应该改成:

js
Vue.prototype.$ajax = function (config) { return axios(config) .then((res) => res.data) .catch((err) => { throw err; }); };

或者如果你有响应拦截器,也要保证:

js
axios.interceptors.response.use( (response) => { return response; // 或 return response.data }, (error) => { return Promise.reject(error); } );

你现在这个报错最像哪种情况

我判断最像这个:

  • 接口其实发出去了
  • 但是 $ajax 封装里没有把 axios Promise return 出来
  • 所以 await this.$ajax(...) 直接拿到 undefined

因为如果是网络错误,通常会直接进 catch,而不是先 console.log(undefined, "999...")


你下一步最该查的文件

去看你项目里这几个位置:

  • Vue.prototype.$ajax = ...
  • request.js
  • axios.js
  • 响应拦截器 interceptors.response.use(...)

重点搜:

js
$ajax axios( then( return interceptors.response.use

$ajax 的代码贴出来,我可以直接帮你把封装一并改好。

Condividi questa Q&A