- 新增 GET/PUT /api/me:登录用户可查看并修改自己的 nickname/gender/birthday,空串清空、缺省保持不变,生日校验格式与未来日期 - users 表新增 gender/birthday 字段(迁移 v6)及 model.Date 日期类型,管理员用户接口同步支持 - 前端新增 /profile 个人中心页面、头像下拉入口与登录守卫,保存后同步会话用户信息 - 静态服务对未命中的无扩展名路径回退 index.html,避免刷新前端路由 404 - 重新生成 Swagger 文档,补充 /api/me 与资料字段相关测试
82 lines
1.7 KiB
Go
82 lines
1.7 KiB
Go
package model
|
|
|
|
import (
|
|
"database/sql/driver"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
const dateLayout = "2006-01-02"
|
|
|
|
// Date 仅日期字段(YYYY-MM-DD),零值表示未设置,JSON 序列化为 null。
|
|
type Date struct {
|
|
time.Time
|
|
}
|
|
|
|
// IsZero 是否未设置。
|
|
func (d Date) IsZero() bool {
|
|
return d.Time.IsZero()
|
|
}
|
|
|
|
// Value 实现 driver.Valuer:零值写入 NULL。
|
|
func (d Date) Value() (driver.Value, error) {
|
|
if d.Time.IsZero() {
|
|
return nil, nil
|
|
}
|
|
return d.Time.Format(dateLayout), nil
|
|
}
|
|
|
|
// Scan 实现 sql.Scanner,兼容 time.Time、字符串与 []byte。
|
|
func (d *Date) Scan(value any) error {
|
|
switch v := value.(type) {
|
|
case nil:
|
|
d.Time = time.Time{}
|
|
case time.Time:
|
|
d.Time = v
|
|
case string:
|
|
return d.parse(v)
|
|
case []byte:
|
|
return d.parse(string(v))
|
|
default:
|
|
return fmt.Errorf("unsupported date value: %T", value)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *Date) parse(value string) error {
|
|
if value == "" {
|
|
d.Time = time.Time{}
|
|
return nil
|
|
}
|
|
for _, layout := range []string{dateLayout, time.RFC3339} {
|
|
if parsed, err := time.Parse(layout, value); err == nil {
|
|
d.Time = parsed
|
|
return nil
|
|
}
|
|
}
|
|
return errors.New("invalid date: " + value)
|
|
}
|
|
|
|
// MarshalJSON 输出 YYYY-MM-DD,未设置时输出 null。
|
|
func (d Date) MarshalJSON() ([]byte, error) {
|
|
if d.Time.IsZero() {
|
|
return []byte("null"), nil
|
|
}
|
|
return json.Marshal(d.Time.Format(dateLayout))
|
|
}
|
|
|
|
// UnmarshalJSON 支持 null、空串与 YYYY-MM-DD。
|
|
func (d *Date) UnmarshalJSON(data []byte) error {
|
|
if string(data) == "null" {
|
|
d.Time = time.Time{}
|
|
return nil
|
|
}
|
|
var value string
|
|
if err := json.Unmarshal(data, &value); err != nil {
|
|
return err
|
|
}
|
|
return d.parse(value)
|
|
}
|