eli-video-interview 1.2.0 → 1.2.2

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 (33) hide show
  1. package/esm/modules/ai-report/Root.d.ts +1 -1
  2. package/esm/modules/ai-report/Root.js +9 -8
  3. package/esm/modules/ai-report/components/AIEvaluate/Evaluate.d.ts +13 -0
  4. package/esm/modules/ai-report/components/AIEvaluate/Evaluate.js +45 -0
  5. package/esm/modules/ai-report/components/AIEvaluate/Graph.d.ts +12 -0
  6. package/esm/modules/ai-report/components/AIEvaluate/Graph.js +195 -0
  7. package/esm/modules/ai-report/components/AIEvaluate/index.d.ts +2 -0
  8. package/esm/modules/ai-report/components/AIEvaluate/index.js +34 -0
  9. package/esm/modules/ai-report/components/VideoQuestion/styled.d.ts +1 -1
  10. package/esm/modules/ai-report/index.js +2 -2
  11. package/esm/modules/ai-report/interface.d.ts +3 -0
  12. package/esm/modules/ai-report/useAiReport.d.ts +2 -0
  13. package/esm/services/ai-report.d.ts +7 -0
  14. package/esm/services/ai-report.js +4 -0
  15. package/esm/store/ai-report/global-store.d.ts +6 -0
  16. package/esm/store/ai-report/global-store.js +3 -1
  17. package/lib/modules/ai-report/Root.d.ts +1 -1
  18. package/lib/modules/ai-report/Root.js +11 -10
  19. package/lib/modules/ai-report/components/AIEvaluate/Evaluate.d.ts +13 -0
  20. package/lib/modules/ai-report/components/AIEvaluate/Evaluate.js +47 -0
  21. package/lib/modules/ai-report/components/AIEvaluate/Graph.d.ts +12 -0
  22. package/lib/modules/ai-report/components/AIEvaluate/Graph.js +197 -0
  23. package/lib/modules/ai-report/components/AIEvaluate/index.d.ts +2 -0
  24. package/lib/modules/ai-report/components/AIEvaluate/index.js +39 -0
  25. package/lib/modules/ai-report/components/VideoQuestion/styled.d.ts +1 -1
  26. package/lib/modules/ai-report/index.js +2 -2
  27. package/lib/modules/ai-report/interface.d.ts +3 -0
  28. package/lib/modules/ai-report/useAiReport.d.ts +2 -0
  29. package/lib/services/ai-report.d.ts +7 -0
  30. package/lib/services/ai-report.js +6 -1
  31. package/lib/store/ai-report/global-store.d.ts +6 -0
  32. package/lib/store/ai-report/global-store.js +3 -1
  33. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import React from 'react';
2
1
  import { AiReportProps } from './interface';
2
+ import React from 'react';
3
3
  declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<AiReportProps & React.RefAttributes<any>>>;
4
4
  export default _default;
@@ -10,15 +10,16 @@ var __assign = (this && this.__assign) || function () {
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
12
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
13
- import { forwardRef, useEffect, useCallback, useRef, useImperativeHandle, useMemo, memo } from 'react';
14
- import { Box, Typography, Button } from 'fbm-ui';
15
- import { useRequest } from 'ahooks';
16
- import { useAiReportStore } from "../../store/ai-report/global-store";
17
- import { PostAiInterviewResult } from "../../services/ai-report";
18
- import { INTERVIEW_STATUS } from "../../enum/ai-report";
13
+ import AIEvaluate from './components/AIEvaluate';
14
+ import NotFinish from './components/NotFinish';
19
15
  import ScoreReport from './components/ScoreReport';
20
16
  import VideoQuestion from './components/VideoQuestion';
21
- import NotFinish from './components/NotFinish';
17
+ import { INTERVIEW_STATUS } from "../../enum/ai-report";
18
+ import { PostAiInterviewResult } from "../../services/ai-report";
19
+ import { useAiReportStore } from "../../store/ai-report/global-store";
20
+ import { useRequest } from 'ahooks';
21
+ import { Box, Typography, Button } from 'fbm-ui';
22
+ import { forwardRef, useEffect, useCallback, useRef, useImperativeHandle, useMemo, memo } from 'react';
22
23
  var NO_ANSWER = INTERVIEW_STATUS.NO_ANSWER;
23
24
  var AiReportRoot = forwardRef(function (props, ref) {
24
25
  var token = props.token, reminderSent = props.reminderSent, operableButtons = props.operableButtons, onLoad = props.onLoad, onSendReminderClick = props.onSendReminderClick;
@@ -64,7 +65,7 @@ var AiReportRoot = forwardRef(function (props, ref) {
64
65
  return (_jsxs(Box, __assign({ width: "100%", display: "flex", alignItems: "center", justifyContent: "center", flexDirection: "column", style: { marginTop: '149px' } }, { children: [_jsx(Box, { children: _jsx("img", { src: "//webcdn.fbmms.cn/web/saas/asset/image/CandidateInfoEmpty.png", alt: "", style: { width: '140px', height: '140px' } }) }), _jsx(Box, __assign({ mt: 2 }, { children: _jsx(Typography, __assign({ variant: "body1", color: "textPrimary", style: { fontWeight: '500' } }, { children: "\u8BE5\u5019\u9009\u4EBA\u5C1A\u672A\u5F00\u59CB\u9762\u8BD5" })) })), (operableButtons === null || operableButtons === void 0 ? void 0 : operableButtons.includes('sendReminder')) && (_jsxs(_Fragment, { children: [_jsx(Box, __assign({ style: { marginTop: '2px' } }, { children: _jsx(Typography, __assign({ variant: "body2", color: "textSecondary" }, { children: "\u82E5\u957F\u65F6\u95F4\u672A\u5F00\u59CB\uFF0C\u5EFA\u8BAE\u4F60\u7ED9\u5019\u9009\u4EBA\u53D1\u9001\u77ED\u4FE1\u63D0\u9192" })) })), _jsx(Box, __assign({ mt: 2 }, { children: _jsx(Button, __assign({ size: "large", variant: "outlined", color: "primary", disabled: reminderSent, onClick: onSendReminderClick }, { children: reminderSent ? '已提醒' : '发送提醒' })) }))] }))] })));
65
66
  }
66
67
  else {
67
- return (_jsxs(Box, { children: [_jsx(NotFinish, {}), _jsx(ScoreReport, { onRefreshSuccess: handleRefreshSuccess }), _jsx(VideoQuestion, {})] }));
68
+ return (_jsxs(Box, { children: [_jsx(NotFinish, {}), _jsx(ScoreReport, { onRefreshSuccess: handleRefreshSuccess }), _jsx(AIEvaluate, {}), _jsx(VideoQuestion, {})] }));
68
69
  }
69
70
  }, [handleRefreshSuccess, onSendReminderClick, reminderSent, status, operableButtons]);
70
71
  return (_jsx(Box, __assign({ loading: firstLoad.current && loading, sx: { width: '100%', minHeight: '584px', height: '100%', margin: '0 auto', overflow: 'auto' } }, { children: aiReportResult })));
@@ -0,0 +1,13 @@
1
+ /// <reference types="react" />
2
+ declare type Mode = 'edit' | 'show';
3
+ declare type Field = 'evaluations' | 'suggestions';
4
+ interface EvaluateProps {
5
+ title: string;
6
+ token: string;
7
+ field: Field;
8
+ evaluations: Array<string>;
9
+ mode?: Mode;
10
+ canEdit?: boolean;
11
+ }
12
+ declare const Evaluate: React.FC<EvaluateProps>;
13
+ export default Evaluate;
@@ -0,0 +1,45 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { PostAiInterviewEvaluation } from "../../../../services/ai-report";
14
+ import { Button, EditIcon, IconButton, Typography } from 'fbm-ui';
15
+ import { Box, Stack, TextField } from 'fbm-ui/lib/mui';
16
+ import { useCallback, useEffect, useState } from 'react';
17
+ var Evaluate = function (_a) {
18
+ var title = _a.title, evaluations = _a.evaluations, token = _a.token, field = _a.field, _b = _a.mode, mode = _b === void 0 ? 'show' : _b, _c = _a.canEdit, canEdit = _c === void 0 ? 'true' : _c;
19
+ var _d = useState(evaluations === null || evaluations === void 0 ? void 0 : evaluations.join('\n')), content = _d[0], setContent = _d[1];
20
+ var _e = useState('show'), internalMode = _e[0], setInternalMode = _e[1];
21
+ var handleChange = useCallback(function (e) {
22
+ var value = e.target.value;
23
+ setContent(value);
24
+ }, []);
25
+ var handleModeChange = useCallback(function () {
26
+ setInternalMode(internalMode === 'show' ? 'edit' : 'show');
27
+ }, [internalMode]);
28
+ var handleSubmit = useCallback(function () {
29
+ var data = field === 'evaluations'
30
+ ? {
31
+ evaluationToken: token,
32
+ manualEvaluations: [content],
33
+ }
34
+ : {
35
+ evaluationToken: token,
36
+ manualSuggestions: [content],
37
+ };
38
+ PostAiInterviewEvaluation(data).then(handleModeChange).catch(console.log);
39
+ }, [token, content, field, handleModeChange]);
40
+ useEffect(function () {
41
+ setInternalMode(mode);
42
+ }, [mode]);
43
+ return (_jsxs(Stack, { children: [_jsxs(Stack, __assign({ direction: "row", alignItems: "center", justifyContent: "space-between" }, { children: [_jsx(Typography, __assign({ variant: "body2", fontWeight: "medium" }, { children: title })), canEdit && (_jsx(IconButton, __assign({ onClick: handleModeChange }, { children: _jsx(EditIcon, {}) })))] })), internalMode === 'edit' && (_jsxs(Box, __assign({ width: 1, position: "relative" }, { children: [_jsx(TextField, { fullWidth: true, value: content, onChange: handleChange, rows: 3.5, multiline: true }), _jsxs(Stack, __assign({ p: 1, spacing: 1, direction: "row", position: "absolute", bottom: 0, right: 0 }, { children: [_jsx(Button, __assign({ size: "small", color: "inherit", onClick: handleModeChange }, { children: "\u53D6\u6D88" })), _jsx(Button, __assign({ size: "small", onClick: handleSubmit }, { children: "\u4FDD\u5B58" }))] }))] }))), internalMode === 'show' && (_jsx(Typography, __assign({ variant: "body2", color: "textSecondary", sx: { whiteSpace: 'pre-wrap' } }, { children: content })))] }));
44
+ };
45
+ export default Evaluate;
@@ -0,0 +1,12 @@
1
+ /// <reference types="react" />
2
+ interface Dimension {
3
+ name: string;
4
+ score: number;
5
+ rank: number;
6
+ total: number;
7
+ }
8
+ interface GraphProps {
9
+ items: Array<Dimension>;
10
+ }
11
+ declare const Graph: React.FC<GraphProps>;
12
+ export default Graph;
@@ -0,0 +1,195 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useRef, useState } from 'react';
3
+ function setupCanvas(canvas) {
4
+ // Get the device pixel ratio, falling back to 1.
5
+ var dpr = window.devicePixelRatio || 1;
6
+ // Get the size of the canvas in CSS pixels.
7
+ var rect = canvas.getBoundingClientRect();
8
+ // Give the canvas pixel dimensions of their CSS
9
+ // size * the device pixel ratio.
10
+ canvas.width = rect.width * dpr;
11
+ canvas.height = rect.height * dpr;
12
+ var ctx = canvas.getContext('2d');
13
+ // Scale all drawing operations by the dpr, so you
14
+ // don't have to worry about the difference.
15
+ ctx.scale(dpr, dpr);
16
+ return ctx;
17
+ }
18
+ var levelOrder = ['Bad', 'Good', 'Best'];
19
+ var levelConf = {
20
+ Bad: {
21
+ label: '欠佳',
22
+ width: 134,
23
+ color: [229, 115, 115],
24
+ endScore: 30,
25
+ pointColor: ['RGB(229, 115, 115)', 'RGB(255, 67, 102)'],
26
+ },
27
+ Good: {
28
+ label: '适中',
29
+ width: 171,
30
+ color: [255, 183, 77],
31
+ endScore: 70,
32
+ pointColor: ['RGB(255, 183, 77)', 'RGB(255, 152, 0)'],
33
+ },
34
+ Best: {
35
+ label: '优秀',
36
+ width: 134,
37
+ color: [0, 217, 157],
38
+ endScore: 100,
39
+ pointColor: ['RGB(0, 217, 157)', 'RGB(0, 176, 127)'],
40
+ },
41
+ };
42
+ var tipEl = document.createElement('div');
43
+ var measureTextWidth = function (ctx, text) {
44
+ var width = ctx.measureText(text).width;
45
+ return width;
46
+ };
47
+ function isInPath(x, y, tx, ty, ctx) {
48
+ ctx.beginPath();
49
+ ctx.arc(tx / 2, ty / 2, 10 / 2, 0, Math.PI * 2, true);
50
+ var ret = ctx.isPointInPath(x, y);
51
+ ctx.closePath();
52
+ return ret;
53
+ }
54
+ var drawTop = function (layout, ctx) {
55
+ ctx.font = '12px sans-serif';
56
+ ctx.fillText('排名(%)', 10, 10);
57
+ ctx.fillStyle = '#ccc';
58
+ ctx.fillText('0', layout.leftLableWidth, 10);
59
+ ctx.strokeStyle = '#ccc';
60
+ var offset = 0;
61
+ levelOrder.forEach(function (x) {
62
+ var c = levelConf[x];
63
+ var labelWidth = measureTextWidth(ctx, c.label);
64
+ var endScoreWidth = measureTextWidth(ctx, c.endScore);
65
+ ctx.moveTo(layout.leftLableWidth + offset + endScoreWidth / 2 + 5, 6);
66
+ ctx.lineTo(layout.leftLableWidth + offset + c.width / 2 - labelWidth / 2 - 5, 6);
67
+ ctx.fillStyle = 'black';
68
+ ctx.fillText(c.label, layout.leftLableWidth + offset + c.width / 2 - labelWidth / 2, 10);
69
+ ctx.moveTo(layout.leftLableWidth + offset + c.width / 2 + labelWidth / 2 + 5, 6);
70
+ ctx.lineTo(layout.leftLableWidth + offset + c.width - endScoreWidth - 5, 6);
71
+ ctx.fillStyle = '#ccc';
72
+ ctx.fillText(c.endScore, layout.leftLableWidth + offset + c.width - endScoreWidth, 10);
73
+ ctx.stroke();
74
+ offset += c.width;
75
+ });
76
+ };
77
+ var drowBackground = function (layout, ctx) {
78
+ var leftOffset = layout.leftLableWidth;
79
+ levelOrder.forEach(function (x) {
80
+ var c = levelConf[x];
81
+ ctx.fillStyle = "rgb(".concat(c.color.join(','), ")");
82
+ ctx.fillRect(0 + leftOffset, layout.topLableHeight, c.width, 4);
83
+ var linearGradient0 = ctx.createLinearGradient(0, 0, 0, layout.height - layout.topLableHeight);
84
+ linearGradient0.addColorStop(0, "RGBA(".concat(c.color.join(','), ", 0.3)"));
85
+ linearGradient0.addColorStop(1, "RGBA(".concat(c.color.join(','), ", 0.05)"));
86
+ ctx.fillStyle = linearGradient0;
87
+ ctx.fillRect(0 + leftOffset, layout.topLableHeight, c.width, layout.height - layout.topLableHeight);
88
+ leftOffset += c.width + 4;
89
+ });
90
+ };
91
+ var percent = function (_a) {
92
+ var rank = _a.rank, total = _a.total;
93
+ return Math.min(0.975, parseFloat((1 - (rank - 1) / total).toFixed(2)));
94
+ };
95
+ var getPointColor = function (s) {
96
+ var conf = Object.entries(levelConf);
97
+ for (var _i = 0, conf_1 = conf; _i < conf_1.length; _i++) {
98
+ var _a = conf_1[_i], v = _a[1];
99
+ if (v.endScore >= s * 100)
100
+ return v.pointColor;
101
+ }
102
+ return [];
103
+ };
104
+ var drawLable = function (lable, x, y, ctx) {
105
+ ctx.fillStyle = 'black';
106
+ ctx.fillText(lable, x, y + 5);
107
+ ctx.strokeStyle = '#ccc';
108
+ };
109
+ var drawLine = function (sx, ex, ey, ctx) {
110
+ ctx.beginPath();
111
+ ctx.setLineDash([2, 1]);
112
+ ctx.moveTo(sx, ey);
113
+ ctx.lineTo(ex, ey);
114
+ ctx.stroke();
115
+ };
116
+ var drawPoint = function (fill, stroke, x, y, ctx) {
117
+ ctx.fillStyle = fill;
118
+ ctx.strokeStyle = stroke;
119
+ ctx.lineWidth = 1;
120
+ ctx.beginPath();
121
+ ctx.arc(x, y, 4, 0, Math.PI * 2, true);
122
+ ctx.closePath();
123
+ ctx.fill();
124
+ ctx.stroke();
125
+ };
126
+ var draw = function (layout, color, dimensions, pathRef, ctx) {
127
+ drawTop(layout, ctx);
128
+ drowBackground(layout, ctx);
129
+ var maxWidth = 439;
130
+ dimensions.forEach(function (v, i) {
131
+ var p = percent(v);
132
+ var target = maxWidth * p + 4;
133
+ var endPointX = target + layout.leftLableWidth;
134
+ var endPointY = 65 + layout.itemSpacing * i;
135
+ drawLable(v.name, 10, endPointY, ctx);
136
+ drawLine(layout.leftLableWidth, endPointX, endPointY, ctx);
137
+ var _a = getPointColor(p), fill = _a[0], stroke = _a[1];
138
+ drawPoint(fill, stroke, endPointX, endPointY, ctx);
139
+ pathRef.push({ x: endPointX, y: endPointY, tips: "".concat(v === null || v === void 0 ? void 0 : v.name, "\u5F97\u5206:").concat(v === null || v === void 0 ? void 0 : v.score, "\u5206") });
140
+ });
141
+ };
142
+ var Graph = function (_a) {
143
+ var _b = _a.items, items = _b === void 0 ? [] : _b;
144
+ var ref = useRef(null);
145
+ var pathRef = useRef([]);
146
+ var _c = useState(), ctx = _c[0], setCtx = _c[1];
147
+ useEffect(function () {
148
+ var currentCtx = setupCanvas(ref.current);
149
+ setCtx(currentCtx);
150
+ tipEl.style.background = 'rgba(0,0,0,.7)';
151
+ tipEl.style.color = '#fff';
152
+ tipEl.style.borderRadius = '2px';
153
+ tipEl.style.padding = '2px 5px';
154
+ tipEl.style.position = 'absolute';
155
+ tipEl.style.zIndex = '999';
156
+ tipEl.style.fontSize = '12px';
157
+ tipEl.style.display = 'none';
158
+ document.body.appendChild(tipEl);
159
+ }, [ref]);
160
+ useEffect(function () {
161
+ if (ctx) {
162
+ var layout = {
163
+ leftLableWidth: 80,
164
+ topLableHeight: 40,
165
+ itemSpacing: 32,
166
+ height: 32 * items.length + 40 + 16,
167
+ };
168
+ var gradeColor = {
169
+ Bad: [229, 115, 115],
170
+ Good: [255, 183, 77],
171
+ Best: [0, 217, 157],
172
+ };
173
+ draw(layout, gradeColor, items, pathRef.current, ctx);
174
+ }
175
+ }, [ctx, items]);
176
+ useEffect(function () {
177
+ console.log(pathRef);
178
+ }, [pathRef]);
179
+ var handleMouseMove = useCallback(function (e) {
180
+ if (ctx) {
181
+ var p = pathRef.current.find(function (p) { return isInPath(e.nativeEvent.offsetX, e.nativeEvent.offsetY, p.x, p.y, ctx); });
182
+ if (p) {
183
+ tipEl.style.left = e.pageX + 10 + 'px';
184
+ tipEl.style.top = e.pageY + 10 + 'px';
185
+ tipEl.innerHTML = p.tips;
186
+ tipEl.style.display = 'block';
187
+ }
188
+ else {
189
+ tipEl.style.display = 'none';
190
+ }
191
+ }
192
+ }, [ctx, pathRef]);
193
+ return (_jsx("canvas", { ref: ref, onMouseOut: function () { return (tipEl.style.display = 'none'); }, onMouseMove: handleMouseMove, style: { width: '100%', height: 32 * items.length + 40 + 16 } }));
194
+ };
195
+ export default Graph;
@@ -0,0 +1,2 @@
1
+ declare const Index: () => JSX.Element | null;
2
+ export default Index;
@@ -0,0 +1,34 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import Evaluate from './Evaluate';
14
+ import Graph from './Graph';
15
+ import { useAiReportStore } from "../../../../store/ai-report/global-store";
16
+ import { Divider, InfoOutlineIcon, Link, Typography } from 'fbm-ui';
17
+ import { Box, Paper, Stack, Collapse } from 'fbm-ui/lib/mui';
18
+ import { useCallback, useState } from 'react';
19
+ var Index = function () {
20
+ var _a;
21
+ var _b = useAiReportStore(function (store) { return [store.reportResult, store.operableButtons]; }), reportResult = _b.reportResult, showAiDimension = _b.showAiDimension, canEditAiDimension = _b.canEditAiDimension;
22
+ var _c = useState(false), expand = _c[0], setExpand = _c[1];
23
+ var handleExpandChange = useCallback(function () {
24
+ setExpand(!expand);
25
+ }, [expand]);
26
+ if (!showAiDimension)
27
+ return null;
28
+ return (_jsxs(Box, __assign({ component: Paper, variant: "outlined", px: 2, mt: 2 }, { children: [_jsxs(Stack, __assign({ direction: "row", height: 56, alignItems: "center", spacing: 1 }, { children: [_jsx(Typography, __assign({ variant: "body1", fontWeight: "medium" }, { children: "AI\u7EF4\u5EA6\u8868\u73B0" })), _jsx(InfoOutlineIcon, { sx: { fontSize: '16px' } })] })), _jsxs(Collapse, __assign({ in: expand }, { children: [(_a = reportResult === null || reportResult === void 0 ? void 0 : reportResult.evaluations) === null || _a === void 0 ? void 0 : _a.map(function (v) {
29
+ var _a;
30
+ var rank = (1 - (v.rank - 1) / v.total) * 100;
31
+ return (_jsxs(Box, __assign({ component: Paper, elevation: 0, bgcolor: "#f9f9f9", mb: 2, pb: 2 }, { children: [_jsxs(Stack, __assign({ px: 2, pt: 2 }, { children: [_jsxs(Stack, __assign({ direction: "row", alignItems: "center", spacing: 2 }, { children: [_jsx(Typography, __assign({ variant: "h6" }, { children: v.evaluationDimensionName })), !isNaN(rank) && (_jsxs(Typography, __assign({ variant: "body2" }, { children: ["\u51FB\u8D25\u4E86", _jsxs(Typography, __assign({ variant: "body2", fontWeight: "medium", display: "inline", color: "#4caf50" }, { children: [rank.toFixed(2), "%"] })), "\u7684\u5019\u9009\u4EBA"] })))] })), _jsx(Typography, __assign({ mt: 1, mb: 2, variant: "body2", fontWeight: "medium", color: "success" }, { children: v.impressions.join('、') }))] })), _jsx(Divider, {}), _jsxs(Stack, __assign({ px: 2 }, { children: [((_a = v.items) === null || _a === void 0 ? void 0 : _a.length) > 0 && (_jsx(Box, __assign({ mt: 2 }, { children: _jsx(Graph, { items: v.items }) }))), _jsxs(Stack, __assign({ spacing: 2, mt: 2 }, { children: [_jsx(Evaluate, { canEdit: canEditAiDimension, token: v.evaluationToken, evaluations: v.evaluations, title: "\u8BC4\u4EF7\u5185\u5BB9", field: "evaluations", mode: "show" }), _jsx(Evaluate, { canEdit: canEditAiDimension, token: v.evaluationToken, evaluations: v.suggestions, title: "\u63D0\u9AD8\u5EFA\u8BAE", field: "suggestions", mode: "show" })] }))] }))] }), v.evaluationToken));
32
+ }), _jsxs(Stack, __assign({ spacing: 1, mt: 4 }, { children: [_jsx(Typography, __assign({ variant: "body2", fontWeight: "medium", color: "textSecondary" }, { children: "\u7ED3\u679C\u8BF4\u660E" })), _jsxs(Typography, __assign({ variant: "caption", color: "disabled" }, { children: ["AI\u7EF4\u5EA6\u8868\u73B0\u4ECE\u8BED\u901F\u3001\u666E\u901A\u8BDD\u3001\u8BED\u8A00\u6D41\u7545\u5EA6\u3001\u8981\u70B9\u5206\u6790\u5339\u914D\u5EA6\u3001\u8BED\u8A00\u4E30\u5BCC\u5EA6\u3001\u5F62\u8C61\u516D\u4E2A\u7EF4\u5EA6\u5BF9\u5019\u9009\u4EBA\u5728\u9762\u8BD5\u4E2D\u7684\u56DE\u7B54\u8868\u73B0\u8FDB\u884C\u8BC4\u4EF7\uFF0C\u6BCF\u4E2A\u7EF4\u5EA6\u5206\u4E3A\u4E09\u4E2A\u6863\uFF0C\u5206\u522B\u4E3A\uFF1A\u524D30%\u4EE3\u8868\u4F18\u79C0\u3001\u4E2D\u95F430%~70%\u4EE3\u8868\u9002\u4E2D\u3001\u540E30%\u4EE3\u8868\u6B20\u4F73\u3002", _jsx("br", {}), "\u6BCF\u4E2A\u80FD\u529B\u7684\u4E09\u6863\u7684\u5206\u6570\u503C\u4F9D\u636E\u5168\u56FD\u5927\u6570\u636E\u7EDF\u8BA1\u800C\u5B9A\u3002\u6839\u636E\u5019\u9009\u4EBA\u5F53\u524DAI\u89C6\u9891\u6B65\u9AA4\u4E0B\u7684\u6BCF\u4E2A\u80FD\u529B\u7684\u5E73\u5747\u5206\u6765\u786E\u5B9A\u6BCF\u4E2A\u80FD\u529B\u7684\u8BC4\u4EF7\u3002\u76F8\u540C\u7684\u5F97\u5206\uFF0C\u6210\u7EE9\u5148\u51FA\u7684\u6392\u540D\u9760\u524D\u3002"] }))] }))] })), _jsx(Box, __assign({ display: "flex", justifyContent: "flex-end", alignItems: "center", mt: 1, mb: 2 }, { children: _jsx(Link, { href: "#", onClick: handleExpandChange, text: expand ? '收起' : '查看详情' }) }))] })));
33
+ };
34
+ export default Index;
@@ -46,7 +46,7 @@ export declare const StyledSlider: import("@emotion/styled").StyledComponent<{
46
46
  name?: string | undefined;
47
47
  onChange?: ((event: Event, value: number | number[], activeThumb: number) => void) | undefined;
48
48
  onChangeCommitted?: ((event: Event | import("react").SyntheticEvent<Element, Event>, value: number | number[]) => void) | undefined;
49
- orientation?: "vertical" | "horizontal" | undefined;
49
+ orientation?: "horizontal" | "vertical" | undefined;
50
50
  scale?: ((value: number) => number) | undefined;
51
51
  step?: number | null | undefined;
52
52
  tabIndex?: number | undefined;
@@ -10,9 +10,9 @@ var __assign = (this && this.__assign) || function () {
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
12
  import { jsx as _jsx } from "react/jsx-runtime";
13
- import { forwardRef, memo } from 'react';
14
- import RootProvider from "../../components/RootProvider";
15
13
  import ReportRoot from './Root';
14
+ import RootProvider from "../../components/RootProvider";
15
+ import { forwardRef, memo } from 'react';
16
16
  var AiReport = forwardRef(function (props, ref) {
17
17
  return (_jsx(RootProvider, { children: _jsx(ReportRoot, __assign({ ref: ref }, props)) }));
18
18
  });
@@ -76,6 +76,7 @@ export interface AiInterviewReportList {
76
76
  collection: Collection[];
77
77
  faceUrl: string;
78
78
  faceAnalysis: FaceAnalysis;
79
+ evaluations: Array<any>;
79
80
  score: number;
80
81
  status: number;
81
82
  completedStatus: number;
@@ -109,6 +110,8 @@ export interface AiReportProps {
109
110
  disabledScore?: boolean;
110
111
  reminderSent?: boolean;
111
112
  showAbilitiesDetails?: boolean;
113
+ showAiDimension?: boolean;
114
+ canEditAiDimension?: boolean;
112
115
  operableButtons?: Array<'export' | 'refresh' | 'scoreRank' | 'abilities' | 'sendReminder'>;
113
116
  stepToken?: string;
114
117
  interviewCheat?: InterviewCheat;
@@ -7,6 +7,8 @@ export declare const useAiReport: (props: AiReportProps) => {
7
7
  disabledScore?: boolean | undefined;
8
8
  reminderSent?: boolean | undefined;
9
9
  showAbilitiesDetails?: boolean | undefined;
10
+ showAiDimension?: boolean | undefined;
11
+ canEditAiDimension?: boolean | undefined;
10
12
  operableButtons?: ("export" | "refresh" | "scoreRank" | "abilities" | "sendReminder")[] | undefined;
11
13
  stepToken?: string | undefined;
12
14
  interviewCheat?: import("./interface").InterviewCheat | undefined;
@@ -1,2 +1,9 @@
1
1
  export declare const PostAiInterviewResult: <R>(orderTokens: string[]) => import("axios").AxiosPromise<R>;
2
2
  export declare const PostAiInterviewRefresh: <R>(orderID: string) => import("axios").AxiosPromise<R>;
3
+ interface PostAiInterviewEvaluationData {
4
+ evaluationToken: string;
5
+ manualEvaluations?: Array<string>;
6
+ manualSuggestions?: Array<string>;
7
+ }
8
+ export declare const PostAiInterviewEvaluation: <R>(data: PostAiInterviewEvaluationData) => import("axios").AxiosPromise<R>;
9
+ export {};
@@ -3,3 +3,7 @@ import { POST } from "../utils/request";
3
3
  export var PostAiInterviewResult = function (orderTokens) { return POST({ url: "/standard/b/aiInterview/result", data: { orderTokens: orderTokens } }); };
4
4
  // 刷新ai评分
5
5
  export var PostAiInterviewRefresh = function (orderID) { return POST({ url: "/standard/b/aiInterview/aiScore/refresh/single", data: { orderID: orderID } }); };
6
+ // 更新评价
7
+ export var PostAiInterviewEvaluation = function (data) {
8
+ return POST({ url: "/standard/b/aiInterview/aiEvaluation/modify", data: data });
9
+ };
@@ -9,6 +9,8 @@ export declare const useAiReportStore: (depsFn?: import("hox/es/types").DepsFn<{
9
9
  disabledScore?: boolean | undefined;
10
10
  reminderSent?: boolean | undefined;
11
11
  showAbilitiesDetails?: boolean | undefined;
12
+ showAiDimension?: boolean | undefined;
13
+ canEditAiDimension?: boolean | undefined;
12
14
  operableButtons?: ("export" | "refresh" | "scoreRank" | "abilities" | "sendReminder")[] | undefined;
13
15
  stepToken?: string | undefined;
14
16
  interviewCheat?: import("@/modules/ai-report/interface").InterviewCheat | undefined;
@@ -28,6 +30,8 @@ export declare const useAiReportStore: (depsFn?: import("hox/es/types").DepsFn<{
28
30
  disabledScore?: boolean | undefined;
29
31
  reminderSent?: boolean | undefined;
30
32
  showAbilitiesDetails?: boolean | undefined;
33
+ showAiDimension?: boolean | undefined;
34
+ canEditAiDimension?: boolean | undefined;
31
35
  operableButtons?: ("export" | "refresh" | "scoreRank" | "abilities" | "sendReminder")[] | undefined;
32
36
  stepToken?: string | undefined;
33
37
  interviewCheat?: import("@/modules/ai-report/interface").InterviewCheat | undefined;
@@ -47,6 +51,8 @@ export declare const useAiReportStore: (depsFn?: import("hox/es/types").DepsFn<{
47
51
  disabledScore?: boolean | undefined;
48
52
  reminderSent?: boolean | undefined;
49
53
  showAbilitiesDetails?: boolean | undefined;
54
+ showAiDimension?: boolean | undefined;
55
+ canEditAiDimension?: boolean | undefined;
50
56
  operableButtons?: ("export" | "refresh" | "scoreRank" | "abilities" | "sendReminder")[] | undefined;
51
57
  stepToken?: string | undefined;
52
58
  interviewCheat?: import("@/modules/ai-report/interface").InterviewCheat | undefined;
@@ -10,14 +10,16 @@ var __assign = (this && this.__assign) || function () {
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
12
  var _a;
13
- import { useState } from 'react';
14
13
  import { useSetState } from 'ahooks';
15
14
  import { createGlobalStore } from 'hox';
15
+ import { useState } from 'react';
16
16
  export var useAiReportStore = (_a = createGlobalStore(function () {
17
17
  var _a = useSetState({
18
18
  token: '',
19
19
  stepToken: '',
20
20
  disabledScore: true,
21
+ showAiDimension: true,
22
+ canEditAiDimension: true,
21
23
  scoreRankIntervals: [],
22
24
  operableButtons: [],
23
25
  }), state = _a[0], updateState = _a[1];
@@ -1,4 +1,4 @@
1
- import React from 'react';
2
1
  import { AiReportProps } from './interface';
2
+ import React from 'react';
3
3
  declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<AiReportProps & React.RefAttributes<any>>>;
4
4
  export default _default;
@@ -15,21 +15,22 @@ 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 react_1 = require("react");
19
- var fbm_ui_1 = require("fbm-ui");
20
- var ahooks_1 = require("ahooks");
21
- var global_store_1 = require("../../store/ai-report/global-store");
22
- var ai_report_1 = require("../../services/ai-report");
23
- var ai_report_2 = require("../../enum/ai-report");
18
+ var AIEvaluate_1 = __importDefault(require("./components/AIEvaluate"));
19
+ var NotFinish_1 = __importDefault(require("./components/NotFinish"));
24
20
  var ScoreReport_1 = __importDefault(require("./components/ScoreReport"));
25
21
  var VideoQuestion_1 = __importDefault(require("./components/VideoQuestion"));
26
- var NotFinish_1 = __importDefault(require("./components/NotFinish"));
27
- var NO_ANSWER = ai_report_2.INTERVIEW_STATUS.NO_ANSWER;
22
+ var ai_report_1 = require("../../enum/ai-report");
23
+ var ai_report_2 = require("../../services/ai-report");
24
+ var global_store_1 = require("../../store/ai-report/global-store");
25
+ var ahooks_1 = require("ahooks");
26
+ var fbm_ui_1 = require("fbm-ui");
27
+ var react_1 = require("react");
28
+ var NO_ANSWER = ai_report_1.INTERVIEW_STATUS.NO_ANSWER;
28
29
  var AiReportRoot = (0, react_1.forwardRef)(function (props, ref) {
29
30
  var token = props.token, reminderSent = props.reminderSent, operableButtons = props.operableButtons, onLoad = props.onLoad, onSendReminderClick = props.onSendReminderClick;
30
31
  var firstLoad = (0, react_1.useRef)(true);
31
32
  var _a = (0, global_store_1.useAiReportStore)(), updateState = _a.updateState, updateReportResult = _a.updateReportResult;
32
- var _b = (0, ahooks_1.useRequest)(function () { return (0, ai_report_1.PostAiInterviewResult)([token]); }, {
33
+ var _b = (0, ahooks_1.useRequest)(function () { return (0, ai_report_2.PostAiInterviewResult)([token]); }, {
33
34
  manual: true,
34
35
  onSuccess: function (_a) {
35
36
  var list = _a.data.list;
@@ -69,7 +70,7 @@ var AiReportRoot = (0, react_1.forwardRef)(function (props, ref) {
69
70
  return ((0, jsx_runtime_1.jsxs)(fbm_ui_1.Box, __assign({ width: "100%", display: "flex", alignItems: "center", justifyContent: "center", flexDirection: "column", style: { marginTop: '149px' } }, { children: [(0, jsx_runtime_1.jsx)(fbm_ui_1.Box, { children: (0, jsx_runtime_1.jsx)("img", { src: "//webcdn.fbmms.cn/web/saas/asset/image/CandidateInfoEmpty.png", alt: "", style: { width: '140px', height: '140px' } }) }), (0, jsx_runtime_1.jsx)(fbm_ui_1.Box, __assign({ mt: 2 }, { children: (0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "body1", color: "textPrimary", style: { fontWeight: '500' } }, { children: "\u8BE5\u5019\u9009\u4EBA\u5C1A\u672A\u5F00\u59CB\u9762\u8BD5" })) })), (operableButtons === null || operableButtons === void 0 ? void 0 : operableButtons.includes('sendReminder')) && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(fbm_ui_1.Box, __assign({ style: { marginTop: '2px' } }, { children: (0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "body2", color: "textSecondary" }, { children: "\u82E5\u957F\u65F6\u95F4\u672A\u5F00\u59CB\uFF0C\u5EFA\u8BAE\u4F60\u7ED9\u5019\u9009\u4EBA\u53D1\u9001\u77ED\u4FE1\u63D0\u9192" })) })), (0, jsx_runtime_1.jsx)(fbm_ui_1.Box, __assign({ mt: 2 }, { children: (0, jsx_runtime_1.jsx)(fbm_ui_1.Button, __assign({ size: "large", variant: "outlined", color: "primary", disabled: reminderSent, onClick: onSendReminderClick }, { children: reminderSent ? '已提醒' : '发送提醒' })) }))] }))] })));
70
71
  }
71
72
  else {
72
- return ((0, jsx_runtime_1.jsxs)(fbm_ui_1.Box, { children: [(0, jsx_runtime_1.jsx)(NotFinish_1.default, {}), (0, jsx_runtime_1.jsx)(ScoreReport_1.default, { onRefreshSuccess: handleRefreshSuccess }), (0, jsx_runtime_1.jsx)(VideoQuestion_1.default, {})] }));
73
+ return ((0, jsx_runtime_1.jsxs)(fbm_ui_1.Box, { children: [(0, jsx_runtime_1.jsx)(NotFinish_1.default, {}), (0, jsx_runtime_1.jsx)(ScoreReport_1.default, { onRefreshSuccess: handleRefreshSuccess }), (0, jsx_runtime_1.jsx)(AIEvaluate_1.default, {}), (0, jsx_runtime_1.jsx)(VideoQuestion_1.default, {})] }));
73
74
  }
74
75
  }, [handleRefreshSuccess, onSendReminderClick, reminderSent, status, operableButtons]);
75
76
  return ((0, jsx_runtime_1.jsx)(fbm_ui_1.Box, __assign({ loading: firstLoad.current && loading, sx: { width: '100%', minHeight: '584px', height: '100%', margin: '0 auto', overflow: 'auto' } }, { children: aiReportResult })));
@@ -0,0 +1,13 @@
1
+ /// <reference types="react" />
2
+ declare type Mode = 'edit' | 'show';
3
+ declare type Field = 'evaluations' | 'suggestions';
4
+ interface EvaluateProps {
5
+ title: string;
6
+ token: string;
7
+ field: Field;
8
+ evaluations: Array<string>;
9
+ mode?: Mode;
10
+ canEdit?: boolean;
11
+ }
12
+ declare const Evaluate: React.FC<EvaluateProps>;
13
+ export default Evaluate;
@@ -0,0 +1,47 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ var jsx_runtime_1 = require("react/jsx-runtime");
15
+ var ai_report_1 = require("../../../../services/ai-report");
16
+ var fbm_ui_1 = require("fbm-ui");
17
+ var mui_1 = require("fbm-ui/lib/mui");
18
+ var react_1 = require("react");
19
+ var Evaluate = function (_a) {
20
+ var title = _a.title, evaluations = _a.evaluations, token = _a.token, field = _a.field, _b = _a.mode, mode = _b === void 0 ? 'show' : _b, _c = _a.canEdit, canEdit = _c === void 0 ? 'true' : _c;
21
+ var _d = (0, react_1.useState)(evaluations === null || evaluations === void 0 ? void 0 : evaluations.join('\n')), content = _d[0], setContent = _d[1];
22
+ var _e = (0, react_1.useState)('show'), internalMode = _e[0], setInternalMode = _e[1];
23
+ var handleChange = (0, react_1.useCallback)(function (e) {
24
+ var value = e.target.value;
25
+ setContent(value);
26
+ }, []);
27
+ var handleModeChange = (0, react_1.useCallback)(function () {
28
+ setInternalMode(internalMode === 'show' ? 'edit' : 'show');
29
+ }, [internalMode]);
30
+ var handleSubmit = (0, react_1.useCallback)(function () {
31
+ var data = field === 'evaluations'
32
+ ? {
33
+ evaluationToken: token,
34
+ manualEvaluations: [content],
35
+ }
36
+ : {
37
+ evaluationToken: token,
38
+ manualSuggestions: [content],
39
+ };
40
+ (0, ai_report_1.PostAiInterviewEvaluation)(data).then(handleModeChange).catch(console.log);
41
+ }, [token, content, field, handleModeChange]);
42
+ (0, react_1.useEffect)(function () {
43
+ setInternalMode(mode);
44
+ }, [mode]);
45
+ return ((0, jsx_runtime_1.jsxs)(mui_1.Stack, { children: [(0, jsx_runtime_1.jsxs)(mui_1.Stack, __assign({ direction: "row", alignItems: "center", justifyContent: "space-between" }, { children: [(0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "body2", fontWeight: "medium" }, { children: title })), canEdit && ((0, jsx_runtime_1.jsx)(fbm_ui_1.IconButton, __assign({ onClick: handleModeChange }, { children: (0, jsx_runtime_1.jsx)(fbm_ui_1.EditIcon, {}) })))] })), internalMode === 'edit' && ((0, jsx_runtime_1.jsxs)(mui_1.Box, __assign({ width: 1, position: "relative" }, { children: [(0, jsx_runtime_1.jsx)(mui_1.TextField, { fullWidth: true, value: content, onChange: handleChange, rows: 3.5, multiline: true }), (0, jsx_runtime_1.jsxs)(mui_1.Stack, __assign({ p: 1, spacing: 1, direction: "row", position: "absolute", bottom: 0, right: 0 }, { children: [(0, jsx_runtime_1.jsx)(fbm_ui_1.Button, __assign({ size: "small", color: "inherit", onClick: handleModeChange }, { children: "\u53D6\u6D88" })), (0, jsx_runtime_1.jsx)(fbm_ui_1.Button, __assign({ size: "small", onClick: handleSubmit }, { children: "\u4FDD\u5B58" }))] }))] }))), internalMode === 'show' && ((0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "body2", color: "textSecondary", sx: { whiteSpace: 'pre-wrap' } }, { children: content })))] }));
46
+ };
47
+ exports.default = Evaluate;
@@ -0,0 +1,12 @@
1
+ /// <reference types="react" />
2
+ interface Dimension {
3
+ name: string;
4
+ score: number;
5
+ rank: number;
6
+ total: number;
7
+ }
8
+ interface GraphProps {
9
+ items: Array<Dimension>;
10
+ }
11
+ declare const Graph: React.FC<GraphProps>;
12
+ export default Graph;
@@ -0,0 +1,197 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var jsx_runtime_1 = require("react/jsx-runtime");
4
+ var react_1 = require("react");
5
+ function setupCanvas(canvas) {
6
+ // Get the device pixel ratio, falling back to 1.
7
+ var dpr = window.devicePixelRatio || 1;
8
+ // Get the size of the canvas in CSS pixels.
9
+ var rect = canvas.getBoundingClientRect();
10
+ // Give the canvas pixel dimensions of their CSS
11
+ // size * the device pixel ratio.
12
+ canvas.width = rect.width * dpr;
13
+ canvas.height = rect.height * dpr;
14
+ var ctx = canvas.getContext('2d');
15
+ // Scale all drawing operations by the dpr, so you
16
+ // don't have to worry about the difference.
17
+ ctx.scale(dpr, dpr);
18
+ return ctx;
19
+ }
20
+ var levelOrder = ['Bad', 'Good', 'Best'];
21
+ var levelConf = {
22
+ Bad: {
23
+ label: '欠佳',
24
+ width: 134,
25
+ color: [229, 115, 115],
26
+ endScore: 30,
27
+ pointColor: ['RGB(229, 115, 115)', 'RGB(255, 67, 102)'],
28
+ },
29
+ Good: {
30
+ label: '适中',
31
+ width: 171,
32
+ color: [255, 183, 77],
33
+ endScore: 70,
34
+ pointColor: ['RGB(255, 183, 77)', 'RGB(255, 152, 0)'],
35
+ },
36
+ Best: {
37
+ label: '优秀',
38
+ width: 134,
39
+ color: [0, 217, 157],
40
+ endScore: 100,
41
+ pointColor: ['RGB(0, 217, 157)', 'RGB(0, 176, 127)'],
42
+ },
43
+ };
44
+ var tipEl = document.createElement('div');
45
+ var measureTextWidth = function (ctx, text) {
46
+ var width = ctx.measureText(text).width;
47
+ return width;
48
+ };
49
+ function isInPath(x, y, tx, ty, ctx) {
50
+ ctx.beginPath();
51
+ ctx.arc(tx / 2, ty / 2, 10 / 2, 0, Math.PI * 2, true);
52
+ var ret = ctx.isPointInPath(x, y);
53
+ ctx.closePath();
54
+ return ret;
55
+ }
56
+ var drawTop = function (layout, ctx) {
57
+ ctx.font = '12px sans-serif';
58
+ ctx.fillText('排名(%)', 10, 10);
59
+ ctx.fillStyle = '#ccc';
60
+ ctx.fillText('0', layout.leftLableWidth, 10);
61
+ ctx.strokeStyle = '#ccc';
62
+ var offset = 0;
63
+ levelOrder.forEach(function (x) {
64
+ var c = levelConf[x];
65
+ var labelWidth = measureTextWidth(ctx, c.label);
66
+ var endScoreWidth = measureTextWidth(ctx, c.endScore);
67
+ ctx.moveTo(layout.leftLableWidth + offset + endScoreWidth / 2 + 5, 6);
68
+ ctx.lineTo(layout.leftLableWidth + offset + c.width / 2 - labelWidth / 2 - 5, 6);
69
+ ctx.fillStyle = 'black';
70
+ ctx.fillText(c.label, layout.leftLableWidth + offset + c.width / 2 - labelWidth / 2, 10);
71
+ ctx.moveTo(layout.leftLableWidth + offset + c.width / 2 + labelWidth / 2 + 5, 6);
72
+ ctx.lineTo(layout.leftLableWidth + offset + c.width - endScoreWidth - 5, 6);
73
+ ctx.fillStyle = '#ccc';
74
+ ctx.fillText(c.endScore, layout.leftLableWidth + offset + c.width - endScoreWidth, 10);
75
+ ctx.stroke();
76
+ offset += c.width;
77
+ });
78
+ };
79
+ var drowBackground = function (layout, ctx) {
80
+ var leftOffset = layout.leftLableWidth;
81
+ levelOrder.forEach(function (x) {
82
+ var c = levelConf[x];
83
+ ctx.fillStyle = "rgb(".concat(c.color.join(','), ")");
84
+ ctx.fillRect(0 + leftOffset, layout.topLableHeight, c.width, 4);
85
+ var linearGradient0 = ctx.createLinearGradient(0, 0, 0, layout.height - layout.topLableHeight);
86
+ linearGradient0.addColorStop(0, "RGBA(".concat(c.color.join(','), ", 0.3)"));
87
+ linearGradient0.addColorStop(1, "RGBA(".concat(c.color.join(','), ", 0.05)"));
88
+ ctx.fillStyle = linearGradient0;
89
+ ctx.fillRect(0 + leftOffset, layout.topLableHeight, c.width, layout.height - layout.topLableHeight);
90
+ leftOffset += c.width + 4;
91
+ });
92
+ };
93
+ var percent = function (_a) {
94
+ var rank = _a.rank, total = _a.total;
95
+ return Math.min(0.975, parseFloat((1 - (rank - 1) / total).toFixed(2)));
96
+ };
97
+ var getPointColor = function (s) {
98
+ var conf = Object.entries(levelConf);
99
+ for (var _i = 0, conf_1 = conf; _i < conf_1.length; _i++) {
100
+ var _a = conf_1[_i], v = _a[1];
101
+ if (v.endScore >= s * 100)
102
+ return v.pointColor;
103
+ }
104
+ return [];
105
+ };
106
+ var drawLable = function (lable, x, y, ctx) {
107
+ ctx.fillStyle = 'black';
108
+ ctx.fillText(lable, x, y + 5);
109
+ ctx.strokeStyle = '#ccc';
110
+ };
111
+ var drawLine = function (sx, ex, ey, ctx) {
112
+ ctx.beginPath();
113
+ ctx.setLineDash([2, 1]);
114
+ ctx.moveTo(sx, ey);
115
+ ctx.lineTo(ex, ey);
116
+ ctx.stroke();
117
+ };
118
+ var drawPoint = function (fill, stroke, x, y, ctx) {
119
+ ctx.fillStyle = fill;
120
+ ctx.strokeStyle = stroke;
121
+ ctx.lineWidth = 1;
122
+ ctx.beginPath();
123
+ ctx.arc(x, y, 4, 0, Math.PI * 2, true);
124
+ ctx.closePath();
125
+ ctx.fill();
126
+ ctx.stroke();
127
+ };
128
+ var draw = function (layout, color, dimensions, pathRef, ctx) {
129
+ drawTop(layout, ctx);
130
+ drowBackground(layout, ctx);
131
+ var maxWidth = 439;
132
+ dimensions.forEach(function (v, i) {
133
+ var p = percent(v);
134
+ var target = maxWidth * p + 4;
135
+ var endPointX = target + layout.leftLableWidth;
136
+ var endPointY = 65 + layout.itemSpacing * i;
137
+ drawLable(v.name, 10, endPointY, ctx);
138
+ drawLine(layout.leftLableWidth, endPointX, endPointY, ctx);
139
+ var _a = getPointColor(p), fill = _a[0], stroke = _a[1];
140
+ drawPoint(fill, stroke, endPointX, endPointY, ctx);
141
+ pathRef.push({ x: endPointX, y: endPointY, tips: "".concat(v === null || v === void 0 ? void 0 : v.name, "\u5F97\u5206:").concat(v === null || v === void 0 ? void 0 : v.score, "\u5206") });
142
+ });
143
+ };
144
+ var Graph = function (_a) {
145
+ var _b = _a.items, items = _b === void 0 ? [] : _b;
146
+ var ref = (0, react_1.useRef)(null);
147
+ var pathRef = (0, react_1.useRef)([]);
148
+ var _c = (0, react_1.useState)(), ctx = _c[0], setCtx = _c[1];
149
+ (0, react_1.useEffect)(function () {
150
+ var currentCtx = setupCanvas(ref.current);
151
+ setCtx(currentCtx);
152
+ tipEl.style.background = 'rgba(0,0,0,.7)';
153
+ tipEl.style.color = '#fff';
154
+ tipEl.style.borderRadius = '2px';
155
+ tipEl.style.padding = '2px 5px';
156
+ tipEl.style.position = 'absolute';
157
+ tipEl.style.zIndex = '999';
158
+ tipEl.style.fontSize = '12px';
159
+ tipEl.style.display = 'none';
160
+ document.body.appendChild(tipEl);
161
+ }, [ref]);
162
+ (0, react_1.useEffect)(function () {
163
+ if (ctx) {
164
+ var layout = {
165
+ leftLableWidth: 80,
166
+ topLableHeight: 40,
167
+ itemSpacing: 32,
168
+ height: 32 * items.length + 40 + 16,
169
+ };
170
+ var gradeColor = {
171
+ Bad: [229, 115, 115],
172
+ Good: [255, 183, 77],
173
+ Best: [0, 217, 157],
174
+ };
175
+ draw(layout, gradeColor, items, pathRef.current, ctx);
176
+ }
177
+ }, [ctx, items]);
178
+ (0, react_1.useEffect)(function () {
179
+ console.log(pathRef);
180
+ }, [pathRef]);
181
+ var handleMouseMove = (0, react_1.useCallback)(function (e) {
182
+ if (ctx) {
183
+ var p = pathRef.current.find(function (p) { return isInPath(e.nativeEvent.offsetX, e.nativeEvent.offsetY, p.x, p.y, ctx); });
184
+ if (p) {
185
+ tipEl.style.left = e.pageX + 10 + 'px';
186
+ tipEl.style.top = e.pageY + 10 + 'px';
187
+ tipEl.innerHTML = p.tips;
188
+ tipEl.style.display = 'block';
189
+ }
190
+ else {
191
+ tipEl.style.display = 'none';
192
+ }
193
+ }
194
+ }, [ctx, pathRef]);
195
+ return ((0, jsx_runtime_1.jsx)("canvas", { ref: ref, onMouseOut: function () { return (tipEl.style.display = 'none'); }, onMouseMove: handleMouseMove, style: { width: '100%', height: 32 * items.length + 40 + 16 } }));
196
+ };
197
+ exports.default = Graph;
@@ -0,0 +1,2 @@
1
+ declare const Index: () => JSX.Element | null;
2
+ export default Index;
@@ -0,0 +1,39 @@
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 __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ var jsx_runtime_1 = require("react/jsx-runtime");
18
+ var Evaluate_1 = __importDefault(require("./Evaluate"));
19
+ var Graph_1 = __importDefault(require("./Graph"));
20
+ var global_store_1 = require("../../../../store/ai-report/global-store");
21
+ var fbm_ui_1 = require("fbm-ui");
22
+ var mui_1 = require("fbm-ui/lib/mui");
23
+ var react_1 = require("react");
24
+ var Index = function () {
25
+ var _a;
26
+ var _b = (0, global_store_1.useAiReportStore)(function (store) { return [store.reportResult, store.operableButtons]; }), reportResult = _b.reportResult, showAiDimension = _b.showAiDimension, canEditAiDimension = _b.canEditAiDimension;
27
+ var _c = (0, react_1.useState)(false), expand = _c[0], setExpand = _c[1];
28
+ var handleExpandChange = (0, react_1.useCallback)(function () {
29
+ setExpand(!expand);
30
+ }, [expand]);
31
+ if (!showAiDimension)
32
+ return null;
33
+ return ((0, jsx_runtime_1.jsxs)(mui_1.Box, __assign({ component: mui_1.Paper, variant: "outlined", px: 2, mt: 2 }, { children: [(0, jsx_runtime_1.jsxs)(mui_1.Stack, __assign({ direction: "row", height: 56, alignItems: "center", spacing: 1 }, { children: [(0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "body1", fontWeight: "medium" }, { children: "AI\u7EF4\u5EA6\u8868\u73B0" })), (0, jsx_runtime_1.jsx)(fbm_ui_1.InfoOutlineIcon, { sx: { fontSize: '16px' } })] })), (0, jsx_runtime_1.jsxs)(mui_1.Collapse, __assign({ in: expand }, { children: [(_a = reportResult === null || reportResult === void 0 ? void 0 : reportResult.evaluations) === null || _a === void 0 ? void 0 : _a.map(function (v) {
34
+ var _a;
35
+ var rank = (1 - (v.rank - 1) / v.total) * 100;
36
+ return ((0, jsx_runtime_1.jsxs)(mui_1.Box, __assign({ component: mui_1.Paper, elevation: 0, bgcolor: "#f9f9f9", mb: 2, pb: 2 }, { children: [(0, jsx_runtime_1.jsxs)(mui_1.Stack, __assign({ px: 2, pt: 2 }, { children: [(0, jsx_runtime_1.jsxs)(mui_1.Stack, __assign({ direction: "row", alignItems: "center", spacing: 2 }, { children: [(0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "h6" }, { children: v.evaluationDimensionName })), !isNaN(rank) && ((0, jsx_runtime_1.jsxs)(fbm_ui_1.Typography, __assign({ variant: "body2" }, { children: ["\u51FB\u8D25\u4E86", (0, jsx_runtime_1.jsxs)(fbm_ui_1.Typography, __assign({ variant: "body2", fontWeight: "medium", display: "inline", color: "#4caf50" }, { children: [rank.toFixed(2), "%"] })), "\u7684\u5019\u9009\u4EBA"] })))] })), (0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ mt: 1, mb: 2, variant: "body2", fontWeight: "medium", color: "success" }, { children: v.impressions.join('、') }))] })), (0, jsx_runtime_1.jsx)(fbm_ui_1.Divider, {}), (0, jsx_runtime_1.jsxs)(mui_1.Stack, __assign({ px: 2 }, { children: [((_a = v.items) === null || _a === void 0 ? void 0 : _a.length) > 0 && ((0, jsx_runtime_1.jsx)(mui_1.Box, __assign({ mt: 2 }, { children: (0, jsx_runtime_1.jsx)(Graph_1.default, { items: v.items }) }))), (0, jsx_runtime_1.jsxs)(mui_1.Stack, __assign({ spacing: 2, mt: 2 }, { children: [(0, jsx_runtime_1.jsx)(Evaluate_1.default, { canEdit: canEditAiDimension, token: v.evaluationToken, evaluations: v.evaluations, title: "\u8BC4\u4EF7\u5185\u5BB9", field: "evaluations", mode: "show" }), (0, jsx_runtime_1.jsx)(Evaluate_1.default, { canEdit: canEditAiDimension, token: v.evaluationToken, evaluations: v.suggestions, title: "\u63D0\u9AD8\u5EFA\u8BAE", field: "suggestions", mode: "show" })] }))] }))] }), v.evaluationToken));
37
+ }), (0, jsx_runtime_1.jsxs)(mui_1.Stack, __assign({ spacing: 1, mt: 4 }, { children: [(0, jsx_runtime_1.jsx)(fbm_ui_1.Typography, __assign({ variant: "body2", fontWeight: "medium", color: "textSecondary" }, { children: "\u7ED3\u679C\u8BF4\u660E" })), (0, jsx_runtime_1.jsxs)(fbm_ui_1.Typography, __assign({ variant: "caption", color: "disabled" }, { children: ["AI\u7EF4\u5EA6\u8868\u73B0\u4ECE\u8BED\u901F\u3001\u666E\u901A\u8BDD\u3001\u8BED\u8A00\u6D41\u7545\u5EA6\u3001\u8981\u70B9\u5206\u6790\u5339\u914D\u5EA6\u3001\u8BED\u8A00\u4E30\u5BCC\u5EA6\u3001\u5F62\u8C61\u516D\u4E2A\u7EF4\u5EA6\u5BF9\u5019\u9009\u4EBA\u5728\u9762\u8BD5\u4E2D\u7684\u56DE\u7B54\u8868\u73B0\u8FDB\u884C\u8BC4\u4EF7\uFF0C\u6BCF\u4E2A\u7EF4\u5EA6\u5206\u4E3A\u4E09\u4E2A\u6863\uFF0C\u5206\u522B\u4E3A\uFF1A\u524D30%\u4EE3\u8868\u4F18\u79C0\u3001\u4E2D\u95F430%~70%\u4EE3\u8868\u9002\u4E2D\u3001\u540E30%\u4EE3\u8868\u6B20\u4F73\u3002", (0, jsx_runtime_1.jsx)("br", {}), "\u6BCF\u4E2A\u80FD\u529B\u7684\u4E09\u6863\u7684\u5206\u6570\u503C\u4F9D\u636E\u5168\u56FD\u5927\u6570\u636E\u7EDF\u8BA1\u800C\u5B9A\u3002\u6839\u636E\u5019\u9009\u4EBA\u5F53\u524DAI\u89C6\u9891\u6B65\u9AA4\u4E0B\u7684\u6BCF\u4E2A\u80FD\u529B\u7684\u5E73\u5747\u5206\u6765\u786E\u5B9A\u6BCF\u4E2A\u80FD\u529B\u7684\u8BC4\u4EF7\u3002\u76F8\u540C\u7684\u5F97\u5206\uFF0C\u6210\u7EE9\u5148\u51FA\u7684\u6392\u540D\u9760\u524D\u3002"] }))] }))] })), (0, jsx_runtime_1.jsx)(mui_1.Box, __assign({ display: "flex", justifyContent: "flex-end", alignItems: "center", mt: 1, mb: 2 }, { children: (0, jsx_runtime_1.jsx)(fbm_ui_1.Link, { href: "#", onClick: handleExpandChange, text: expand ? '收起' : '查看详情' }) }))] })));
38
+ };
39
+ exports.default = Index;
@@ -46,7 +46,7 @@ export declare const StyledSlider: import("@emotion/styled").StyledComponent<{
46
46
  name?: string | undefined;
47
47
  onChange?: ((event: Event, value: number | number[], activeThumb: number) => void) | undefined;
48
48
  onChangeCommitted?: ((event: Event | import("react").SyntheticEvent<Element, Event>, value: number | number[]) => void) | undefined;
49
- orientation?: "vertical" | "horizontal" | undefined;
49
+ orientation?: "horizontal" | "vertical" | undefined;
50
50
  scale?: ((value: number) => number) | undefined;
51
51
  step?: number | null | undefined;
52
52
  tabIndex?: number | undefined;
@@ -15,9 +15,9 @@ 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 react_1 = require("react");
19
- var RootProvider_1 = __importDefault(require("../../components/RootProvider"));
20
18
  var Root_1 = __importDefault(require("./Root"));
19
+ var RootProvider_1 = __importDefault(require("../../components/RootProvider"));
20
+ var react_1 = require("react");
21
21
  var AiReport = (0, react_1.forwardRef)(function (props, ref) {
22
22
  return ((0, jsx_runtime_1.jsx)(RootProvider_1.default, { children: (0, jsx_runtime_1.jsx)(Root_1.default, __assign({ ref: ref }, props)) }));
23
23
  });
@@ -76,6 +76,7 @@ export interface AiInterviewReportList {
76
76
  collection: Collection[];
77
77
  faceUrl: string;
78
78
  faceAnalysis: FaceAnalysis;
79
+ evaluations: Array<any>;
79
80
  score: number;
80
81
  status: number;
81
82
  completedStatus: number;
@@ -109,6 +110,8 @@ export interface AiReportProps {
109
110
  disabledScore?: boolean;
110
111
  reminderSent?: boolean;
111
112
  showAbilitiesDetails?: boolean;
113
+ showAiDimension?: boolean;
114
+ canEditAiDimension?: boolean;
112
115
  operableButtons?: Array<'export' | 'refresh' | 'scoreRank' | 'abilities' | 'sendReminder'>;
113
116
  stepToken?: string;
114
117
  interviewCheat?: InterviewCheat;
@@ -7,6 +7,8 @@ export declare const useAiReport: (props: AiReportProps) => {
7
7
  disabledScore?: boolean | undefined;
8
8
  reminderSent?: boolean | undefined;
9
9
  showAbilitiesDetails?: boolean | undefined;
10
+ showAiDimension?: boolean | undefined;
11
+ canEditAiDimension?: boolean | undefined;
10
12
  operableButtons?: ("export" | "refresh" | "scoreRank" | "abilities" | "sendReminder")[] | undefined;
11
13
  stepToken?: string | undefined;
12
14
  interviewCheat?: import("./interface").InterviewCheat | undefined;
@@ -1,2 +1,9 @@
1
1
  export declare const PostAiInterviewResult: <R>(orderTokens: string[]) => import("axios").AxiosPromise<R>;
2
2
  export declare const PostAiInterviewRefresh: <R>(orderID: string) => import("axios").AxiosPromise<R>;
3
+ interface PostAiInterviewEvaluationData {
4
+ evaluationToken: string;
5
+ manualEvaluations?: Array<string>;
6
+ manualSuggestions?: Array<string>;
7
+ }
8
+ export declare const PostAiInterviewEvaluation: <R>(data: PostAiInterviewEvaluationData) => import("axios").AxiosPromise<R>;
9
+ export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PostAiInterviewRefresh = exports.PostAiInterviewResult = void 0;
3
+ exports.PostAiInterviewEvaluation = exports.PostAiInterviewRefresh = exports.PostAiInterviewResult = void 0;
4
4
  var request_1 = require("../utils/request");
5
5
  // 查询面试结果
6
6
  var PostAiInterviewResult = function (orderTokens) { return (0, request_1.POST)({ url: "/standard/b/aiInterview/result", data: { orderTokens: orderTokens } }); };
@@ -8,3 +8,8 @@ exports.PostAiInterviewResult = PostAiInterviewResult;
8
8
  // 刷新ai评分
9
9
  var PostAiInterviewRefresh = function (orderID) { return (0, request_1.POST)({ url: "/standard/b/aiInterview/aiScore/refresh/single", data: { orderID: orderID } }); };
10
10
  exports.PostAiInterviewRefresh = PostAiInterviewRefresh;
11
+ // 更新评价
12
+ var PostAiInterviewEvaluation = function (data) {
13
+ return (0, request_1.POST)({ url: "/standard/b/aiInterview/aiEvaluation/modify", data: data });
14
+ };
15
+ exports.PostAiInterviewEvaluation = PostAiInterviewEvaluation;
@@ -9,6 +9,8 @@ export declare const useAiReportStore: (depsFn?: import("hox/es/types").DepsFn<{
9
9
  disabledScore?: boolean | undefined;
10
10
  reminderSent?: boolean | undefined;
11
11
  showAbilitiesDetails?: boolean | undefined;
12
+ showAiDimension?: boolean | undefined;
13
+ canEditAiDimension?: boolean | undefined;
12
14
  operableButtons?: ("export" | "refresh" | "scoreRank" | "abilities" | "sendReminder")[] | undefined;
13
15
  stepToken?: string | undefined;
14
16
  interviewCheat?: import("@/modules/ai-report/interface").InterviewCheat | undefined;
@@ -28,6 +30,8 @@ export declare const useAiReportStore: (depsFn?: import("hox/es/types").DepsFn<{
28
30
  disabledScore?: boolean | undefined;
29
31
  reminderSent?: boolean | undefined;
30
32
  showAbilitiesDetails?: boolean | undefined;
33
+ showAiDimension?: boolean | undefined;
34
+ canEditAiDimension?: boolean | undefined;
31
35
  operableButtons?: ("export" | "refresh" | "scoreRank" | "abilities" | "sendReminder")[] | undefined;
32
36
  stepToken?: string | undefined;
33
37
  interviewCheat?: import("@/modules/ai-report/interface").InterviewCheat | undefined;
@@ -47,6 +51,8 @@ export declare const useAiReportStore: (depsFn?: import("hox/es/types").DepsFn<{
47
51
  disabledScore?: boolean | undefined;
48
52
  reminderSent?: boolean | undefined;
49
53
  showAbilitiesDetails?: boolean | undefined;
54
+ showAiDimension?: boolean | undefined;
55
+ canEditAiDimension?: boolean | undefined;
50
56
  operableButtons?: ("export" | "refresh" | "scoreRank" | "abilities" | "sendReminder")[] | undefined;
51
57
  stepToken?: string | undefined;
52
58
  interviewCheat?: import("@/modules/ai-report/interface").InterviewCheat | undefined;
@@ -13,14 +13,16 @@ var __assign = (this && this.__assign) || function () {
13
13
  var _a;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.getAiReportStore = exports.useAiReportStore = void 0;
16
- var react_1 = require("react");
17
16
  var ahooks_1 = require("ahooks");
18
17
  var hox_1 = require("hox");
18
+ var react_1 = require("react");
19
19
  exports.useAiReportStore = (_a = (0, hox_1.createGlobalStore)(function () {
20
20
  var _a = (0, ahooks_1.useSetState)({
21
21
  token: '',
22
22
  stepToken: '',
23
23
  disabledScore: true,
24
+ showAiDimension: true,
25
+ canEditAiDimension: true,
24
26
  scoreRankIntervals: [],
25
27
  operableButtons: [],
26
28
  }), state = _a[0], updateState = _a[1];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eli-video-interview",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "鳄梨科技 AI视频面试 React SDK",
5
5
  "author": "鳄梨科技",
6
6
  "license": "MIT",
@@ -55,5 +55,5 @@
55
55
  "type": "git",
56
56
  "url": "https://jihulab.com/elihr/elifront/open/lerna-avocado-sdk.git"
57
57
  },
58
- "gitHead": "a899beede4d71da37bfb3a4cb34bd745c4c29cef"
58
+ "gitHead": "be5d2221ff5dd71c14fcdf531474fdfa8d1030fd"
59
59
  }