我先并行做两件事:读取并整理项目记忆文件,同时定位相关代码。Grep 在这个大工程上超时了,我换成限定文件类型来搜。找到了 /manage-income 控制器,我读一下它。前端源码不在这个工程里(tabyperf 有独立前端),我从后端入手。先看 DDManageIncomeServiceImpl 和"冻结"关键字。这些提示是前端文案,后端没有。我在 tabyperf 打包好的前端 JS 里找找。这些 JS 带 source map,可以直接还原前端源码。我解析一下。核心逻辑找到了。现在确认 maxMonth 在 Vuex store 里是怎么存的。getMaxMonth 用了自定义的 originalData: true,我看下 axios 封装是怎么处理它的。transformResponse 被替换成了空函数——这是关键。我再看下新版页面 wageManagement.vue 的对应逻辑。逻辑已经完全对上了。再确认几个细节:操作类型枚举、后端返回类型、以及时间戳换算。时间戳确认是 2026-08-01。操作枚举也对上了。最后确认下日期序列化配置。找到一条关键线索:日期格式配置写错了前缀。我看下 tabyperf 的配置文件。后端行为已完全确认。现在按系统要求整理超限的项目记忆文件。

结论:不是"冻结"逻辑的问题,也不是你操作错了 —— 是前端把时间戳当字符串解析失败了

1. 1785513600000 是什么意思

它是 2026-08-01 00:00:00(东八区)的毫秒时间戳。

来源是后端 /tabyperf/manage-income/max-month → DDCalculateIncomeBizNew.getCurrentMonth(channel):

Sql
复制成功
select max(t.date) from tk_ywy_income -- channel=0 时不加渠道条件

date 存的是"月份第一天",所以这个值 = 系统里已生成工资数据的最大月份。换句话说,库里已经有 2026-08 的工资数据了。

2. "Invalid date" 是怎么冒出来的(根因)

问题出在 tabyperf 前端(源码不在本仓库,我从 tabyperf-app/.../static/static/js/app.*.js.map 里还原出来的):

环节 代码位置 做了什么
① utils/request.js axios 实例的 transformResponse 被写成了空函数(函数体被注释掉、没有 return)→ response.data === undefined
② 同上 于是走 fallback 分支 data = response.request.responseText,拿到的是原始字符串 "1785513600000",不是数字
③ api/income-manage.js getMaxMonth 带了 originalData: true,把这个字符串原样塞进 Vuex 的 state.incomeManage.maxMonth
④ IncomeManage.vue moment(this.maxMonth).format('YYYY-MM') —— moment 不把纯数字字符串当时间戳(只按日期字符串解析)→ 结果就是 "Invalid date"

3. 两条提示都是这一个 bug 的产物

第 ④ 步之后 shouldCalMonth 变成了字符串 "Invalid date",接下来全是字符串比较:

  • 选「计算工资表」(actionType=2):"Invalid date" != "2026-08" 恒为真 → "请先生成2026-08的工资表"
  • 选「生成工资表」(actionType=1):"Invalid date" > "2026-08" 恒为真('I'=0x49 > '2'=0x32,按字典序)→ "2026-08的工资表已经冻结,当前工资最新操作记录是Invalid date"

所以那两条看起来自相矛盾的提示,其实后端从来没有真正判断过"冻结",它只返回了一个月份时间戳。

另外注意 if (this.maxMonth) 这个条件:当接口返回 null(该渠道无数据)时响应体为空,maxMonth 是空字符串 → 整段校验被跳过,功能"正常"。所以这类前端缺陷是数据一多就暴露。

4. 附带发现:日期格式配置写错了前缀

tabyperf-app/src/main/resources/application.properties:

Properties
复制成功
jackson.date-format= yyyy-MM-dd HH:mm:ss # ← 少了 spring. 前缀,不生效
jackson.time-zone= UTC # ← 同样不生效
#spring.jackson.date-format=yyyy-MM-dd # ← 历史上正确写法的残留

正确的 key 是 spring.jackson.date-format。因为少了前缀,Date 一律被序列化成毫秒时间戳;如果它当时是生效的,接口会返回 "2026-08-01 00:00:00" 这类字符串,moment 能解析,页面就不会报错。这很可能就是"以前能用、现在不行"的回归点。

5. 建议你先核实这两条 SQL

Sql
复制成功
SELECT date, channel, COUNT(*) FROM tk_ywy_income
WHERE date >= '2026-07-01' GROUP BY date, channel ORDER BY date, channel;
 
SELECT COUNT(*) FROM tk_ywy_income WHERE date = '2026-08-01';

如果 8 月确实已有数据,说明 8 月工资表其实已经生成过,你要做的是「计算工资表」(算金额),而不是「生成工资表」;但在当前前端缺陷下,这两个操作都会被上面那句字符串比较拦下来。

浏览器控制台里也可以直接自证:new Date(1785513600000) 正常,new Date("1785513600000") 是 Invalid Date。


我没有改任何代码(按你的要求)。这个问题根子在前端,修法有两条:

  • 前端:moment(Number(this.maxMonth)),或先判断空值 —— 改动小,但需要前端发版;
  • 后端:让 max-month 直接返回 "yyyy-MM" 字符串(前端 moment 就能正常解析),属于后端改动,我可以做,但这个接口目前工资管理页在用,需确认没有别处依赖时间戳格式。

你想走哪条?

本页笔记

加载中…