skill-calorie 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (373) hide show
  1. package/dist/analysis/anomaly/common.d.ts +53 -0
  2. package/dist/analysis/anomaly/common.d.ts.map +1 -0
  3. package/dist/analysis/anomaly/common.js +69 -0
  4. package/dist/analysis/anomaly/common.js.map +1 -0
  5. package/dist/analysis/anomaly/diet.d.ts +8 -0
  6. package/dist/analysis/anomaly/diet.d.ts.map +1 -0
  7. package/dist/analysis/anomaly/diet.js +95 -0
  8. package/dist/analysis/anomaly/diet.js.map +1 -0
  9. package/dist/analysis/anomaly/exercise.d.ts +9 -0
  10. package/dist/analysis/anomaly/exercise.d.ts.map +1 -0
  11. package/dist/analysis/anomaly/exercise.js +116 -0
  12. package/dist/analysis/anomaly/exercise.js.map +1 -0
  13. package/dist/analysis/anomaly/index.d.ts +19 -0
  14. package/dist/analysis/anomaly/index.d.ts.map +1 -0
  15. package/dist/analysis/anomaly/index.js +51 -0
  16. package/dist/analysis/anomaly/index.js.map +1 -0
  17. package/dist/analysis/anomaly/overall.d.ts +13 -0
  18. package/dist/analysis/anomaly/overall.d.ts.map +1 -0
  19. package/dist/analysis/anomaly/overall.js +128 -0
  20. package/dist/analysis/anomaly/overall.js.map +1 -0
  21. package/dist/analysis/anomaly/overall2.d.ts +5 -0
  22. package/dist/analysis/anomaly/overall2.d.ts.map +1 -0
  23. package/dist/analysis/anomaly/overall2.js +94 -0
  24. package/dist/analysis/anomaly/overall2.js.map +1 -0
  25. package/dist/analysis/anomaly/weight.d.ts +8 -0
  26. package/dist/analysis/anomaly/weight.d.ts.map +1 -0
  27. package/dist/analysis/anomaly/weight.js +106 -0
  28. package/dist/analysis/anomaly/weight.js.map +1 -0
  29. package/dist/analysis/anomaly/weight2.d.ts +4 -0
  30. package/dist/analysis/anomaly/weight2.d.ts.map +1 -0
  31. package/dist/analysis/anomaly/weight2.js +59 -0
  32. package/dist/analysis/anomaly/weight2.js.map +1 -0
  33. package/dist/analysis/contraindications.d.ts +63 -0
  34. package/dist/analysis/contraindications.d.ts.map +1 -0
  35. package/dist/analysis/contraindications.js +121 -0
  36. package/dist/analysis/contraindications.js.map +1 -0
  37. package/dist/analysis/cross.d.ts +75 -0
  38. package/dist/analysis/cross.d.ts.map +1 -0
  39. package/dist/analysis/cross.js +283 -0
  40. package/dist/analysis/cross.js.map +1 -0
  41. package/dist/analysis/dashboard.d.ts +18 -0
  42. package/dist/analysis/dashboard.d.ts.map +1 -0
  43. package/dist/analysis/dashboard.js +48 -0
  44. package/dist/analysis/dashboard.js.map +1 -0
  45. package/dist/analysis/deficit.d.ts +44 -0
  46. package/dist/analysis/deficit.d.ts.map +1 -0
  47. package/dist/analysis/deficit.js +54 -0
  48. package/dist/analysis/deficit.js.map +1 -0
  49. package/dist/analysis/diet.d.ts +76 -0
  50. package/dist/analysis/diet.d.ts.map +1 -0
  51. package/dist/analysis/diet.js +164 -0
  52. package/dist/analysis/diet.js.map +1 -0
  53. package/dist/analysis/exercise.d.ts +98 -0
  54. package/dist/analysis/exercise.d.ts.map +1 -0
  55. package/dist/analysis/exercise.js +298 -0
  56. package/dist/analysis/exercise.js.map +1 -0
  57. package/dist/analysis/exerciseReview.d.ts +36 -0
  58. package/dist/analysis/exerciseReview.d.ts.map +1 -0
  59. package/dist/analysis/exerciseReview.js +50 -0
  60. package/dist/analysis/exerciseReview.js.map +1 -0
  61. package/dist/analysis/precision.d.ts +15 -0
  62. package/dist/analysis/precision.d.ts.map +1 -0
  63. package/dist/analysis/precision.js +38 -0
  64. package/dist/analysis/precision.js.map +1 -0
  65. package/dist/analysis/result.d.ts +15 -0
  66. package/dist/analysis/result.d.ts.map +1 -0
  67. package/dist/analysis/result.js +13 -0
  68. package/dist/analysis/result.js.map +1 -0
  69. package/dist/analysis/review.d.ts +118 -0
  70. package/dist/analysis/review.d.ts.map +1 -0
  71. package/dist/analysis/review.js +195 -0
  72. package/dist/analysis/review.js.map +1 -0
  73. package/dist/analysis/series.d.ts +42 -0
  74. package/dist/analysis/series.d.ts.map +1 -0
  75. package/dist/analysis/series.js +127 -0
  76. package/dist/analysis/series.js.map +1 -0
  77. package/dist/analysis/simulate.d.ts +43 -0
  78. package/dist/analysis/simulate.d.ts.map +1 -0
  79. package/dist/analysis/simulate.js +109 -0
  80. package/dist/analysis/simulate.js.map +1 -0
  81. package/dist/analysis/simulate2.d.ts +65 -0
  82. package/dist/analysis/simulate2.d.ts.map +1 -0
  83. package/dist/analysis/simulate2.js +173 -0
  84. package/dist/analysis/simulate2.js.map +1 -0
  85. package/dist/analysis/trend.d.ts +39 -0
  86. package/dist/analysis/trend.d.ts.map +1 -0
  87. package/dist/analysis/trend.js +48 -0
  88. package/dist/analysis/trend.js.map +1 -0
  89. package/dist/analysis/utils.d.ts +17 -0
  90. package/dist/analysis/utils.d.ts.map +1 -0
  91. package/dist/analysis/utils.js +52 -0
  92. package/dist/analysis/utils.js.map +1 -0
  93. package/dist/analysis/volatility.d.ts +43 -0
  94. package/dist/analysis/volatility.d.ts.map +1 -0
  95. package/dist/analysis/volatility.js +96 -0
  96. package/dist/analysis/volatility.js.map +1 -0
  97. package/dist/analysis/weight.d.ts +86 -0
  98. package/dist/analysis/weight.d.ts.map +1 -0
  99. package/dist/analysis/weight.js +219 -0
  100. package/dist/analysis/weight.js.map +1 -0
  101. package/dist/analysis/weightCompare.d.ts +63 -0
  102. package/dist/analysis/weightCompare.d.ts.map +1 -0
  103. package/dist/analysis/weightCompare.js +212 -0
  104. package/dist/analysis/weightCompare.js.map +1 -0
  105. package/dist/analysis/weightCompare2.d.ts +63 -0
  106. package/dist/analysis/weightCompare2.d.ts.map +1 -0
  107. package/dist/analysis/weightCompare2.js +211 -0
  108. package/dist/analysis/weightCompare2.js.map +1 -0
  109. package/dist/analysis/weightCompare3.d.ts +13 -0
  110. package/dist/analysis/weightCompare3.d.ts.map +1 -0
  111. package/dist/analysis/weightCompare3.js +199 -0
  112. package/dist/analysis/weightCompare3.js.map +1 -0
  113. package/dist/cli/cmd_read.d.ts +8 -0
  114. package/dist/cli/cmd_read.d.ts.map +1 -0
  115. package/dist/cli/cmd_read.js +719 -0
  116. package/dist/cli/cmd_read.js.map +1 -0
  117. package/dist/cli/keys.d.ts +333 -0
  118. package/dist/cli/keys.d.ts.map +1 -0
  119. package/dist/cli/keys.js +103 -0
  120. package/dist/cli/keys.js.map +1 -0
  121. package/dist/cli/write.d.ts +24 -0
  122. package/dist/cli/write.d.ts.map +1 -0
  123. package/dist/cli/write.js +832 -0
  124. package/dist/cli/write.js.map +1 -0
  125. package/dist/fetch/audit.d.ts +25 -0
  126. package/dist/fetch/audit.d.ts.map +1 -0
  127. package/dist/fetch/audit.js +46 -0
  128. package/dist/fetch/audit.js.map +1 -0
  129. package/dist/fetch/batch.d.ts +68 -0
  130. package/dist/fetch/batch.d.ts.map +1 -0
  131. package/dist/fetch/batch.js +183 -0
  132. package/dist/fetch/batch.js.map +1 -0
  133. package/dist/fetch/body.d.ts +89 -0
  134. package/dist/fetch/body.d.ts.map +1 -0
  135. package/dist/fetch/body.js +217 -0
  136. package/dist/fetch/body.js.map +1 -0
  137. package/dist/fetch/cli.d.ts +3 -0
  138. package/dist/fetch/cli.d.ts.map +1 -0
  139. package/dist/fetch/cli.js +195 -0
  140. package/dist/fetch/cli.js.map +1 -0
  141. package/dist/fetch/cross-skill.d.ts +29 -0
  142. package/dist/fetch/cross-skill.d.ts.map +1 -0
  143. package/dist/fetch/cross-skill.js +42 -0
  144. package/dist/fetch/cross-skill.js.map +1 -0
  145. package/dist/fetch/db.d.ts +5 -0
  146. package/dist/fetch/db.d.ts.map +1 -0
  147. package/dist/fetch/db.js +4 -0
  148. package/dist/fetch/db.js.map +1 -0
  149. package/dist/fetch/diet.d.ts +174 -0
  150. package/dist/fetch/diet.d.ts.map +1 -0
  151. package/dist/fetch/diet.js +239 -0
  152. package/dist/fetch/diet.js.map +1 -0
  153. package/dist/fetch/errors.d.ts +5 -0
  154. package/dist/fetch/errors.d.ts.map +1 -0
  155. package/dist/fetch/errors.js +8 -0
  156. package/dist/fetch/errors.js.map +1 -0
  157. package/dist/fetch/exercise.d.ts +72 -0
  158. package/dist/fetch/exercise.d.ts.map +1 -0
  159. package/dist/fetch/exercise.js +270 -0
  160. package/dist/fetch/exercise.js.map +1 -0
  161. package/dist/fetch/goal.d.ts +48 -0
  162. package/dist/fetch/goal.d.ts.map +1 -0
  163. package/dist/fetch/goal.js +73 -0
  164. package/dist/fetch/goal.js.map +1 -0
  165. package/dist/fetch/goalHistory.d.ts +24 -0
  166. package/dist/fetch/goalHistory.d.ts.map +1 -0
  167. package/dist/fetch/goalHistory.js +51 -0
  168. package/dist/fetch/goalHistory.js.map +1 -0
  169. package/dist/fetch/history.d.ts +28 -0
  170. package/dist/fetch/history.d.ts.map +1 -0
  171. package/dist/fetch/history.js +29 -0
  172. package/dist/fetch/history.js.map +1 -0
  173. package/dist/fetch/index.d.ts +23 -0
  174. package/dist/fetch/index.d.ts.map +1 -0
  175. package/dist/fetch/index.js +16 -0
  176. package/dist/fetch/index.js.map +1 -0
  177. package/dist/fetch/nutritionGoal.d.ts +115 -0
  178. package/dist/fetch/nutritionGoal.d.ts.map +1 -0
  179. package/dist/fetch/nutritionGoal.js +154 -0
  180. package/dist/fetch/nutritionGoal.js.map +1 -0
  181. package/dist/fetch/photos.d.ts +76 -0
  182. package/dist/fetch/photos.d.ts.map +1 -0
  183. package/dist/fetch/photos.js +193 -0
  184. package/dist/fetch/photos.js.map +1 -0
  185. package/dist/fetch/plan.d.ts +145 -0
  186. package/dist/fetch/plan.d.ts.map +1 -0
  187. package/dist/fetch/plan.js +258 -0
  188. package/dist/fetch/plan.js.map +1 -0
  189. package/dist/fetch/products.d.ts +62 -0
  190. package/dist/fetch/products.d.ts.map +1 -0
  191. package/dist/fetch/products.js +73 -0
  192. package/dist/fetch/products.js.map +1 -0
  193. package/dist/fetch/profile.d.ts +46 -0
  194. package/dist/fetch/profile.d.ts.map +1 -0
  195. package/dist/fetch/profile.js +105 -0
  196. package/dist/fetch/profile.js.map +1 -0
  197. package/dist/fetch/shapes.d.ts +41 -0
  198. package/dist/fetch/shapes.d.ts.map +1 -0
  199. package/dist/fetch/shapes.js +38 -0
  200. package/dist/fetch/shapes.js.map +1 -0
  201. package/dist/fetch/validate.d.ts +11 -0
  202. package/dist/fetch/validate.d.ts.map +1 -0
  203. package/dist/fetch/validate.js +64 -0
  204. package/dist/fetch/validate.js.map +1 -0
  205. package/dist/fetch/weight.d.ts +109 -0
  206. package/dist/fetch/weight.d.ts.map +1 -0
  207. package/dist/fetch/weight.js +210 -0
  208. package/dist/fetch/weight.js.map +1 -0
  209. package/dist/fetch/xunji-catalog.d.ts +17 -0
  210. package/dist/fetch/xunji-catalog.d.ts.map +1 -0
  211. package/dist/fetch/xunji-catalog.js +57 -0
  212. package/dist/fetch/xunji-catalog.js.map +1 -0
  213. package/dist/index.d.ts +17 -0
  214. package/dist/index.d.ts.map +1 -0
  215. package/dist/index.js +12 -0
  216. package/dist/index.js.map +1 -0
  217. package/dist/kcal.d.ts +21 -0
  218. package/dist/kcal.d.ts.map +1 -0
  219. package/dist/kcal.js +27 -0
  220. package/dist/kcal.js.map +1 -0
  221. package/dist/migrate/migrate.d.ts +71 -0
  222. package/dist/migrate/migrate.d.ts.map +1 -0
  223. package/dist/migrate/migrate.js +450 -0
  224. package/dist/migrate/migrate.js.map +1 -0
  225. package/dist/paths.d.ts +6 -0
  226. package/dist/paths.d.ts.map +1 -0
  227. package/dist/paths.js +34 -0
  228. package/dist/paths.js.map +1 -0
  229. package/dist/render/analysisPlate.d.ts +49 -0
  230. package/dist/render/analysisPlate.d.ts.map +1 -0
  231. package/dist/render/analysisPlate.js +149 -0
  232. package/dist/render/analysisPlate.js.map +1 -0
  233. package/dist/render/bodyPlate.d.ts +55 -0
  234. package/dist/render/bodyPlate.d.ts.map +1 -0
  235. package/dist/render/bodyPlate.js +97 -0
  236. package/dist/render/bodyPlate.js.map +1 -0
  237. package/dist/render/diet.d.ts +47 -0
  238. package/dist/render/diet.d.ts.map +1 -0
  239. package/dist/render/diet.js +94 -0
  240. package/dist/render/diet.js.map +1 -0
  241. package/dist/render/envelope.d.ts +60 -0
  242. package/dist/render/envelope.d.ts.map +1 -0
  243. package/dist/render/envelope.js +111 -0
  244. package/dist/render/envelope.js.map +1 -0
  245. package/dist/render/errors.d.ts +10 -0
  246. package/dist/render/errors.d.ts.map +1 -0
  247. package/dist/render/errors.js +9 -0
  248. package/dist/render/errors.js.map +1 -0
  249. package/dist/render/exercise.d.ts +20 -0
  250. package/dist/render/exercise.d.ts.map +1 -0
  251. package/dist/render/exercise.js +32 -0
  252. package/dist/render/exercise.js.map +1 -0
  253. package/dist/render/goal.d.ts +24 -0
  254. package/dist/render/goal.d.ts.map +1 -0
  255. package/dist/render/goal.js +23 -0
  256. package/dist/render/goal.js.map +1 -0
  257. package/dist/render/goalExtra.d.ts +45 -0
  258. package/dist/render/goalExtra.d.ts.map +1 -0
  259. package/dist/render/goalExtra.js +94 -0
  260. package/dist/render/goalExtra.js.map +1 -0
  261. package/dist/render/goalPlate.d.ts +66 -0
  262. package/dist/render/goalPlate.d.ts.map +1 -0
  263. package/dist/render/goalPlate.js +110 -0
  264. package/dist/render/goalPlate.js.map +1 -0
  265. package/dist/render/health.d.ts +21 -0
  266. package/dist/render/health.d.ts.map +1 -0
  267. package/dist/render/health.js +41 -0
  268. package/dist/render/health.js.map +1 -0
  269. package/dist/render/help.d.ts +18 -0
  270. package/dist/render/help.d.ts.map +1 -0
  271. package/dist/render/help.js +58 -0
  272. package/dist/render/help.js.map +1 -0
  273. package/dist/render/home.d.ts +30 -0
  274. package/dist/render/home.d.ts.map +1 -0
  275. package/dist/render/home.js +73 -0
  276. package/dist/render/home.js.map +1 -0
  277. package/dist/render/html.d.ts +66 -0
  278. package/dist/render/html.d.ts.map +1 -0
  279. package/dist/render/html.js +510 -0
  280. package/dist/render/html.js.map +1 -0
  281. package/dist/render/index.d.ts +47 -0
  282. package/dist/render/index.d.ts.map +1 -0
  283. package/dist/render/index.js +26 -0
  284. package/dist/render/index.js.map +1 -0
  285. package/dist/render/insightPlate.d.ts +55 -0
  286. package/dist/render/insightPlate.d.ts.map +1 -0
  287. package/dist/render/insightPlate.js +97 -0
  288. package/dist/render/insightPlate.js.map +1 -0
  289. package/dist/render/library.d.ts +32 -0
  290. package/dist/render/library.d.ts.map +1 -0
  291. package/dist/render/library.js +54 -0
  292. package/dist/render/library.js.map +1 -0
  293. package/dist/render/photo.d.ts +101 -0
  294. package/dist/render/photo.d.ts.map +1 -0
  295. package/dist/render/photo.js +241 -0
  296. package/dist/render/photo.js.map +1 -0
  297. package/dist/render/planPlate.d.ts +40 -0
  298. package/dist/render/planPlate.d.ts.map +1 -0
  299. package/dist/render/planPlate.js +72 -0
  300. package/dist/render/planPlate.js.map +1 -0
  301. package/dist/render/profilePlate.d.ts +17 -0
  302. package/dist/render/profilePlate.d.ts.map +1 -0
  303. package/dist/render/profilePlate.js +18 -0
  304. package/dist/render/profilePlate.js.map +1 -0
  305. package/dist/render/ranking.d.ts +22 -0
  306. package/dist/render/ranking.d.ts.map +1 -0
  307. package/dist/render/ranking.js +63 -0
  308. package/dist/render/ranking.js.map +1 -0
  309. package/dist/render/receipt.d.ts +71 -0
  310. package/dist/render/receipt.d.ts.map +1 -0
  311. package/dist/render/receipt.js +65 -0
  312. package/dist/render/receipt.js.map +1 -0
  313. package/dist/render/weightPlate.d.ts +54 -0
  314. package/dist/render/weightPlate.d.ts.map +1 -0
  315. package/dist/render/weightPlate.js +110 -0
  316. package/dist/render/weightPlate.js.map +1 -0
  317. package/dist/schema.d.ts +25 -0
  318. package/dist/schema.d.ts.map +1 -0
  319. package/dist/schema.js +281 -0
  320. package/dist/schema.js.map +1 -0
  321. package/dist/triggers/help-lookup.d.ts +28 -0
  322. package/dist/triggers/help-lookup.d.ts.map +1 -0
  323. package/dist/triggers/help-lookup.js +163 -0
  324. package/dist/triggers/help-lookup.js.map +1 -0
  325. package/dist/triggers/index.d.ts +24 -0
  326. package/dist/triggers/index.d.ts.map +1 -0
  327. package/dist/triggers/index.js +78 -0
  328. package/dist/triggers/index.js.map +1 -0
  329. package/dist/triggers/scene-01-home.d.ts +4 -0
  330. package/dist/triggers/scene-01-home.d.ts.map +1 -0
  331. package/dist/triggers/scene-01-home.js +13 -0
  332. package/dist/triggers/scene-01-home.js.map +1 -0
  333. package/dist/triggers/scene-02-diet.d.ts +4 -0
  334. package/dist/triggers/scene-02-diet.d.ts.map +1 -0
  335. package/dist/triggers/scene-02-diet.js +74 -0
  336. package/dist/triggers/scene-02-diet.js.map +1 -0
  337. package/dist/triggers/scene-03-weight.d.ts +4 -0
  338. package/dist/triggers/scene-03-weight.d.ts.map +1 -0
  339. package/dist/triggers/scene-03-weight.js +62 -0
  340. package/dist/triggers/scene-03-weight.js.map +1 -0
  341. package/dist/triggers/scene-04-exercise.d.ts +4 -0
  342. package/dist/triggers/scene-04-exercise.d.ts.map +1 -0
  343. package/dist/triggers/scene-04-exercise.js +43 -0
  344. package/dist/triggers/scene-04-exercise.js.map +1 -0
  345. package/dist/triggers/scene-05-workout.d.ts +4 -0
  346. package/dist/triggers/scene-05-workout.d.ts.map +1 -0
  347. package/dist/triggers/scene-05-workout.js +36 -0
  348. package/dist/triggers/scene-05-workout.js.map +1 -0
  349. package/dist/triggers/scene-06-goal.d.ts +4 -0
  350. package/dist/triggers/scene-06-goal.d.ts.map +1 -0
  351. package/dist/triggers/scene-06-goal.js +29 -0
  352. package/dist/triggers/scene-06-goal.js.map +1 -0
  353. package/dist/triggers/scene-07-profile.d.ts +4 -0
  354. package/dist/triggers/scene-07-profile.d.ts.map +1 -0
  355. package/dist/triggers/scene-07-profile.js +8 -0
  356. package/dist/triggers/scene-07-profile.js.map +1 -0
  357. package/dist/triggers/scene-08-body.d.ts +4 -0
  358. package/dist/triggers/scene-08-body.d.ts.map +1 -0
  359. package/dist/triggers/scene-08-body.js +17 -0
  360. package/dist/triggers/scene-08-body.js.map +1 -0
  361. package/dist/triggers/scene-09-photo.d.ts +4 -0
  362. package/dist/triggers/scene-09-photo.d.ts.map +1 -0
  363. package/dist/triggers/scene-09-photo.js +14 -0
  364. package/dist/triggers/scene-09-photo.js.map +1 -0
  365. package/dist/triggers/scene-10-analysis.d.ts +4 -0
  366. package/dist/triggers/scene-10-analysis.d.ts.map +1 -0
  367. package/dist/triggers/scene-10-analysis.js +180 -0
  368. package/dist/triggers/scene-10-analysis.js.map +1 -0
  369. package/dist/triggers/types.d.ts +66 -0
  370. package/dist/triggers/types.d.ts.map +1 -0
  371. package/dist/triggers/types.js +3 -0
  372. package/dist/triggers/types.js.map +1 -0
  373. package/package.json +35 -0
@@ -0,0 +1,105 @@
1
+ import { ACTIVITY_LEVELS } from '../kcal.js';
2
+ import { FetchError } from './errors.js';
3
+ export const ACTIVITY_ALIASES = {
4
+ '久坐': 'sedentary',
5
+ '轻度': 'light',
6
+ '中度': 'moderate',
7
+ '活跃': 'active',
8
+ '高度活跃': 'very_active',
9
+ };
10
+ export function normalizeActivityLevel(v) {
11
+ const s = String(v ?? '').trim();
12
+ if (ACTIVITY_LEVELS.includes(s))
13
+ return s;
14
+ const hit = ACTIVITY_ALIASES[s];
15
+ if (hit)
16
+ return hit;
17
+ throw new FetchError('activity_level 非法:' + JSON.stringify(s) + '(英文 ' + ACTIVITY_LEVELS.join('/') + ' 或中文 久坐/轻度/中度/活跃/高度活跃)');
18
+ }
19
+ export function normalizeGender(v) {
20
+ const s = String(v ?? '').trim();
21
+ if (s === 'male' || s === 'female')
22
+ return s;
23
+ if (s === '男')
24
+ return 'male';
25
+ if (s === '女')
26
+ return 'female';
27
+ throw new FetchError('gender 非法:' + JSON.stringify(s) + '(male/female 或 男/女)');
28
+ }
29
+ function toAge(v) {
30
+ const n = typeof v === 'number' ? v : Number(String(v ?? '').trim());
31
+ if (!Number.isInteger(n) || n < 1 || n > 130)
32
+ throw new FetchError('age 非法:' + JSON.stringify(v) + '(须 1..130 整数)');
33
+ return n;
34
+ }
35
+ function toHeightCm(v) {
36
+ const n = typeof v === 'number' ? v : Number(String(v ?? '').trim());
37
+ if (!Number.isFinite(n) || n < 50 || n > 250)
38
+ throw new FetchError('heightCm 非法:' + JSON.stringify(v) + '(须 50..250)');
39
+ return n;
40
+ }
41
+ export function getProfile(db) {
42
+ const row = db.prepare('SELECT id, age, gender, height_cm, note, activity_level FROM user_profile WHERE id = 1').get();
43
+ return row ?? null;
44
+ }
45
+ function normalizedPatch(input) {
46
+ const patch = {};
47
+ if (input.age !== undefined)
48
+ patch.age = input.age === null ? null : toAge(input.age);
49
+ if (input.gender !== undefined)
50
+ patch.gender = input.gender === null ? null : normalizeGender(input.gender);
51
+ if (input.heightCm !== undefined)
52
+ patch.height_cm = input.heightCm === null ? null : toHeightCm(input.heightCm);
53
+ if (input.activityLevel !== undefined)
54
+ patch.activity_level = input.activityLevel === null ? null : normalizeActivityLevel(input.activityLevel);
55
+ if (input.note !== undefined)
56
+ patch.note = input.note === null ? null : String(input.note);
57
+ return patch;
58
+ }
59
+ function ensureRow(db) {
60
+ db.prepare('INSERT OR IGNORE INTO user_profile (id) VALUES (1)').run();
61
+ }
62
+ /** 设置档案(单例 upsert;至少 1 个字段,否则缺失阻断)。 */
63
+ export function setProfile(db, input) {
64
+ const patch = normalizedPatch(input);
65
+ const keys = Object.keys(patch);
66
+ if (keys.length === 0)
67
+ throw new FetchError('至少传 1 个档案字段(age/gender/heightCm/activityLevel/note)');
68
+ const before = getProfile(db);
69
+ ensureRow(db);
70
+ const sets = keys.map((k) => k + ' = ?').join(', ');
71
+ const vals = keys.map((k) => patch[k] ?? null);
72
+ db.prepare('UPDATE user_profile SET ' + sets + ", updated_at = CURRENT_TIMESTAMP WHERE id = 1").run(...vals);
73
+ const after = getProfile(db);
74
+ if (!after)
75
+ throw new FetchError('set 后 user_profile#1 缺失');
76
+ return { before, after };
77
+ }
78
+ /** 单独设活动量(--live-profile-activity 对照)。 */
79
+ export function setActivityLevel(db, activityLevel) {
80
+ if (activityLevel === undefined || activityLevel === null || String(activityLevel).trim() === '') {
81
+ throw new FetchError('activityLevel 必填');
82
+ }
83
+ const norm = normalizeActivityLevel(activityLevel);
84
+ const before = getProfile(db)?.activity_level ?? null;
85
+ ensureRow(db);
86
+ db.prepare('UPDATE user_profile SET activity_level = ?, updated_at = CURRENT_TIMESTAMP WHERE id = 1').run(norm);
87
+ return { before, after: norm };
88
+ }
89
+ export const PROFILE_UPDATABLE = ['age', 'gender', 'heightCm', 'activityLevel', 'note'];
90
+ /** 改档案(--live-profile-update 对照:field+value 单字段或 fields 多字段)。 */
91
+ export function updateProfile(db, fields) {
92
+ const bad = Object.keys(fields).filter((k) => !PROFILE_UPDATABLE.includes(k));
93
+ if (bad.length)
94
+ throw new FetchError('不支持字段: ' + bad.join(', ') + ';支持: ' + PROFILE_UPDATABLE.join(', '));
95
+ if (!Object.keys(fields).length)
96
+ throw new FetchError('至少传 1 个字段');
97
+ const before = getProfile(db);
98
+ const { after } = setProfile(db, fields);
99
+ const changed = Object.keys(fields).filter((k) => {
100
+ const col = k === 'heightCm' ? 'height_cm' : k === 'activityLevel' ? 'activity_level' : k;
101
+ return before?.[col] !== after[col];
102
+ });
103
+ return { before, after, changed };
104
+ }
105
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/fetch/profile.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAWzC,MAAM,CAAC,MAAM,gBAAgB,GAAkC;IAC7D,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,aAAa;CACtB,CAAC;AAEF,MAAM,UAAU,sBAAsB,CAAC,CAAU;IAC/C,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACjC,IAAK,eAAqC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,CAAkB,CAAC;IAClF,MAAM,GAAG,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC;IACpB,MAAM,IAAI,UAAU,CAAC,oBAAoB,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,wBAAwB,CAAC,CAAC;AACjI,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,CAAU;IACxC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACjC,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK,GAAG;QAAE,OAAO,MAAM,CAAC;IAC7B,IAAI,CAAC,KAAK,GAAG;QAAE,OAAO,QAAQ,CAAC;IAC/B,MAAM,IAAI,UAAU,CAAC,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,KAAK,CAAC,CAAU;IACvB,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACrE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG;QAAE,MAAM,IAAI,UAAU,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC;IACpH,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,UAAU,CAAC,CAAU;IAC5B,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACrE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,GAAG;QAAE,MAAM,IAAI,UAAU,CAAC,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC;IACvH,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAgB;IACzC,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,wFAAwF,CAAC,CAAC,GAAG,EAEvG,CAAC;IACd,OAAO,GAAG,IAAI,IAAI,CAAC;AACrB,CAAC;AAUD,SAAS,eAAe,CAAC,KAAsB;IAC7C,MAAM,KAAK,GAAqI,EAAE,CAAC;IACnJ,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS;QAAE,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtF,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;QAAE,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5G,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;QAAE,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAChH,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS;QAAE,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC,aAAa,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,sBAAsB,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAChJ,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3F,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,SAAS,CAAC,EAAgB;IACjC,EAAE,CAAC,OAAO,CAAC,oDAAoD,CAAC,CAAC,GAAG,EAAE,CAAC;AACzE,CAAC;AAED,uCAAuC;AACvC,MAAM,UAAU,UAAU,CAAC,EAAgB,EAAE,KAAsB;IACjE,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,qDAAqD,CAAC,CAAC;IACnG,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;IAC9B,SAAS,CAAC,EAAE,CAAC,CAAC;IACd,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAuB,CAAC,IAAI,IAAI,CAAC,CAAC;IACrE,EAAE,CAAC,OAAO,CAAC,0BAA0B,GAAG,IAAI,GAAG,+CAA+C,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7G,MAAM,KAAK,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;IAC7B,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,UAAU,CAAC,yBAAyB,CAAC,CAAC;IAC5D,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,gBAAgB,CAAC,EAAgB,EAAE,aAAsB;IACvE,IAAI,aAAa,KAAK,SAAS,IAAI,aAAa,KAAK,IAAI,IAAI,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACjG,MAAM,IAAI,UAAU,CAAC,kBAAkB,CAAC,CAAC;IAC3C,CAAC;IACD,MAAM,IAAI,GAAG,sBAAsB,CAAC,aAAa,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,CAAC,EAAE,cAAc,IAAI,IAAI,CAAC;IACtD,SAAS,CAAC,EAAE,CAAC,CAAC;IACd,EAAE,CAAC,OAAO,CAAC,yFAAyF,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,CAAU,CAAC;AAEjG,iEAAiE;AACjE,MAAM,UAAU,aAAa,CAAC,EAAgB,EAAE,MAA+B;IAC7E,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAE,iBAAuC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACrG,IAAI,GAAG,CAAC,MAAM;QAAE,MAAM,IAAI,UAAU,CAAC,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1G,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM;QAAE,MAAM,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;IAC9B,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC,EAAE,EAAE,MAAyB,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QAC/C,MAAM,GAAG,GAAG,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,eAAe,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1F,OAAQ,MAAoD,EAAE,CAAC,GAAG,CAAC,KAAM,KAA4C,CAAC,GAAG,CAAC,CAAC;IAC7H,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACpC,CAAC"}
@@ -0,0 +1,41 @@
1
+ /** T3 #22 · envelope 取数段(结构段):取数函数产出可直接装 envelope 的载荷。
2
+ *
3
+ * 仅 type-only 消费 link-core(零运行时依赖,沿 02 render type-only 前例);
4
+ * version/skill 由 T11 cmd_read 统一装配,此处只定 shape+key+data。
5
+ * key 命名空间形如 calorie.<域>_<动作>,registry 对不上即 fail(T11 校验)。
6
+ */
7
+ import type { EnvelopeDataByShape, EnvelopeShape } from 'base-link-core';
8
+ export declare const CALORIE_SKILL: "calorie";
9
+ export declare function calorieKey(domain: string, op: string): string;
10
+ export interface FetchPayload<S extends EnvelopeShape = EnvelopeShape> {
11
+ shape: S;
12
+ key: string;
13
+ data: EnvelopeDataByShape[S];
14
+ }
15
+ export declare function fetchPayload<S extends EnvelopeShape>(shape: S, key: string, data: EnvelopeDataByShape[S]): FetchPayload<S>;
16
+ export declare const KEYS: {
17
+ readonly dietList: string;
18
+ readonly dietDetail: string;
19
+ readonly dietStat: string;
20
+ readonly dietReceipt: string;
21
+ readonly weightList: string;
22
+ readonly weightDetail: string;
23
+ readonly weightStat: string;
24
+ readonly weightReceipt: string;
25
+ readonly exerciseList: string;
26
+ readonly exerciseStat: string;
27
+ readonly exerciseReceipt: string;
28
+ readonly bodyList: string;
29
+ readonly bodyStat: string;
30
+ readonly bodyReceipt: string;
31
+ readonly goalStatus: string;
32
+ readonly goalHistory: string;
33
+ readonly nutritionGoal: string;
34
+ readonly nutritionRecommend: string;
35
+ readonly planDetail: string;
36
+ readonly planList: string;
37
+ readonly productList: string;
38
+ readonly productDetail: string;
39
+ readonly photoList: string;
40
+ };
41
+ //# sourceMappingURL=shapes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shapes.d.ts","sourceRoot":"","sources":["../../src/fetch/shapes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEzE,eAAO,MAAM,aAAa,EAAG,SAAkB,CAAC;AAEhD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa;IACnE,KAAK,EAAE,CAAC,CAAC;IACT,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,mBAAmB,CAAC,CAAC,CAAC,CAAC;CAC9B;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,aAAa,EAClD,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAClD,YAAY,CAAC,CAAC,CAAC,CAKjB;AAID,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;CAwBP,CAAC"}
@@ -0,0 +1,38 @@
1
+ export const CALORIE_SKILL = 'calorie';
2
+ export function calorieKey(domain, op) {
3
+ return `${CALORIE_SKILL}.${domain}_${op}`;
4
+ }
5
+ export function fetchPayload(shape, key, data) {
6
+ if (!key.startsWith(`${CALORIE_SKILL}.`)) {
7
+ throw new Error(`key 命名空间非法(须 calorie.*):${key}`);
8
+ }
9
+ return { shape, key, data };
10
+ }
11
+ // 域常用 key(T8-T10 渲染与 T11 出口复用同一命名):
12
+ // T4 #23 落子时只定了 T3 四域;T4 五域(目标/计划/食品库/照片)key 在 T8 #27 内补,T9 #28 复用同值。
13
+ export const KEYS = {
14
+ dietList: calorieKey('diet', 'list'),
15
+ dietDetail: calorieKey('diet', 'detail'),
16
+ dietStat: calorieKey('diet', 'stat'),
17
+ dietReceipt: calorieKey('diet', 'receipt'),
18
+ weightList: calorieKey('weight', 'list'),
19
+ weightDetail: calorieKey('weight', 'detail'),
20
+ weightStat: calorieKey('weight', 'stat'),
21
+ weightReceipt: calorieKey('weight', 'receipt'),
22
+ exerciseList: calorieKey('exercise', 'list'),
23
+ exerciseStat: calorieKey('exercise', 'stat'),
24
+ exerciseReceipt: calorieKey('exercise', 'receipt'),
25
+ bodyList: calorieKey('body', 'list'),
26
+ bodyStat: calorieKey('body', 'stat'),
27
+ bodyReceipt: calorieKey('body', 'receipt'),
28
+ goalStatus: calorieKey('goal', 'status'),
29
+ goalHistory: calorieKey('goal', 'history'),
30
+ nutritionGoal: calorieKey('nutrition', 'goal'),
31
+ nutritionRecommend: calorieKey('nutrition', 'recommend'),
32
+ planDetail: calorieKey('plan', 'detail'),
33
+ planList: calorieKey('plan', 'list'),
34
+ productList: calorieKey('product', 'list'),
35
+ productDetail: calorieKey('product', 'detail'),
36
+ photoList: calorieKey('photo', 'list'),
37
+ };
38
+ //# sourceMappingURL=shapes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shapes.js","sourceRoot":"","sources":["../../src/fetch/shapes.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,aAAa,GAAG,SAAkB,CAAC;AAEhD,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,EAAU;IACnD,OAAO,GAAG,aAAa,IAAI,MAAM,IAAI,EAAE,EAAE,CAAC;AAC5C,CAAC;AAQD,MAAM,UAAU,YAAY,CAC1B,KAAQ,EAAE,GAAW,EAAE,IAA4B;IAEnD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,aAAa,GAAG,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED,oCAAoC;AACpC,sEAAsE;AACtE,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,QAAQ,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC;IACpC,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC;IACxC,QAAQ,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC;IACpC,WAAW,EAAE,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC;IAC1C,UAAU,EAAE,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;IACxC,YAAY,EAAE,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5C,UAAU,EAAE,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;IACxC,aAAa,EAAE,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC9C,YAAY,EAAE,UAAU,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5C,YAAY,EAAE,UAAU,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5C,eAAe,EAAE,UAAU,CAAC,UAAU,EAAE,SAAS,CAAC;IAClD,QAAQ,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC;IACpC,QAAQ,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC;IACpC,WAAW,EAAE,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC;IAC1C,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC;IACxC,WAAW,EAAE,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC;IAC1C,aAAa,EAAE,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC;IAC9C,kBAAkB,EAAE,UAAU,CAAC,WAAW,EAAE,WAAW,CAAC;IACxD,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC;IACxC,QAAQ,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC;IACpC,WAAW,EAAE,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC;IAC1C,aAAa,EAAE,UAAU,CAAC,SAAS,EAAE,QAAQ,CAAC;IAC9C,SAAS,EAAE,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC;CAC9B,CAAC"}
@@ -0,0 +1,11 @@
1
+ /** T6 #25 · 批量导入校验:与老家 batch_import.validate_record 同规则(只读对照)。 */
2
+ export declare const REQUIRED_FIELDS: readonly ["product_name", "calories", "protein", "fat", "carbohydrates", "sodium", "source"];
3
+ export declare const OPTIONAL_FIELDS: readonly ["brand", "saturated_fat", "sugar", "dietary_fiber", "note", "is_deprecated"];
4
+ export declare const NUMERIC_FIELDS: readonly ["calories", "protein", "fat", "saturated_fat", "carbohydrates", "sugar", "dietary_fiber", "sodium"];
5
+ export interface ValidationResult {
6
+ ok: boolean;
7
+ error?: string;
8
+ }
9
+ /** 单条校验,返回 (是否通过, 错误信息)。规则与老家逐条一致。 */
10
+ export declare function validateRecord(record: unknown): ValidationResult;
11
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/fetch/validate.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAElE,eAAO,MAAM,eAAe,8FAQlB,CAAC;AAEX,eAAO,MAAM,eAAe,wFAOlB,CAAC;AAEX,eAAO,MAAM,cAAc,+GASjB,CAAC;AAEX,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,sCAAsC;AACtC,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAiChE"}
@@ -0,0 +1,64 @@
1
+ /** T6 #25 · 批量导入校验:与老家 batch_import.validate_record 同规则(只读对照)。 */
2
+ export const REQUIRED_FIELDS = [
3
+ 'product_name',
4
+ 'calories',
5
+ 'protein',
6
+ 'fat',
7
+ 'carbohydrates',
8
+ 'sodium',
9
+ 'source',
10
+ ];
11
+ export const OPTIONAL_FIELDS = [
12
+ 'brand',
13
+ 'saturated_fat',
14
+ 'sugar',
15
+ 'dietary_fiber',
16
+ 'note',
17
+ 'is_deprecated',
18
+ ];
19
+ export const NUMERIC_FIELDS = [
20
+ 'calories',
21
+ 'protein',
22
+ 'fat',
23
+ 'saturated_fat',
24
+ 'carbohydrates',
25
+ 'sugar',
26
+ 'dietary_fiber',
27
+ 'sodium',
28
+ ];
29
+ /** 单条校验,返回 (是否通过, 错误信息)。规则与老家逐条一致。 */
30
+ export function validateRecord(record) {
31
+ if (typeof record !== 'object' || record === null || Array.isArray(record)) {
32
+ return { ok: false, error: '记录必须是对象' };
33
+ }
34
+ const rec = record;
35
+ for (const field of REQUIRED_FIELDS) {
36
+ if (!(field in rec) || rec[field] === null || rec[field] === undefined) {
37
+ return { ok: false, error: `缺少必填字段: ${field}` };
38
+ }
39
+ // source 必须如实标注、非空;未知就写“未知”,不许空着
40
+ if (field === 'source') {
41
+ if (typeof rec[field] !== 'string' || rec[field].trim() === '') {
42
+ return { ok: false, error: 'source 必须是非空字符串(如实记录数据来源,可以是“未知”)' };
43
+ }
44
+ }
45
+ if (field === 'product_name') {
46
+ if (typeof rec[field] !== 'string' || rec[field].trim() === '') {
47
+ return { ok: false, error: 'product_name 必须是非空字符串' };
48
+ }
49
+ }
50
+ }
51
+ for (const field of NUMERIC_FIELDS) {
52
+ if (field in rec && rec[field] !== null && rec[field] !== undefined) {
53
+ const v = rec[field];
54
+ if (typeof v !== 'number' || Number.isNaN(v)) {
55
+ return { ok: false, error: `${field} 必须是数字` };
56
+ }
57
+ if (v < 0) {
58
+ return { ok: false, error: `${field} 必须 >= 0,当前: ${v}` };
59
+ }
60
+ }
61
+ }
62
+ return { ok: true };
63
+ }
64
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/fetch/validate.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAElE,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,cAAc;IACd,UAAU;IACV,SAAS;IACT,KAAK;IACL,eAAe;IACf,QAAQ;IACR,QAAQ;CACA,CAAC;AAEX,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,OAAO;IACP,eAAe;IACf,OAAO;IACP,eAAe;IACf,MAAM;IACN,eAAe;CACP,CAAC;AAEX,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,UAAU;IACV,SAAS;IACT,KAAK;IACL,eAAe;IACf,eAAe;IACf,OAAO;IACP,eAAe;IACf,QAAQ;CACA,CAAC;AAOX,sCAAsC;AACtC,MAAM,UAAU,cAAc,CAAC,MAAe;IAC5C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3E,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IACzC,CAAC;IACD,MAAM,GAAG,GAAG,MAAiC,CAAC;IAC9C,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;QACpC,IAAI,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,SAAS,EAAE,CAAC;YACvE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,KAAK,EAAE,EAAE,CAAC;QAClD,CAAC;QACD,iCAAiC;QACjC,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvB,IAAI,OAAO,GAAG,CAAC,KAAK,CAAC,KAAK,QAAQ,IAAK,GAAG,CAAC,KAAK,CAAY,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;gBAC3E,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,mCAAmC,EAAE,CAAC;YACnE,CAAC;QACH,CAAC;QACD,IAAI,KAAK,KAAK,cAAc,EAAE,CAAC;YAC7B,IAAI,OAAO,GAAG,CAAC,KAAK,CAAC,KAAK,QAAQ,IAAK,GAAG,CAAC,KAAK,CAAY,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;gBAC3E,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;YACvD,CAAC;QACH,CAAC;IACH,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,IAAI,KAAK,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,SAAS,EAAE,CAAC;YACpE,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;YACrB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,QAAQ,EAAE,CAAC;YAChD,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACV,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,gBAAgB,CAAC,EAAE,EAAE,CAAC;YAC3D,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC"}
@@ -0,0 +1,109 @@
1
+ /** T3 #22 · 体重取数(对照老家 scripts/weight.py)。
2
+ *
3
+ * 身高单一来源 user_profile(老家 2026-07-20 改);C5 #43 去身高强前置:缺身高仍记,BMI 记 null(延后算),回执给补档案链。
4
+ * 删除为硬删除(老家语义);失败抛 FetchError。
5
+ */
6
+ import type { DatabaseSync } from 'node:sqlite';
7
+ export declare const NOTE_TAGS: string[];
8
+ export declare function noteTag(note: string | null | undefined): string | null;
9
+ export interface WeightRow {
10
+ id: number;
11
+ date: string;
12
+ time: string | null;
13
+ weight_kg: number;
14
+ bmi: number | null;
15
+ note: string | null;
16
+ }
17
+ export interface LogWeightResult {
18
+ id: number;
19
+ date: string;
20
+ time: string;
21
+ kg: number;
22
+ bmi: number | null;
23
+ note: string;
24
+ rowsAffected: number;
25
+ }
26
+ export declare function logWeight(db: DatabaseSync, weightKg: number, note?: string, targetDate?: string, targetTime?: string): LogWeightResult;
27
+ export interface UpdateWeightResult {
28
+ id: number;
29
+ date: string;
30
+ time: string | null;
31
+ oldWeight: number;
32
+ newWeight: number;
33
+ bmi: number | null;
34
+ note: string | null;
35
+ rowsAffected: number;
36
+ }
37
+ export declare function updateWeight(db: DatabaseSync, weightId: number, weightKg?: number, note?: string): UpdateWeightResult;
38
+ export interface WeightHistory {
39
+ range: string;
40
+ rows: {
41
+ date: string;
42
+ time: string | null;
43
+ weight_kg: number;
44
+ bmi: number | null;
45
+ note: string | null;
46
+ }[];
47
+ change: {
48
+ spanDays: number;
49
+ first: number;
50
+ last: number;
51
+ delta: number;
52
+ dailyAvg: number;
53
+ } | null;
54
+ }
55
+ export declare function getWeightHistory(db: DatabaseSync, opts?: {
56
+ days?: number;
57
+ startDate?: string;
58
+ endDate?: string;
59
+ }): WeightHistory;
60
+ export declare function getWeightGoalValue(db: DatabaseSync): number | null;
61
+ export declare function deltaLast(db: DatabaseSync, targetDate?: string, excludeTime?: string): number | null;
62
+ export declare function goalDiff(db: DatabaseSync, weightKg: number): number | null;
63
+ export declare function deleteWeight(db: DatabaseSync, weightId: number): WeightRow & {
64
+ deletedCount: number;
65
+ };
66
+ export declare function deleteWeightByDate(db: DatabaseSync, targetDate: string): {
67
+ date: string;
68
+ deletedCount: number;
69
+ snapshot: WeightRow[];
70
+ };
71
+ export declare function deleteWeightRange(db: DatabaseSync, startDate: string, endDate: string): {
72
+ start: string;
73
+ end: string;
74
+ deletedCount: number;
75
+ snapshot: WeightRow[];
76
+ };
77
+ export declare function updateWeightByDate(db: DatabaseSync, targetDate: string, weightKg?: number, note?: string): {
78
+ date: string;
79
+ hitCount: number;
80
+ oldRows: WeightRow[];
81
+ newWeight: number | null;
82
+ bmi: number | null;
83
+ note: string | null;
84
+ };
85
+ export interface BatchWeightItem {
86
+ date?: string;
87
+ kg?: number;
88
+ }
89
+ export declare function batchLogWeight(db: DatabaseSync, items: BatchWeightItem[]): {
90
+ wrote: number;
91
+ skipped: number;
92
+ failed: number;
93
+ items: {
94
+ date: string | undefined;
95
+ kg: number | undefined;
96
+ status: string;
97
+ reason: string;
98
+ }[];
99
+ };
100
+ export interface WeightLogItem {
101
+ date: string;
102
+ kg: number;
103
+ bmi: number | null;
104
+ delta: number;
105
+ note: string;
106
+ tag: string | null;
107
+ }
108
+ export declare function fetchWeightLogs(db: DatabaseSync, start: string, end: string, noteOnly?: boolean): WeightLogItem[];
109
+ //# sourceMappingURL=weight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weight.d.ts","sourceRoot":"","sources":["../../src/fetch/weight.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,210 @@
1
+ import { FetchError } from './errors.js';
2
+ export const NOTE_TAGS = ['晨起空腹', '运动后', '睡前', '餐前', '餐后', '晨起', '空腹', '早起', '运动前', '生理期'];
3
+ export function noteTag(note) {
4
+ if (!note)
5
+ return null;
6
+ for (const tag of NOTE_TAGS)
7
+ if (note.includes(tag))
8
+ return tag;
9
+ return '其他';
10
+ }
11
+ function todayStr() { return new Date().toISOString().slice(0, 10); }
12
+ function nowStr() { return new Date().toTimeString().slice(0, 8); }
13
+ function profileHeightCm(db) {
14
+ const row = db.prepare('SELECT height_cm FROM user_profile WHERE id = 1').get();
15
+ const h = row?.height_cm;
16
+ // C5 #43 · 缺身高不抛:回 null,调用方记 BMI null(延后算)。
17
+ if (h === undefined || h === null || h <= 0)
18
+ return null;
19
+ return h;
20
+ }
21
+ function bmiOf(kg, heightCm) {
22
+ return Math.round((kg / (heightCm / 100) ** 2) * 10) / 10;
23
+ }
24
+ export function logWeight(db, weightKg, note = '', targetDate, targetTime) {
25
+ const kg = Number(weightKg);
26
+ if (!Number.isFinite(kg))
27
+ throw new FetchError('体重必须是数字');
28
+ if (kg <= 0)
29
+ throw new FetchError('体重必须为正数');
30
+ const heightCm = profileHeightCm(db);
31
+ const date = targetDate ?? todayStr();
32
+ const time = targetTime ?? nowStr();
33
+ const bmi = heightCm === null ? null : bmiOf(kg, heightCm);
34
+ const info = db.prepare('INSERT INTO weight_log (date, time, weight_kg, height_cm, bmi, note) VALUES (?, ?, ?, ?, ?, ?)').run(date, time, kg, heightCm, bmi, note);
35
+ return { id: Number(info.lastInsertRowid), date, time, kg, bmi, note, rowsAffected: 1 };
36
+ }
37
+ export function updateWeight(db, weightId, weightKg, note) {
38
+ const id = Number(weightId);
39
+ if (!Number.isInteger(id))
40
+ throw new FetchError('体重记录 ID 必须是数字');
41
+ if (weightKg === undefined && note === undefined)
42
+ throw new FetchError('至少需要传入 weight 与 note 中的一个');
43
+ const heightCm = profileHeightCm(db);
44
+ const row = db.prepare('SELECT id, weight_kg, date, time FROM weight_log WHERE id = ?').get(id);
45
+ if (!row)
46
+ throw new FetchError(`体重记录 ID ${id} 不存在`);
47
+ const newWeight = weightKg === undefined ? row.weight_kg : Number(weightKg);
48
+ if (!Number.isFinite(newWeight))
49
+ throw new FetchError('体重必须是数字');
50
+ const bmi = heightCm === null ? null : bmiOf(newWeight, heightCm);
51
+ // 老家语义:height_cm 列保留不动,只改 weight_kg/bmi(+note)。
52
+ const sets = ['weight_kg = ?', 'bmi = ?'];
53
+ const vals = [newWeight, bmi];
54
+ if (note !== undefined) {
55
+ sets.push('note = ?');
56
+ vals.push(note);
57
+ }
58
+ vals.push(id);
59
+ const info = db.prepare(`UPDATE weight_log SET ${sets.join(', ')} WHERE id = ?`).run(...vals);
60
+ return {
61
+ id: row.id, date: row.date, time: row.time, oldWeight: row.weight_kg,
62
+ newWeight, bmi, note: note ?? null, rowsAffected: Number(info.changes),
63
+ };
64
+ }
65
+ export function getWeightHistory(db, opts = {}) {
66
+ const { days = 30, startDate, endDate } = opts;
67
+ let rows;
68
+ let range;
69
+ if (startDate && endDate) {
70
+ rows = db.prepare('SELECT date, time, weight_kg, bmi, note FROM weight_log WHERE date >= ? AND date <= ? ORDER BY date DESC, time DESC').all(startDate, endDate);
71
+ range = startDate === endDate ? startDate : `${startDate} ~ ${endDate}`;
72
+ }
73
+ else if (startDate) {
74
+ rows = db.prepare('SELECT date, time, weight_kg, bmi, note FROM weight_log WHERE date = ? ORDER BY time DESC').all(startDate);
75
+ range = startDate;
76
+ }
77
+ else {
78
+ rows = db.prepare('SELECT date, time, weight_kg, bmi, note FROM weight_log ORDER BY date DESC, time DESC LIMIT ?').all(days);
79
+ range = `最近${days}天`;
80
+ }
81
+ if (!rows.length)
82
+ throw new FetchError(`无体重记录(${range})`);
83
+ let change = null;
84
+ if (rows.length >= 2) {
85
+ const first = rows[rows.length - 1].weight_kg;
86
+ const last = rows[0].weight_kg;
87
+ const spanDays = Math.round((new Date(rows[0].date).getTime() - new Date(rows[rows.length - 1].date).getTime()) / 86400000) + 1;
88
+ const delta = Math.round((last - first) * 10) / 10;
89
+ change = { spanDays, first, last, delta, dailyAvg: spanDays > 0 ? Math.round((delta / spanDays) * 100) / 100 : 0 };
90
+ }
91
+ return { range, rows, change };
92
+ }
93
+ export function getWeightGoalValue(db) {
94
+ const row = db.prepare('SELECT weight_goal FROM daily_goal WHERE id = 1').get();
95
+ return row?.weight_goal ?? null;
96
+ }
97
+ export function deltaLast(db, targetDate, excludeTime) {
98
+ const d = targetDate ?? todayStr();
99
+ const row = excludeTime
100
+ ? db.prepare('SELECT weight_kg FROM weight_log WHERE date < ? OR (date = ? AND time < ?) ORDER BY date DESC, time DESC LIMIT 1').get(d, d, excludeTime)
101
+ : db.prepare('SELECT weight_kg FROM weight_log WHERE date < ? OR (date = ? AND time < (SELECT MIN(time) FROM weight_log WHERE date = ?)) ORDER BY date DESC, time DESC LIMIT 1').get(d, d, d);
102
+ return row ? row.weight_kg : null;
103
+ }
104
+ export function goalDiff(db, weightKg) {
105
+ const goal = getWeightGoalValue(db);
106
+ if (goal === null)
107
+ return null;
108
+ return Math.round((weightKg - goal) * 10) / 10;
109
+ }
110
+ export function deleteWeight(db, weightId) {
111
+ const id = Number(weightId);
112
+ if (!Number.isInteger(id))
113
+ throw new FetchError('体重记录 ID 必须是数字');
114
+ const row = db.prepare('SELECT id, date, time, weight_kg, bmi, note FROM weight_log WHERE id = ?').get(id);
115
+ if (!row)
116
+ throw new FetchError(`体重记录 ID ${id} 不存在`);
117
+ db.prepare('DELETE FROM weight_log WHERE id = ?').run(id);
118
+ return { ...row, deletedCount: 1 };
119
+ }
120
+ function snapWeightRows(db, where, params) {
121
+ return db.prepare(`SELECT id, date, time, weight_kg, bmi, note FROM weight_log WHERE ${where} ORDER BY date, time`).all(...params);
122
+ }
123
+ export function deleteWeightByDate(db, targetDate) {
124
+ const snapshot = snapWeightRows(db, 'date = ?', [targetDate]);
125
+ if (!snapshot.length)
126
+ throw new FetchError(`${targetDate} 无体重记录`);
127
+ db.prepare('DELETE FROM weight_log WHERE date = ?').run(targetDate);
128
+ return { date: targetDate, deletedCount: snapshot.length, snapshot };
129
+ }
130
+ export function deleteWeightRange(db, startDate, endDate) {
131
+ const snapshot = snapWeightRows(db, 'date BETWEEN ? AND ?', [startDate, endDate]);
132
+ if (!snapshot.length)
133
+ throw new FetchError(`${startDate} ~ ${endDate} 无体重记录`);
134
+ db.prepare('DELETE FROM weight_log WHERE date BETWEEN ? AND ?').run(startDate, endDate);
135
+ return { start: startDate, end: endDate, deletedCount: snapshot.length, snapshot };
136
+ }
137
+ export function updateWeightByDate(db, targetDate, weightKg, note) {
138
+ if (weightKg === undefined && note === undefined)
139
+ throw new FetchError('至少需要传入 weight 与 note 中的一个');
140
+ const heightCm = profileHeightCm(db);
141
+ const oldRows = snapWeightRows(db, 'date = ?', [targetDate]);
142
+ if (!oldRows.length)
143
+ throw new FetchError(`${targetDate} 无体重记录`);
144
+ let newBmi = null;
145
+ let newKg = null;
146
+ if (weightKg !== undefined) {
147
+ newKg = Number(weightKg);
148
+ if (!Number.isFinite(newKg))
149
+ throw new FetchError('体重必须是数字');
150
+ newBmi = heightCm === null ? null : bmiOf(newKg, heightCm);
151
+ db.prepare('UPDATE weight_log SET weight_kg = ?, bmi = ? WHERE date = ?').run(newKg, newBmi, targetDate);
152
+ }
153
+ if (note !== undefined)
154
+ db.prepare('UPDATE weight_log SET note = ? WHERE date = ?').run(note, targetDate);
155
+ return { date: targetDate, hitCount: oldRows.length, oldRows, newWeight: newKg, bmi: newBmi, note: note ?? null };
156
+ }
157
+ export function batchLogWeight(db, items) {
158
+ const heightRow = db.prepare('SELECT height_cm FROM user_profile WHERE id = 1').get();
159
+ const heightCm = heightRow?.height_cm ?? null;
160
+ let wrote = 0, skipped = 0, failed = 0;
161
+ const out = [];
162
+ for (const it of items) {
163
+ const d = it.date;
164
+ const kg = Number(it.kg);
165
+ if (!Number.isFinite(kg)) {
166
+ failed++;
167
+ out.push({ date: d, kg: it.kg, status: '失败', reason: '体重非数字' });
168
+ continue;
169
+ }
170
+ if (kg <= 0) {
171
+ failed++;
172
+ out.push({ date: d, kg, status: '失败', reason: '体重必须为正数' });
173
+ continue;
174
+ }
175
+ if (!d || Number.isNaN(Date.parse(d))) {
176
+ failed++;
177
+ out.push({ date: d, kg, status: '失败', reason: '日期格式错误' });
178
+ continue;
179
+ }
180
+ const exist = db.prepare('SELECT weight_kg FROM weight_log WHERE date = ? ORDER BY time DESC LIMIT 1').get(d);
181
+ if (exist) {
182
+ skipped++;
183
+ out.push({ date: d, kg, status: '跳过', reason: `已有记录 ${exist.weight_kg}kg` });
184
+ continue;
185
+ }
186
+ const bmi = heightCm ? bmiOf(kg, heightCm) : null;
187
+ db.prepare('INSERT INTO weight_log (date, time, weight_kg, height_cm, bmi, note) VALUES (?, ?, ?, ?, ?, ?)').run(d, '08:00:00', kg, heightCm, bmi, '');
188
+ wrote++;
189
+ out.push({ date: d, kg, status: '写入', reason: '' });
190
+ }
191
+ return { wrote, skipped, failed, items: out };
192
+ }
193
+ export function fetchWeightLogs(db, start, end, noteOnly = false) {
194
+ const rows = (noteOnly
195
+ ? db.prepare(`SELECT date, weight_kg, bmi, note FROM weight_log
196
+ WHERE date BETWEEN ? AND ? AND note IS NOT NULL AND note != '' ORDER BY date, time`).all(start, end)
197
+ : db.prepare('SELECT date, weight_kg, bmi, note FROM weight_log WHERE date BETWEEN ? AND ? ORDER BY date, time').all(start, end));
198
+ const h = db.prepare('SELECT height_cm FROM user_profile ORDER BY id DESC LIMIT 1').get();
199
+ const heightM = h?.height_cm ? h.height_cm / 100 : null;
200
+ const items = [];
201
+ let prev = null;
202
+ for (const r of rows) {
203
+ const bmi = r.bmi ?? (heightM ? bmiOf(r.weight_kg, heightM * 100) : null);
204
+ const delta = prev === null ? 0 : Math.round((r.weight_kg - prev) * 10) / 10;
205
+ items.push({ date: r.date, kg: r.weight_kg, bmi, delta, note: r.note ?? '', tag: noteTag(r.note) });
206
+ prev = r.weight_kg;
207
+ }
208
+ return items;
209
+ }
210
+ //# sourceMappingURL=weight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weight.js","sourceRoot":"","sources":["../../src/fetch/weight.ts"],"names":[],"mappings":"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"}