综合训练(多物种合并模型)全链路:合并打包/独立版本序列/App 覆盖互斥 + 管理端发布入口
- 后端:/admin/trainings/combined 发起(≥2 数据集、类别重映射、防重名、负样本单份); model_training/model_version 加 kind+dataset_ids(迁移 v14),综合任务 dataset_id=0、 文件基名 combined(_n)、版本序列独立;训练列表补 published 标记 - 管理端:数据训练页工具栏发起综合训练;横幅常驻进行中任务 + 每档最近一条已结束任务, 成功未发布给「发布模型」入口(可关闭收起) - App:目录解析 kind/datasetIds、激活覆盖互斥、自动更新退场改目标档待办横幅手动一键下载
This commit is contained in:
@@ -18,8 +18,9 @@ String _variantLabel(String v) => v == kVariantN ? '高性能' : '高精度';
|
||||
/// - 任一档失败 → 错误提示 + 重试(只补下未成功的档);
|
||||
/// - 目标档已激活 →「使用中」点击取消使用;
|
||||
/// - 目标档已下载未激活 →「使用」直接启用(另一档在运行会被自动停用);
|
||||
/// - 目标档未下载 →「下载」取回缺失档(目标档落地自动启用、伴档备好;
|
||||
/// 另一档在使用时补下目标档后自动切换过去)。
|
||||
/// - 目标档未下载 →「下载」只取回目标档(2026-09-09 双档分别下载,伴档不随下);
|
||||
/// 另一档在使用时补下目标档后自动切换过去。切档/刷新检测目标档「未下载/
|
||||
/// 待更新」出横幅,用户手动一键下载/更新(自动更新已退场)。
|
||||
class ModelCatalogSection extends StatelessWidget {
|
||||
final ModelManager manager;
|
||||
|
||||
@@ -61,6 +62,50 @@ class ModelCatalogSection extends StatelessWidget {
|
||||
'卡片操作面向所选档位;同一动物一次只运行一档,切换会自动停用另一档',
|
||||
style: TextStyle(color: Colors.white38, fontSize: 11),
|
||||
),
|
||||
// 目标档待办横幅(切档检测):未下载/版本落后的模型,用户手动一键触发
|
||||
if (manager.modePending.isNotEmpty) ...[
|
||||
const SizedBox(height: 8),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10, vertical: 6),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.orange.withValues(alpha: 0.15),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.system_update_alt,
|
||||
color: Colors.orangeAccent, size: 15),
|
||||
const SizedBox(width: 6),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'${_variantLabel(manager.mode)}模式:'
|
||||
'${manager.modePending.length} 个模型待下载/更新',
|
||||
style: const TextStyle(
|
||||
color: Colors.orangeAccent, fontSize: 11.5),
|
||||
),
|
||||
),
|
||||
TextButton.icon(
|
||||
onPressed: () {
|
||||
for (final i in manager.modePending.toList()) {
|
||||
manager.downloadModel(i);
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.download, size: 14),
|
||||
label: const Text('一键下载',
|
||||
style: TextStyle(fontSize: 11.5)),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: Colors.orangeAccent,
|
||||
visualDensity: VisualDensity.compact,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6),
|
||||
minimumSize: const Size(0, 26),
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
children: [
|
||||
@@ -414,24 +459,21 @@ class _SpeciesCard extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// 目标档未下载:下载全部缺失档(目标档落地自动启用、伴档备好待切);
|
||||
// 另一档在使用时按钮同样为「下载」:补下目标档后自动切换(停用另一档)
|
||||
// 目标档未下载:只下载目标档(2026-09-09 双档分别下载——伴档不随下,
|
||||
// 缺失/待更新由切档横幅提示手动补);另一档在使用时补下目标档后自动切换
|
||||
final use = activeOther.isNotEmpty;
|
||||
mainBtn = SizedBox(
|
||||
height: 30,
|
||||
child: FilledButton(
|
||||
onPressed: () async {
|
||||
if (!use) {
|
||||
for (final i in items) {
|
||||
if (!manager.isDownloaded(i.datasetId, i.variant)) {
|
||||
manager.downloadModel(i);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!manager.isDownloaded(target.datasetId, target.variant)) {
|
||||
final ok = await manager.downloadModel(target);
|
||||
if (!ok) return; // 下载失败/取消:错误分支展示,保持现状
|
||||
if (use) {
|
||||
final ok = await manager.downloadModel(target);
|
||||
if (!ok) return; // 下载失败/取消:错误分支展示,保持现状
|
||||
} else {
|
||||
manager.downloadModel(target);
|
||||
return;
|
||||
}
|
||||
}
|
||||
await manager.setActive(target.datasetId, target.variant, true);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user