update:bug修复

This commit is contained in:
ltx 2026-09-22 09:04:56 +08:00
parent a419e3da30
commit cb9b8d7791
6 changed files with 81 additions and 17 deletions

View File

@ -113,6 +113,7 @@ class ApiClient {
Future<JudgeScorePreview> saveJudgeScoreDraft({
required String sessionEntryId,
required List<JudgeScoreItemInput> items,
double? deductionCoefficient,
}) async {
final data = await _requestMap(
'POST',
@ -120,6 +121,8 @@ class ApiClient {
data: {
'sessionEntryId': sessionEntryId,
'items': items.map((item) => item.toJson()).toList(),
if (deductionCoefficient != null)
'deductionCoefficient': deductionCoefficient,
},
);
return JudgeScorePreview.fromJson(data);
@ -130,6 +133,7 @@ class ApiClient {
required List<JudgeScoreItemInput> items,
required String idempotencyKey,
String? disqualifyRemark,
double? deductionCoefficient,
}) async {
final data = await _requestMap(
'POST',
@ -138,6 +142,8 @@ class ApiClient {
'sessionEntryId': sessionEntryId,
'items': items.map((item) => item.toJson()).toList(),
'idempotencyKey': idempotencyKey,
if (deductionCoefficient != null)
'deductionCoefficient': deductionCoefficient,
if (disqualifyRemark?.trim().isNotEmpty == true)
'disqualifyRemark': disqualifyRemark!.trim(),
},

View File

@ -70,19 +70,25 @@ class JudgeApiRepository {
Future<JudgeScorePreview> saveDraft({
required String sessionEntryId,
required List<JudgeScoreItemInput> items,
}) =>
_client.saveJudgeScoreDraft(sessionEntryId: sessionEntryId, items: items);
double? deductionCoefficient,
}) => _client.saveJudgeScoreDraft(
sessionEntryId: sessionEntryId,
items: items,
deductionCoefficient: deductionCoefficient,
);
Future<SubmitJudgeScoreOutput> submitScore({
required String sessionEntryId,
required List<JudgeScoreItemInput> items,
required String idempotencyKey,
String? disqualifyRemark,
double? deductionCoefficient,
}) => _client.submitJudgeScore(
sessionEntryId: sessionEntryId,
items: items,
idempotencyKey: idempotencyKey,
disqualifyRemark: disqualifyRemark,
deductionCoefficient: deductionCoefficient,
);
Future<ApiLoad<List<JudgeEntryResult>>> loadResults(String sessionId) async {

View File

@ -43,6 +43,7 @@ class QueuedScoreRequest {
required this.items,
this.idempotencyKey,
this.disqualifyRemark,
this.deductionCoefficient,
});
final String sessionEntryId;
@ -50,26 +51,36 @@ class QueuedScoreRequest {
final String? idempotencyKey;
final String? disqualifyRemark;
/// 主裁花样赛各扣分项合计后的扣分系数,例如 0.125。
///
/// 页面展示的是得分系数 M = 1 - deductionCoefficient;服务端仍会
/// 根据各项明细重算并校验该值,客户端不上传最终成绩。
final double? deductionCoefficient;
Map<String, dynamic> toJson() => {
'sessionEntryId': sessionEntryId,
'items': items.map((item) => item.toJson()).toList(),
'idempotencyKey': idempotencyKey,
'disqualifyRemark': disqualifyRemark,
if (deductionCoefficient != null)
'deductionCoefficient': deductionCoefficient,
};
factory QueuedScoreRequest.fromJson(Map<String, dynamic> json) =>
QueuedScoreRequest(
sessionEntryId: '${json['sessionEntryId'] ?? ''}',
items: (json['items'] as List<dynamic>? ?? const [])
.map(
(item) => JudgeScoreItemInput.fromJson(
(item as Map).cast<String, dynamic>(),
),
)
.toList(growable: false),
idempotencyKey: json['idempotencyKey']?.toString(),
disqualifyRemark: json['disqualifyRemark']?.toString(),
);
factory QueuedScoreRequest.fromJson(
Map<String, dynamic> json,
) => QueuedScoreRequest(
sessionEntryId: '${json['sessionEntryId'] ?? ''}',
items: (json['items'] as List<dynamic>? ?? const [])
.map(
(item) => JudgeScoreItemInput.fromJson(
(item as Map).cast<String, dynamic>(),
),
)
.toList(growable: false),
idempotencyKey: json['idempotencyKey']?.toString(),
disqualifyRemark: json['disqualifyRemark']?.toString(),
deductionCoefficient: (json['deductionCoefficient'] as num?)?.toDouble(),
);
String encode() => jsonEncode(toJson());

View File

@ -1166,6 +1166,7 @@ class ScoringController extends GetxController {
final preview = await _judgeApi.saveDraft(
sessionEntryId: request.sessionEntryId,
items: request.items,
deductionCoefficient: request.deductionCoefficient,
);
serverPreview.value = preview;
await _cacheDraftSnapshot(request, preview);
@ -1317,6 +1318,7 @@ class ScoringController extends GetxController {
items: request.items,
idempotencyKey: idempotencyKey,
disqualifyRemark: request.disqualifyRemark,
deductionCoefficient: request.deductionCoefficient,
);
await _completeRemoteSubmission(operation, output);
return true;
@ -1489,9 +1491,45 @@ class ScoringController extends GetxController {
items: items,
idempotencyKey: sheet.idempotencyKey,
disqualifyRemark: disqualifyRemark,
deductionCoefficient:
profile.role == ScoreRole.technical &&
profile.competition != CompetitionKind.prescribed
? _remoteDeductionCoefficient(items)
: null,
);
}
/// 使用评分表下发的单位值和递进扣分序列计算上传系数,避免本地规则目录
/// 与服务端规则版本不一致。服务端收到后会根据同一批明细再次计算并校验。
double _remoteDeductionCoefficient(List<JudgeScoreItemInput> inputs) {
final sheet = apiScoreSheet;
if (sheet == null) return _deductionValue();
final values = {for (final input in inputs) input.itemCode: input};
var coefficient = 0.0;
for (final item in sheet.items.where(
(item) =>
!item.isAutoGenerated &&
!item.isDisqualifyReason &&
(item.itemType == 4 || item.scoreDimension == 4),
)) {
final input = values[item.code];
final count = (input?.countValue ?? 0).round();
if (item.stepDeductions.isNotEmpty) {
for (var index = 0; index < count; index++) {
final stepIndex = index < item.stepDeductions.length
? index
: item.stepDeductions.length - 1;
coefficient += item.stepDeductions[stepIndex];
}
} else if (item.inputMode == 'count') {
coefficient += count * item.unitValue;
} else {
coefficient += input?.inputValue ?? 0;
}
}
return coefficient.clamp(0, 1).toDouble();
}
num _remoteValueFor(JudgeScoreItem item) {
if (item.isDisqualifyReason) {
return disqualified.value && selectedDisqualifyReasonCode == item.code

View File

@ -1585,7 +1585,7 @@ class _ChiefRequiredDeductionPanel extends StatelessWidget {
children: [
_ChiefDeductionSummary(
value: factor.toStringAsFixed(3),
detail: '当前扣分系数',
detail: '当前得分系数',
compact: true,
),
Positioned(
@ -1663,7 +1663,7 @@ class _ChiefDeductionPanel extends StatelessWidget {
children: [
_ChiefDeductionSummary(
value: summaryValue,
detail: prescribed ? '当前累计扣分(分)' : '当前扣分系数',
detail: prescribed ? '当前累计扣分(分)' : '当前得分系数',
),
Positioned(
right: 26,

View File

@ -8,6 +8,7 @@ void main() {
sessionEntryId: '201',
idempotencyKey: 'judge-201-v1',
disqualifyRemark: '现场记录',
deductionCoefficient: .125,
items: [
JudgeScoreItemInput(itemCode: 'MUSIC_PLUS', countValue: 2),
JudgeScoreItemInput(itemCode: 'MUSIC_MINUS', countValue: 1),
@ -20,6 +21,8 @@ void main() {
expect(restored.sessionEntryId, original.sessionEntryId);
expect(restored.idempotencyKey, original.idempotencyKey);
expect(restored.disqualifyRemark, original.disqualifyRemark);
expect(restored.deductionCoefficient, .125);
expect(restored.toJson()['deductionCoefficient'], .125);
expect(restored.items.map((item) => item.toJson()), [
{'itemCode': 'MUSIC_PLUS', 'countValue': 2.0},
{'itemCode': 'MUSIC_MINUS', 'countValue': 1.0},