从 PHP 到 AI + Golang,程序员自救转型手记(三十五):控制台静态页面、深入研究时间格式化方案

发布时间:2026/7/14 19:11:53
从 PHP 到 AI + Golang,程序员自救转型手记(三十五):控制台静态页面、深入研究时间格式化方案 这是一个系列 Blog作者将以一个 PHP 全栈工程师的身份利用 AI 工具claude code、codex、deepseek、豆包等从零开始学习 golang 语言并最终完成 ai-go-admingithub | gitee开源项目的制作全程记录分享。在上一期我们进行了 “后台初始化请求实现”本期将完成控制台静态页面、深入研究时间格式化方案控制台静态页面后台系统为了控制台好看一般不会使用真实数据比如会员数、插件数等而是整一些花里胡哨的图表即可相当于留给系统开发者自定义。又是静态页面来了上一次搞纯静态 AI 表现的很好这一次提示词依旧很简单于web/src/views/admin/dashboard.vue实现静态控制台页面展示一些静态数据精致的图表等。失算了这次静态页面调了非常久大概得 4 个小时推翻重构了很多然后又人工打磨一些细节和逐行review最终落地效果如下这一次几乎是每个卡片都做了修改原版非常花哨颜色杂乱动效亮眼也有布局不合理的地方只是乍一看还行。深入研究时间格式化方案目前如管理员上次登录时间last_login_at输出的格式是这样的2026-07-17T20:58:58.97627708:00而我们的日常格式一般是2026-07-17 20:58:58这里让问问 AI在什么地方改以及怎么改。我主要是不太确定 GORM 输出字段能是否自定义时间输出的格式而如果可以最好的方式应该是在模型层设置 json 转换相关 tag。同时鉴于我们之前已经建立了dto目录这次应该刚好能将一些散乱在各处的响应数据结构体封装进去不再和模型等层强耦合。这里直接问 AI时间字段如internal/model/admin.goadmin表的LastLoginAt字段接口响应的格式是2026-07-17T20:58:58.97627708:00我希望改为简洁一点的2026-07-17 20:58:58从哪里入手比较好结果而且它最终提供的方案我还不太认可大概是要自定义一个Time类型嵌入time.Time实现很多时间转换的接口然后将所有的time.Time字段类型改为Time这里还问了豆包它首先也是这个思路。换了 AI 查资料果然DTO层将time.Time字段转为string格式化为2023-02-05 09:09:09是完全可行的。让 CC 先搓一个出来看看在DTO层将time.Time字段转为string格式化为2006-01-02 15:04:05先做internal/dto/admin.go中的AdminSession看看效果结果出了点问题dto层转换的话以后每个带时间日期字段的dto都需要写MarshalJSON方法这显得非常麻烦我甚至又退回第一步再次确定了一下模型层转换是不是正确方案但模型层确实需要坚持使用time.Time类型担心GORM这边的兼容性问题而且有出库入库的性能损耗时间没必要模型层就转换为合适的格式自定义格式主要是展示用你提前转了后面要用时间搞不好还得转回去dto层是最合适的gorm.DeletedAt这种又不能改用自定义的Time类型这就显得不统一了dto可以随时分版本模型怎么分版本所以最终方案后端在modeldto层的数据转换时对时间进行格式化而不是在json序列化时自动格式化DTO 层这个说法严格来讲是错误的dto 只是一个存储数据对象的目录只是有时候把它叫做层才能显得它里边也能搞点什么而不是纯数据对象。经过约 两小时的查资料、研究终于找到了完美时间格式转换方案我们有dto层model本来就需要转dto只是json序列化时转换的写法又太啰嗦每个dto都要写MarshalJSON最终安装github.com/jinzhu/copier依赖这是一个数据拷贝工具可以方便的将model拷贝到dto避免将字段一一对应的硬编码copier在进行数据拷贝时可以自定义一些转换器据此我创建了pkg/copierx包x是社区惯例意思是copier的扩展里边建立一个converter.go文件存放所有的自定义转换器第一个转换器就是copierx.Time用于在数据装换时将2006-01-02T15:04:05Z07:00转化为任意自定义的事件格式用法如下iferr:copier.CopyWithOption(dto.Admin,adminModel,copier.Option{// time.DateTime 就是我们想要的格式Converters:[]copier.TypeConverter{copierx.Time(time.DateTime)},});err!nil{returnnil,数据转换失败}不涉及时间的还可以直接用copier.Copy涉及时间的就是上面这种copier.CopyWithOption的写法然后将我们自定义的Time转换器放进去大佬们这是否是最完美的方案你项目的时间格式转换方案是什么呢