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.
- package/dist/analysis/anomaly/common.d.ts +53 -0
- package/dist/analysis/anomaly/common.d.ts.map +1 -0
- package/dist/analysis/anomaly/common.js +69 -0
- package/dist/analysis/anomaly/common.js.map +1 -0
- package/dist/analysis/anomaly/diet.d.ts +8 -0
- package/dist/analysis/anomaly/diet.d.ts.map +1 -0
- package/dist/analysis/anomaly/diet.js +95 -0
- package/dist/analysis/anomaly/diet.js.map +1 -0
- package/dist/analysis/anomaly/exercise.d.ts +9 -0
- package/dist/analysis/anomaly/exercise.d.ts.map +1 -0
- package/dist/analysis/anomaly/exercise.js +116 -0
- package/dist/analysis/anomaly/exercise.js.map +1 -0
- package/dist/analysis/anomaly/index.d.ts +19 -0
- package/dist/analysis/anomaly/index.d.ts.map +1 -0
- package/dist/analysis/anomaly/index.js +51 -0
- package/dist/analysis/anomaly/index.js.map +1 -0
- package/dist/analysis/anomaly/overall.d.ts +13 -0
- package/dist/analysis/anomaly/overall.d.ts.map +1 -0
- package/dist/analysis/anomaly/overall.js +128 -0
- package/dist/analysis/anomaly/overall.js.map +1 -0
- package/dist/analysis/anomaly/overall2.d.ts +5 -0
- package/dist/analysis/anomaly/overall2.d.ts.map +1 -0
- package/dist/analysis/anomaly/overall2.js +94 -0
- package/dist/analysis/anomaly/overall2.js.map +1 -0
- package/dist/analysis/anomaly/weight.d.ts +8 -0
- package/dist/analysis/anomaly/weight.d.ts.map +1 -0
- package/dist/analysis/anomaly/weight.js +106 -0
- package/dist/analysis/anomaly/weight.js.map +1 -0
- package/dist/analysis/anomaly/weight2.d.ts +4 -0
- package/dist/analysis/anomaly/weight2.d.ts.map +1 -0
- package/dist/analysis/anomaly/weight2.js +59 -0
- package/dist/analysis/anomaly/weight2.js.map +1 -0
- package/dist/analysis/contraindications.d.ts +63 -0
- package/dist/analysis/contraindications.d.ts.map +1 -0
- package/dist/analysis/contraindications.js +121 -0
- package/dist/analysis/contraindications.js.map +1 -0
- package/dist/analysis/cross.d.ts +75 -0
- package/dist/analysis/cross.d.ts.map +1 -0
- package/dist/analysis/cross.js +283 -0
- package/dist/analysis/cross.js.map +1 -0
- package/dist/analysis/dashboard.d.ts +18 -0
- package/dist/analysis/dashboard.d.ts.map +1 -0
- package/dist/analysis/dashboard.js +48 -0
- package/dist/analysis/dashboard.js.map +1 -0
- package/dist/analysis/deficit.d.ts +44 -0
- package/dist/analysis/deficit.d.ts.map +1 -0
- package/dist/analysis/deficit.js +54 -0
- package/dist/analysis/deficit.js.map +1 -0
- package/dist/analysis/diet.d.ts +76 -0
- package/dist/analysis/diet.d.ts.map +1 -0
- package/dist/analysis/diet.js +164 -0
- package/dist/analysis/diet.js.map +1 -0
- package/dist/analysis/exercise.d.ts +98 -0
- package/dist/analysis/exercise.d.ts.map +1 -0
- package/dist/analysis/exercise.js +298 -0
- package/dist/analysis/exercise.js.map +1 -0
- package/dist/analysis/exerciseReview.d.ts +36 -0
- package/dist/analysis/exerciseReview.d.ts.map +1 -0
- package/dist/analysis/exerciseReview.js +50 -0
- package/dist/analysis/exerciseReview.js.map +1 -0
- package/dist/analysis/precision.d.ts +15 -0
- package/dist/analysis/precision.d.ts.map +1 -0
- package/dist/analysis/precision.js +38 -0
- package/dist/analysis/precision.js.map +1 -0
- package/dist/analysis/result.d.ts +15 -0
- package/dist/analysis/result.d.ts.map +1 -0
- package/dist/analysis/result.js +13 -0
- package/dist/analysis/result.js.map +1 -0
- package/dist/analysis/review.d.ts +118 -0
- package/dist/analysis/review.d.ts.map +1 -0
- package/dist/analysis/review.js +195 -0
- package/dist/analysis/review.js.map +1 -0
- package/dist/analysis/series.d.ts +42 -0
- package/dist/analysis/series.d.ts.map +1 -0
- package/dist/analysis/series.js +127 -0
- package/dist/analysis/series.js.map +1 -0
- package/dist/analysis/simulate.d.ts +43 -0
- package/dist/analysis/simulate.d.ts.map +1 -0
- package/dist/analysis/simulate.js +109 -0
- package/dist/analysis/simulate.js.map +1 -0
- package/dist/analysis/simulate2.d.ts +65 -0
- package/dist/analysis/simulate2.d.ts.map +1 -0
- package/dist/analysis/simulate2.js +173 -0
- package/dist/analysis/simulate2.js.map +1 -0
- package/dist/analysis/trend.d.ts +39 -0
- package/dist/analysis/trend.d.ts.map +1 -0
- package/dist/analysis/trend.js +48 -0
- package/dist/analysis/trend.js.map +1 -0
- package/dist/analysis/utils.d.ts +17 -0
- package/dist/analysis/utils.d.ts.map +1 -0
- package/dist/analysis/utils.js +52 -0
- package/dist/analysis/utils.js.map +1 -0
- package/dist/analysis/volatility.d.ts +43 -0
- package/dist/analysis/volatility.d.ts.map +1 -0
- package/dist/analysis/volatility.js +96 -0
- package/dist/analysis/volatility.js.map +1 -0
- package/dist/analysis/weight.d.ts +86 -0
- package/dist/analysis/weight.d.ts.map +1 -0
- package/dist/analysis/weight.js +219 -0
- package/dist/analysis/weight.js.map +1 -0
- package/dist/analysis/weightCompare.d.ts +63 -0
- package/dist/analysis/weightCompare.d.ts.map +1 -0
- package/dist/analysis/weightCompare.js +212 -0
- package/dist/analysis/weightCompare.js.map +1 -0
- package/dist/analysis/weightCompare2.d.ts +63 -0
- package/dist/analysis/weightCompare2.d.ts.map +1 -0
- package/dist/analysis/weightCompare2.js +211 -0
- package/dist/analysis/weightCompare2.js.map +1 -0
- package/dist/analysis/weightCompare3.d.ts +13 -0
- package/dist/analysis/weightCompare3.d.ts.map +1 -0
- package/dist/analysis/weightCompare3.js +199 -0
- package/dist/analysis/weightCompare3.js.map +1 -0
- package/dist/cli/cmd_read.d.ts +8 -0
- package/dist/cli/cmd_read.d.ts.map +1 -0
- package/dist/cli/cmd_read.js +719 -0
- package/dist/cli/cmd_read.js.map +1 -0
- package/dist/cli/keys.d.ts +333 -0
- package/dist/cli/keys.d.ts.map +1 -0
- package/dist/cli/keys.js +103 -0
- package/dist/cli/keys.js.map +1 -0
- package/dist/cli/write.d.ts +24 -0
- package/dist/cli/write.d.ts.map +1 -0
- package/dist/cli/write.js +832 -0
- package/dist/cli/write.js.map +1 -0
- package/dist/fetch/audit.d.ts +25 -0
- package/dist/fetch/audit.d.ts.map +1 -0
- package/dist/fetch/audit.js +46 -0
- package/dist/fetch/audit.js.map +1 -0
- package/dist/fetch/batch.d.ts +68 -0
- package/dist/fetch/batch.d.ts.map +1 -0
- package/dist/fetch/batch.js +183 -0
- package/dist/fetch/batch.js.map +1 -0
- package/dist/fetch/body.d.ts +89 -0
- package/dist/fetch/body.d.ts.map +1 -0
- package/dist/fetch/body.js +217 -0
- package/dist/fetch/body.js.map +1 -0
- package/dist/fetch/cli.d.ts +3 -0
- package/dist/fetch/cli.d.ts.map +1 -0
- package/dist/fetch/cli.js +195 -0
- package/dist/fetch/cli.js.map +1 -0
- package/dist/fetch/cross-skill.d.ts +29 -0
- package/dist/fetch/cross-skill.d.ts.map +1 -0
- package/dist/fetch/cross-skill.js +42 -0
- package/dist/fetch/cross-skill.js.map +1 -0
- package/dist/fetch/db.d.ts +5 -0
- package/dist/fetch/db.d.ts.map +1 -0
- package/dist/fetch/db.js +4 -0
- package/dist/fetch/db.js.map +1 -0
- package/dist/fetch/diet.d.ts +174 -0
- package/dist/fetch/diet.d.ts.map +1 -0
- package/dist/fetch/diet.js +239 -0
- package/dist/fetch/diet.js.map +1 -0
- package/dist/fetch/errors.d.ts +5 -0
- package/dist/fetch/errors.d.ts.map +1 -0
- package/dist/fetch/errors.js +8 -0
- package/dist/fetch/errors.js.map +1 -0
- package/dist/fetch/exercise.d.ts +72 -0
- package/dist/fetch/exercise.d.ts.map +1 -0
- package/dist/fetch/exercise.js +270 -0
- package/dist/fetch/exercise.js.map +1 -0
- package/dist/fetch/goal.d.ts +48 -0
- package/dist/fetch/goal.d.ts.map +1 -0
- package/dist/fetch/goal.js +73 -0
- package/dist/fetch/goal.js.map +1 -0
- package/dist/fetch/goalHistory.d.ts +24 -0
- package/dist/fetch/goalHistory.d.ts.map +1 -0
- package/dist/fetch/goalHistory.js +51 -0
- package/dist/fetch/goalHistory.js.map +1 -0
- package/dist/fetch/history.d.ts +28 -0
- package/dist/fetch/history.d.ts.map +1 -0
- package/dist/fetch/history.js +29 -0
- package/dist/fetch/history.js.map +1 -0
- package/dist/fetch/index.d.ts +23 -0
- package/dist/fetch/index.d.ts.map +1 -0
- package/dist/fetch/index.js +16 -0
- package/dist/fetch/index.js.map +1 -0
- package/dist/fetch/nutritionGoal.d.ts +115 -0
- package/dist/fetch/nutritionGoal.d.ts.map +1 -0
- package/dist/fetch/nutritionGoal.js +154 -0
- package/dist/fetch/nutritionGoal.js.map +1 -0
- package/dist/fetch/photos.d.ts +76 -0
- package/dist/fetch/photos.d.ts.map +1 -0
- package/dist/fetch/photos.js +193 -0
- package/dist/fetch/photos.js.map +1 -0
- package/dist/fetch/plan.d.ts +145 -0
- package/dist/fetch/plan.d.ts.map +1 -0
- package/dist/fetch/plan.js +258 -0
- package/dist/fetch/plan.js.map +1 -0
- package/dist/fetch/products.d.ts +62 -0
- package/dist/fetch/products.d.ts.map +1 -0
- package/dist/fetch/products.js +73 -0
- package/dist/fetch/products.js.map +1 -0
- package/dist/fetch/profile.d.ts +46 -0
- package/dist/fetch/profile.d.ts.map +1 -0
- package/dist/fetch/profile.js +105 -0
- package/dist/fetch/profile.js.map +1 -0
- package/dist/fetch/shapes.d.ts +41 -0
- package/dist/fetch/shapes.d.ts.map +1 -0
- package/dist/fetch/shapes.js +38 -0
- package/dist/fetch/shapes.js.map +1 -0
- package/dist/fetch/validate.d.ts +11 -0
- package/dist/fetch/validate.d.ts.map +1 -0
- package/dist/fetch/validate.js +64 -0
- package/dist/fetch/validate.js.map +1 -0
- package/dist/fetch/weight.d.ts +109 -0
- package/dist/fetch/weight.d.ts.map +1 -0
- package/dist/fetch/weight.js +210 -0
- package/dist/fetch/weight.js.map +1 -0
- package/dist/fetch/xunji-catalog.d.ts +17 -0
- package/dist/fetch/xunji-catalog.d.ts.map +1 -0
- package/dist/fetch/xunji-catalog.js +57 -0
- package/dist/fetch/xunji-catalog.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/kcal.d.ts +21 -0
- package/dist/kcal.d.ts.map +1 -0
- package/dist/kcal.js +27 -0
- package/dist/kcal.js.map +1 -0
- package/dist/migrate/migrate.d.ts +71 -0
- package/dist/migrate/migrate.d.ts.map +1 -0
- package/dist/migrate/migrate.js +450 -0
- package/dist/migrate/migrate.js.map +1 -0
- package/dist/paths.d.ts +6 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +34 -0
- package/dist/paths.js.map +1 -0
- package/dist/render/analysisPlate.d.ts +49 -0
- package/dist/render/analysisPlate.d.ts.map +1 -0
- package/dist/render/analysisPlate.js +149 -0
- package/dist/render/analysisPlate.js.map +1 -0
- package/dist/render/bodyPlate.d.ts +55 -0
- package/dist/render/bodyPlate.d.ts.map +1 -0
- package/dist/render/bodyPlate.js +97 -0
- package/dist/render/bodyPlate.js.map +1 -0
- package/dist/render/diet.d.ts +47 -0
- package/dist/render/diet.d.ts.map +1 -0
- package/dist/render/diet.js +94 -0
- package/dist/render/diet.js.map +1 -0
- package/dist/render/envelope.d.ts +60 -0
- package/dist/render/envelope.d.ts.map +1 -0
- package/dist/render/envelope.js +111 -0
- package/dist/render/envelope.js.map +1 -0
- package/dist/render/errors.d.ts +10 -0
- package/dist/render/errors.d.ts.map +1 -0
- package/dist/render/errors.js +9 -0
- package/dist/render/errors.js.map +1 -0
- package/dist/render/exercise.d.ts +20 -0
- package/dist/render/exercise.d.ts.map +1 -0
- package/dist/render/exercise.js +32 -0
- package/dist/render/exercise.js.map +1 -0
- package/dist/render/goal.d.ts +24 -0
- package/dist/render/goal.d.ts.map +1 -0
- package/dist/render/goal.js +23 -0
- package/dist/render/goal.js.map +1 -0
- package/dist/render/goalExtra.d.ts +45 -0
- package/dist/render/goalExtra.d.ts.map +1 -0
- package/dist/render/goalExtra.js +94 -0
- package/dist/render/goalExtra.js.map +1 -0
- package/dist/render/goalPlate.d.ts +66 -0
- package/dist/render/goalPlate.d.ts.map +1 -0
- package/dist/render/goalPlate.js +110 -0
- package/dist/render/goalPlate.js.map +1 -0
- package/dist/render/health.d.ts +21 -0
- package/dist/render/health.d.ts.map +1 -0
- package/dist/render/health.js +41 -0
- package/dist/render/health.js.map +1 -0
- package/dist/render/help.d.ts +18 -0
- package/dist/render/help.d.ts.map +1 -0
- package/dist/render/help.js +58 -0
- package/dist/render/help.js.map +1 -0
- package/dist/render/home.d.ts +30 -0
- package/dist/render/home.d.ts.map +1 -0
- package/dist/render/home.js +73 -0
- package/dist/render/home.js.map +1 -0
- package/dist/render/html.d.ts +66 -0
- package/dist/render/html.d.ts.map +1 -0
- package/dist/render/html.js +510 -0
- package/dist/render/html.js.map +1 -0
- package/dist/render/index.d.ts +47 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +26 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/insightPlate.d.ts +55 -0
- package/dist/render/insightPlate.d.ts.map +1 -0
- package/dist/render/insightPlate.js +97 -0
- package/dist/render/insightPlate.js.map +1 -0
- package/dist/render/library.d.ts +32 -0
- package/dist/render/library.d.ts.map +1 -0
- package/dist/render/library.js +54 -0
- package/dist/render/library.js.map +1 -0
- package/dist/render/photo.d.ts +101 -0
- package/dist/render/photo.d.ts.map +1 -0
- package/dist/render/photo.js +241 -0
- package/dist/render/photo.js.map +1 -0
- package/dist/render/planPlate.d.ts +40 -0
- package/dist/render/planPlate.d.ts.map +1 -0
- package/dist/render/planPlate.js +72 -0
- package/dist/render/planPlate.js.map +1 -0
- package/dist/render/profilePlate.d.ts +17 -0
- package/dist/render/profilePlate.d.ts.map +1 -0
- package/dist/render/profilePlate.js +18 -0
- package/dist/render/profilePlate.js.map +1 -0
- package/dist/render/ranking.d.ts +22 -0
- package/dist/render/ranking.d.ts.map +1 -0
- package/dist/render/ranking.js +63 -0
- package/dist/render/ranking.js.map +1 -0
- package/dist/render/receipt.d.ts +71 -0
- package/dist/render/receipt.d.ts.map +1 -0
- package/dist/render/receipt.js +65 -0
- package/dist/render/receipt.js.map +1 -0
- package/dist/render/weightPlate.d.ts +54 -0
- package/dist/render/weightPlate.d.ts.map +1 -0
- package/dist/render/weightPlate.js +110 -0
- package/dist/render/weightPlate.js.map +1 -0
- package/dist/schema.d.ts +25 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +281 -0
- package/dist/schema.js.map +1 -0
- package/dist/triggers/help-lookup.d.ts +28 -0
- package/dist/triggers/help-lookup.d.ts.map +1 -0
- package/dist/triggers/help-lookup.js +163 -0
- package/dist/triggers/help-lookup.js.map +1 -0
- package/dist/triggers/index.d.ts +24 -0
- package/dist/triggers/index.d.ts.map +1 -0
- package/dist/triggers/index.js +78 -0
- package/dist/triggers/index.js.map +1 -0
- package/dist/triggers/scene-01-home.d.ts +4 -0
- package/dist/triggers/scene-01-home.d.ts.map +1 -0
- package/dist/triggers/scene-01-home.js +13 -0
- package/dist/triggers/scene-01-home.js.map +1 -0
- package/dist/triggers/scene-02-diet.d.ts +4 -0
- package/dist/triggers/scene-02-diet.d.ts.map +1 -0
- package/dist/triggers/scene-02-diet.js +74 -0
- package/dist/triggers/scene-02-diet.js.map +1 -0
- package/dist/triggers/scene-03-weight.d.ts +4 -0
- package/dist/triggers/scene-03-weight.d.ts.map +1 -0
- package/dist/triggers/scene-03-weight.js +62 -0
- package/dist/triggers/scene-03-weight.js.map +1 -0
- package/dist/triggers/scene-04-exercise.d.ts +4 -0
- package/dist/triggers/scene-04-exercise.d.ts.map +1 -0
- package/dist/triggers/scene-04-exercise.js +43 -0
- package/dist/triggers/scene-04-exercise.js.map +1 -0
- package/dist/triggers/scene-05-workout.d.ts +4 -0
- package/dist/triggers/scene-05-workout.d.ts.map +1 -0
- package/dist/triggers/scene-05-workout.js +36 -0
- package/dist/triggers/scene-05-workout.js.map +1 -0
- package/dist/triggers/scene-06-goal.d.ts +4 -0
- package/dist/triggers/scene-06-goal.d.ts.map +1 -0
- package/dist/triggers/scene-06-goal.js +29 -0
- package/dist/triggers/scene-06-goal.js.map +1 -0
- package/dist/triggers/scene-07-profile.d.ts +4 -0
- package/dist/triggers/scene-07-profile.d.ts.map +1 -0
- package/dist/triggers/scene-07-profile.js +8 -0
- package/dist/triggers/scene-07-profile.js.map +1 -0
- package/dist/triggers/scene-08-body.d.ts +4 -0
- package/dist/triggers/scene-08-body.d.ts.map +1 -0
- package/dist/triggers/scene-08-body.js +17 -0
- package/dist/triggers/scene-08-body.js.map +1 -0
- package/dist/triggers/scene-09-photo.d.ts +4 -0
- package/dist/triggers/scene-09-photo.d.ts.map +1 -0
- package/dist/triggers/scene-09-photo.js +14 -0
- package/dist/triggers/scene-09-photo.js.map +1 -0
- package/dist/triggers/scene-10-analysis.d.ts +4 -0
- package/dist/triggers/scene-10-analysis.d.ts.map +1 -0
- package/dist/triggers/scene-10-analysis.js +180 -0
- package/dist/triggers/scene-10-analysis.js.map +1 -0
- package/dist/triggers/types.d.ts +66 -0
- package/dist/triggers/types.d.ts.map +1 -0
- package/dist/triggers/types.js +3 -0
- package/dist/triggers/types.js.map +1 -0
- package/package.json +35 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { basename, join } from 'node:path';
|
|
3
|
+
import { getPhotoRow, listPhotos, planGif, tagsContain, } from '../fetch/photos.js';
|
|
4
|
+
import { shiftISODate, todayISO } from '../analysis/utils.js';
|
|
5
|
+
import { CalorieRenderError } from './errors.js';
|
|
6
|
+
import { buildCrudReceipt } from './receipt.js';
|
|
7
|
+
export function toCard(row, photosDir) {
|
|
8
|
+
let fileExists = null;
|
|
9
|
+
if (photosDir) {
|
|
10
|
+
try {
|
|
11
|
+
fileExists = existsSync(join(photosDir, basename(row.photo_path)));
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
fileExists = false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
id: row.id,
|
|
19
|
+
date: row.date,
|
|
20
|
+
time: row.time,
|
|
21
|
+
photoPath: basename(row.photo_path),
|
|
22
|
+
tagList: [...row.tag_list],
|
|
23
|
+
note: row.note,
|
|
24
|
+
fileExists,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const ISO_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
28
|
+
function assertISO(v, field) {
|
|
29
|
+
if (!ISO_RE.test(v))
|
|
30
|
+
throw new CalorieRenderError('bad-input', field + ' 非法(须 YYYY-MM-DD):' + v);
|
|
31
|
+
}
|
|
32
|
+
function diffDays(a, b) {
|
|
33
|
+
return Math.round((Date.parse(b + 'T12:00:00Z') - Date.parse(a + 'T12:00:00Z')) / 86400000);
|
|
34
|
+
}
|
|
35
|
+
/** 看身材照:网格 + 时间/标签筛选 + 计数(老家 gallery build 对应,默认 90 天窗)。 */
|
|
36
|
+
export function buildGalleryData(db, filter = {}, photosDir) {
|
|
37
|
+
const today = filter.today ?? todayISO();
|
|
38
|
+
assertISO(today, 'today');
|
|
39
|
+
let dateFrom = filter.dateFrom ?? '';
|
|
40
|
+
let dateTo = filter.dateTo ?? '';
|
|
41
|
+
if (dateFrom)
|
|
42
|
+
assertISO(dateFrom, 'dateFrom');
|
|
43
|
+
if (dateTo)
|
|
44
|
+
assertISO(dateTo, 'dateTo');
|
|
45
|
+
if (dateFrom && !dateTo)
|
|
46
|
+
dateTo = dateFrom;
|
|
47
|
+
if (!dateFrom && !dateTo) {
|
|
48
|
+
const days = filter.days ?? 90;
|
|
49
|
+
if (!Number.isInteger(days) || days < 1 || days > 36500) {
|
|
50
|
+
throw new CalorieRenderError('bad-input', 'days 须为 1..36500 整数');
|
|
51
|
+
}
|
|
52
|
+
dateTo = today;
|
|
53
|
+
dateFrom = shiftISODate(today, -(days - 1));
|
|
54
|
+
}
|
|
55
|
+
if (dateFrom > dateTo)
|
|
56
|
+
throw new CalorieRenderError('bad-input', 'dateFrom 不得晚于 dateTo');
|
|
57
|
+
const rows = listPhotos(db, {
|
|
58
|
+
dateFrom,
|
|
59
|
+
dateTo,
|
|
60
|
+
tag: filter.tag ?? null,
|
|
61
|
+
limit: filter.limit === undefined ? 500 : filter.limit,
|
|
62
|
+
});
|
|
63
|
+
if (rows.length === 0) {
|
|
64
|
+
throw new CalorieRenderError('missing-data', '无身材照(' + dateFrom + ' ~ ' + dateTo + (filter.tag ? ' · 标签 ' + filter.tag : '') + ')');
|
|
65
|
+
}
|
|
66
|
+
const counts = new Map();
|
|
67
|
+
for (const r of listPhotos(db, { days: 36500, limit: null })) {
|
|
68
|
+
for (const t of r.tag_list)
|
|
69
|
+
counts.set(t, (counts.get(t) ?? 0) + 1);
|
|
70
|
+
}
|
|
71
|
+
const daysSinceLast = diffDays(rows[0]?.date, today) >= 0 ? diffDays(rows[0]?.date, today) : null;
|
|
72
|
+
return {
|
|
73
|
+
scene: '看身材照',
|
|
74
|
+
filters: { tag: filter.tag ?? '', dateFrom, dateTo },
|
|
75
|
+
totalCount: rows.length,
|
|
76
|
+
tagCounts: [...counts.entries()].sort((a, b) => (a[0] < b[0] ? -1 : 1)).map(([tag, count]) => ({ tag, count })),
|
|
77
|
+
daysSinceLast,
|
|
78
|
+
photos: rows.map((r) => toCard(r, photosDir)),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/** 对比两张照片:并排 + 间隔天数 + 跨标签警告(老家方案 B:警告不拦截)。 */
|
|
82
|
+
export function buildCompareData(db, id1, id2, photosDir) {
|
|
83
|
+
if (!Number.isInteger(id1) || !Number.isInteger(id2)) {
|
|
84
|
+
throw new CalorieRenderError('bad-input', '照片 id 须为整数');
|
|
85
|
+
}
|
|
86
|
+
if (id1 === id2)
|
|
87
|
+
throw new CalorieRenderError('bad-input', '对比的两张照片不能是同一张');
|
|
88
|
+
const p1 = getPhotoRow(db, id1);
|
|
89
|
+
if (!p1)
|
|
90
|
+
throw new CalorieRenderError('missing-data', '照片 #' + id1 + ' 不存在');
|
|
91
|
+
const p2 = getPhotoRow(db, id2);
|
|
92
|
+
if (!p2)
|
|
93
|
+
throw new CalorieRenderError('missing-data', '照片 #' + id2 + ' 不存在');
|
|
94
|
+
const intervalDays = Math.abs(diffDays(p1.date, p2.date));
|
|
95
|
+
const crossTagWarning = [...p1.tag_list].sort().join(',') !== [...p2.tag_list].sort().join(',');
|
|
96
|
+
return {
|
|
97
|
+
scene: '对比两张照片',
|
|
98
|
+
photo1: toCard(p1, photosDir),
|
|
99
|
+
photo2: toCard(p2, photosDir),
|
|
100
|
+
intervalDays,
|
|
101
|
+
orderByDate: p1.date <= p2.date,
|
|
102
|
+
crossTagWarning,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/** 单图查看:照片 + 同标签 prev/next(老家 viewer 邻居口径:同 tag 按日期排序)。 */
|
|
106
|
+
export function buildViewerData(db, id, photosDir) {
|
|
107
|
+
if (!Number.isInteger(id))
|
|
108
|
+
throw new CalorieRenderError('bad-input', '照片 id 须为整数');
|
|
109
|
+
const row = getPhotoRow(db, id);
|
|
110
|
+
if (!row)
|
|
111
|
+
throw new CalorieRenderError('missing-data', '照片 #' + id + ' 不存在');
|
|
112
|
+
const anchor = row.tag_list[0];
|
|
113
|
+
const pool = listPhotos(db, { days: 36500, limit: null })
|
|
114
|
+
.filter((r) => (anchor ? tagsContain(r.tag, anchor) : true))
|
|
115
|
+
.sort((a, b) => (a.date + ' ' + (a.time ?? '') + '#' + a.id < b.date + ' ' + (b.time ?? '') + '#' + b.id ? -1 : 1));
|
|
116
|
+
const idx = pool.findIndex((r) => r.id === id);
|
|
117
|
+
return {
|
|
118
|
+
scene: '查身材照',
|
|
119
|
+
photo: toCard(row, photosDir),
|
|
120
|
+
prevId: idx > 0 ? (pool[idx - 1]?.id ?? null) : null,
|
|
121
|
+
nextId: idx >= 0 && idx < pool.length - 1 ? (pool[idx + 1]?.id ?? null) : null,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
export const GIF_PASSTHROUGH_NOTE = 'GIF 合成由外部按本任务描述执行,本渲染不碰二进制';
|
|
125
|
+
/** 动图规划器:只出任务描述(T4 planGif 直通;photoIds 显式交集,不跑合成)。 */
|
|
126
|
+
export function buildGifTask(db, input) {
|
|
127
|
+
const tag = String(input.tag ?? '').trim();
|
|
128
|
+
if (!tag)
|
|
129
|
+
throw new CalorieRenderError('bad-input', 'tag 必填(GIF 按标签选照片)');
|
|
130
|
+
if (input.dateFrom)
|
|
131
|
+
assertISO(input.dateFrom, 'dateFrom');
|
|
132
|
+
if (input.dateTo)
|
|
133
|
+
assertISO(input.dateTo, 'dateTo');
|
|
134
|
+
const plan = planGif(db, {
|
|
135
|
+
tag,
|
|
136
|
+
dateFrom: input.dateFrom ?? null,
|
|
137
|
+
dateTo: input.dateTo ?? null,
|
|
138
|
+
days: input.days ?? 90,
|
|
139
|
+
});
|
|
140
|
+
let ids = [...plan.photoIds];
|
|
141
|
+
if (input.photoIds) {
|
|
142
|
+
const want = new Set(input.photoIds);
|
|
143
|
+
ids = ids.filter((x) => want.has(x));
|
|
144
|
+
}
|
|
145
|
+
let firstDate = plan.dateFrom;
|
|
146
|
+
let lastDate = plan.dateTo;
|
|
147
|
+
if (input.photoIds) {
|
|
148
|
+
const dates = ids
|
|
149
|
+
.map((x) => getPhotoRow(db, x))
|
|
150
|
+
.filter((r) => r !== null && tagsContain(r.tag, tag))
|
|
151
|
+
.map((r) => r.date)
|
|
152
|
+
.sort();
|
|
153
|
+
firstDate = dates.length > 0 ? dates[0] : null;
|
|
154
|
+
lastDate = dates.length > 0 ? dates[dates.length - 1] : null;
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
task: 'generate_gif',
|
|
158
|
+
tag,
|
|
159
|
+
dateFrom: firstDate,
|
|
160
|
+
dateTo: lastDate,
|
|
161
|
+
photoCount: ids.length,
|
|
162
|
+
photoIds: ids,
|
|
163
|
+
firstDate,
|
|
164
|
+
lastDate,
|
|
165
|
+
note: ids.length === 0 ? '无匹配照片(检查标签/日期范围) · ' + GIF_PASSTHROUGH_NOTE : GIF_PASSTHROUGH_NOTE,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/** 存照片回执:单张/含备注/批量(items 逐张状态由调用方按 T4 addPhotos 结果组装)。 */
|
|
169
|
+
export function buildAddReceipt(added, opts) {
|
|
170
|
+
const scene = added.length > 1 ? '批量存照片' : (opts.note ? '存照片(含备注)' : '存一张照片');
|
|
171
|
+
let summary = '已存入 ' + added.length + ' 张身材照';
|
|
172
|
+
if (opts.distance)
|
|
173
|
+
summary += ';距上次「' + opts.distance.tag + '」照已隔 ' + opts.distance.days + ' 天';
|
|
174
|
+
if (opts.failedCount)
|
|
175
|
+
summary += ',' + opts.failedCount + ' 张未存入';
|
|
176
|
+
return buildCrudReceipt({
|
|
177
|
+
scene,
|
|
178
|
+
action: 'add',
|
|
179
|
+
op: 'create',
|
|
180
|
+
recordId: added.length > 0 ? (added[0]?.id ?? null) : null,
|
|
181
|
+
summary,
|
|
182
|
+
items: added.map((a) => ({ id: a.id, file: a.file, status: '成功', reason: '' })),
|
|
183
|
+
wakeWord: '记身材照',
|
|
184
|
+
source: 'body_photos (写库回执)',
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
/** 删照片回执:删除前快照(调用方先 getPhotoRow 取快照,再调 T4 deletePhoto)。 */
|
|
188
|
+
export function buildDeleteReceipt(snapshot) {
|
|
189
|
+
const tags = [...snapshot.tag_list].join('、') || '无标签';
|
|
190
|
+
const summary = '已删除身材照 #' + snapshot.id + '(' + snapshot.date + ' · ' + tags + ')' +
|
|
191
|
+
(snapshot.note ? ' · ' + snapshot.note : '');
|
|
192
|
+
return buildCrudReceipt({
|
|
193
|
+
scene: '删身材照',
|
|
194
|
+
action: 'delete',
|
|
195
|
+
op: 'delete',
|
|
196
|
+
recordId: snapshot.id,
|
|
197
|
+
summary,
|
|
198
|
+
items: [{
|
|
199
|
+
id: snapshot.id,
|
|
200
|
+
date: snapshot.date,
|
|
201
|
+
photoPath: basename(snapshot.photo_path),
|
|
202
|
+
tagList: [...snapshot.tag_list],
|
|
203
|
+
status: '已删除',
|
|
204
|
+
reason: '',
|
|
205
|
+
}],
|
|
206
|
+
wakeWord: '删身材照',
|
|
207
|
+
source: 'body_photos (删除快照)',
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
/** 标签回执:改前/改后对比 + 无变化明示(set 整套覆盖 / add 追加判重 / remove 移除)。 */
|
|
211
|
+
export function buildTagReceipt(photoId, before, after, scene) {
|
|
212
|
+
if (!Number.isInteger(photoId))
|
|
213
|
+
throw new CalorieRenderError('bad-input', '照片 id 须为整数');
|
|
214
|
+
const noChange = [...before].join(',') === [...after].join(',');
|
|
215
|
+
let summary;
|
|
216
|
+
if (scene === '改照片标签') {
|
|
217
|
+
summary = '照片 #' + photoId + ' 标签已改为:' + after.join('、') + (noChange ? ';以上标签与原来一致,未产生实际变化' : '');
|
|
218
|
+
}
|
|
219
|
+
else if (scene === '加照片标签') {
|
|
220
|
+
summary = noChange
|
|
221
|
+
? '⚠ 标签已存在(当前标签:' + before.join('、') + '),未做修改'
|
|
222
|
+
: '已为照片 #' + photoId + ' 追加标签,当前标签:' + after.join('、');
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
summary = noChange
|
|
226
|
+
? '⚠ 标签不存在(当前标签:' + before.join('、') + '),未做修改'
|
|
227
|
+
: '已从照片 #' + photoId + ' 移除标签,剩余标签:' + after.join('、');
|
|
228
|
+
}
|
|
229
|
+
return buildCrudReceipt({
|
|
230
|
+
scene,
|
|
231
|
+
action: scene,
|
|
232
|
+
op: 'update',
|
|
233
|
+
recordId: photoId,
|
|
234
|
+
summary,
|
|
235
|
+
tagDiff: { before: [...before], after: [...after] },
|
|
236
|
+
noChange,
|
|
237
|
+
wakeWord: scene,
|
|
238
|
+
source: 'body_photos (标签更新)',
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=photo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"photo.js","sourceRoot":"","sources":["../../src/render/photo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** #41 · 训练计划读链 render 数据(计划看/构建向导/运动目标视图)。
|
|
2
|
+
*
|
|
3
|
+
* 数据源全复用既有取数层:
|
|
4
|
+
* 计划看=fetch/plan.getPlan(无配置且无会话即 missing);
|
|
5
|
+
* 构建向导=fetch/plan.validatePlan 纯校验 dryRun(不写库,写链归 #40);
|
|
6
|
+
* 运动目标= daily_goal.exercise_goal(日耗目标,未设即 missing)+ analysis/exerciseReview。
|
|
7
|
+
* 缺失阻断不返空;plan JSON 非法走 bad-input。
|
|
8
|
+
*/
|
|
9
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
10
|
+
import type { PlanSessionRow } from '../fetch/plan.js';
|
|
11
|
+
export interface PlanView {
|
|
12
|
+
title: string | null;
|
|
13
|
+
totalWeeks: number | null;
|
|
14
|
+
sessions: PlanSessionRow[];
|
|
15
|
+
totalSessions: number;
|
|
16
|
+
totalMovements: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function buildPlanView(db: DatabaseSync): PlanView;
|
|
19
|
+
export interface PlanWizardView {
|
|
20
|
+
errors: string[];
|
|
21
|
+
warnings: string[];
|
|
22
|
+
errorCount: number;
|
|
23
|
+
warningCount: number;
|
|
24
|
+
insertedCount: number;
|
|
25
|
+
dryRun: true;
|
|
26
|
+
}
|
|
27
|
+
export declare function buildPlanWizardView(plan: unknown, catalog?: unknown): PlanWizardView;
|
|
28
|
+
export interface ExerciseGoalView {
|
|
29
|
+
start: string;
|
|
30
|
+
end: string;
|
|
31
|
+
days: number;
|
|
32
|
+
dailyGoal: number;
|
|
33
|
+
goalTotal: number;
|
|
34
|
+
actual: number;
|
|
35
|
+
pct: number | null;
|
|
36
|
+
gap: number;
|
|
37
|
+
achieved: boolean;
|
|
38
|
+
}
|
|
39
|
+
export declare function buildExerciseGoalView(db: DatabaseSync, start: string, end: string): ExerciseGoalView;
|
|
40
|
+
//# sourceMappingURL=planPlate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planPlate.d.ts","sourceRoot":"","sources":["../../src/render/planPlate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,KAAK,EAAa,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAWlE,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,QAAQ,CAcxD;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,IAAI,CAAC;CACd;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,cAAc,CAiBpF;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,gBAAgB,CA0BpG"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { getPlan, validatePlan } from '../fetch/plan.js';
|
|
2
|
+
import { buildExerciseReview } from '../analysis/exerciseReview.js';
|
|
3
|
+
import { FetchError } from '../fetch/errors.js';
|
|
4
|
+
import { CalorieRenderError } from './errors.js';
|
|
5
|
+
function assertDate(s) {
|
|
6
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(s) || Number.isNaN(Date.parse(s + 'T12:00:00Z'))) {
|
|
7
|
+
throw new CalorieRenderError('bad-input', '日期非法: ' + String(s));
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function buildPlanView(db) {
|
|
11
|
+
const plan = getPlan(db);
|
|
12
|
+
if (!plan.config && plan.sessions.length === 0) {
|
|
13
|
+
throw new CalorieRenderError('missing-data', '无训练计划(先定训练计划)');
|
|
14
|
+
}
|
|
15
|
+
let movements = 0;
|
|
16
|
+
for (const s of plan.sessions)
|
|
17
|
+
movements += Array.isArray(s.movements) ? s.movements.length : 0;
|
|
18
|
+
return {
|
|
19
|
+
title: plan.config?.title ?? null,
|
|
20
|
+
totalWeeks: plan.config?.total_weeks ?? null,
|
|
21
|
+
sessions: plan.sessions,
|
|
22
|
+
totalSessions: plan.sessions.length,
|
|
23
|
+
totalMovements: movements,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function buildPlanWizardView(plan, catalog) {
|
|
27
|
+
if (typeof plan !== 'object' || plan === null || Array.isArray(plan)) {
|
|
28
|
+
throw new CalorieRenderError('bad-input', 'plan 必填(PlanInput 对象,含 weeks 数组)');
|
|
29
|
+
}
|
|
30
|
+
const p = plan;
|
|
31
|
+
if (!Array.isArray(p.weeks)) {
|
|
32
|
+
throw new CalorieRenderError('bad-input', 'plan.weeks 必填数组');
|
|
33
|
+
}
|
|
34
|
+
let cats;
|
|
35
|
+
if (catalog !== undefined && catalog !== null) {
|
|
36
|
+
if (!Array.isArray(catalog) || !catalog.every((x) => typeof x === 'string')) {
|
|
37
|
+
throw new CalorieRenderError('bad-input', 'catalog 须为字符串数组');
|
|
38
|
+
}
|
|
39
|
+
cats = catalog;
|
|
40
|
+
}
|
|
41
|
+
const { errors, warnings } = validatePlan(p, cats ? { catalog: cats } : {});
|
|
42
|
+
return { errors, warnings, errorCount: errors.length, warningCount: warnings.length, insertedCount: 0, dryRun: true };
|
|
43
|
+
}
|
|
44
|
+
export function buildExerciseGoalView(db, start, end) {
|
|
45
|
+
assertDate(start);
|
|
46
|
+
assertDate(end);
|
|
47
|
+
if (start > end)
|
|
48
|
+
throw new CalorieRenderError('bad-input', 'start 不得晚于 end');
|
|
49
|
+
const row = db.prepare('SELECT exercise_goal FROM daily_goal WHERE id = 1').get();
|
|
50
|
+
const daily = row?.exercise_goal ?? null;
|
|
51
|
+
if (daily === null || daily === undefined) {
|
|
52
|
+
throw new CalorieRenderError('missing-data', '未设运动目标(daily_goal.exercise_goal 缺失,先维护运动目标)');
|
|
53
|
+
}
|
|
54
|
+
if (!Number.isFinite(daily) || daily <= 0) {
|
|
55
|
+
throw new CalorieRenderError('missing-data', '运动目标非法(须正数):' + String(daily));
|
|
56
|
+
}
|
|
57
|
+
let review;
|
|
58
|
+
try {
|
|
59
|
+
review = buildExerciseReview(db, start, end);
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
if (e instanceof FetchError)
|
|
63
|
+
throw new CalorieRenderError('missing-data', e.message);
|
|
64
|
+
throw e;
|
|
65
|
+
}
|
|
66
|
+
const days = Math.round((Date.parse(end + 'T12:00:00Z') - Date.parse(start + 'T12:00:00Z')) / 86400000) + 1;
|
|
67
|
+
const goalTotal = daily * days;
|
|
68
|
+
const actual = review.totalBurned;
|
|
69
|
+
const pct = goalTotal > 0 ? Math.round((actual / goalTotal) * 10000) / 100 : null;
|
|
70
|
+
return { start, end, days, dailyGoal: daily, goalTotal, actual, pct, gap: Math.round((actual - goalTotal) * 100) / 100, achieved: actual >= goalTotal };
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=planPlate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planPlate.js","sourceRoot":"","sources":["../../src/render/planPlate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** #41 · 档案读链 render 数据(profile/档案视图,旧 profile 查档案)。
|
|
2
|
+
*
|
|
3
|
+
* 数据源:fetch/profile.getProfile(单例 id=1,无行即 missing)+
|
|
4
|
+
* fetch/nutritionGoal.getNutritionGoal(可选)+ weight_log 最新一条(可选)。
|
|
5
|
+
* 写链(profile.set/activity/update)已由 #40 承接,本票只补看链。
|
|
6
|
+
*/
|
|
7
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
8
|
+
import type { ProfileRow } from '../fetch/profile.js';
|
|
9
|
+
import type { NutritionGoalRow } from '../fetch/nutritionGoal.js';
|
|
10
|
+
export interface ProfileView {
|
|
11
|
+
profile: ProfileRow;
|
|
12
|
+
nutrition: NutritionGoalRow | null;
|
|
13
|
+
latestWeightKg: number | null;
|
|
14
|
+
hasGoal: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare function buildProfileView(db: DatabaseSync): ProfileView;
|
|
17
|
+
//# sourceMappingURL=profilePlate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profilePlate.d.ts","sourceRoot":"","sources":["../../src/render/profilePlate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAGlE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,UAAU,CAAC;IACpB,SAAS,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACnC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,YAAY,GAAG,WAAW,CAa9D"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { getProfile } from '../fetch/profile.js';
|
|
2
|
+
import { getNutritionGoal } from '../fetch/nutritionGoal.js';
|
|
3
|
+
import { CalorieRenderError } from './errors.js';
|
|
4
|
+
export function buildProfileView(db) {
|
|
5
|
+
const profile = getProfile(db);
|
|
6
|
+
if (!profile)
|
|
7
|
+
throw new CalorieRenderError('missing-data', '未设档案(user_profile#1 缺失,先设置档案)');
|
|
8
|
+
const nutrition = getNutritionGoal(db);
|
|
9
|
+
let latest;
|
|
10
|
+
try {
|
|
11
|
+
latest = db.prepare('SELECT weight_kg FROM weight_log ORDER BY date DESC, id DESC LIMIT 1').get();
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
latest = undefined;
|
|
15
|
+
}
|
|
16
|
+
return { profile, nutrition, latestWeightKg: latest?.weight_kg ?? null, hasGoal: nutrition !== null };
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=profilePlate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profilePlate.js","sourceRoot":"","sources":["../../src/render/profilePlate.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AASjD,MAAM,UAAU,gBAAgB,CAAC,EAAgB;IAC/C,MAAM,OAAO,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;IAC/B,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,kBAAkB,CAAC,cAAc,EAAE,+BAA+B,CAAC,CAAC;IAC5F,MAAM,SAAS,GAAG,gBAAgB,CAAC,EAAE,CAAC,CAAC;IACvC,IAAI,MAAyC,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC,sEAAsE,CAAC,CAAC,GAAG,EAElF,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,GAAG,SAAS,CAAC;IACrB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,IAAI,IAAI,EAAE,OAAO,EAAE,SAAS,KAAK,IAAI,EAAE,CAAC;AACxG,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** T9 #28 · 排行盘数据(food_ranking 对应:5 榜 + 全榜)。
|
|
2
|
+
*
|
|
3
|
+
* 数据源 T5 dietFoodRanking(low_calorie/frequent 榜已排除 water/💧水 B-205,老家原样);
|
|
4
|
+
* 本层只做薄校验与 rejection→missing-data 转译,不自排序(排序口径归 T5)。
|
|
5
|
+
* topN 范围 1..50(触发词默认 10,本票上限 50 防大页)。
|
|
6
|
+
*/
|
|
7
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
8
|
+
import type { FoodRanking } from '../analysis/diet.js';
|
|
9
|
+
export declare const RANK_CATEGORIES: readonly ["high_calorie", "low_calorie", "frequent", "high_carb", "high_protein"];
|
|
10
|
+
export type RankCategory = (typeof RANK_CATEGORIES)[number];
|
|
11
|
+
/** 单榜(food_ranking 某 category):rejection/空窗即 missing-data。 */
|
|
12
|
+
export declare function buildFoodRankingPlate(db: DatabaseSync, start: string, end: string, category?: string, topN?: number): FoodRanking;
|
|
13
|
+
export interface AllRankings {
|
|
14
|
+
start: string;
|
|
15
|
+
end: string;
|
|
16
|
+
topN: number;
|
|
17
|
+
boards: Record<RankCategory, FoodRanking | null>;
|
|
18
|
+
okCount: number;
|
|
19
|
+
}
|
|
20
|
+
/** 全榜(ranking_all):5 榜各取,单榜 rejection 记 null;5 榜全空即 missing-data。 */
|
|
21
|
+
export declare function buildAllRankings(db: DatabaseSync, start: string, end: string, topN?: number): AllRankings;
|
|
22
|
+
//# sourceMappingURL=ranking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ranking.d.ts","sourceRoot":"","sources":["../../src/render/ranking.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,eAAO,MAAM,eAAe,mFAAoF,CAAC;AACjH,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAiB5D,8DAA8D;AAC9D,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,YAAY,EAChB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,MAAuB,EACjC,IAAI,SAAI,GACP,WAAW,CAcb;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC,CAAC;IACjD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,SAAI,GAAG,WAAW,CAmBpG"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { dietFoodRanking } from '../analysis/diet.js';
|
|
2
|
+
import { FetchError } from '../fetch/errors.js';
|
|
3
|
+
import { CalorieRenderError } from './errors.js';
|
|
4
|
+
export const RANK_CATEGORIES = ['high_calorie', 'low_calorie', 'frequent', 'high_carb', 'high_protein'];
|
|
5
|
+
function assertDate(s) {
|
|
6
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(s) || Number.isNaN(Date.parse(s + 'T12:00:00Z'))) {
|
|
7
|
+
throw new CalorieRenderError('bad-input', '日期非法: ' + String(s));
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function assertArgs(start, end, topN) {
|
|
11
|
+
assertDate(start);
|
|
12
|
+
assertDate(end);
|
|
13
|
+
if (start > end)
|
|
14
|
+
throw new CalorieRenderError('bad-input', 'start 不得晚于 end');
|
|
15
|
+
if (!Number.isInteger(topN) || topN < 1 || topN > 50) {
|
|
16
|
+
throw new CalorieRenderError('bad-input', 'topN 须为 1..50 整数');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/** 单榜(food_ranking 某 category):rejection/空窗即 missing-data。 */
|
|
20
|
+
export function buildFoodRankingPlate(db, start, end, category = 'high_calorie', topN = 5) {
|
|
21
|
+
assertArgs(start, end, topN);
|
|
22
|
+
if (!RANK_CATEGORIES.includes(category)) {
|
|
23
|
+
throw new CalorieRenderError('bad-input', 'category 非法: ' + String(category));
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const r = dietFoodRanking(db, start, end, category, topN);
|
|
27
|
+
if (r.status !== 'ok' || !r.data)
|
|
28
|
+
throw new CalorieRenderError('missing-data', r.message);
|
|
29
|
+
return r.data;
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
if (e instanceof CalorieRenderError)
|
|
33
|
+
throw e;
|
|
34
|
+
if (e instanceof FetchError)
|
|
35
|
+
throw new CalorieRenderError('missing-data', e.message);
|
|
36
|
+
throw e;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** 全榜(ranking_all):5 榜各取,单榜 rejection 记 null;5 榜全空即 missing-data。 */
|
|
40
|
+
export function buildAllRankings(db, start, end, topN = 5) {
|
|
41
|
+
assertArgs(start, end, topN);
|
|
42
|
+
const boards = {};
|
|
43
|
+
let okCount = 0;
|
|
44
|
+
for (const c of RANK_CATEGORIES) {
|
|
45
|
+
try {
|
|
46
|
+
const r = dietFoodRanking(db, start, end, c, topN);
|
|
47
|
+
if (r.status === 'ok' && r.data) {
|
|
48
|
+
boards[c] = r.data;
|
|
49
|
+
okCount += 1;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
boards[c] = null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
boards[c] = null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (okCount === 0)
|
|
60
|
+
throw new CalorieRenderError('missing-data', '无排行数据(' + start + ' ~ ' + end + ')');
|
|
61
|
+
return { start, end, topN, boards, okCount };
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=ranking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ranking.js","sourceRoot":"","sources":["../../src/render/ranking.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export interface TagDiff {
|
|
2
|
+
before: string[];
|
|
3
|
+
after: string[];
|
|
4
|
+
}
|
|
5
|
+
export interface PhotoDistance {
|
|
6
|
+
tag: string;
|
|
7
|
+
days: number;
|
|
8
|
+
}
|
|
9
|
+
export interface ReceiptItem {
|
|
10
|
+
id?: number;
|
|
11
|
+
date?: string;
|
|
12
|
+
file?: string;
|
|
13
|
+
photoPath?: string;
|
|
14
|
+
tagList?: string[];
|
|
15
|
+
status: string;
|
|
16
|
+
reason: string;
|
|
17
|
+
detail?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ReceiptMeta {
|
|
20
|
+
actionAt: string;
|
|
21
|
+
entityType: string;
|
|
22
|
+
wakeWord: string;
|
|
23
|
+
source: string;
|
|
24
|
+
}
|
|
25
|
+
export interface CrudReceipt {
|
|
26
|
+
scene: string;
|
|
27
|
+
action: string;
|
|
28
|
+
op: 'create' | 'update' | 'delete';
|
|
29
|
+
recordId: number | null;
|
|
30
|
+
summary: string;
|
|
31
|
+
items: ReceiptItem[];
|
|
32
|
+
tagDiff: TagDiff | null;
|
|
33
|
+
distance: PhotoDistance | null;
|
|
34
|
+
noChange: boolean;
|
|
35
|
+
meta: ReceiptMeta;
|
|
36
|
+
}
|
|
37
|
+
export interface ErrorReceipt {
|
|
38
|
+
sceneName: string;
|
|
39
|
+
op: string;
|
|
40
|
+
sub: string;
|
|
41
|
+
reason: string;
|
|
42
|
+
dataText: string;
|
|
43
|
+
suggestions: string[];
|
|
44
|
+
fixPrompt: string;
|
|
45
|
+
meta: ReceiptMeta;
|
|
46
|
+
}
|
|
47
|
+
export declare function buildReceiptMeta(entityType: string, wakeWord: string, source: string): ReceiptMeta;
|
|
48
|
+
export declare function buildCrudReceipt(input: {
|
|
49
|
+
scene: string;
|
|
50
|
+
action: string;
|
|
51
|
+
op: CrudReceipt['op'];
|
|
52
|
+
recordId?: number | null;
|
|
53
|
+
summary: string;
|
|
54
|
+
items?: ReceiptItem[];
|
|
55
|
+
tagDiff?: TagDiff | null;
|
|
56
|
+
distance?: PhotoDistance | null;
|
|
57
|
+
noChange?: boolean;
|
|
58
|
+
wakeWord: string;
|
|
59
|
+
source: string;
|
|
60
|
+
}): CrudReceipt;
|
|
61
|
+
export declare function buildErrorReceipt(input: {
|
|
62
|
+
sceneName?: string;
|
|
63
|
+
wakeWord?: string;
|
|
64
|
+
op?: string;
|
|
65
|
+
sub?: string;
|
|
66
|
+
reason?: string;
|
|
67
|
+
data?: unknown;
|
|
68
|
+
suggestions?: string[];
|
|
69
|
+
fixPrompt?: string;
|
|
70
|
+
}): ErrorReceipt;
|
|
71
|
+
//# sourceMappingURL=receipt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receipt.d.ts","sourceRoot":"","sources":["../../src/render/receipt.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACnC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/B,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,WAAW,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,WAAW,CAAC;CACnB;AAQD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAIlG;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,WAAW,CAkBd;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,YAAY,CAsBf"}
|