소스 검색

fix:修正tou模版结构体类型,明确日表的类型逻辑

Jerry Liang 2 달 전
부모
커밋
b04c8346fd
3개의 변경된 파일과 160개의 추가작업 그리고 123개의 파일을 삭제
  1. 92 67
      service/cmd/mcp/.kiro/skills/tou-template-scheduling/SKILL.md
  2. 2 2
      service/cmd/mcp/tools/service/tou_template.go
  3. 66 54
      service/dto/fwhTestTouTemplateDTO.go

+ 92 - 67
service/cmd/mcp/.kiro/skills/tou-template-scheduling/SKILL.md

@@ -49,27 +49,27 @@ save 与 cites 目前仅支持 `test`。读操作默认走 `pro`,需要读测
 }
 ```
 
-- 所有字段都是 JSON **字符串**。数值型字段以「字符串形式的数字」传递;**未设置的字段传空串 `""`**(不要传 `null`)。**例外**:`strategyList[]` 下的策略级电价字段(`eleticRatePeak`/`eleticSellPeak` 等 11 个)是**数值类型**,未设置传 `null`(见「策略级电价字段」)。
-- `template.templateId`:**创建模板时不需要此字段(省略);更新模板时必须带此字段并填入模板 ID**。读取(`detail`/`list` 返回)时该字段必定存在。
-- `template.sourceType`:**必填**。当前**仅允许写入系统模板 `"0"`**(`1`API模板 / `2`用户推荐 暂不支持写入,`save` 会拒绝)。
+- 字段按真实类型传值:**数值字段传数字(不是字符串)**,字符串字段传字符串。**可选的数值字段未设置时直接省略该 key**(不要传空串 `""`,也不要传 `null`)。
+- `template.templateId`:**创建模板时不需要此字段(省略);更新模板时必须带此字段并填入模板 ID(数值)**。读取(`detail`/`list` 返回)时该字段必定存在。
+- `template.sourceType`:**必填**(数值)。当前**仅允许写入系统模板 `0`**(`1`API模板 / `2`用户推荐 暂不支持写入,`save` 会拒绝)。
 
 ### 1. `template`(模板主体 · `FwhTestTouTemplateInfo`)
 
 | 字段                 | 类型              | 含义 / 取值                                                                                             |
 | -------------------- | ----------------- | ------------------------------------------------------------------------------------------------------- |
-| `countryId`          | string(数值)      | 国家 ID                                                                                                 |
-| `provinceId`         | string(数值)      | 州/省 ID                                                                                                |
+| `countryId`          | number            | 国家 ID                                                                                                 |
+| `provinceId`         | number            | 州/省 ID                                                                                                |
 | `derSchdule`         | string            | DER 调度配置                                                                                            |
 | `eleCompanyFullName` | string            | 电力公司全称                                                                                            |
 | `electricCompany`    | string            | 电力公司(简称)                                                                                        |
 | `gridType`           | string            | 电网类型 / 套餐类型                                                                                     |
-| `electricityType`    | string(数值)      | 电价类型:`1`分时电价 `2`阶梯电价 `3`固定电价 `4`分时&阶梯电价 `5`BB套餐 `6`Peak Demand                 |
+| `electricityType`    | number            | 电价类型:`1`分时电价 `2`阶梯电价 `3`固定电价 `4`分时&阶梯电价 `5`BB套餐 `6`Peak Demand                 |
 | `name`               | string            | 模板/策略表名称                                                                                         |
-| `mookRunCount`       | string(数值)      | 模式执行次数(loop):`0`不限次数 `1`执行一次                                                             |
-| `priority`           | string(数值)      | 模式优先级,默认`0`;`0` 最低,数字越大优先级越高                                                       |
-| `env`                | string(数值·位域) | 模式使用条件,默认`0`;bit0~1 光伏;bit2~3 馈网;bit4~5 电网充电                                        |
-| `templateId`         | string(数值)      | 模板 ID。**创建时不需要(省略此字段);更新时必须带上并填 ID**。读取(detail/list)返回时该字段必定存在 |
-| `sourceType`         | string(数值·必填) | 模板类型。**必填,当前仅允许 `0`系统模板**(`1`API模板 `2`用户推荐 暂不支持写入)                       |
+| `mookRunCount`       | number            | 模式执行次数(loop):`0`不限次数 `1`执行一次                                                             |
+| `priority`           | number            | 模式优先级,默认`0`;`0` 最低,数字越大优先级越高                                                       |
+| `env`                | number(位域)      | 模式使用条件,默认`0`;bit0~1 光伏;bit2~3 馈网;bit4~5 电网充电                                        |
+| `templateId`         | number            | 模板 ID。**创建时不需要(省略此字段);更新时必须带上并填 ID**。读取(detail/list)返回时该字段必定存在 |
+| `sourceType`         | number(必填)      | 模板类型。**必填,当前仅允许 `0`系统模板**(`1`API模板 `2`用户推荐 暂不支持写入)                       |
 
 ### 2. `strategyList[]`(策略 · `FwhTestTouTemplateStrategy`)
 
@@ -77,59 +77,74 @@ save 与 cites 目前仅支持 `test`。读操作默认走 `pro`,需要读测
 
 | 字段           | 类型         | 含义 / 取值                                                      |
 | -------------- | ------------ | ---------------------------------------------------------------- |
-| `ccociateType` | string(数值) | 关联类型编码,如`1`                                              |
-| `ccociateSn`   | string       | 关联设备 SN(无则空串)                                          |
+| `ccociateType` | number       | 关联类型:`1`每天 `2`工作日 `3`周末/节假日(与 `dayType`/`dayName` 配套,见下方「日类型配套逻辑」) |
+| `ccociateSn`   | string       | 关联序号:每天为`""`;工作日与其配对的周末/节假日共用同一序号(从 `"0"` 递增) |
 | `detailVoList` | array        | 时段明细表,**所有时段必须覆盖一整天**(见下表)                 |
 | `seasonName`   | string       | 季节名,用于标识策略范围,可自定义,如`summer`、`All months`     |
 | `month`        | string       | 逗号分隔的月份,如`1,2,3,4,5,6,7,8,9,10,11,12`                   |
-| `dayName`      | string       | 日期类型可读名称,如`Every day`、`Weekdays`(与 `dayType` 对应) |
-| `dayType`      | string(数值) | 日期类型编码:`1`工作日 `2`节假日 `3`每天(可读名见 `dayName`)  |
-
-**策略级电价字段(可选)**:以下字段描述该策略各时段的电价,**类型为数值(number),未设置传 `null`**(注意:与本请求体其它字符串字段的空串约定不同,这几个电价字段是数值且用 `null` 表示未设置)。
-
-| 字段                     | 类型         | 含义                    |
-| ------------------------ | ------------ | ----------------------- |
-| `eleticRatePeak`         | number/null  | 峰时购电电价            |
-| `eleticRateShoulder`     | number/null  | 平时购电电价            |
-| `eleticRateValley`       | number/null  | 谷时购电电价            |
-| `eleticRateSharp`        | number/null  | 尖峰购电电价            |
-| `eleticRateSuperOffPeak` | number/null  | 超低谷购电电价          |
-| `eleticRateGridFee`      | number/null  | 电网附加费              |
-| `eleticSellPeak`         | number/null  | 峰时卖电(上网)电价    |
-| `eleticSellShoulder`     | number/null  | 平时卖电(上网)电价    |
-| `eleticSellValley`       | number/null  | 谷时卖电(上网)电价    |
-| `eleticSellSharp`        | number/null  | 尖峰卖电(上网)电价    |
-| `eleticSellSuperOffPeak` | number/null  | 超低谷卖电(上网)电价  |
+| `dayName`      | string       | 日类型可读名:每天=`Every day` 工作日=`Weekdays` 周末/节假日=`Weekends,Holidays`(与 `dayType` 对应) |
+| `dayType`      | number       | 日类型编码:`1`工作日 `2`周末/节假日 `3`每天(可读名见 `dayName`) |
+
+#### 日类型配套逻辑(`ccociateType` / `ccociateSn` / `dayType` / `dayName`)
+
+这四个字段必须成套填写,用于表示策略的「日类型」及工作日与周末/节假日的配对关系:
+
+| 日类型         | `ccociateType` | `ccociateSn`                 | `dayType` | `dayName`             |
+| -------------- | :------------: | ---------------------------- | :-------: | --------------------- |
+| 每天           | `1`            | `""`                         | `3`       | `Every day`           |
+| 工作日         | `2`            | 序号(从 `"0"` 递增)          | `1`       | `Weekdays`            |
+| 周末或节假日   | `3`            | 同组工作日的序号             | `2`       | `Weekends,Holidays`   |
+
+- **每天**是独立策略,无需配对,`ccociateSn` 恒为空串 `""`。
+- **工作日(2) 与 周末/节假日(3) 成对出现**,通过**相同的 `ccociateSn`** 关联为同一组。
+- `ccociateSn` 是从 `"0"` 开始的序号字符串:第一对「工作日+周末/节假日」用 `"0"`,第二对用 `"1"`,以此类推(每新增一对 +1)。
+- 因此,用「每天」时只有 1 条策略;用「工作日/周末」时至少成对出现 2 条策略(一条 `type=2`、一条 `type=3`,共用同一 `ccociateSn`)。
+
+**策略级电价字段(可选)**:以下字段描述该策略各时段的电价,**类型为数值(number);未设置时直接省略该 key**(不要传 `""` 或 `null`)。
+
+| 字段                     | 类型   | 含义                    |
+| ------------------------ | ------ | ----------------------- |
+| `eleticRatePeak`         | number | 峰时购电电价            |
+| `eleticRateShoulder`     | number | 平时购电电价            |
+| `eleticRateValley`       | number | 谷时购电电价            |
+| `eleticRateSharp`        | number | 尖峰购电电价            |
+| `eleticRateSuperOffPeak` | number | 超低谷购电电价          |
+| `eleticRateGridFee`      | number | 电网附加费              |
+| `eleticSellPeak`         | number | 峰时卖电(上网)电价    |
+| `eleticSellShoulder`     | number | 平时卖电(上网)电价    |
+| `eleticSellValley`       | number | 谷时卖电(上网)电价    |
+| `eleticSellSharp`        | number | 尖峰卖电(上网)电价    |
+| `eleticSellSuperOffPeak` | number | 超低谷卖电(上网)电价  |
 
 ### 3. `detailVoList[]`(时段明细 · `FwhTestTouTemplateDetailVo`)
 
-同一策略内的所有时段必须铺满一整天:每个 `endHourTime` 等于下一段的 `startHourTime`,第一段是 `00:00`,最后一段是 `24:00`。值均为字符串,`""` 表示未设置(勿传 `null`)。
+同一策略内的所有时段必须铺满一整天:每个 `endHourTime` 等于下一段的 `startHourTime`,第一段是 `00:00`,最后一段是 `24:00`。**数值字段传数字**(`waveType`、`solarCutoff` 每段必填;功率/SOC/使能等为可选);**可选数值字段未设置时直接省略该 key**(不要传 `""` 或 `null`)。字符串字段(时间、名称、优先级、`powerOffApower`)传字符串。
 
 | 字段               | 类型              | 含义 / 取值                                                                                                                                                       |
 | ------------------ | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
 | `startHourTime`    | string            | 开始时间,格式`HH:mm`,如 `06:30`                                                                                                                                 |
 | `endHourTime`      | string            | 结束时间,格式`HH:mm`;需与下一段 `startHourTime` 衔接,所有时段覆盖一整天                                                                                        |
-| `waveType`         | string(数值·flag) | 峰平谷定义:`0`谷/off-peak `1`平/mid-peak `2`峰/on-peak `3`尖峰/super-on-peak `4`低谷/super-off-peak                                                              |
+| `waveType`         | number(flag,必填) | 峰平谷定义:`0`谷/off-peak `1`平/mid-peak `2`峰/on-peak `3`尖峰/super-on-peak `4`低谷/super-off-peak                                                              |
 | `name`             | string            | 时段名,一般为`supper-off-peak`、`off-peak`、`mid-peak`、`on-peak`、`supper-on-peak` 等                                                                           |
 | `briefDescribe`    | string            | 时段描述,如`Self-consumption`                                                                                                                                    |
 | `solarPriority`    | string            | **光伏供电优先级**,格式 `"市电,负载,FHP"`,如 `"1,3,2"`;优先级 `0/1/2/3`,可相同(表示按比例/功率分配),`0`=不涉及,数字越大优先级越高                           |
 | `loadPriority`     | string            | **负载取电优先级**,格式 `"市电,光伏,FHP"`,如 `"1,3,2"`;优先级 `0/1/2/3`,可相同(按比例/功率分配),`0`=不使用此源,数字越大优先级越高                           |
-| `gridDischargeMax` | string(kW,0.1)    | 电池最大允许馈网功率;可选,默认`0` 不能馈网;`0`不可馈网,`-1`不限制                                                                                             |
-| `gridChargeMax`    | string(kW,0.1)    | 电网允许最大充电功率;可选,默认`0` 不允许;`0`不允许,`-1`不限制                                                                                                 |
-| `chargePower`      | string(kW,0.1)    | 固定电池充电功率,按单台功率计算;可选,默认`-1` 未设置                                                                                                           |
-| `dischargePower`   | string(kW,0.1)    | 固定电池放电功率,按单台功率计算;可选,默认`-1` 未设置                                                                                                           |
-| `chargeMax`        | string(kW,0.1)    | 电池最大允许充电功率,按单台功率计算;`-1`无限制,默认 `-1`                                                                                                       |
-| `dischargeMax`     | string(kW,0.1)    | 电池最大允许放电功率,按单台功率计算;`-1`无限制,默认 `-1`                                                                                                       |
-| `gcaoMax`          | string(kW,0.1)    | GCAO(grid charge after an outage):停电后补电至预留 SOC 的单台市电取电功率;可选;`0`不允许,`-1`不限制;默认未设置(`-3`);使能后未设值则为 `5kw*N`(用 `-2` 标识) |
-| `gridFeedMax`      | string(kW,0.1)    | 电网允许最大馈网功率;可选,默认`-2`;`0`不允许,`-1`不限制,`-2`未设置                                                                                           |
-| `gridMax`          | string(kW,0.1)    | 电网允许最大取电功率;可选,默认`-1` 不限制;`0`不允许,`-1`不限制                                                                                                |
-| `minDischargeSoc`  | string(%,整数)    | 放电截止 SOC;达到此 SOC 后电池不放电,可选,默认`0%`;若 `reserved_soc` 大于此值则以 `reserved_soc` 为准                                                         |
-| `maxChargeSoc`     | string(%,整数)    | 充电截止 SOC;可选,默认`100%`                                                                                                                                    |
-| `heatEnable`       | string(数值)      | 充电加热使能:`0`未设置(默认) `1`不使能 `2`使能                                                                                                                   |
-| `powerOffApower`   | string(数值)      | 主动关闭 APower;可选,`0`不控制(默认) `1`关机 `2`开机(预留)                                                                                                      |
-| `rampTime`         | string(秒)        | 爬坡时间,`0~300`;默认 `0`,BB套餐默认 `300`                                                                                                                     |
-| `offGrid`          | string(数值)      | 主动断开市电继电器:`0`不控制(默认) `1`断开 `2`闭合(预留)                                                                                                         |
-| `solarCutoff`      | string(数值)      | 主动断开光伏继电器:`0`不控制(默认) `1`断开 `2`闭合(预留)                                                                                                         |
+| `gridDischargeMax` | number(kW,0.1,可选) | 电池最大允许馈网功率;可选,默认`0` 不能馈网;`0`不可馈网,`-1`不限制                                                                                             |
+| `gridChargeMax`    | number(kW,0.1,可选) | 电网允许最大充电功率;可选,默认`0` 不允许;`0`不允许,`-1`不限制                                                                                                 |
+| `chargePower`      | number(kW,0.1,可选) | 固定电池充电功率,按单台功率计算;可选,默认`-1` 未设置                                                                                                           |
+| `dischargePower`   | number(kW,0.1,可选) | 固定电池放电功率,按单台功率计算;可选,默认`-1` 未设置                                                                                                           |
+| `chargeMax`        | number(kW,0.1,可选) | 电池最大允许充电功率,按单台功率计算;`-1`无限制,默认 `-1`                                                                                                       |
+| `dischargeMax`     | number(kW,0.1,可选) | 电池最大允许放电功率,按单台功率计算;`-1`无限制,默认 `-1`                                                                                                       |
+| `gcaoMax`          | number(kW,0.1,可选) | GCAO(grid charge after an outage):停电后补电至预留 SOC 的单台市电取电功率;可选;`0`不允许,`-1`不限制;默认未设置(`-3`);使能后未设值则为 `5kw*N`(用 `-2` 标识) |
+| `gridFeedMax`      | number(kW,0.1,可选) | 电网允许最大馈网功率;可选,默认`-2`;`0`不允许,`-1`不限制,`-2`未设置                                                                                           |
+| `gridMax`          | number(kW,0.1,可选) | 电网允许最大取电功率;可选,默认`-1` 不限制;`0`不允许,`-1`不限制                                                                                                |
+| `minDischargeSoc`  | number(%,整数,可选) | 放电截止 SOC;达到此 SOC 后电池不放电,可选,默认`0%`;若 `reserved_soc` 大于此值则以 `reserved_soc` 为准                                                         |
+| `maxChargeSoc`     | number(%,整数,可选) | 充电截止 SOC;可选,默认`100%`                                                                                                                                    |
+| `heatEnable`       | number(可选)      | 充电加热使能:`0`未设置(默认) `1`不使能 `2`使能                                                                                                                   |
+| `powerOffApower`   | string            | 主动关闭 APower;可选,`0`不控制(默认) `1`关机 `2`开机(预留)                                                                                                      |
+| `rampTime`         | number(秒,可选)   | 爬坡时间,`0~300`;默认 `0`,BB套餐默认 `300`                                                                                                                     |
+| `offGrid`          | number(可选)      | 主动断开市电继电器:`0`不控制(默认) `1`断开 `2`闭合(预留)                                                                                                         |
+| `solarCutoff`      | number(必填)      | 主动断开光伏继电器:`0`不控制(默认) `1`断开 `2`闭合(预留)                                                                                                         |
 
 **要点**:
 
@@ -138,30 +153,40 @@ save 与 cites 目前仅支持 `test`。读操作默认走 `pro`,需要读测
 
 ### 完整 detailVoList 单段示例
 
+未设置的可选功率/SOC 字段直接省略(下例只保留有值字段):
+
 ```json
 {
   "startHourTime": "00:00",
   "endHourTime": "11:00",
-  "waveType": "1",
+  "waveType": 1,
   "name": "mid-peak",
   "briefDescribe": "Self-consumption",
   "solarPriority": "1,3,2",
   "loadPriority": "1,3,2",
-  "gridChargeMax": "",
-  "gridDischargeMax": "",
-  "gridFeedMax": "",
-  "gridMax": "",
-  "chargePower": "",
-  "dischargePower": "",
-  "chargeMax": "",
-  "dischargeMax": "",
-  "gcaoMax": "",
-  "minDischargeSoc": "",
-  "maxChargeSoc": "",
-  "heatEnable": "",
-  "rampTime": "",
-  "offGrid": "",
-  "solarCutoff": "0",
+  "solarCutoff": 0,
+  "powerOffApower": ""
+}
+```
+
+带部分功率设置的示例段(有值传数字,其余省略):
+
+```json
+{
+  "startHourTime": "18:00",
+  "endHourTime": "21:00",
+  "waveType": 2,
+  "name": "on-peak",
+  "briefDescribe": "Zero Import",
+  "solarPriority": "9,9,9",
+  "loadPriority": "9,9,9",
+  "gridDischargeMax": 0.1,
+  "gridFeedMax": 0.1,
+  "dischargePower": 10,
+  "gridMax": 0,
+  "gcaoMax": 0,
+  "heatEnable": 1,
+  "solarCutoff": 0,
   "powerOffApower": ""
 }
 ```
@@ -202,7 +227,7 @@ save 与 cites 目前仅支持 `test`。读操作默认走 `pro`,需要读测
 ## 规则
 
 1. **时间覆盖**:每个策略的 `detailVoList` 必须覆盖 00:00→24:00,无空档、无重叠;`endHourTime` == 下一段 `startHourTime`;时间格式 `HH:mm`。
-2. **未设置传 ""**:明细字段绝不传 `null`,用空串;数字也以字符串形式传。
+2. **按真实类型传值**:数值字段传数字(不是字符串);可选数值字段未设置时**省略该 key**(不传 `""`、不传 `null`)。字符串字段(时间、名称、优先级、`powerOffApower`)传字符串。
 3. **功率单位是 kW**(步进 0.1),按单台 aPower 计。不要对这些模板字段套用设备侧的 W 或 `5kw*N/-2` 约定。
 4. **优先级是 3 值字符串** `"a,b,c"`,顺序为 `[市电, 负载/光伏, aPower]`。
 5. **新增 vs 更新**:`template.templateId` 留空为新增;填入 ID 为更新。
@@ -215,6 +240,6 @@ save 与 cites 目前仅支持 `test`。读操作默认走 `pro`,需要读测
 ## 示例流程:构建一个标准自发自用模板
 
 1. `service_tou_template_cites { "country_id": 3 }` → 选出 `provinceId`。
-2. 构建一个策略(dayType 3 = 每天),用策略 D(`solarPriority:"1,3,2"`,`loadPriority:"1,3,2"`)铺一整天单一时段,或拆成 off/mid/on-peak 多个时段。
+2. 构建一个策略(「每天」类型:`ccociateType:1`、`ccociateSn:""`、`dayType:3`、`dayName:"Every day"`),用策略 D(`solarPriority:"1,3,2"`,`loadPriority:"1,3,2"`)铺一整天单一时段,或拆成 off/mid/on-peak 多个时段。若需区分工作日与周末/节假日,则改用成对策略(见「日类型配套逻辑」)。
 3. `service_tou_template_save { "env":"test", "payload": "<json>" }` → 记下返回的 `templateId`。
 4. `service_tou_template_detail { "env":"test", "id": <templateId> }` 确认结果。

+ 2 - 2
service/cmd/mcp/tools/service/tou_template.go

@@ -42,8 +42,8 @@ func registerTouTemplateTools(s *server.MCPServer) {
 			mcp.WithString("env", mcp.Description("目标服务器环境:test-测试(默认,当前仅支持)")),
 			mcp.WithString("payload", mcp.Required(),
 				mcp.Description("模版请求体 JSON,结构:{\"template\":{...},\"strategyList\":[{...}],\"lang\":\"ZH_CN\"}。"+
-					"template 含 countryId、provinceId、electricityType、name、mookRunCount、priority、env、templateId(更新时填)、sourceType 等;"+
-					"strategyList[].detailVoList[] 为时段明细,含 startHourTime/endHourTime(HH:mm)、waveType、solarPriority/loadPriority(\"市电,负载,FHP\")、各功率(kW)、SOC(%) 等,未设置字段传空串。")),
+					"template 含 countryId、provinceId、electricityType、name、mookRunCount、priority、env、templateId(更新时填)、sourceType 等(均为数值,字符串字段除外);"+
+					"strategyList[].detailVoList[] 为时段明细,含 startHourTime/endHourTime(HH:mm)、waveType、solarPriority/loadPriority(\"市电,负载,FHP\")、各功率(kW,数值)、SOC(%,数值) 等;数值字段传数字,可选数值字段未设置时省略该 key(不传空串或 null)。")),
 		),
 		handleTouTemplateSave,
 	)

+ 66 - 54
service/dto/fwhTestTouTemplateDTO.go

@@ -3,75 +3,87 @@ package dto
 /************ updateOrSaveIotTouTemplate(新增/更新模板) ************/
 
 // FwhTestTouTemplateDetailVo 时段明细
-// 说明:字段统一用 string,未设置传空串 "";有值时按下方各字段说明的数值格式填写(与前端 HAR 行为一致)。
+// 说明:数值字段直接用数值类型;可选字段用指针 + omitempty —— 未设置(nil)时该字段整个从 JSON 中省略。
+//   - startHourTime/endHourTime/name/briefDescribe/solarPriority/loadPriority/powerOffApower 为字符串
+//   - waveType 每段必填(数值)
+//   - 功率(kW,精度0.1) 与 SOC/使能/时间类可选字段:有值填数字,未设置留 nil(不发送该 key)
 type FwhTestTouTemplateDetailVo struct {
-	StartHourTime    string `json:"startHourTime"`    // 开始时间 格式 HH:mm,如 06:30
-	EndHourTime      string `json:"endHourTime"`      // 结束时间 格式 HH:mm,需与下一个 startHourTime 重叠,所有时段需覆盖一整天
-	WaveType         string `json:"waveType"`         // 峰平谷定义(flag) 数值:0-谷 1-平 2-峰 3-尖峰 4-低谷
-	Name             string `json:"name"`             // 时段名 一般为 supper-off-peak、off-peak、mid-peak、on-peak、supper-on-peak 等
-	BriefDescribe    string `json:"briefDescribe"`    // 时段描述
-	SolarPriority    string `json:"solarPriority"`    // 光伏供电优先级 格式 "市电,负载,FHP",如 "1,3,2";优先级 0/1/2/3,可相同(表示按比例/功率分配),0-不涉及,数字越大优先级越高
-	GridDischargeMax string `json:"gridDischargeMax"` // 电池最大允许馈网功率 数值(单位kW,精度0.1);可选,默认0不能馈网;0-不可馈网,-1-不限制
-	GridChargeMax    string `json:"gridChargeMax"`    // 电网允许最大充电功率 数值(单位kW,精度0.1);可选,默认0不允许;0-不允许,-1-不限制
-	ChargePower      string `json:"chargePower"`      // 固定电池充电功率 数值(单位kW,精度0.1),按单台功率计算;可选,默认-1未设置
-	DischargePower   string `json:"dischargePower"`   // 固定电池放电功率 数值(单位kW,精度0.1),按单台功率计算;可选,默认-1未设置
-	ChargeMax        string `json:"chargeMax"`        // 电池最大允许充电功率 数值(单位kW,精度0.1),按单台功率计算;-1-无限制,默认-1
-	DischargeMax     string `json:"dischargeMax"`     // 电池最大允许放电功率 数值(单位kW,精度0.1),按单台功率计算;-1-无限制,默认-1
-	GcaoMax          string `json:"gcaoMax"`          // GCAO(grid charge after an outage) 停电后补电至预留SOC的单台市电取电功率 可选;0-不允许,-1-不限制;默认未设置(-3);使能后未设值则为 5kw*N(用-2标识)
-	LoadPriority     string `json:"loadPriority"`     // 负载取电优先级 格式 "市电,光伏,FHP",如 "1,3,2";优先级 0/1/2/3,可相同(表示按比例/功率分配),0-不使用此源,数字越大优先级越高
-	GridFeedMax      string `json:"gridFeedMax"`      // 电网允许最大馈网功率 数值(单位kW,精度0.1);可选,默认-2;0-不允许,-1-不限制,-2-未设置
-	GridMax          string `json:"gridMax"`          // 电网允许最大取电功率 数值(单位kW,精度0.1);可选,默认-1不限制;0-不允许,-1-不限制
-	MinDischargeSoc  string `json:"minDischargeSoc"`  // 放电截止SOC 数值(单位%,整数);达到此SOC后电池不放电,可选,默认0%;若 reserved_soc 大于此值则以 reserved_soc 为准
-	MaxChargeSoc     string `json:"maxChargeSoc"`     // 充电截止SOC 数值(单位%,整数);可选,默认100%
-	HeatEnable       string `json:"heatEnable"`       // 充电加热使能 数值:0-未设置(默认) 1-不使能 2-使能
-	PowerOffApower   string `json:"powerOffApower"`   // 主动关闭APower 可选,0-不控制(默认) 1-关机 2-开机(预留)
-	RampTime         string `json:"rampTime"`         // 爬坡时间 数值(单位秒,0~300);默认0,BB套餐默认300
-	OffGrid          string `json:"offGrid"`          // 主动断开市电继电器 数值:0-不控制(默认) 1-断开 2-闭合(预留)
-	SolarCutoff      string `json:"solarCutoff"`      // 主动断开光伏继电器 数值:0-不控制(默认) 1-断开 2-闭合(预留)
+	StartHourTime    string   `json:"startHourTime"`              // 开始时间 格式 HH:mm,如 06:30
+	EndHourTime      string   `json:"endHourTime"`                // 结束时间 格式 HH:mm,需与下一个 startHourTime 重叠,所有时段需覆盖一整天
+	WaveType         int      `json:"waveType"`                   // 峰平谷定义(flag) 数值:0-谷 1-平 2-峰 3-尖峰 4-低谷
+	Name             string   `json:"name"`                       // 时段名 一般为 supper-off-peak、off-peak、mid-peak、on-peak、supper-on-peak 等
+	BriefDescribe    string   `json:"briefDescribe"`              // 时段描述
+	SolarPriority    string   `json:"solarPriority"`              // 光伏供电优先级 格式 "市电,负载,FHP",如 "1,3,2";优先级 0/1/2/3,可相同(表示按比例/功率分配),0-不涉及,数字越大优先级越高
+	GridDischargeMax *float64 `json:"gridDischargeMax,omitempty"` // 电池最大允许馈网功率 数值(单位kW,精度0.1);可选,默认0不能馈网;0-不可馈网,-1-不限制
+	GridChargeMax    *float64 `json:"gridChargeMax,omitempty"`    // 电网允许最大充电功率 数值(单位kW,精度0.1);可选,默认0不允许;0-不允许,-1-不限制
+	ChargePower      *float64 `json:"chargePower,omitempty"`      // 固定电池充电功率 数值(单位kW,精度0.1),按单台功率计算;可选,默认-1未设置
+	DischargePower   *float64 `json:"dischargePower,omitempty"`   // 固定电池放电功率 数值(单位kW,精度0.1),按单台功率计算;可选,默认-1未设置
+	ChargeMax        *float64 `json:"chargeMax,omitempty"`        // 电池最大允许充电功率 数值(单位kW,精度0.1),按单台功率计算;-1-无限制,默认-1
+	DischargeMax     *float64 `json:"dischargeMax,omitempty"`     // 电池最大允许放电功率 数值(单位kW,精度0.1),按单台功率计算;-1-无限制,默认-1
+	GcaoMax          *float64 `json:"gcaoMax,omitempty"`          // GCAO(grid charge after an outage) 停电后补电至预留SOC的单台市电取电功率 可选;0-不允许,-1-不限制;默认未设置(-3);使能后未设值则为 5kw*N(用-2标识)
+	LoadPriority     string   `json:"loadPriority"`               // 负载取电优先级 格式 "市电,光伏,FHP",如 "1,3,2";优先级 0/1/2/3,可相同(表示按比例/功率分配),0-不使用此源,数字越大优先级越高
+	GridFeedMax      *float64 `json:"gridFeedMax,omitempty"`      // 电网允许最大馈网功率 数值(单位kW,精度0.1);可选,默认-2;0-不允许,-1-不限制,-2-未设置
+	GridMax          *float64 `json:"gridMax,omitempty"`          // 电网允许最大取电功率 数值(单位kW,精度0.1);可选,默认-1不限制;0-不允许,-1-不限制
+	MinDischargeSoc  *int     `json:"minDischargeSoc,omitempty"`  // 放电截止SOC 数值(单位%,整数);达到此SOC后电池不放电,可选,默认0%;若 reserved_soc 大于此值则以 reserved_soc 为准
+	MaxChargeSoc     *int     `json:"maxChargeSoc,omitempty"`     // 充电截止SOC 数值(单位%,整数);可选,默认100%
+	HeatEnable       *int     `json:"heatEnable,omitempty"`       // 充电加热使能 数值:0-未设置(默认) 1-不使能 2-使能
+	PowerOffApower   string   `json:"powerOffApower"`             // 主动关闭APower 可选,0-不控制(默认) 1-关机 2-开机(预留)
+	RampTime         *int     `json:"rampTime,omitempty"`         // 爬坡时间 数值(单位秒,0~300);默认0,BB套餐默认300
+	OffGrid          *int     `json:"offGrid,omitempty"`          // 主动断开市电继电器 数值:0-不控制(默认) 1-断开 2-闭合(预留)
+	SolarCutoff      int      `json:"solarCutoff"`                // 主动断开光伏继电器 数值:0-不控制(默认) 1-断开 2-闭合(预留)
 }
 
 // FwhTestTouTemplateStrategy 策略(季节/日类型 + 时段明细列表)
+//
+// ccociateType / ccociateSn / dayType / dayName 四个字段配套填写,表示该策略的「日类型」及配对关系:
+//   1. 每天(Every day):            ccociateType=1, ccociateSn="",  dayType=3, dayName="Every day"
+//   2. 工作日(Weekdays):           ccociateType=2, ccociateSn=序号, dayType=1, dayName="Weekdays"
+//   3. 周末或节假日(Weekends,Holidays):ccociateType=3, ccociateSn=同组工作日的序号, dayType=2, dayName="Weekends,Holidays"
+//
+// 说明:工作日(2)与周末/节假日(3)成对出现,通过相同的 ccociateSn 关联为同一组。
+// ccociateSn 是从 "0" 开始的序号字符串,每新增一对「工作日+周末/节假日」就 +1(第一对 "0",第二对 "1"...)。
+// 每天(1) 是独立策略,无需配对,ccociateSn 恒为空串 ""。
 type FwhTestTouTemplateStrategy struct {
-	CcociateType string                       `json:"ccociateType"` // 关联类型 数值编码,如 1
-	CcociateSn   string                       `json:"ccociateSn"`   // 关联设备SN
+	CcociateType int                          `json:"ccociateType"` // 关联类型:1-每天 2-工作日 3-周末/节假日(与 dayType/dayName 配套)
+	CcociateSn   string                       `json:"ccociateSn"`   // 关联序号:每天为 "";工作日与其配对的周末/节假日共用同一序号(从 "0" 递增)
 	DetailVoList []FwhTestTouTemplateDetailVo `json:"detailVoList"` // 时段策略表,所有配置的时间需覆盖一整天
 	SeasonName   string                       `json:"seasonName"`   // 季节名 用于标识策略范围,可自定义,如 summer、All months
 	Month        string                       `json:"month"`        // 逗号分隔的月份,如 1,2,3...
-	DayName      string                       `json:"dayName"`      // 日期类型的可读名称,如 Every day、Weekdays(与 dayType 对应)
-	DayType      string                       `json:"dayType"`      // 日期类型 数值编码(非自定义字符串),如 3-Every day;可读名见 dayName
+	DayName      string                       `json:"dayName"`      // 日类型可读名:每天=Every day 工作日=Weekdays 周末/节假日=Weekends,Holidays(与 dayType 对应)
+	DayType      int                          `json:"dayType"`      // 日类型编码:1-工作日 2-周末/节假日 3-每天(可读名见 dayName)
 
-	// 购电电价(各时段单价;未设置传 null)
-	EleticRatePeak         *float64 `json:"eleticRatePeak"`         // 峰时购电电价
-	EleticRateShoulder     *float64 `json:"eleticRateShoulder"`     // 平时购电电价
-	EleticRateValley       *float64 `json:"eleticRateValley"`       // 谷时购电电价
-	EleticRateSharp        *float64 `json:"eleticRateSharp"`        // 尖峰购电电价
-	EleticRateSuperOffPeak *float64 `json:"eleticRateSuperOffPeak"` // 超低谷购电电价
-	EleticRateGridFee      *float64 `json:"eleticRateGridFee"`      // 电网附加费
+	// 购电电价(各时段单价;未设置留 nil,序列化时省略该字段)
+	EleticRatePeak         *float64 `json:"eleticRatePeak,omitempty"`         // 峰时购电电价
+	EleticRateShoulder     *float64 `json:"eleticRateShoulder,omitempty"`     // 平时购电电价
+	EleticRateValley       *float64 `json:"eleticRateValley,omitempty"`       // 谷时购电电价
+	EleticRateSharp        *float64 `json:"eleticRateSharp,omitempty"`        // 尖峰购电电价
+	EleticRateSuperOffPeak *float64 `json:"eleticRateSuperOffPeak,omitempty"` // 超低谷购电电价
+	EleticRateGridFee      *float64 `json:"eleticRateGridFee,omitempty"`      // 电网附加费
 
-	// 卖电(上网)电价(各时段单价;未设置传 null)
-	EleticSellPeak         *float64 `json:"eleticSellPeak"`         // 峰时卖电电价
-	EleticSellShoulder     *float64 `json:"eleticSellShoulder"`     // 平时卖电电价
-	EleticSellValley       *float64 `json:"eleticSellValley"`       // 谷时卖电电价
-	EleticSellSharp        *float64 `json:"eleticSellSharp"`        // 尖峰卖电电价
-	EleticSellSuperOffPeak *float64 `json:"eleticSellSuperOffPeak"` // 超低谷卖电电价
+	// 卖电(上网)电价(各时段单价;未设置留 nil,序列化时省略该字段)
+	EleticSellPeak         *float64 `json:"eleticSellPeak,omitempty"`         // 峰时卖电电价
+	EleticSellShoulder     *float64 `json:"eleticSellShoulder,omitempty"`     // 平时卖电电价
+	EleticSellValley       *float64 `json:"eleticSellValley,omitempty"`       // 谷时卖电电价
+	EleticSellSharp        *float64 `json:"eleticSellSharp,omitempty"`        // 尖峰卖电电价
+	EleticSellSuperOffPeak *float64 `json:"eleticSellSuperOffPeak,omitempty"` // 超低谷卖电电价
 }
 
 // FwhTestTouTemplateInfo 模板主体
 // templateId:创建模板时省略此字段(nil);更新模板时必须带此字段并填入模板ID。读取(detail/list)返回时该字段必定存在。
 type FwhTestTouTemplateInfo struct {
-	CountryId          string  `json:"countryId"`            // 国家ID 数值
-	ProvinceId         string  `json:"provinceId"`           // 州/省ID 数值
-	DerSchdule         string  `json:"derSchdule"`           // DER 调度配置
-	EleCompanyFullName string  `json:"eleCompanyFullName"`   // 电力公司全称
-	ElectricCompany    string  `json:"electricCompany"`      // 电力公司
-	GridType           string  `json:"gridType"`             // 电网类型
-	ElectricityType    string  `json:"electricityType"`      // 电价类型 数值:1-分时电价 2-阶梯电价 3-固定电价 4-分时&阶梯电价 5-BB套餐 6-Peak Demand
-	Name               string  `json:"name"`                 // 模板/策略表名称
-	MookRunCount       string  `json:"mookRunCount"`         // 模式执行次数(loop) 数值:0-不限次数 1-执行一次
-	Priority           string  `json:"priority"`             // 模式优先级 数值,默认0,0最低,数字越大优先级越高
-	Env                string  `json:"env"`                  // 模式使用条件 数值(位域),默认0;bit0~1 光伏;bit2~3 馈网;bit4~5 电网充电
-	TemplateId         *string `json:"templateId,omitempty"` // 模板ID 数值;创建时省略(nil),更新时必填。读取返回时必定存在
-	SourceType         string  `json:"sourceType"`           // 模板类型 数值,必填;当前仅允许 0-系统模板(1-API模板 2-用户推荐 暂不支持写入)
+	CountryId          int    `json:"countryId"`            // 国家ID 数值
+	ProvinceId         int    `json:"provinceId"`           // 州/省ID 数值
+	DerSchdule         string `json:"derSchdule"`           // DER 调度配置
+	EleCompanyFullName string `json:"eleCompanyFullName"`   // 电力公司全称
+	ElectricCompany    string `json:"electricCompany"`      // 电力公司
+	GridType           string `json:"gridType"`             // 电网类型
+	ElectricityType    int    `json:"electricityType"`      // 电价类型 数值:1-分时电价 2-阶梯电价 3-固定电价 4-分时&阶梯电价 5-BB套餐 6-Peak Demand
+	Name               string `json:"name"`                 // 模板/策略表名称
+	MookRunCount       int    `json:"mookRunCount"`         // 模式执行次数(loop) 数值:0-不限次数 1-执行一次
+	Priority           int    `json:"priority"`             // 模式优先级 数值,默认0,0最低,数字越大优先级越高
+	Env                int    `json:"env"`                  // 模式使用条件 数值(位域),默认0;bit0~1 光伏;bit2~3 馈网;bit4~5 电网充电
+	TemplateId         *int   `json:"templateId,omitempty"` // 模板ID 数值;创建时省略(nil),更新时必填。读取返回时必定存在
+	SourceType         int    `json:"sourceType"`           // 模板类型 数值,必填;当前仅允许 0-系统模板(1-API模板 2-用户推荐 暂不支持写入)
 }
 
 // FwhTestUpdateOrSaveTouTemplatePayload 新增/更新模板请求体(JSON)