feat: 生命阶段按猫狗真实生理规律细分,划分标准和判定用同一份数据
## 你问的「养了半年会不会自动切换」
原来的答案是「都不会,而且比这更糟」:
age「2个月」 建档时算好存进库,养半年后首页还显示 2个月
stage「幼年期」同上,一年后还是幼年期
养护方案 按 stage 挑的,所以永远给幼猫那套
NormalizeStage 只在建档那一次调用(handler/pet.go:51),之后就是两个死字符串。
现在:
age 改成计算字段(gorm:"-"),读取时现算。它没有手改需求,存下来只会过期。
填在 ownedPet 这个收口里,不是逐个函数补——那样漏一个就返回空年龄。
stage 保留存储(有正当的手改需求:领养的猫生日是估的,主人按体型判断更准),
但加了漂移检测 GET /pets/:id/stage-drift。
**系统负责发现,用户负责决定。** 不自动改的三个理由:
1. 用户可能手改过
2. 已经排好的这个月计划不该被推翻(套用是「往里加」不是「替换」)
3. 偷偷换会让用户莫名发现计划变了,找不到原因
## 猫狗不能共用阈值 —— 这是这次最实质的发现
原来一刀切「<12月幼年,>=7岁老年」,对猫勉强,对狗两头都错:
吉娃娃 8 个月已性成熟、可换成犬粮;大丹犬 8 个月还在长骨头,
这时喂成犬粮(钙磷比和热量密度都不同)会加重关节负担。
吉娃娃 7 岁还在成年期(8 岁才进中年,能活 13-16 年);
大丹犬 7 岁已是老年(平均寿命 7-10 年)。
所以狗的阶段判定要看体型。体型不能靠当前体重(幼犬体重说明不了成年后多大),
只能靠品种 —— breeds 表加 size_class,45 个犬种逐个标了。
实测:同样 10 个月大 → 吉娃娃青年期、柴犬幼年期、金毛幼年期、大丹犬幼年期;
同样 7 岁 → 吉娃娃成年期、大丹犬老年期。
## 阶段 3 段 → 5 段
幼年期 / 青年期 / 成年期 / 中年期 / 老年期。
标签做成物种中立(不分幼猫期/幼犬期)——物种本来是另一个字段,
分开会让 (species,stage) 的组合和方案配置都翻倍。
「刚到家 0-30 天」不进这五段:它和年龄正交(刚接回家的成年猫两套都需要),
代码里本来就是叠加处理的。
猫按 AAFP/AAHA 猫生命阶段指南那套,在成年里细分出中年。
狗五段的阈值按体型走四组,越大的犬种生长期越长、老得越早。
## 划分标准和判定用同一张表
StageRules 那张表既驱动判定,也直接吐给前端当依据展示
(GET /api/life-stages?species=dog&size=giant)。
不是「代码里判定 + 文档里写标准」——后者一定会漂:改了阈值忘了改文档,
用户看到的说明和实际行为对不上,比没有说明更糟。
建档第三步的阶段选择器现在会显示「0-18 月 · 巨型犬生长期最长,18 个月还在长;
这阶段最忌过度补钙」,还会标出「巨型犬(成年 >40kg)——阶段阈值按体型算」。
前端和后台的 STAGES 硬编码列表都删了,改成读后端。
## 10 套方案,内容按各阶段真实重点配
不是把同一份换个名字:
幼年期 疫苗序列 + 驱虫 + 社会化,大型犬还要控制生长速度
青年期 绝育窗口 + 换成年粮
成年期 维持期,把基线数据记下来
中年期 年度血检开始有意义,体重和牙结石重点看
老年期 体检半年一次;猫记饮水量(多饮多尿是慢性肾病最典型的早期表现)、
狗记精神食欲,都设成「重要」
老的 8 套(按 3 段配的)改名停用不删:万一新内容有问题还能翻回去看;
而且已套用出去的计划早就和模板断开了,停用不影响任何用户。
## 验证(预生产库实跑)
体型判定 10 个月 / 7 岁两组对照,四个体型都落在预期阶段
age '13个月' 现算,不入库
漂移检测 手改成幼年期后 drifted=true,连带给出新阶段的依据和重点
划分标准 猫 5 段、狗 4 个体型各 5 段,老年起点 7/8/10/11 岁
全链路 3 个月大丹犬建档 → 幼年期 → 0 任务 + 4 条必要提醒 →
挑「幼犬标准照护」→ 套用下月 104 条节点,
周四那天正确出现每周项(检查爪垫和耳朵)
迁移 45 个犬种体型回填;现有 5 只宠物阶段重算后无变化(原本都对)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,233 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/sundynix/pets-be/internal/model"
|
||||
)
|
||||
|
||||
// 养护方案预置:5 个阶段 × 2 物种,各一套「标准照护」。
|
||||
//
|
||||
// 内容按各阶段的真实生理重点配,不是把同一份东西换个名字:
|
||||
// 幼年期 疫苗序列 + 驱虫 + 社会化,大型犬还要控制生长速度
|
||||
// 青年期 绝育窗口 + 换成年粮
|
||||
// 成年期 维持期,重点是把基线数据记下来(体重趋势、年度体检)
|
||||
// 中年期 年度血检开始有意义,体重和牙结石重点看
|
||||
// 老年期 体检频率加倍,猫看肾和甲状腺、狗看关节和心脏
|
||||
//
|
||||
// 和 record_types / breeds 一样只在表为空时铺一次,之后一切以数据库为准。
|
||||
//
|
||||
// 这些是「结构」不是「内容」:方案表空着的话建档最后一步没东西可挑,
|
||||
// 用户建完档只能自己从零排计划。
|
||||
|
||||
func plan(title, desc, repeat, sheet string) model.CareTemplateItem {
|
||||
return model.CareTemplateItem{Kind: model.CareKindPlan, Repeat: repeat,
|
||||
Title: title, Description: desc, SheetType: sheet}
|
||||
}
|
||||
func weekly(title, desc, weekdays, sheet string) model.CareTemplateItem {
|
||||
it := plan(title, desc, model.RepeatWeekly, sheet)
|
||||
it.Weekdays = weekdays
|
||||
return it
|
||||
}
|
||||
func monthly(title, desc string, day int, sheet string) model.CareTemplateItem {
|
||||
it := plan(title, desc, model.RepeatMonthly, sheet)
|
||||
it.MonthDay = day
|
||||
return it
|
||||
}
|
||||
func once(title, desc string, day int, sheet string) model.CareTemplateItem {
|
||||
it := plan(title, desc, model.RepeatOnce, sheet)
|
||||
it.Day = day
|
||||
return it
|
||||
}
|
||||
func remind(rtype, title string, offset int, freq string) model.CareTemplateItem {
|
||||
return model.CareTemplateItem{Kind: model.CareKindReminder, ReminderType: rtype,
|
||||
Title: title, OffsetDays: offset, Frequency: freq}
|
||||
}
|
||||
func important(it model.CareTemplateItem) model.CareTemplateItem {
|
||||
it.Priority = "重要"
|
||||
return it
|
||||
}
|
||||
|
||||
// TplDef 一套方案的定义(迁移程序要读它)
|
||||
type tplDef struct {
|
||||
Species string
|
||||
Stage string
|
||||
Name string
|
||||
Summary string
|
||||
Items []model.CareTemplateItem
|
||||
}
|
||||
|
||||
// CareTemplateDefs 导出给一次性迁移程序用
|
||||
func CareTemplateDefs() []tplDef { return careTemplateDefs() }
|
||||
|
||||
// SeedCareTemplatesForce 不检查表空,直接铺。只给迁移程序用
|
||||
func SeedCareTemplatesForce(db *gorm.DB) error { return insertCareTemplates(db) }
|
||||
|
||||
func careTemplateDefs() []tplDef {
|
||||
const (
|
||||
J = "幼年期"
|
||||
Y = "青年期"
|
||||
A = "成年期"
|
||||
M = "中年期"
|
||||
S = "老年期"
|
||||
)
|
||||
return []tplDef{
|
||||
// ───────────────── 猫 ─────────────────
|
||||
{model.SpeciesCat, J, "幼猫标准照护", "少量多餐、疫苗序列和社会化,六月龄前把基础打好", []model.CareTemplateItem{
|
||||
important(plan("喂食 3-4 次", "幼猫胃容量小,一天分 3-4 顿,用幼猫粮", model.RepeatDaily, "food")),
|
||||
plan("清理猫砂盆", "每天铲一次,顺手看便便形状和颜色", model.RepeatDaily, "litterbox"),
|
||||
plan("陪玩 15 分钟", "逗猫棒模拟狩猎,消耗精力也是社会化", model.RepeatDaily, ""),
|
||||
weekly("称一次体重", "幼猫每周都在长,体重曲线比单次数值有用", "1", "weight"),
|
||||
weekly("检查耳朵和眼睛", "幼猫耳螨和眼部分泌物高发", "4", "ear"),
|
||||
once("核对疫苗进度", "对照月龄看第几针,三针核心疫苗要在六月龄前打完", 2, "vaccine"),
|
||||
once("首次体内驱虫", "幼猫驱虫比成猫频繁,按体重给药", 5, "deworm"),
|
||||
remind("vaccine", "下一针疫苗", 21, "幼猫期每 3-4 周一针,共三针"),
|
||||
remind("deworm", "体内外驱虫", 30, "幼猫每月一次"),
|
||||
remind("weight", "记录体重", 7, "每周一次"),
|
||||
}},
|
||||
{model.SpeciesCat, Y, "青年猫标准照护", "绝育窗口、换成猫粮,开始把体重控住", []model.CareTemplateItem{
|
||||
plan("喂食 2 次", "六月龄后可以改成早晚两顿", model.RepeatDaily, "food"),
|
||||
plan("清理猫砂盆", "每天铲一次", model.RepeatDaily, "litterbox"),
|
||||
plan("陪玩 15 分钟", "性成熟后精力旺盛,玩够了才不拆家", model.RepeatDaily, ""),
|
||||
weekly("称一次体重", "绝育前后代谢会变,体重要盯紧", "1", "weight"),
|
||||
weekly("梳毛", "换毛期减少毛球", "4", "brush"),
|
||||
once("咨询绝育时间", "多数猫 6-8 月龄可做,术前要空腹和体检", 3, "vet"),
|
||||
once("换成猫粮", "一岁前后用 7 天时间按比例过渡,别一次换完", 14, "food"),
|
||||
remind("vaccine", "年度加强疫苗", 60, "一年一次"),
|
||||
remind("deworm", "体内外驱虫", 60, "每 2-3 个月一次"),
|
||||
}},
|
||||
{model.SpeciesCat, A, "成年猫标准照护", "维持期,重点是把基线数据记下来", []model.CareTemplateItem{
|
||||
plan("喂食和换水", "定时定量,水每天换", model.RepeatDaily, "food"),
|
||||
plan("清理猫砂盆", "每天铲一次,便便异常是最早的信号", model.RepeatDaily, "litterbox"),
|
||||
weekly("梳毛", "长毛猫每天,短毛猫每周两次", "2,5", "brush"),
|
||||
weekly("刷牙", "牙结石是成年猫最常被忽略的问题", "6", "tooth"),
|
||||
monthly("称一次体重", "成年后体重该是平的,涨跌超过 5% 要留意", 1, "weight"),
|
||||
monthly("洗猫砂盆", "整盆倒空清洗一次", 15, "litterbox"),
|
||||
once("安排年度体检", "成年期一年一次,做基础血检建立基线", 7, "checkup"),
|
||||
remind("vaccine", "年度加强疫苗", 90, "一年一次"),
|
||||
remind("deworm", "体内外驱虫", 90, "每 3 个月一次"),
|
||||
remind("monthlyReport", "看看这个月的记录", 30, "每月一次"),
|
||||
}},
|
||||
{model.SpeciesCat, M, "中年猫标准照护", "七岁起代谢变慢,年度血检开始能查出早期问题", []model.CareTemplateItem{
|
||||
plan("喂食和换水", "中年后容易发胖,按体重控制热量", model.RepeatDaily, "food"),
|
||||
plan("清理猫砂盆", "尿量和尿块大小要留意,肾病最早从这里看出来", model.RepeatDaily, "litterbox"),
|
||||
weekly("梳毛", "自我梳理会减少,需要帮忙", "2,5", "brush"),
|
||||
weekly("刷牙", "牙结石到这个年龄已经开始影响进食", "6", "tooth"),
|
||||
monthly("称一次体重", "不明原因掉体重是中年猫要警惕的信号", 1, "weight"),
|
||||
monthly("检查口腔", "看牙龈颜色和有没有结石", 15, ""),
|
||||
once("安排年度体检", "血检 + 尿检,重点看肾功能和甲状腺", 7, "checkup"),
|
||||
remind("vaccine", "年度加强疫苗", 90, "一年一次"),
|
||||
remind("deworm", "体内外驱虫", 90, "每 3 个月一次"),
|
||||
remind("weight", "记录体重", 30, "每月一次"),
|
||||
}},
|
||||
{model.SpeciesCat, S, "老年猫标准照护", "体检半年一次,肾和甲状腺是重点", []model.CareTemplateItem{
|
||||
important(plan("记录饮水量", "多饮多尿是慢性肾病最典型的早期表现", model.RepeatDaily, "water")),
|
||||
plan("喂食", "老年猫可能需要处方粮,少量多次更好消化", model.RepeatDaily, "food"),
|
||||
plan("清理猫砂盆", "尿块变大或变多要立刻记下来", model.RepeatDaily, "litterbox"),
|
||||
weekly("梳毛", "老年猫自己舔不到的地方要帮它梳", "2,5", "brush"),
|
||||
weekly("称一次体重", "老年期体重变化要按周盯,不是按月", "1", "weight"),
|
||||
monthly("检查关节活动", "跳不上原来能跳的地方就是信号", 1, ""),
|
||||
once("安排半年体检", "血检 + 尿检 + 甲状腺,老年期半年一次", 7, "checkup"),
|
||||
remind("vaccine", "年度加强疫苗", 90, "一年一次(可与医生商量减免)"),
|
||||
remind("deworm", "体内外驱虫", 90, "每 3 个月一次"),
|
||||
remind("monthlyReport", "看看这个月的记录", 30, "每月一次"),
|
||||
}},
|
||||
|
||||
// ───────────────── 狗 ─────────────────
|
||||
{model.SpeciesDog, J, "幼犬标准照护", "疫苗序列、社会化,大型犬还要控制生长速度", []model.CareTemplateItem{
|
||||
important(plan("喂食 3-4 次", "幼犬一天分 3-4 顿;大型犬别过量补钙,长太快伤关节", model.RepeatDaily, "food")),
|
||||
plan("外出排便和散步", "疫苗打齐前避免去流浪动物多的地方", model.RepeatDaily, ""),
|
||||
plan("基础训练 10 分钟", "坐、等待、唤回。幼犬期是社会化窗口,错过很难补", model.RepeatDaily, ""),
|
||||
weekly("称一次体重", "幼犬长得快,体重曲线也是喂食量的依据", "1", "weight"),
|
||||
weekly("检查爪垫和耳朵", "散步后看有没有扎伤,垂耳犬要重点看耳道", "4", "ear"),
|
||||
once("核对疫苗进度", "对照月龄看第几针,狂犬疫苗按当地规定单独安排", 2, "vaccine"),
|
||||
once("首次体内驱虫", "按体重给药,幼犬比成犬频繁", 5, "deworm"),
|
||||
remind("vaccine", "下一针疫苗", 21, "幼犬期每 3-4 周一针"),
|
||||
remind("deworm", "体内外驱虫", 30, "幼犬每月一次"),
|
||||
remind("weight", "记录体重", 7, "每周一次"),
|
||||
}},
|
||||
{model.SpeciesDog, Y, "青年犬标准照护", "骨骼刚闭合,可以加运动量了;绝育窗口也在这里", []model.CareTemplateItem{
|
||||
plan("喂食 2 次", "改成早晚两顿", model.RepeatDaily, "food"),
|
||||
plan("散步 30 分钟以上", "骨骼闭合后可以正常运动,之前不宜长距离跑跳", model.RepeatDaily, ""),
|
||||
plan("训练 10 分钟", "把幼犬期学的固化下来", model.RepeatDaily, ""),
|
||||
weekly("称一次体重", "换成犬粮期间容易长胖", "1", "weight"),
|
||||
weekly("梳毛", "换毛期每天,平时每周两次", "2,5", "brush"),
|
||||
once("咨询绝育时间", "大型犬建议等骨骼闭合后再做", 3, "vet"),
|
||||
once("换成犬粮", "用 7 天按比例过渡,别一次换完", 14, "food"),
|
||||
remind("vaccine", "年度加强疫苗", 60, "一年一次"),
|
||||
remind("deworm", "体内外驱虫", 60, "每 2-3 个月一次"),
|
||||
}},
|
||||
{model.SpeciesDog, A, "成年犬标准照护", "维持期,重点是把基线数据记下来", []model.CareTemplateItem{
|
||||
plan("喂食和换水", "定时定量,水每天换", model.RepeatDaily, "food"),
|
||||
plan("散步 30-60 分钟", "运动量不够是成年犬发胖和行为问题的主因", model.RepeatDaily, ""),
|
||||
weekly("梳毛", "顺手摸一遍有没有肿块", "2,5", "brush"),
|
||||
weekly("刷牙", "牙结石是成年犬最常被忽略的问题", "6", "tooth"),
|
||||
monthly("称一次体重", "成年后体重该是平的,涨跌超过 5% 要留意", 1, "weight"),
|
||||
monthly("剪指甲", "听到走路哒哒响就该剪了", 15, "nail"),
|
||||
once("安排年度体检", "一年一次,做基础血检建立基线", 7, "checkup"),
|
||||
remind("vaccine", "年度加强疫苗", 90, "一年一次"),
|
||||
remind("deworm", "体内外驱虫", 90, "每 3 个月一次"),
|
||||
remind("monthlyReport", "看看这个月的记录", 30, "每月一次"),
|
||||
}},
|
||||
{model.SpeciesDog, M, "中年犬标准照护", "体重和关节是重点,年度血检开始有意义", []model.CareTemplateItem{
|
||||
plan("喂食和换水", "代谢变慢,按体重下调热量", model.RepeatDaily, "food"),
|
||||
plan("散步 30 分钟", "保持规律但降低强度,避免急停急转", model.RepeatDaily, ""),
|
||||
weekly("梳毛并摸一遍身体", "中年后肿块发生率上升,每周摸一遍是最便宜的筛查", "2,5", "brush"),
|
||||
weekly("刷牙", "牙结石到这个年龄已经开始影响进食", "6", "tooth"),
|
||||
monthly("称一次体重", "中年犬超重会直接加重关节负担", 1, "weight"),
|
||||
monthly("检查关节活动", "起身变慢、不愿上楼就是信号", 15, ""),
|
||||
once("安排年度体检", "血检 + 关节检查,大型犬加拍髋关节", 7, "checkup"),
|
||||
remind("vaccine", "年度加强疫苗", 90, "一年一次"),
|
||||
remind("deworm", "体内外驱虫", 90, "每 3 个月一次"),
|
||||
remind("weight", "记录体重", 30, "每月一次"),
|
||||
}},
|
||||
{model.SpeciesDog, S, "老年犬标准照护", "体检半年一次,关节和心脏是重点", []model.CareTemplateItem{
|
||||
important(plan("记录精神和食欲", "老年犬变化来得快,每天一句话记下来", model.RepeatDaily, "")),
|
||||
plan("喂食", "老年犬可能需要处方粮,少量多次更好消化", model.RepeatDaily, "food"),
|
||||
plan("散步 15-20 分钟", "短而多次,比一次走久对关节友好", model.RepeatDaily, ""),
|
||||
weekly("梳毛并摸一遍身体", "重点摸有没有新长的肿块", "2,5", "brush"),
|
||||
weekly("称一次体重", "老年期体重变化要按周盯", "1", "weight"),
|
||||
monthly("检查关节和牙齿", "起身、上楼、咀嚼有没有变吃力", 1, ""),
|
||||
once("安排半年体检", "血检 + 心脏听诊 + 关节,老年期半年一次", 7, "checkup"),
|
||||
remind("vaccine", "年度加强疫苗", 90, "一年一次(可与医生商量减免)"),
|
||||
remind("deworm", "体内外驱虫", 90, "每 3 个月一次"),
|
||||
remind("monthlyReport", "看看这个月的记录", 30, "每月一次"),
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
// seedCareTemplates 只在方案表为空时铺一次
|
||||
func seedCareTemplates(db *gorm.DB) error {
|
||||
var count int64
|
||||
if err := db.Model(&model.CareTemplate{}).Count(&count).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if count > 0 {
|
||||
return nil
|
||||
}
|
||||
return insertCareTemplates(db)
|
||||
}
|
||||
|
||||
func insertCareTemplates(db *gorm.DB) error {
|
||||
for i, d := range careTemplateDefs() {
|
||||
tpl := model.CareTemplate{
|
||||
Species: d.Species, Stage: d.Stage, Name: d.Name,
|
||||
Summary: d.Summary, Sort: (i + 1) * 10, Enabled: true,
|
||||
}
|
||||
if err := db.Create(&tpl).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
items := make([]model.CareTemplateItem, 0, len(d.Items))
|
||||
for j, it := range d.Items {
|
||||
it.TemplateID = tpl.ID
|
||||
it.Sort = j
|
||||
items = append(items, it)
|
||||
}
|
||||
if len(items) > 0 {
|
||||
if err := db.Create(&items).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -23,7 +23,10 @@ func Seed(db *gorm.DB, cfg *config.Config) error {
|
||||
if err := seedRecordTypes(db); err != nil {
|
||||
return err
|
||||
}
|
||||
return seedBreeds(db)
|
||||
if err := seedBreeds(db); err != nil {
|
||||
return err
|
||||
}
|
||||
return seedCareTemplates(db)
|
||||
}
|
||||
|
||||
// seedBreeds 品种预置。同 record_types:只在表完全为空时铺一次。
|
||||
@@ -76,51 +79,51 @@ func seedBreeds(db *gorm.DB) error {
|
||||
{Species: model.SpeciesCat, Initial: "Y", Name: "英国短毛猫", Sort: 330},
|
||||
{Species: model.SpeciesCat, Initial: "Z", Name: "中华田园猫", Sort: 340},
|
||||
// 狗 46 种
|
||||
{Species: model.SpeciesDog, Initial: "A", Name: "阿拉斯加雪橇犬", Sort: 10},
|
||||
{Species: model.SpeciesDog, Initial: "A", Name: "阿富汗猎犬", Sort: 20},
|
||||
{Species: model.SpeciesDog, Initial: "A", Name: "澳洲牧羊犬", Sort: 30},
|
||||
{Species: model.SpeciesDog, Initial: "B", Name: "比熊犬", Sort: 40},
|
||||
{Species: model.SpeciesDog, Initial: "B", Name: "比格犬", Sort: 50},
|
||||
{Species: model.SpeciesDog, Initial: "B", Name: "边境牧羊犬", Sort: 60},
|
||||
{Species: model.SpeciesDog, Initial: "B", Name: "巴哥犬", Sort: 70},
|
||||
{Species: model.SpeciesDog, Initial: "B", Name: "博美犬", Sort: 80},
|
||||
{Species: model.SpeciesDog, Initial: "B", Name: "巴吉度猎犬", Sort: 90},
|
||||
{Species: model.SpeciesDog, Initial: "B", Name: "北京犬", Sort: 100},
|
||||
{Species: model.SpeciesDog, Initial: "C", Name: "柴犬", Sort: 110},
|
||||
{Species: model.SpeciesDog, Initial: "C", Name: "川东猎犬", Sort: 120},
|
||||
{Species: model.SpeciesDog, Initial: "D", Name: "德国牧羊犬", Sort: 130},
|
||||
{Species: model.SpeciesDog, Initial: "D", Name: "杜宾犬", Sort: 140},
|
||||
{Species: model.SpeciesDog, Initial: "D", Name: "大丹犬", Sort: 150},
|
||||
{Species: model.SpeciesDog, Initial: "D", Name: "斗牛犬", Sort: 160},
|
||||
{Species: model.SpeciesDog, Initial: "F", Name: "法国斗牛犬", Sort: 170},
|
||||
{Species: model.SpeciesDog, Initial: "G", Name: "贵宾犬(泰迪)", Sort: 180},
|
||||
{Species: model.SpeciesDog, Initial: "G", Name: "古代牧羊犬", Sort: 190},
|
||||
{Species: model.SpeciesDog, Initial: "H", Name: "哈士奇", Sort: 200},
|
||||
{Species: model.SpeciesDog, Initial: "H", Name: "蝴蝶犬", Sort: 210},
|
||||
{Species: model.SpeciesDog, Initial: "J", Name: "金毛寻回犬", Sort: 220},
|
||||
{Species: model.SpeciesDog, Initial: "J", Name: "吉娃娃", Sort: 230},
|
||||
{Species: model.SpeciesDog, Initial: "K", Name: "柯基犬", Sort: 240},
|
||||
{Species: model.SpeciesDog, Initial: "K", Name: "可卡犬", Sort: 250},
|
||||
{Species: model.SpeciesDog, Initial: "K", Name: "苏格兰柯利犬", Sort: 260},
|
||||
{Species: model.SpeciesDog, Initial: "L", Name: "拉布拉多寻回犬", Sort: 270},
|
||||
{Species: model.SpeciesDog, Initial: "L", Name: "罗威纳犬", Sort: 280},
|
||||
{Species: model.SpeciesDog, Initial: "L", Name: "灵缇犬", Sort: 290},
|
||||
{Species: model.SpeciesDog, Initial: "L", Name: "腊肠犬", Sort: 300},
|
||||
{Species: model.SpeciesDog, Initial: "M", Name: "马尔济斯犬", Sort: 310},
|
||||
{Species: model.SpeciesDog, Initial: "M", Name: "迷你雪纳瑞", Sort: 320},
|
||||
{Species: model.SpeciesDog, Initial: "N", Name: "牛头梗", Sort: 330},
|
||||
{Species: model.SpeciesDog, Initial: "Q", Name: "秋田犬", Sort: 340},
|
||||
{Species: model.SpeciesDog, Initial: "S", Name: "萨摩耶", Sort: 350},
|
||||
{Species: model.SpeciesDog, Initial: "S", Name: "松狮犬", Sort: 360},
|
||||
{Species: model.SpeciesDog, Initial: "S", Name: "圣伯纳犬", Sort: 370},
|
||||
{Species: model.SpeciesDog, Initial: "X", Name: "雪纳瑞", Sort: 390},
|
||||
{Species: model.SpeciesDog, Initial: "X", Name: "西高地白梗", Sort: 400},
|
||||
{Species: model.SpeciesDog, Initial: "X", Name: "喜乐蒂牧羊犬", Sort: 410},
|
||||
{Species: model.SpeciesDog, Initial: "Y", Name: "约克夏梗", Sort: 420},
|
||||
{Species: model.SpeciesDog, Initial: "Y", Name: "银狐犬", Sort: 430},
|
||||
{Species: model.SpeciesDog, Initial: "Z", Name: "中华田园犬", Sort: 440},
|
||||
{Species: model.SpeciesDog, Initial: "Z", Name: "中亚牧羊犬", Sort: 450},
|
||||
{Species: model.SpeciesDog, Initial: "Z", Name: "藏獒", Sort: 460},
|
||||
{Species: model.SpeciesDog, Initial: "A", Name: "阿拉斯加雪橇犬", SizeClass: "large", Sort: 10},
|
||||
{Species: model.SpeciesDog, Initial: "A", Name: "阿富汗猎犬", SizeClass: "large", Sort: 20},
|
||||
{Species: model.SpeciesDog, Initial: "A", Name: "澳洲牧羊犬", SizeClass: "medium", Sort: 30},
|
||||
{Species: model.SpeciesDog, Initial: "B", Name: "比熊犬", SizeClass: "small", Sort: 40},
|
||||
{Species: model.SpeciesDog, Initial: "B", Name: "比格犬", SizeClass: "medium", Sort: 50},
|
||||
{Species: model.SpeciesDog, Initial: "B", Name: "边境牧羊犬", SizeClass: "medium", Sort: 60},
|
||||
{Species: model.SpeciesDog, Initial: "B", Name: "巴哥犬", SizeClass: "small", Sort: 70},
|
||||
{Species: model.SpeciesDog, Initial: "B", Name: "博美犬", SizeClass: "small", Sort: 80},
|
||||
{Species: model.SpeciesDog, Initial: "B", Name: "巴吉度猎犬", SizeClass: "medium", Sort: 90},
|
||||
{Species: model.SpeciesDog, Initial: "B", Name: "北京犬", SizeClass: "small", Sort: 100},
|
||||
{Species: model.SpeciesDog, Initial: "C", Name: "柴犬", SizeClass: "medium", Sort: 110},
|
||||
{Species: model.SpeciesDog, Initial: "C", Name: "川东猎犬", SizeClass: "medium", Sort: 120},
|
||||
{Species: model.SpeciesDog, Initial: "D", Name: "德国牧羊犬", SizeClass: "large", Sort: 130},
|
||||
{Species: model.SpeciesDog, Initial: "D", Name: "杜宾犬", SizeClass: "large", Sort: 140},
|
||||
{Species: model.SpeciesDog, Initial: "D", Name: "大丹犬", SizeClass: "giant", Sort: 150},
|
||||
{Species: model.SpeciesDog, Initial: "D", Name: "斗牛犬", SizeClass: "medium", Sort: 160},
|
||||
{Species: model.SpeciesDog, Initial: "F", Name: "法国斗牛犬", SizeClass: "medium", Sort: 170},
|
||||
{Species: model.SpeciesDog, Initial: "G", Name: "贵宾犬(泰迪)", SizeClass: "small", Sort: 180},
|
||||
{Species: model.SpeciesDog, Initial: "G", Name: "古代牧羊犬", SizeClass: "medium", Sort: 190},
|
||||
{Species: model.SpeciesDog, Initial: "H", Name: "哈士奇", SizeClass: "large", Sort: 200},
|
||||
{Species: model.SpeciesDog, Initial: "H", Name: "蝴蝶犬", SizeClass: "small", Sort: 210},
|
||||
{Species: model.SpeciesDog, Initial: "J", Name: "金毛寻回犬", SizeClass: "large", Sort: 220},
|
||||
{Species: model.SpeciesDog, Initial: "J", Name: "吉娃娃", SizeClass: "small", Sort: 230},
|
||||
{Species: model.SpeciesDog, Initial: "K", Name: "柯基犬", SizeClass: "small", Sort: 240},
|
||||
{Species: model.SpeciesDog, Initial: "K", Name: "可卡犬", SizeClass: "medium", Sort: 250},
|
||||
{Species: model.SpeciesDog, Initial: "K", Name: "苏格兰柯利犬", SizeClass: "medium", Sort: 260},
|
||||
{Species: model.SpeciesDog, Initial: "L", Name: "拉布拉多寻回犬", SizeClass: "large", Sort: 270},
|
||||
{Species: model.SpeciesDog, Initial: "L", Name: "罗威纳犬", SizeClass: "large", Sort: 280},
|
||||
{Species: model.SpeciesDog, Initial: "L", Name: "灵缇犬", SizeClass: "large", Sort: 290},
|
||||
{Species: model.SpeciesDog, Initial: "L", Name: "腊肠犬", SizeClass: "small", Sort: 300},
|
||||
{Species: model.SpeciesDog, Initial: "M", Name: "马尔济斯犬", SizeClass: "small", Sort: 310},
|
||||
{Species: model.SpeciesDog, Initial: "M", Name: "迷你雪纳瑞", SizeClass: "small", Sort: 320},
|
||||
{Species: model.SpeciesDog, Initial: "N", Name: "牛头梗", SizeClass: "medium", Sort: 330},
|
||||
{Species: model.SpeciesDog, Initial: "Q", Name: "秋田犬", SizeClass: "large", Sort: 340},
|
||||
{Species: model.SpeciesDog, Initial: "S", Name: "萨摩耶", SizeClass: "large", Sort: 350},
|
||||
{Species: model.SpeciesDog, Initial: "S", Name: "松狮犬", SizeClass: "medium", Sort: 360},
|
||||
{Species: model.SpeciesDog, Initial: "S", Name: "圣伯纳犬", SizeClass: "giant", Sort: 370},
|
||||
{Species: model.SpeciesDog, Initial: "X", Name: "雪纳瑞", SizeClass: "medium", Sort: 390},
|
||||
{Species: model.SpeciesDog, Initial: "X", Name: "西高地白梗", SizeClass: "small", Sort: 400},
|
||||
{Species: model.SpeciesDog, Initial: "X", Name: "喜乐蒂牧羊犬", SizeClass: "small", Sort: 410},
|
||||
{Species: model.SpeciesDog, Initial: "Y", Name: "约克夏梗", SizeClass: "small", Sort: 420},
|
||||
{Species: model.SpeciesDog, Initial: "Y", Name: "银狐犬", SizeClass: "medium", Sort: 430},
|
||||
{Species: model.SpeciesDog, Initial: "Z", Name: "中华田园犬", SizeClass: "medium", Sort: 440},
|
||||
{Species: model.SpeciesDog, Initial: "Z", Name: "中亚牧羊犬", SizeClass: "large", Sort: 450},
|
||||
{Species: model.SpeciesDog, Initial: "Z", Name: "藏獒", SizeClass: "giant", Sort: 460},
|
||||
}
|
||||
for i := range breeds {
|
||||
breeds[i].Enabled = true
|
||||
|
||||
Reference in New Issue
Block a user