eli-video-interview 1.7.0 → 1.9.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 (93) hide show
  1. package/esm/components/Charts/ReportPie.js +27 -10
  2. package/esm/components/react-photo-view/hooks/useAnimationPosition.d.ts +1 -1
  3. package/esm/modules/ai-question/Root.js +11 -5
  4. package/esm/modules/ai-question/components/GlobalDimensions/Dialog.d.ts +9 -0
  5. package/esm/modules/ai-question/components/GlobalDimensions/Dialog.js +154 -0
  6. package/esm/modules/ai-question/components/GlobalDimensions/index.d.ts +3 -0
  7. package/esm/modules/ai-question/components/GlobalDimensions/index.js +57 -0
  8. package/esm/modules/ai-question/components/QuestionModel/index.js +2 -1
  9. package/esm/modules/ai-question/components/QuestionModel/interface.d.ts +12 -0
  10. package/esm/modules/ai-question/components/QuestionPreview/styled.d.ts +2 -2
  11. package/esm/modules/ai-question/utils/weight.d.ts +17 -0
  12. package/esm/modules/ai-question/utils/weight.js +38 -0
  13. package/esm/modules/ai-report/components/ScoreReport/styled.d.ts +3 -3
  14. package/esm/modules/ai-report/components/VideoQuestion/styled.d.ts +2 -2
  15. package/esm/modules/ai-report/components/WorkPlaces/styled.d.ts +2 -2
  16. package/esm/modules/ai-report/interface.d.ts +16 -0
  17. package/esm/modules/ai-report-v2/Root.js +2 -1
  18. package/esm/modules/ai-report-v2/components/AIEvaluate/Graph.d.ts +2 -0
  19. package/esm/modules/ai-report-v2/components/AIEvaluate/Graph.js +57 -6
  20. package/esm/modules/ai-report-v2/components/AIEvaluate/index.js +1 -0
  21. package/esm/modules/ai-report-v2/components/GlobalDimensions/index.d.ts +3 -0
  22. package/esm/modules/ai-report-v2/components/GlobalDimensions/index.js +84 -0
  23. package/esm/modules/ai-report-v2/components/ReportHeader/ReportHeader.js +3 -2
  24. package/esm/modules/ai-report-v2/components/ScoreReport/styled.d.ts +3 -3
  25. package/esm/modules/ai-report-v2/components/VideoQuestion/styled.d.ts +2 -2
  26. package/esm/modules/ai-report-v2/components/WorkPlaces/styled.d.ts +2 -2
  27. package/esm/modules/ai-report-v2/components/styled.d.ts +3 -0
  28. package/esm/modules/ai-report-v2/components/styled.js +10 -0
  29. package/esm/modules/ai-report-v2/interface.d.ts +16 -0
  30. package/esm/modules/ai-report-v3/Root.js +2 -1
  31. package/esm/modules/ai-report-v3/components/AIEvaluate/Graph.d.ts +2 -0
  32. package/esm/modules/ai-report-v3/components/AIEvaluate/Graph.js +75 -48
  33. package/esm/modules/ai-report-v3/components/AIEvaluate/index.js +1 -0
  34. package/esm/modules/ai-report-v3/components/CheatRisk/CheatRisk.js +9 -4
  35. package/esm/modules/ai-report-v3/components/GlobalDimensions/index.d.ts +3 -0
  36. package/esm/modules/ai-report-v3/components/GlobalDimensions/index.js +82 -0
  37. package/esm/modules/ai-report-v3/components/ModuleTitle.d.ts +1 -1
  38. package/esm/modules/ai-report-v3/components/ModuleTitle.js +3 -1
  39. package/esm/modules/ai-report-v3/components/ScoreReport/styled.d.ts +3 -3
  40. package/esm/modules/ai-report-v3/components/VideoQuestion/styled.d.ts +2 -2
  41. package/esm/modules/ai-report-v3/components/WorkPlaces/styled.d.ts +2 -2
  42. package/esm/modules/ai-report-v3/interface.d.ts +16 -0
  43. package/esm/modules/ai-template/components/TemplateList/styled.d.ts +3 -3
  44. package/esm/modules/ai-template/components/TemplateMenu/styled.d.ts +1 -1
  45. package/esm/store/ai-question/question-model-store.d.ts +4 -1
  46. package/esm/store/ai-question/question-model-store.js +41 -5
  47. package/lib/components/Charts/ReportPie.js +27 -10
  48. package/lib/components/react-photo-view/hooks/useAnimationPosition.d.ts +1 -1
  49. package/lib/modules/ai-question/Root.js +11 -5
  50. package/lib/modules/ai-question/components/GlobalDimensions/Dialog.d.ts +9 -0
  51. package/lib/modules/ai-question/components/GlobalDimensions/Dialog.js +156 -0
  52. package/lib/modules/ai-question/components/GlobalDimensions/index.d.ts +3 -0
  53. package/lib/modules/ai-question/components/GlobalDimensions/index.js +62 -0
  54. package/lib/modules/ai-question/components/QuestionModel/index.js +2 -1
  55. package/lib/modules/ai-question/components/QuestionModel/interface.d.ts +12 -0
  56. package/lib/modules/ai-question/components/QuestionPreview/styled.d.ts +2 -2
  57. package/lib/modules/ai-question/utils/weight.d.ts +17 -0
  58. package/lib/modules/ai-question/utils/weight.js +43 -0
  59. package/lib/modules/ai-report/components/ScoreReport/styled.d.ts +3 -3
  60. package/lib/modules/ai-report/components/VideoQuestion/styled.d.ts +2 -2
  61. package/lib/modules/ai-report/components/WorkPlaces/styled.d.ts +2 -2
  62. package/lib/modules/ai-report/interface.d.ts +16 -0
  63. package/lib/modules/ai-report-v2/Root.js +2 -1
  64. package/lib/modules/ai-report-v2/components/AIEvaluate/Graph.d.ts +2 -0
  65. package/lib/modules/ai-report-v2/components/AIEvaluate/Graph.js +57 -6
  66. package/lib/modules/ai-report-v2/components/AIEvaluate/index.js +1 -0
  67. package/lib/modules/ai-report-v2/components/GlobalDimensions/index.d.ts +3 -0
  68. package/lib/modules/ai-report-v2/components/GlobalDimensions/index.js +89 -0
  69. package/lib/modules/ai-report-v2/components/ReportHeader/ReportHeader.js +2 -1
  70. package/lib/modules/ai-report-v2/components/ScoreReport/styled.d.ts +3 -3
  71. package/lib/modules/ai-report-v2/components/VideoQuestion/styled.d.ts +2 -2
  72. package/lib/modules/ai-report-v2/components/WorkPlaces/styled.d.ts +2 -2
  73. package/lib/modules/ai-report-v2/components/styled.d.ts +3 -0
  74. package/lib/modules/ai-report-v2/components/styled.js +11 -1
  75. package/lib/modules/ai-report-v2/interface.d.ts +16 -0
  76. package/lib/modules/ai-report-v3/Root.js +2 -1
  77. package/lib/modules/ai-report-v3/components/AIEvaluate/Graph.d.ts +2 -0
  78. package/lib/modules/ai-report-v3/components/AIEvaluate/Graph.js +75 -48
  79. package/lib/modules/ai-report-v3/components/AIEvaluate/index.js +1 -0
  80. package/lib/modules/ai-report-v3/components/CheatRisk/CheatRisk.js +9 -4
  81. package/lib/modules/ai-report-v3/components/GlobalDimensions/index.d.ts +3 -0
  82. package/lib/modules/ai-report-v3/components/GlobalDimensions/index.js +87 -0
  83. package/lib/modules/ai-report-v3/components/ModuleTitle.d.ts +1 -1
  84. package/lib/modules/ai-report-v3/components/ModuleTitle.js +3 -1
  85. package/lib/modules/ai-report-v3/components/ScoreReport/styled.d.ts +3 -3
  86. package/lib/modules/ai-report-v3/components/VideoQuestion/styled.d.ts +2 -2
  87. package/lib/modules/ai-report-v3/components/WorkPlaces/styled.d.ts +2 -2
  88. package/lib/modules/ai-report-v3/interface.d.ts +16 -0
  89. package/lib/modules/ai-template/components/TemplateList/styled.d.ts +3 -3
  90. package/lib/modules/ai-template/components/TemplateMenu/styled.d.ts +1 -1
  91. package/lib/store/ai-question/question-model-store.d.ts +4 -1
  92. package/lib/store/ai-question/question-model-store.js +41 -5
  93. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  /// <reference types="react" />
2
- import { QuestionModelData, QuestionModelStep } from '@/modules/ai-question/components/QuestionModel/interface';
2
+ import { GlobalDimension, QuestionModelData, QuestionModelStep } from '@/modules/ai-question/components/QuestionModel/interface';
3
3
  export declare const useQuestionModelStore: (depsFn?: import("hox/es/types").DepsFn<{
4
4
  isEdit: boolean;
5
5
  questionModelData: QuestionModelData | undefined;
@@ -8,6 +8,7 @@ export declare const useQuestionModelStore: (depsFn?: import("hox/es/types").Dep
8
8
  removeModel: (index: number) => void;
9
9
  updateModel: import("react").Dispatch<import("react").SetStateAction<QuestionModelData | undefined>>;
10
10
  updateModelWeight: (value: string, index: number) => void;
11
+ updateGlobalDimensions: (dimensions: GlobalDimension[]) => void;
11
12
  }> | undefined) => {
12
13
  isEdit: boolean;
13
14
  questionModelData: QuestionModelData | undefined;
@@ -16,6 +17,7 @@ export declare const useQuestionModelStore: (depsFn?: import("hox/es/types").Dep
16
17
  removeModel: (index: number) => void;
17
18
  updateModel: import("react").Dispatch<import("react").SetStateAction<QuestionModelData | undefined>>;
18
19
  updateModelWeight: (value: string, index: number) => void;
20
+ updateGlobalDimensions: (dimensions: GlobalDimension[]) => void;
19
21
  }, getQuestionModelStore: () => {
20
22
  isEdit: boolean;
21
23
  questionModelData: QuestionModelData | undefined;
@@ -24,4 +26,5 @@ export declare const useQuestionModelStore: (depsFn?: import("hox/es/types").Dep
24
26
  removeModel: (index: number) => void;
25
27
  updateModel: import("react").Dispatch<import("react").SetStateAction<QuestionModelData | undefined>>;
26
28
  updateModelWeight: (value: string, index: number) => void;
29
+ updateGlobalDimensions: (dimensions: GlobalDimension[]) => void;
27
30
  } | undefined;
@@ -26,6 +26,7 @@ var __read = (this && this.__read) || function (o, n) {
26
26
  return ar;
27
27
  };
28
28
  var _a;
29
+ import { computeQuestionWeightPool, rebalanceWeights } from "../../modules/ai-question/utils/weight";
29
30
  import { IS_AI_ANALYSIS } from "../../constants/ai-question";
30
31
  import { computeDecimalValue, formatNumberDecimal, uniqueId } from "../../utils/utils";
31
32
  import { createGlobalStore } from 'hox';
@@ -37,9 +38,17 @@ export var useQuestionModelStore = (_a = __read(createGlobalStore(function () {
37
38
  /**
38
39
  * 权重值计算
39
40
  * @param steps 模型数据
41
+ * @param isManualUpdate 是否手动调整(true 时保留已有权重,由最后一道 AI 题吸收差额)
42
+ * @param options.globalDimensions 本次要写入的全局维度(默认取当前试卷已配置的)
43
+ * @param options.questionWeightPool 题目权重池(默认 100 - 全局维度权重合计)
40
44
  */
41
- var computeWeight = useCallback(function (steps, isManualUpdate) {
45
+ var computeWeight = useCallback(function (steps, isManualUpdate, options) {
42
46
  if (isManualUpdate === void 0) { isManualUpdate = false; }
47
+ if (options === void 0) { options = {}; }
48
+ var nextGlobalDimensions = options.globalDimensions !== undefined ? options.globalDimensions : questionModelData === null || questionModelData === void 0 ? void 0 : questionModelData.globalDimensions;
49
+ var questionWeightPool = options.questionWeightPool !== undefined
50
+ ? Math.max(0, Number(options.questionWeightPool) || 0)
51
+ : computeQuestionWeightPool(nextGlobalDimensions);
43
52
  var lastAiTestIndex = 0;
44
53
  // AI评分题
45
54
  var aiTypeList = steps.filter(function (step, index) {
@@ -68,12 +77,12 @@ export var useQuestionModelStore = (_a = __read(createGlobalStore(function () {
68
77
  var getWeight = function (_a, i) {
69
78
  var weight = _a.weight;
70
79
  if (weightsLen <= 1 && !isManualUpdate) {
71
- var averageWeight = Math.floor((100 / aiTypeListLength) * 100) / 100;
72
- var disableWeight = 100 - Math.floor(averageWeight * (aiTypeListLength - 1) * 100) / 100;
80
+ var averageWeight = Math.floor((questionWeightPool / aiTypeListLength) * 100) / 100;
81
+ var disableWeight = questionWeightPool - Math.floor(averageWeight * (aiTypeListLength - 1) * 100) / 100;
73
82
  return i === lastAiTestIndex ? computeDecimalValue(disableWeight.toString()) : computeDecimalValue(averageWeight.toString());
74
83
  }
75
84
  else {
76
- return i !== lastAiTestIndex ? weight : computeDecimalValue((100 - beforeTotalWeight).toString());
85
+ return i !== lastAiTestIndex ? weight : computeDecimalValue((questionWeightPool - beforeTotalWeight).toString());
77
86
  }
78
87
  };
79
88
  var $splice = steps.map(function (step, i) {
@@ -85,8 +94,34 @@ export var useQuestionModelStore = (_a = __read(createGlobalStore(function () {
85
94
  __assign(__assign({}, step), { weight: IS_AI_ANALYSIS(step) ? getWeight(step, i) : 0 }),
86
95
  ];
87
96
  });
88
- updateModel(__assign(__assign({}, questionModelData), { duration: totalDuration, steps: update(steps, { $splice: $splice }) }));
97
+ updateModel(__assign(__assign(__assign({}, questionModelData), (nextGlobalDimensions !== undefined ? { globalDimensions: nextGlobalDimensions } : {})), { duration: totalDuration, steps: update(steps, { $splice: $splice }) }));
89
98
  }, [questionModelData]);
99
+ /**
100
+ * 更新全局维度配置
101
+ * 题目权重池随之变化,按现有题目权重重排(最后一道 AI 题吸收差额),保证题目 + 全局合计 100%
102
+ */
103
+ var updateGlobalDimensions = useCallback(function (dimensions) {
104
+ var questionWeightPool = computeQuestionWeightPool(dimensions);
105
+ var steps = (questionModelData === null || questionModelData === void 0 ? void 0 : questionModelData.steps) || [];
106
+ // 题目权重按比例缩放到新的权重池,保证「题目 + 全局」恒等于 100%,且不会出现负权重
107
+ var aiStepIndexes = steps.reduce(function (indexes, step, index) {
108
+ if (IS_AI_ANALYSIS(step)) {
109
+ indexes.push(index);
110
+ }
111
+ return indexes;
112
+ }, []);
113
+ var rebalancedWeights = rebalanceWeights(aiStepIndexes.map(function (index) { return Number(steps[index].weight) || 0; }), questionWeightPool);
114
+ var nextSteps = aiStepIndexes.length
115
+ ? steps.map(function (step, index) {
116
+ var position = aiStepIndexes.indexOf(index);
117
+ return position < 0 ? step : __assign(__assign({}, step), { weight: rebalancedWeights[position] });
118
+ })
119
+ : steps;
120
+ computeWeight(nextSteps, true, {
121
+ globalDimensions: dimensions,
122
+ questionWeightPool: questionWeightPool,
123
+ });
124
+ }, [computeWeight, questionModelData]);
90
125
  /**
91
126
  * 更新模型数据权重值
92
127
  * @param value 权重值
@@ -150,5 +185,6 @@ export var useQuestionModelStore = (_a = __read(createGlobalStore(function () {
150
185
  removeModel: removeModel,
151
186
  updateModel: updateModel,
152
187
  updateModelWeight: updateModelWeight,
188
+ updateGlobalDimensions: updateGlobalDimensions,
153
189
  };
154
190
  }), 2), _a[0]), getQuestionModelStore = _a[1];
@@ -74,16 +74,18 @@ var ReportPie = function (props) {
74
74
  }).includes(0);
75
75
  var min = Math.min.apply(Math, scores);
76
76
  var max = Math.max.apply(Math, scores);
77
+ // 全局维度(只绑试卷、不绑题目)在圆环里也标出来源:
78
+ // 颜色沿用「按分数档位上色」,来源靠标签里的小号「全局」标记 + tooltip 说明,重名/导出 PDF 时也能分辨
77
79
  var data = source.map(function (_a) {
78
- var name = _a.name, score = _a.score, params = __rest(_a, ["name", "score"]);
79
- return (__assign({ name: formateTitle(name), originalName: name, value: score }, params));
80
+ var name = _a.name, score = _a.score, dimensionSource = _a.source, params = __rest(_a, ["name", "score", "source"]);
81
+ return (__assign({ name: formateTitle(name), originalName: name, value: score, isGlobal: dimensionSource === 2 }, params));
80
82
  });
81
83
  var options = {
82
84
  tooltip: {
83
85
  trigger: 'item',
84
86
  formatter: function (_a) {
85
- var value = _a.value, _b = _a.data, rank = _b.rank, total = _b.total, originalName = _b.originalName;
86
- return "".concat(originalName, "<br />\u5F97\u5206\uFF1A").concat(value, "\u5206").concat(total > 0 ? "<br />\u6392\u540D\uFF1A".concat(rank, "/").concat(total) : '');
87
+ var value = _a.value, _b = _a.data, rank = _b.rank, total = _b.total, originalName = _b.originalName, isGlobal = _b.isGlobal;
88
+ return "".concat(originalName).concat(isGlobal ? '(全局维度·不关联题目)' : '', "<br />\u5F97\u5206\uFF1A").concat(value, "\u5206").concat(total > 0 ? "<br />\u6392\u540D\uFF1A".concat(rank, "/").concat(total) : '');
87
89
  },
88
90
  backgroundColor: 'rgba(0, 0, 0, 0.86)',
89
91
  textStyle: {
@@ -98,15 +100,30 @@ var ReportPie = function (props) {
98
100
  data: data,
99
101
  roseType: 'radius',
100
102
  label: {
101
- color: 'rgba(0, 0, 0, 0.86)',
102
- fontWeight: 500,
103
+ // 维度名正常字号;全局维度在下一行补一个小号浅绿「全局」标记(比同字号后缀清爽)
103
104
  formatter: function (_a) {
104
- var name = _a.name;
105
- return "".concat(name);
105
+ var name = _a.name, item = _a.data;
106
+ return ((item === null || item === void 0 ? void 0 : item.isGlobal) ? "{name|".concat(name, "}\n{tag|\u5168\u5C40}") : "{name|".concat(name, "}"));
107
+ },
108
+ rich: {
109
+ name: {
110
+ color: 'rgba(0, 0, 0, 0.86)',
111
+ fontSize: 12,
112
+ lineHeight: 16,
113
+ fontWeight: 500,
114
+ },
115
+ tag: {
116
+ color: '#33A853',
117
+ fontSize: 10,
118
+ lineHeight: 15,
119
+ padding: [1, 5],
120
+ borderRadius: 8,
121
+ backgroundColor: 'rgba(78, 201, 83, 0.14)',
122
+ align: 'center',
123
+ },
106
124
  },
107
- rich: __assign({}, const_1.levelMapping),
108
125
  overflow: 'break',
109
- width: 70,
126
+ width: 76,
110
127
  lineHeight: 18,
111
128
  },
112
129
  labelLine: {
@@ -1,2 +1,2 @@
1
1
  import type { MutableRefObject } from 'react';
2
- export default function useAnimationPosition(visible: boolean | undefined, originRef: MutableRefObject<HTMLElement | null> | undefined, loaded: boolean, x: number, y: number, width: number, height: number, scale: number, speed: number, updateEasing: (pause: boolean) => void): readonly [number, number, number, number, number, 0 | 1, import("../types").EasingMode, "contain" | "fill" | "cover" | undefined];
2
+ export default function useAnimationPosition(visible: boolean | undefined, originRef: MutableRefObject<HTMLElement | null> | undefined, loaded: boolean, x: number, y: number, width: number, height: number, scale: number, speed: number, updateEasing: (pause: boolean) => void): readonly [number, number, number, number, number, 0 | 1, import("../types").EasingMode, "fill" | "contain" | "cover" | undefined];
@@ -73,7 +73,7 @@ var AiQuestionRoot = (0, react_1.forwardRef)(function (props, ref) {
73
73
  var selctedAbilitys = (0, question_ability_store_1.useAiAbilityListStore)().selctedAbilitys;
74
74
  var isOem = props.isOem;
75
75
  var handleValues = function () { return __awaiter(void 0, void 0, void 0, function () {
76
- var questionModelData, _a, pcUrl, pcThumbUrl, mediaUrl, thumbUrl, appliedAllPosition, steps;
76
+ var questionModelData, _a, pcUrl, pcThumbUrl, mediaUrl, thumbUrl, appliedAllPosition, steps, globalDimensions;
77
77
  return __generator(this, function (_b) {
78
78
  questionModelData = ((0, question_model_store_1.getQuestionModelStore)() || {}).questionModelData;
79
79
  _a = (0, boot_video_store_1.getBootVideoStore)() || {}, pcUrl = _a.pcUrl, pcThumbUrl = _a.pcThumbUrl, mediaUrl = _a.mediaUrl, thumbUrl = _a.thumbUrl, appliedAllPosition = _a.appliedAllPosition;
@@ -85,8 +85,9 @@ var AiQuestionRoot = (0, react_1.forwardRef)(function (props, ref) {
85
85
  });
86
86
  return item;
87
87
  });
88
+ globalDimensions = ((questionModelData === null || questionModelData === void 0 ? void 0 : questionModelData.globalDimensions) || []).map(function (item) { return (__assign(__assign({}, item), { weight: Number(item.weight) })); });
88
89
  return [2 /*return*/, Promise.resolve({
89
- data: __assign(__assign({}, questionModelData), { steps: steps }),
90
+ data: __assign(__assign({}, questionModelData), { steps: steps, globalDimensions: globalDimensions }),
90
91
  media: {
91
92
  pcUrl: pcUrl,
92
93
  pcThumbUrl: pcThumbUrl,
@@ -101,20 +102,25 @@ var AiQuestionRoot = (0, react_1.forwardRef)(function (props, ref) {
101
102
  handleValues: handleValues,
102
103
  handleTemplate: function (steps) { return addModel(steps); },
103
104
  handleSubmit: function () { return __awaiter(void 0, void 0, void 0, function () {
104
- var _a, _b, name, token, questions, aiModel, _c, pcUrl, pcThumbUrl, mediaUrl, thumbUrl, appliedAllPosition, data, error_1;
105
+ var _a, _b, name, token, questions, aiModel, globalDimensions, _c, pcUrl, pcThumbUrl, mediaUrl, thumbUrl, appliedAllPosition, globalWeightSum, data, error_1;
105
106
  return __generator(this, function (_d) {
106
107
  switch (_d.label) {
107
108
  case 0: return [4 /*yield*/, handleValues()];
108
109
  case 1:
109
- _a = _d.sent(), _b = _a.data, name = _b.name, token = _b.token, questions = _b.steps, aiModel = _b.aiModel, _c = _a.media, pcUrl = _c.pcUrl, pcThumbUrl = _c.pcThumbUrl, mediaUrl = _c.mediaUrl, thumbUrl = _c.thumbUrl, appliedAllPosition = _c.appliedAllPosition;
110
+ _a = _d.sent(), _b = _a.data, name = _b.name, token = _b.token, questions = _b.steps, aiModel = _b.aiModel, globalDimensions = _b.globalDimensions, _c = _a.media, pcUrl = _c.pcUrl, pcThumbUrl = _c.pcThumbUrl, mediaUrl = _c.mediaUrl, thumbUrl = _c.thumbUrl, appliedAllPosition = _c.appliedAllPosition;
110
111
  if (!(questions === null || questions === void 0 ? void 0 : questions.length)) {
111
112
  fbm_ui_1.Message.error('还未添加题目,请添加题目');
112
113
  return [2 /*return*/, Promise.reject()];
113
114
  }
115
+ globalWeightSum = globalDimensions.reduce(function (total, item) { return total + (Number(item.weight) || 0); }, 0);
116
+ if (globalWeightSum > 100.005) {
117
+ fbm_ui_1.Message.error("\u5168\u5C40\u7EF4\u5EA6\u6743\u91CD\u5408\u8BA1 ".concat(globalWeightSum, "%\uFF0C\u4E0D\u80FD\u8D85\u8FC7 100%"));
118
+ return [2 /*return*/, Promise.reject()];
119
+ }
114
120
  _d.label = 2;
115
121
  case 2:
116
122
  _d.trys.push([2, 4, , 5]);
117
- return [4 /*yield*/, (0, ai_question_1.PostAiModelUpsert)(__assign(__assign({ name: name, thirdToken: '', aiModel: (props === null || props === void 0 ? void 0 : props.aiModel) || aiModel }, interviewRoomState), { introductoryVideoSetting: {}, selectAbilities: selctedAbilitys, token: token, questions: questions.map(function (item, i) { return (__assign(__assign({}, item), { selfIntroOpt: i < 2 ? item.selfIntroOpt : 0 })); }) }))];
123
+ return [4 /*yield*/, (0, ai_question_1.PostAiModelUpsert)(__assign(__assign({ name: name, thirdToken: '', aiModel: (props === null || props === void 0 ? void 0 : props.aiModel) || aiModel }, interviewRoomState), { introductoryVideoSetting: {}, selectAbilities: selctedAbilitys, token: token, globalDimensions: globalDimensions, questions: questions.map(function (item, i) { return (__assign(__assign({}, item), { selfIntroOpt: i < 2 ? item.selfIntroOpt : 0 })); }) }))];
118
124
  case 3:
119
125
  data = (_d.sent()).data;
120
126
  return [2 /*return*/, Promise.resolve({
@@ -0,0 +1,9 @@
1
+ /// <reference types="react" />
2
+ interface GlobalDimensionDialogProps {
3
+ open: boolean;
4
+ tab: 'library' | 'custom';
5
+ aiQuestionCount: number;
6
+ onClose: () => void;
7
+ }
8
+ declare const GlobalDimensionDialog: ({ open, tab, aiQuestionCount, onClose }: GlobalDimensionDialogProps) => JSX.Element;
9
+ export default GlobalDimensionDialog;
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __read = (this && this.__read) || function (o, n) {
14
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
15
+ if (!m) return o;
16
+ var i = m.call(o), r, ar = [], e;
17
+ try {
18
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
19
+ }
20
+ catch (error) { e = { error: error }; }
21
+ finally {
22
+ try {
23
+ if (r && !r.done && (m = i["return"])) m.call(i);
24
+ }
25
+ finally { if (e) throw e.error; }
26
+ }
27
+ return ar;
28
+ };
29
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
30
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
31
+ if (ar || !(i in from)) {
32
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
33
+ ar[i] = from[i];
34
+ }
35
+ }
36
+ return to.concat(ar || Array.prototype.slice.call(from));
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ var jsx_runtime_1 = require("react/jsx-runtime");
40
+ var ai_ability_1 = require("../../../../services/ai-ability");
41
+ var question_model_store_1 = require("../../../../store/ai-question/question-model-store");
42
+ var enterprise_store_1 = require("../../../../store/enterprise/enterprise-store");
43
+ var ahooks_1 = require("ahooks");
44
+ var fbm_ui_1 = require("fbm-ui");
45
+ var mui_1 = require("fbm-ui/lib/mui");
46
+ var react_1 = require("react");
47
+ /** 一份试卷最多可配置的全局维度个数(与后端 model.MaxGlobalDimensionCount 保持一致) */
48
+ var MAX_GLOBAL_DIMENSION_COUNT = 8;
49
+ var LIBRARY_SOURCE = 1;
50
+ var CUSTOM_SOURCE = 2;
51
+ var formatWeight = function (value) {
52
+ var matched = value.replace(/[^\d.]/g, '').match(/^\d*\.?\d{0,2}/);
53
+ return matched ? matched[0] : '';
54
+ };
55
+ var weightSum = function (dimensions) { return dimensions.reduce(function (total, item) { return total + (Number(item === null || item === void 0 ? void 0 : item.weight) || 0); }, 0); };
56
+ var GlobalDimensionDialog = function (_a) {
57
+ var open = _a.open, tab = _a.tab, aiQuestionCount = _a.aiQuestionCount, onClose = _a.onClose;
58
+ var _b = (0, question_model_store_1.useQuestionModelStore)(function (store) { return [store.questionModelData, store.updateGlobalDimensions]; }), questionModelData = _b.questionModelData, updateGlobalDimensions = _b.updateGlobalDimensions;
59
+ var _c = (0, enterprise_store_1.useEnterpriseStore)().enterprise, jobToken = _c.jobToken, thirdToken = _c.thirdToken;
60
+ var _d = __read((0, react_1.useState)(tab), 2), activeTab = _d[0], setActiveTab = _d[1];
61
+ var _e = __read((0, react_1.useState)([]), 2), selected = _e[0], setSelected = _e[1];
62
+ var _f = __read((0, react_1.useState)(''), 2), keyword = _f[0], setKeyword = _f[1];
63
+ var _g = __read((0, react_1.useState)(''), 2), customName = _g[0], setCustomName = _g[1];
64
+ var _h = __read((0, react_1.useState)(''), 2), customDefine = _h[0], setCustomDefine = _h[1];
65
+ var data = (0, ahooks_1.useRequest)(function () { return (0, ai_ability_1.GetAiAbilityList)({ jobToken: jobToken, thirdToken: thirdToken }); }, {
66
+ refreshDeps: [jobToken, thirdToken],
67
+ }).data;
68
+ var libraryList = (0, react_1.useMemo)(function () { var _a; return ((_a = data === null || data === void 0 ? void 0 : data.data) === null || _a === void 0 ? void 0 : _a.list) || []; }, [data]);
69
+ var filteredLibrary = (0, react_1.useMemo)(function () {
70
+ var text = keyword.trim();
71
+ return text ? libraryList.filter(function (item) { var _a; return (_a = item.name) === null || _a === void 0 ? void 0 : _a.includes(text); }) : libraryList;
72
+ }, [libraryList, keyword]);
73
+ // 打开弹窗时用试卷当前配置初始化(确定前不改动表单数据)
74
+ (0, react_1.useEffect)(function () {
75
+ if (!open) {
76
+ return;
77
+ }
78
+ setActiveTab(tab);
79
+ setSelected(((questionModelData === null || questionModelData === void 0 ? void 0 : questionModelData.globalDimensions) || []).map(function (item) { return (__assign({}, item)); }));
80
+ setKeyword('');
81
+ setCustomName('');
82
+ setCustomDefine('');
83
+ // eslint-disable-next-line react-hooks/exhaustive-deps
84
+ }, [open, tab]);
85
+ var selectedTokens = (0, react_1.useMemo)(function () { return selected.map(function (item) { return item.collectionToken; }).filter(Boolean); }, [selected]);
86
+ var handleToggleLibrary = (0, react_1.useCallback)(function (ability, checked) {
87
+ if (checked) {
88
+ if (selected.length >= MAX_GLOBAL_DIMENSION_COUNT) {
89
+ fbm_ui_1.Message.error("\u4E00\u4E2A\u8BD5\u5377\u6700\u591A\u914D\u7F6E ".concat(MAX_GLOBAL_DIMENSION_COUNT, " \u4E2A\u5168\u5C40\u7EF4\u5EA6"));
90
+ return;
91
+ }
92
+ setSelected(function (prev) { return __spreadArray(__spreadArray([], __read(prev), false), [
93
+ { source: LIBRARY_SOURCE, collectionToken: ability.token, name: ability.name, define: ability.define || '', weight: '' },
94
+ ], false); });
95
+ return;
96
+ }
97
+ setSelected(function (prev) { return prev.filter(function (item) { return item.collectionToken !== ability.token; }); });
98
+ }, [selected.length]);
99
+ var handleAddCustom = (0, react_1.useCallback)(function () {
100
+ var name = customName.trim();
101
+ if (!name) {
102
+ fbm_ui_1.Message.error('请填写维度名称');
103
+ return;
104
+ }
105
+ if (selected.length >= MAX_GLOBAL_DIMENSION_COUNT) {
106
+ fbm_ui_1.Message.error("\u4E00\u4E2A\u8BD5\u5377\u6700\u591A\u914D\u7F6E ".concat(MAX_GLOBAL_DIMENSION_COUNT, " \u4E2A\u5168\u5C40\u7EF4\u5EA6"));
107
+ return;
108
+ }
109
+ setSelected(function (prev) { return __spreadArray(__spreadArray([], __read(prev), false), [{ source: CUSTOM_SOURCE, name: name, define: customDefine.trim(), weight: '' }], false); });
110
+ setCustomName('');
111
+ setCustomDefine('');
112
+ }, [customDefine, customName, selected.length]);
113
+ var handleWeightChange = (0, react_1.useCallback)(function (index, value) {
114
+ var formatValue = formatWeight(value);
115
+ setSelected(function (prev) { return prev.map(function (item, i) { return (i === index ? __assign(__assign({}, item), { weight: formatValue }) : item); }); });
116
+ }, []);
117
+ var handleDefineChange = (0, react_1.useCallback)(function (index, value) {
118
+ setSelected(function (prev) { return prev.map(function (item, i) { return (i === index ? __assign(__assign({}, item), { define: value }) : item); }); });
119
+ }, []);
120
+ var handleRemove = (0, react_1.useCallback)(function (index) {
121
+ setSelected(function (prev) { return prev.filter(function (_, i) { return i !== index; }); });
122
+ }, []);
123
+ var handleSubmit = (0, react_1.useCallback)(function () {
124
+ if (selected.length > MAX_GLOBAL_DIMENSION_COUNT) {
125
+ fbm_ui_1.Message.error("\u4E00\u4E2A\u8BD5\u5377\u6700\u591A\u914D\u7F6E ".concat(MAX_GLOBAL_DIMENSION_COUNT, " \u4E2A\u5168\u5C40\u7EF4\u5EA6"));
126
+ return;
127
+ }
128
+ var emptyWeight = selected.find(function (item) { return !(Number(item.weight) > 0); });
129
+ if (emptyWeight) {
130
+ fbm_ui_1.Message.error("\u8BF7\u586B\u5199\u300C".concat(emptyWeight.name, "\u300D\u7684\u6743\u91CD"));
131
+ return;
132
+ }
133
+ var total = weightSum(selected);
134
+ if (total > 100.005) {
135
+ fbm_ui_1.Message.error("\u5168\u5C40\u7EF4\u5EA6\u6743\u91CD\u5408\u8BA1 ".concat(total, "%\uFF0C\u4E0D\u80FD\u8D85\u8FC7 100%"));
136
+ return;
137
+ }
138
+ updateGlobalDimensions(selected.map(function (item) { return (__assign(__assign({}, item), { weight: Number(item.weight) || 0 })); }));
139
+ onClose();
140
+ }, [onClose, selected, updateGlobalDimensions]);
141
+ return ((0, jsx_runtime_1.jsx)(fbm_ui_1.Dialog, __assign({ open: open, title: "\u6DFB\u52A0\u5168\u5C40\u7EF4\u5EA6", size: "lg", onClose: onClose, onOk: handleSubmit, okText: "\u786E\u5B9A", closeText: "\u53D6\u6D88" }, { children: (0, jsx_runtime_1.jsxs)(mui_1.Box, __assign({ display: "flex", sx: { minHeight: 380 } }, { children: [(0, jsx_runtime_1.jsxs)(mui_1.Box, __assign({ flex: "1 1 0", minWidth: 0, pr: 2.5 }, { children: [(0, jsx_runtime_1.jsx)(fbm_ui_1.Tabs, { borderBottom: "none", value: activeTab, onChange: function (_, value) { return setActiveTab(value); }, tabs: [
142
+ { label: '系统维度库', value: 'library' },
143
+ { label: '自定义维度', value: 'custom' },
144
+ ] }), activeTab === 'library' && ((0, jsx_runtime_1.jsxs)(mui_1.Box, __assign({ mt: 1.5 }, { children: [(0, jsx_runtime_1.jsxs)(mui_1.Stack, __assign({ direction: "row", alignItems: "center", justifyContent: "space-between", mb: 1.5 }, { children: [(0, jsx_runtime_1.jsx)(fbm_ui_1.Input, { sx: { width: 240 }, size: "small", value: keyword, startAdornment: (0, jsx_runtime_1.jsx)(fbm_ui_1.SearchIcon, { color: "disabled" }), placeholder: "\u641C\u7D22\u7EF4\u5EA6\u540D\u79F0", onChange: function (e) { return setKeyword(e.target.value); } }), (0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "caption", color: "secondary" }, { children: "\u53EF\u591A\u9009 \u00B7 \u4E0E\u300C\u8003\u5BDF\u80FD\u529B\u300D\u5171\u7528\u540C\u4E00\u5957\u7EF4\u5EA6\u5B9A\u4E49" }))] })), filteredLibrary.map(function (item) {
145
+ var checked = selectedTokens.includes(item.token);
146
+ return ((0, jsx_runtime_1.jsxs)(mui_1.Box, __assign({ display: "flex", alignItems: "center", sx: {
147
+ border: '1px solid rgba(0, 0, 0, 0.08)',
148
+ borderRadius: 1,
149
+ px: 1.5,
150
+ py: 1,
151
+ mb: 1,
152
+ cursor: 'pointer',
153
+ }, onClick: function () { return handleToggleLibrary(item, !checked); } }, { children: [(0, jsx_runtime_1.jsx)(fbm_ui_1.Checkbox, { checked: checked, onChange: function () { }, sx: { pointerEvents: 'none', p: 0.5, mr: 0.5 } }), (0, jsx_runtime_1.jsxs)(mui_1.Box, __assign({ minWidth: 0 }, { children: [(0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "body2" }, { children: item.name })), item.define && ((0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "caption", color: "secondary", noWrap: true, display: "block", maxWidth: 430 }, { children: item.define })))] }))] }), item.token));
154
+ }), filteredLibrary.length === 0 && ((0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "body2", color: "secondary" }, { children: "\u6CA1\u6709\u5339\u914D\u7684\u7EF4\u5EA6" })))] }))), activeTab === 'custom' && ((0, jsx_runtime_1.jsxs)(mui_1.Stack, __assign({ spacing: 2, mt: 2 }, { children: [(0, jsx_runtime_1.jsx)(fbm_ui_1.TextField, { label: "\u7EF4\u5EA6\u540D\u79F0", value: customName, onChange: function (e) { return setCustomName(e.target.value); } }), (0, jsx_runtime_1.jsx)(fbm_ui_1.TextField, { label: "\u8BC4\u4EF7\u6807\u51C6", multiline: true, rows: 4, value: customDefine, placeholder: "AI \u6309\u8FD9\u6BB5\u63CF\u8FF0\u7ED9\u8BE5\u7EF4\u5EA6\u6253\u5206\u5E76\u7ED9\u51FA\u8BC4\u4EF7", onChange: function (e) { return setCustomDefine(e.target.value); } }), (0, jsx_runtime_1.jsx)(mui_1.Box, { children: (0, jsx_runtime_1.jsx)(fbm_ui_1.Button, __assign({ variant: "outlined", color: "inherit", startIcon: (0, jsx_runtime_1.jsx)(fbm_ui_1.AddIcon, {}), onClick: handleAddCustom }, { children: "\u65B0\u5EFA\u81EA\u5B9A\u4E49\u7EF4\u5EA6" })) }), (0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "caption", color: "secondary" }, { children: "\u81EA\u5B9A\u4E49\u7EF4\u5EA6\u53EA\u5728\u672C\u6B21\u8BD5\u5377\u751F\u6548\uFF0C\u4E0D\u5199\u56DE\u7EF4\u5EA6\u5E93\u3002" }))] })))] })), (0, jsx_runtime_1.jsxs)(mui_1.Box, __assign({ sx: { flex: '0 0 320px', borderLeft: '1px solid rgba(0, 0, 0, 0.08)', pl: 2.5 } }, { children: [(0, jsx_runtime_1.jsxs)(mui_1.Stack, __assign({ direction: "row", alignItems: "center", spacing: 1 }, { children: [(0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "body2", fontWeight: 500 }, { children: "\u5DF2\u9009\u7EF4\u5EA6" })), (0, jsx_runtime_1.jsx)(fbm_ui_1.Chip, { color: "default", label: selected.length, size: "medium" })] })), (0, jsx_runtime_1.jsxs)(mui_1.Box, __assign({ sx: { maxHeight: 320, overflowY: 'auto', pr: 0.5, mt: 1.5 } }, { children: [selected.map(function (item, index) { return ((0, jsx_runtime_1.jsxs)(mui_1.Box, __assign({ sx: { border: '1px solid rgba(0, 0, 0, 0.08)', borderRadius: 1, px: 1.5, py: 1, mb: 1 } }, { children: [(0, jsx_runtime_1.jsxs)(mui_1.Stack, __assign({ direction: "row", alignItems: "center", spacing: 1 }, { children: [(0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "body2", sx: { flex: '1 1 auto', minWidth: 0 }, noWrap: true }, { children: item.name })), (0, jsx_runtime_1.jsx)(fbm_ui_1.Input, { size: "small", sx: { width: 92 }, value: item.weight, placeholder: "0", onChange: function (e) { return handleWeightChange(index, e.target.value); }, endAdornment: (0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "caption", color: "textSecondary" }, { children: "%" })) }), (0, jsx_runtime_1.jsx)(fbm_ui_1.IconButton, __assign({ size: "small", onClick: function () { return handleRemove(index); } }, { children: (0, jsx_runtime_1.jsx)(fbm_ui_1.DeleteIcon, {}) }))] })), (0, jsx_runtime_1.jsx)(fbm_ui_1.TextField, { size: "small", multiline: true, rows: 2, sx: { marginTop: 1 }, placeholder: "\u8BC4\u4EF7\u6807\u51C6\uFF08\u9ED8\u8BA4\u53D6\u7EF4\u5EA6\u5E93\u5B9A\u4E49\uFF09", value: item.define || '', onChange: function (e) { return handleDefineChange(index, e.target.value); } })] }), "".concat(item.collectionToken || item.name, "-").concat(index))); }), selected.length === 0 && ((0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "body2", color: "secondary" }, { children: "\u8FD8\u6CA1\u6709\u9009\u62E9\u5168\u5C40\u7EF4\u5EA6" })))] })), (0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "caption", color: "secondary", display: "block", mt: 1 }, { children: "\u6743\u91CD\u5FC5\u586B\uFF0C\u4E0E\u9898\u76EE\u6743\u91CD\u5408\u8BA1\u9700\u8981\u51D1\u6EE1 100%\uFF1B\u8C03\u6574\u540E\u4F1A\u6309\u6BD4\u4F8B\u91CD\u6392\u9898\u76EE\u6743\u91CD\u3002" })), (0, jsx_runtime_1.jsxs)(fbm_ui_1.Typography, __assign({ variant: "caption", display: "block" }, { children: ["\u5F53\u524D\u5408\u8BA1\uFF1A", weightSum(selected), "%", aiQuestionCount === 0 && '(当前试卷没有可 AI 评分的题目,需要合计 100%)'] }))] }))] })) })));
155
+ };
156
+ exports.default = GlobalDimensionDialog;
@@ -0,0 +1,3 @@
1
+ /// <reference types="react" />
2
+ declare const _default: import("react").MemoExoticComponent<() => JSX.Element>;
3
+ export default _default;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __read = (this && this.__read) || function (o, n) {
14
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
15
+ if (!m) return o;
16
+ var i = m.call(o), r, ar = [], e;
17
+ try {
18
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
19
+ }
20
+ catch (error) { e = { error: error }; }
21
+ finally {
22
+ try {
23
+ if (r && !r.done && (m = i["return"])) m.call(i);
24
+ }
25
+ finally { if (e) throw e.error; }
26
+ }
27
+ return ar;
28
+ };
29
+ var __importDefault = (this && this.__importDefault) || function (mod) {
30
+ return (mod && mod.__esModule) ? mod : { "default": mod };
31
+ };
32
+ Object.defineProperty(exports, "__esModule", { value: true });
33
+ var jsx_runtime_1 = require("react/jsx-runtime");
34
+ var Dialog_1 = __importDefault(require("./Dialog"));
35
+ var ai_question_1 = require("../../../../constants/ai-question");
36
+ var question_model_store_1 = require("../../../../store/ai-question/question-model-store");
37
+ var fbm_ui_1 = require("fbm-ui");
38
+ var mui_1 = require("fbm-ui/lib/mui");
39
+ var react_1 = require("react");
40
+ /**
41
+ * 全局维度:只绑试卷、不绑题目,按整场回答统一评价。
42
+ * 展示样式与「面试间互动方式」「题目」卡片保持一致(Paper outlined + fbm-ui 组件)。
43
+ */
44
+ var GlobalDimensions = function () {
45
+ var _a = (0, question_model_store_1.useQuestionModelStore)(function (store) { return [store.questionModelData, store.updateGlobalDimensions]; }), questionModelData = _a.questionModelData, updateGlobalDimensions = _a.updateGlobalDimensions;
46
+ var _b = (questionModelData || {}).steps, steps = _b === void 0 ? [] : _b;
47
+ var dimensions = (0, react_1.useMemo)(function () { return (questionModelData === null || questionModelData === void 0 ? void 0 : questionModelData.globalDimensions) || []; }, [questionModelData]);
48
+ var aiQuestionCount = (0, react_1.useMemo)(function () { return steps.filter(function (step) { return (0, ai_question_1.IS_AI_ANALYSIS)(step); }).length; }, [steps]);
49
+ var _c = __read((0, react_1.useState)(false), 2), open = _c[0], setOpen = _c[1];
50
+ var _d = __read((0, react_1.useState)('library'), 2), tab = _d[0], setTab = _d[1];
51
+ var handleOpen = (0, react_1.useCallback)(function (nextTab) {
52
+ setTab(nextTab);
53
+ setOpen(true);
54
+ }, []);
55
+ var handleRemove = (0, react_1.useCallback)(function (index) {
56
+ updateGlobalDimensions(dimensions.filter(function (_, i) { return i !== index; }));
57
+ }, [dimensions, updateGlobalDimensions]);
58
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(fbm_ui_1.Paper, __assign({ variant: "outlined", sx: { display: 'block', mt: 2, px: 2, pt: 1.5, pb: 2 } }, { children: [(0, jsx_runtime_1.jsxs)(mui_1.Stack, __assign({ direction: "row", alignItems: "center", justifyContent: "space-between", spacing: 2 }, { children: [(0, jsx_runtime_1.jsxs)(mui_1.Stack, __assign({ direction: "row", alignItems: "center", minWidth: 0 }, { children: [(0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "body2", color: "primary.main", fontWeight: "medium" }, { children: "\u5168\u5C40\u7EF4\u5EA6" })), (0, jsx_runtime_1.jsx)(fbm_ui_1.Chip, { color: "default", label: "\u4E0D\u5173\u8054\u9898\u76EE", size: "medium", sx: { ml: 1 } }), (0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "caption", color: "secondary", ml: 1.5, noWrap: true }, { children: "\u9762\u8BD5\u7ED3\u675F\u540E\u6309\u6574\u573A\u56DE\u7B54\u7EDF\u4E00\u8BC4\u4EF7\uFF0C\u5019\u9009\u4EBA\u4E0D\u9700\u8981\u4F5C\u7B54" }))] })), dimensions.length > 0 && ((0, jsx_runtime_1.jsx)(fbm_ui_1.Button, __assign({ variant: "text", sx: { flexShrink: 0 }, onClick: function () { return handleOpen('library'); } }, { children: "\u7F16\u8F91\u8BC4\u4EF7\u6807\u51C6" })))] })), (0, jsx_runtime_1.jsxs)(mui_1.Box, __assign({ mt: 1.5, display: "flex", flexWrap: "wrap", alignItems: "center", sx: { gap: 1 } }, { children: [dimensions.map(function (item, index) { return ((0, jsx_runtime_1.jsx)(fbm_ui_1.Chip, { color: "default", label: "".concat(item.name, " \u00B7 \u6743\u91CD ").concat(item.weight, "%"), onDelete: function () { return handleRemove(index); } }, "".concat(item.token || item.name, "-").concat(index))); }), (0, jsx_runtime_1.jsx)(fbm_ui_1.Button, __assign({ variant: "text", icon: (0, jsx_runtime_1.jsx)(fbm_ui_1.AddIcon, {}), onClick: function () { return handleOpen('library'); } }, { children: "\u6DFB\u52A0\u5168\u5C40\u7EF4\u5EA6" }))] })), (0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "caption", color: "secondary", display: "block", mt: dimensions.length > 0 ? 1 : 0.5 }, { children: dimensions.length > 0
59
+ ? "\u5DF2\u914D\u7F6E ".concat(dimensions.length, " \u4E2A\u5168\u5C40\u7EF4\u5EA6\uFF0C\u4F1A\u548C\u9898\u76EE\u7EF4\u5EA6\u4E00\u8D77\u51FA\u73B0\u5728\u62A5\u544A\u56FE\u8868\u4E2D")
60
+ : '还没有全局维度。如果希望按整场回答评价某些能力,点上方「添加全局维度」。' }))] })), (0, jsx_runtime_1.jsx)(Dialog_1.default, { open: open, tab: tab, aiQuestionCount: aiQuestionCount, onClose: function () { return setOpen(false); } })] }));
61
+ };
62
+ exports.default = (0, react_1.memo)(GlobalDimensions);
@@ -15,6 +15,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  var jsx_runtime_1 = require("react/jsx-runtime");
18
+ var GlobalDimensions_1 = __importDefault(require("../GlobalDimensions"));
18
19
  var const_1 = require("../QuestionUpdate/const");
19
20
  var Header_1 = __importDefault(require("./Header"));
20
21
  var Interactive_1 = __importDefault(require("./Interactive"));
@@ -84,6 +85,6 @@ var Question = function () {
84
85
  }
85
86
  }
86
87
  }, [token, aiEvaluationData, questionModelData === null || questionModelData === void 0 ? void 0 : questionModelData.steps, templateList, addModel]);
87
- return ((0, jsx_runtime_1.jsx)(styled_1.QuestionModelRoot, { children: loading ? ((0, jsx_runtime_1.jsx)(Skeleton_1.default, {})) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Header_1.default, {}), (0, jsx_runtime_1.jsx)(Interactive_1.default, {}), (0, jsx_runtime_1.jsx)(List_1.default, {})] })) }));
88
+ return ((0, jsx_runtime_1.jsx)(styled_1.QuestionModelRoot, { children: loading ? ((0, jsx_runtime_1.jsx)(Skeleton_1.default, {})) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Header_1.default, {}), (0, jsx_runtime_1.jsx)(Interactive_1.default, {}), (0, jsx_runtime_1.jsx)(GlobalDimensions_1.default, {}), (0, jsx_runtime_1.jsx)(List_1.default, {})] })) }));
88
89
  };
89
90
  exports.default = Question;
@@ -15,6 +15,18 @@ export interface QuestionModelData {
15
15
  aiInterviewerProfile?: AiInterviewerProfile;
16
16
  steps: QuestionModelStep[];
17
17
  interactionMethods?: InteractionMethod[];
18
+ /** 全局维度(只绑试卷、不绑题目,按整场回答统一评价) */
19
+ globalDimensions?: GlobalDimension[];
20
+ }
21
+ /** 全局维度:来源 1=系统维度库 2=自定义 */
22
+ export interface GlobalDimension {
23
+ token?: string;
24
+ source: number;
25
+ collectionId?: number;
26
+ collectionToken?: string;
27
+ name: string;
28
+ define?: string;
29
+ weight: number;
18
30
  }
19
31
  export interface QuestionModelDataRes {
20
32
  data: QuestionModelData;
@@ -5,7 +5,7 @@ export declare const PreviewRoot: import("@emotion/styled").StyledComponent<{
5
5
  elevation?: number | undefined;
6
6
  square?: boolean | undefined;
7
7
  sx?: import("@mui/system").SxProps<import("fbm-ui/lib/mui").Theme> | undefined;
8
- variant?: "outlined" | "elevation" | undefined;
8
+ variant?: "elevation" | "outlined" | undefined;
9
9
  } & import("@mui/material/OverridableComponent").CommonProps & Omit<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof import("react").HTMLAttributes<HTMLDivElement>> & {
10
10
  ref?: ((instance: HTMLDivElement | null) => void) | import("react").RefObject<HTMLDivElement> | null | undefined;
11
- }, keyof import("@mui/material/OverridableComponent").CommonProps | "children" | "sx" | "variant" | "elevation" | "square"> & import("@mui/system").MUIStyledCommonProps<import("fbm-ui/lib/mui").Theme>, {}, {}>;
11
+ }, "children" | keyof import("@mui/material/OverridableComponent").CommonProps | "sx" | "elevation" | "square" | "variant"> & import("@mui/system").MUIStyledCommonProps<import("fbm-ui/lib/mui").Theme>, {}, {}>;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 权重池计算(纯函数,便于单独验证)
3
+ *
4
+ * 口径:题目维度权重 + 全局维度权重 = 100%
5
+ * - 全局维度是试卷级配置,它的权重合计决定了题目还能用多少权重池;
6
+ * - 题目权重需要按比例缩放到这个池子里,否则会出现负权重 / 合计不等于 100% 的脏数据。
7
+ */
8
+ /** 题目维度可用的权重池 = 100 - 全局维度权重合计(不会小于 0) */
9
+ export declare const computeQuestionWeightPool: (globalDimensions?: Array<{
10
+ weight: number | string;
11
+ }>) => number;
12
+ /**
13
+ * 把一组权重按比例缩放到 target,保留 2 位小数。
14
+ * - 总和为 0(新建试卷还没分配权重)时,把 target 全给最后一项;
15
+ * - 最后一个吸收四舍五入误差,并夹到 0 以上,避免出现负权重。
16
+ */
17
+ export declare const rebalanceWeights: (weights: Array<number | string>, target: number) => number[];
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ /**
3
+ * 权重池计算(纯函数,便于单独验证)
4
+ *
5
+ * 口径:题目维度权重 + 全局维度权重 = 100%
6
+ * - 全局维度是试卷级配置,它的权重合计决定了题目还能用多少权重池;
7
+ * - 题目权重需要按比例缩放到这个池子里,否则会出现负权重 / 合计不等于 100% 的脏数据。
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.rebalanceWeights = exports.computeQuestionWeightPool = void 0;
11
+ var round2 = function (value) { return Math.round(value * 100) / 100; };
12
+ /** 题目维度可用的权重池 = 100 - 全局维度权重合计(不会小于 0) */
13
+ var computeQuestionWeightPool = function (globalDimensions) {
14
+ if (globalDimensions === void 0) { globalDimensions = []; }
15
+ var globalWeightSum = globalDimensions.reduce(function (total, item) { return total + (Number(item === null || item === void 0 ? void 0 : item.weight) || 0); }, 0);
16
+ return Math.max(0, round2(100 - globalWeightSum));
17
+ };
18
+ exports.computeQuestionWeightPool = computeQuestionWeightPool;
19
+ /**
20
+ * 把一组权重按比例缩放到 target,保留 2 位小数。
21
+ * - 总和为 0(新建试卷还没分配权重)时,把 target 全给最后一项;
22
+ * - 最后一个吸收四舍五入误差,并夹到 0 以上,避免出现负权重。
23
+ */
24
+ var rebalanceWeights = function (weights, target) {
25
+ if (!weights.length) {
26
+ return [];
27
+ }
28
+ var safeTarget = Math.max(0, round2(target));
29
+ var total = weights.reduce(function (sum, weight) { return sum + (Number(weight) || 0); }, 0);
30
+ if (total <= 0) {
31
+ return weights.map(function (_, index) { return (index === weights.length - 1 ? safeTarget : 0); });
32
+ }
33
+ var result = weights.map(function (weight, index) {
34
+ if (index === weights.length - 1) {
35
+ return 0; // 最后一项统一补差额
36
+ }
37
+ return round2(((Number(weight) || 0) / total) * safeTarget);
38
+ });
39
+ var allocated = result.reduce(function (sum, weight) { return sum + weight; }, 0);
40
+ result[result.length - 1] = Math.max(0, round2(safeTarget - allocated));
41
+ return result;
42
+ };
43
+ exports.rebalanceWeights = rebalanceWeights;