|
|
@@ -1,7 +1,144 @@
|
|
|
import React from "react";
|
|
|
-import {Collapse, Divider, Progress} from "antd";
|
|
|
+import {Card, Collapse, Progress, Skeleton, Statistic} from "antd";
|
|
|
import axios from "axios";
|
|
|
import {BACKEND_URL} from "../config";
|
|
|
+import {Divider} from "antd/es";
|
|
|
+
|
|
|
+
|
|
|
+function showAnalysis(key, data) {
|
|
|
+
|
|
|
+ let table = {
|
|
|
+ elbow_right_angle: "右胳膊⻆度",
|
|
|
+ elbow_left_angle: "左胳膊⻆度",
|
|
|
+ hip_right_angle: "右侧躯⼲-臀-⼤腿⻆度",
|
|
|
+ hip_left_angle: "左侧躯⼲-臀-⼤腿⻆度",
|
|
|
+ knee_right_angle: "右膝盖⻆度",
|
|
|
+ knee_left_angle: "左膝盖⻆度",
|
|
|
+ ankle_right_angle: "右侧⼤脚趾-脚踝-⼩腿⻆度",
|
|
|
+ ankle_left_angle: "左侧⼤脚趾-脚踝-⼩腿⻆度",
|
|
|
+ ankle_small_right_angle: "右侧⼩脚趾-脚踝-⼩腿⻆度",
|
|
|
+ ankle_small_left_angle: "左侧⼩脚趾-脚踝-⼩腿⻆度",
|
|
|
+ neck_right_angle: "右侧胳膊-脖⼦-躯⼲⻆度",
|
|
|
+ neck_left_angle: "左侧胳膊-脖⼦-躯⼲⻆度",
|
|
|
+ should_right_angle: "右侧胳膊-肩膀-脖⼦⻆度",
|
|
|
+ should_left_angle: "左侧胳膊-肩膀-脖⼦⻆度",
|
|
|
+ neck_centre_angle: "左胳膊-脖⼦-右胳膊⻆度",
|
|
|
+ }
|
|
|
+
|
|
|
+ if (table[key] !== undefined) {
|
|
|
+ return <Statistic title={table[key]} value={data} />
|
|
|
+ } else {
|
|
|
+ return <></>
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function renderResult(x, data) {
|
|
|
+ if (data === undefined) {
|
|
|
+ return (
|
|
|
+ <Collapse.Panel header={"任务 ID: " + x} key={x}>
|
|
|
+ <Skeleton/>
|
|
|
+ </Collapse.Panel>
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ let progress = data.status === "FINISHED" ? 100 : data.progress
|
|
|
+ if (progress === undefined) {
|
|
|
+ progress = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ let progress_status
|
|
|
+ let progress_text = "队列中"
|
|
|
+ switch (data.status) {
|
|
|
+ case "ERROR":
|
|
|
+ progress_status = "exception"
|
|
|
+ progress_text = "运行出现未知错误, 请复制上方的任务 ID 向我们报告问题."
|
|
|
+ break
|
|
|
+ case "FINISHED":
|
|
|
+ progress_status = "success"
|
|
|
+ progress_text = "已完成"
|
|
|
+ break
|
|
|
+ case "RUNNING":
|
|
|
+ progress_status = "active"
|
|
|
+ progress_text = "分析中"
|
|
|
+ break
|
|
|
+ default:
|
|
|
+ progress_status = "active"
|
|
|
+ }
|
|
|
+
|
|
|
+ let result = data.result
|
|
|
+ let video_element = <></>
|
|
|
+
|
|
|
+ let advice = ""
|
|
|
+ let analysis = []
|
|
|
+
|
|
|
+ let advice_element = <></>
|
|
|
+
|
|
|
+ if (result !== undefined) {
|
|
|
+ if (result.file !== undefined) {
|
|
|
+ video_element = (
|
|
|
+ <Card type="inner" title="运动3D还原">
|
|
|
+ <video controls>
|
|
|
+ <source src={result.file}/>
|
|
|
+ </video>
|
|
|
+ </Card>
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ advice = result.advice
|
|
|
+
|
|
|
+ if (data.type === "PHOTO_STANDING") {
|
|
|
+ advice_element = advice['front'].filter(x => typeof x === 'string').concat(advice['right'].filter(x => typeof x === 'string')).map(x => <>{x}<br/></>)
|
|
|
+ } else {
|
|
|
+ advice_element = <p>{advice}</p>
|
|
|
+ }
|
|
|
+
|
|
|
+ for (const key in result.data) {
|
|
|
+
|
|
|
+ analysis.push(<h3>关键动作: {key}</h3>)
|
|
|
+
|
|
|
+ analysis.push(result.data[key]['file'] !== undefined && <><img src={result.data[key]['file']} alt="动作图片"/><br/></>)
|
|
|
+ analysis.push(result.data[key]['score'] !== undefined && <><Progress type="circle" percent={result.data[key]['score']} format={percent => `${percent} 分`} strokeColor={{
|
|
|
+ '0%': '#108ee9',
|
|
|
+ '100%': '#87d068',
|
|
|
+ }} /><br/></>)
|
|
|
+
|
|
|
+
|
|
|
+ for (const k in result.data[key]) {
|
|
|
+ analysis.push(showAnalysis(k, result.data[key][k]))
|
|
|
+ }
|
|
|
+
|
|
|
+ analysis.push(<Divider/>)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Collapse.Panel header={"任务 ID: " + x} key={x}>
|
|
|
+
|
|
|
+ <Card type="inner" title="分析进度">
|
|
|
+ <p>状态: {progress_text}</p>
|
|
|
+ <p><Progress style={{width: "50%"}} percent={progress} status={progress_status}/></p>
|
|
|
+ </Card>
|
|
|
+
|
|
|
+ {
|
|
|
+ progress_status === "success" && (
|
|
|
+ <>
|
|
|
+ {video_element}
|
|
|
+
|
|
|
+ <Card type="inner" title="分析建议">
|
|
|
+ {advice_element}
|
|
|
+ </Card>
|
|
|
+
|
|
|
+ <Card type="inner" title="详细数据">
|
|
|
+ {analysis}
|
|
|
+ </Card>
|
|
|
+ </>
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ </Collapse.Panel>
|
|
|
+ );
|
|
|
+}
|
|
|
|
|
|
|
|
|
class TaskList extends React.Component {
|
|
|
@@ -33,56 +170,7 @@ class TaskList extends React.Component {
|
|
|
<div>
|
|
|
<Collapse style={{height: "40%", width: "80%", margin: "0 auto", marginTop: 30}}>
|
|
|
{
|
|
|
- this.props.tasks.map(x => {
|
|
|
-
|
|
|
- let data = this.state.details[x]
|
|
|
- if (data === undefined) {
|
|
|
- return (
|
|
|
- <Collapse.Panel header={"任务 ID: " + x} key={x}>
|
|
|
- <p>状态: 获取中...</p>
|
|
|
- </Collapse.Panel>
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- let progress = data.status === "FINISHED" ? 100 : data.progress
|
|
|
- let result = data.result
|
|
|
- let advice = ""
|
|
|
- let analysis = []
|
|
|
-
|
|
|
- let video_element = <></>
|
|
|
-
|
|
|
- try {
|
|
|
- if (result.file !== undefined) {
|
|
|
- video_element = <p>视频结果: <video controls><source src={result.file}/></video></p>
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if (result !== undefined) {
|
|
|
- advice = result.advice
|
|
|
-
|
|
|
- for (const key in result.data) {
|
|
|
- analysis.push(result.data[key])
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return (
|
|
|
- <Collapse.Panel header={"任务 ID: " + x} key={x}>
|
|
|
- <p>状态: {data.status}</p>
|
|
|
- <p><Progress style={{width: "50%"}} percent={progress}
|
|
|
- status={data.status !== "ERROR" ? "active" : "exception"}/></p>
|
|
|
- <p>建议: {JSON.stringify(advice)}</p>
|
|
|
- {video_element}
|
|
|
- <p>分析数据: {
|
|
|
- analysis.map(x => (<p>
|
|
|
- <p>{Object.keys(x).map(key => <>{key + ": " + x[key]}<br/></>)}</p>
|
|
|
- <img src={x['file']}></img>
|
|
|
- </p>))
|
|
|
- }</p>
|
|
|
- </Collapse.Panel>
|
|
|
- );
|
|
|
- })
|
|
|
+ this.props.tasks.map(x => renderResult(x, this.state.details[x]))
|
|
|
}
|
|
|
</Collapse>
|
|
|
</div>
|