From 242061154a6f4667123d3e4707fd08e9f9e1224a Mon Sep 17 00:00:00 2001
From: hjm <63528605@qq.com>
Date: Thu, 5 Sep 2019 14:53:00 +0800
Subject: [PATCH 1/6] float reader
---
public/react/src/modules/page/MainContent.js | 6 +-
public/react/src/modules/page/VNC.css | 16 +++
public/react/src/modules/page/VNCContainer.js | 33 +++++
.../src/modules/page/component/FloatButton.js | 24 ++++
.../modules/page/component/SecondDrawer.js | 117 ++++++++++++++++++
.../src/modules/page/images/float_switch.jpg | Bin 0 -> 1303 bytes
6 files changed, 193 insertions(+), 3 deletions(-)
create mode 100644 public/react/src/modules/page/VNC.css
create mode 100644 public/react/src/modules/page/VNCContainer.js
create mode 100644 public/react/src/modules/page/component/FloatButton.js
create mode 100644 public/react/src/modules/page/component/SecondDrawer.js
create mode 100644 public/react/src/modules/page/images/float_switch.jpg
diff --git a/public/react/src/modules/page/MainContent.js b/public/react/src/modules/page/MainContent.js
index 601c002a9..30603370a 100644
--- a/public/react/src/modules/page/MainContent.js
+++ b/public/react/src/modules/page/MainContent.js
@@ -13,7 +13,7 @@ import ChooseEvaluateView from './main/ChooseEvaluateView'
import { CircularProgress } from 'material-ui/Progress';
import Button from 'material-ui/Button';
-import VNCDisplay from './VNCDisplay'
+import VNCContainer from './VNCContainer'
import './tpiPage.css';
import './tpiPageForMobile.css';
@@ -94,9 +94,9 @@ class MainContent extends Component {
*/}
- { showIframeContent && vnc_url ?
+ >
:
diff --git a/public/react/src/modules/page/VNC.css b/public/react/src/modules/page/VNC.css
new file mode 100644
index 000000000..a890d3b15
--- /dev/null
+++ b/public/react/src/modules/page/VNC.css
@@ -0,0 +1,16 @@
+.float_button {
+ background-image: url(./images/float_switch.jpg);
+ height: 112px;
+ width: 38px;
+ position: absolute;
+ left: -38px;
+ top: 32%;
+ cursor: pointer;
+}
+.float_button .text {
+ position: relative;
+ writing-mode: vertical-rl;
+ top: 36px;
+ color: #fff;
+ left: 10px;
+}
\ No newline at end of file
diff --git a/public/react/src/modules/page/VNCContainer.js b/public/react/src/modules/page/VNCContainer.js
new file mode 100644
index 000000000..24bee99ae
--- /dev/null
+++ b/public/react/src/modules/page/VNCContainer.js
@@ -0,0 +1,33 @@
+import React, { Component } from 'react';
+import VNCDisplay from './VNCDisplay'
+import FloatButton from './component/FloatButton'
+import SecondDrawer from './component/SecondDrawer'
+
+import './VNC.css'
+const $ = window.$;
+class VNCContainer extends Component {
+ componentDidMount() {
+
+
+ }
+
+ render() {
+ const { challenge, vnc_url } = this.props
+
+ return (
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default VNCContainer;
diff --git a/public/react/src/modules/page/component/FloatButton.js b/public/react/src/modules/page/component/FloatButton.js
new file mode 100644
index 000000000..1b9e191f2
--- /dev/null
+++ b/public/react/src/modules/page/component/FloatButton.js
@@ -0,0 +1,24 @@
+import React, { Component } from 'react';
+
+const $ = window.$;
+class FloatButton extends Component {
+ componentDidMount() {
+
+
+ }
+
+ render() {
+ const { challenge, vnc_url, children } = this.props
+
+ return (
+
+
+ {children || '版本库'}
+
+ );
+ }
+}
+
+export default FloatButton;
diff --git a/public/react/src/modules/page/component/SecondDrawer.js b/public/react/src/modules/page/component/SecondDrawer.js
new file mode 100644
index 000000000..e8a231019
--- /dev/null
+++ b/public/react/src/modules/page/component/SecondDrawer.js
@@ -0,0 +1,117 @@
+import React from "react";
+import ReactDOM from "react-dom";
+import { Drawer } from "antd";
+import FloatButton from './FloatButton'
+
+export default class SecondDrawer extends React.Component {
+ state = { visible: false, childrenDrawer: false };
+
+ showDrawer = () => {
+ this.setState({
+ visible: true
+ });
+ };
+
+ onClose = () => {
+ this.setState({
+ visible: false
+ });
+ };
+
+ showChildrenDrawer = () => {
+ this.setState({
+ childrenDrawer: true
+ });
+ };
+
+ onChildrenDrawerClose = () => {
+ this.setState({
+ childrenDrawer: false
+ });
+ };
+ onCloseInner = () => {};
+ swtichFirstDrawer = () => {
+ this.setState({
+ visible: !this.state.visible,
+ childrenDrawer: false
+ });
+ };
+ componentDidMount() {
+ this.setState({ visible: true }, () => {
+ this.setState({ visible: false });
+ });
+ }
+ render() {
+ const { floatText } = this.props
+ return (
+
+
+
+ {floatText}
+ {/* */}
+
+ This is two-level drawer
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
diff --git a/public/react/src/modules/page/images/float_switch.jpg b/public/react/src/modules/page/images/float_switch.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..12fc6f8788b42a66affd16e81914f5f2202b23be
GIT binary patch
literal 1303
zcmV+y1?c*TP)Px((Md!>RCodHTRm?aRTQ1ijhEd_9NWlCEX-Q5B}+m13qgWF6bVrfBt!=YS{fv3
z8h!wxM06=qQ6eGHq@qd_rHV-eT`Dhj)-EDuxaVolLVBoYh9$-jzkd@A8BGNAeiIoVmeRkEU#tPrU!vl|~hKN$CyA)z#HYa`$~wq8$bx05UubAsL%|*3aIT7|J=fI$|YB`9^-%IipEK
z5QCA-R2)X(rkOp34=TpiBxt<+%&c?5wXZ4$LZ!*w*eeH)0}|71r^x9EmvJ32^yejY
z$z`fn6R|1KX$&;6GjRzif+oh?ned*N?Pc(adBtoMu*Lg5<`uJ5z!vZKm{-hJ0b9J^
zV_q>^1#I!H_SoKEdjXDHw>~z9ZIhS5w<7j33!k*c6SGy&E9MomRlpYS_n24ARsmbQ
z-(y}eTLo`Yuz5~D&>q~uY+
zu}hV7FA&pYG(mY1uy~@uF5{|V=uL7#kr)5CB%^y#F_OW{BxRiE`5zkWGOi;Aa)#i+
z(}Uk7{?8>L_A(E8%YY9{f+*wg`1p9dd~tb0Zi2U2;L3v-iJ&K97;|A9$M?J4?q`zg
zm>EYOnpjC@LJSnbqobp7*2^A7arB|eV{V~FVr-%nV=fpSj2>NBzHlIq&|i}zG3ERs
z0uY;JxJ!f4Xml?-pFN0^_&pge{IXUR(~5a
z)vc_oye99uy%h)XFigTLvVXr6@art#V)Q!Cg_=CD)jHN!J#l(1VsJHzjg5`Y($dlw
zLhuLqjZXCDXE6)lxxW~jMP$IAF8)f)^5s^TtjTe?&f($VGua}4ijw<+xlu=^n$u&(
z^dQ{Eh}WJm>UqM(?`-ebdk<8o?587aLpKXtkE%Z^kz;}>*5~|bp{|!lhk?6
zxACmQT8QaUt7D7{dGGSBZi?ihtgcU84*ktZG)=lBSli1rF_380^MA+Q
Date: Thu, 5 Sep 2019 16:52:01 +0800
Subject: [PATCH 2/6] loadRepoFiles
---
public/react/src/modules/page/VNC.css | 3 +-
public/react/src/modules/page/VNCContainer.js | 19 ++++-
.../modules/page/component/SecondDrawer.js | 69 +++++++------------
.../modules/page/component/repo/RepoTree.js | 0
.../page/main/CodeRepositoryViewContainer.js | 6 ++
5 files changed, 48 insertions(+), 49 deletions(-)
create mode 100644 public/react/src/modules/page/component/repo/RepoTree.js
diff --git a/public/react/src/modules/page/VNC.css b/public/react/src/modules/page/VNC.css
index a890d3b15..cf47d7207 100644
--- a/public/react/src/modules/page/VNC.css
+++ b/public/react/src/modules/page/VNC.css
@@ -12,5 +12,6 @@
writing-mode: vertical-rl;
top: 36px;
color: #fff;
- left: 10px;
+ left: 13px;
+ user-select: none;
}
\ No newline at end of file
diff --git a/public/react/src/modules/page/VNCContainer.js b/public/react/src/modules/page/VNCContainer.js
index 24bee99ae..7634fd700 100644
--- a/public/react/src/modules/page/VNCContainer.js
+++ b/public/react/src/modules/page/VNCContainer.js
@@ -5,20 +5,35 @@ import SecondDrawer from './component/SecondDrawer'
import './VNC.css'
const $ = window.$;
+const firstDrawerWidth = 400;
class VNCContainer extends Component {
componentDidMount() {
}
-
+ getSecondDrawerWidth = () => {
+ return $('#game_right_contents').width() - firstDrawerWidth
+ }
+ renderSecondDrawerChildren = () => {
+ return (
+
+
);
+ }
render() {
const { challenge, vnc_url } = this.props
+ const secondDrawerChildren = this.renderSecondDrawerChildren();
return (
+ maskClosable={false}
+ secondDrawerChildren={secondDrawerChildren}
+ firstDrawerWidth={firstDrawerWidth}
+ getSecondDrawerWidth={this.getSecondDrawerWidth}
+ >
+
+
{
@@ -42,76 +43,52 @@ export default class SecondDrawer extends React.Component {
});
}
render() {
- const { floatText } = this.props
+ const { floatText, maskClosable, children, secondDrawerChildren, firstDrawerWidth, getSecondDrawerWidth } = this.props
+ const secondDrawerWidth = getSecondDrawerWidth();
+ // 180 不知道为什么会偏移 180px
return (
-
{floatText}
- {/* */}
+ { children }
+
- This is two-level drawer
-
+ */}
-
-
-
-
-
);
}
}
+SecondDrawer.propTypes = {
+ floatText: PropTypes.string,
+ maskClosable: PropTypes.bool,
+ secondDrawerChildren: PropTypes.element,
+};
+// firstDrawerWidth={firstDrawerWidth}
+// getSecondDrawerWidth={this.getSecondDrawerWidth}
+export default SecondDrawer
\ No newline at end of file
diff --git a/public/react/src/modules/page/component/repo/RepoTree.js b/public/react/src/modules/page/component/repo/RepoTree.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/public/react/src/modules/page/main/CodeRepositoryViewContainer.js b/public/react/src/modules/page/main/CodeRepositoryViewContainer.js
index 8efe7b0e1..19f6cfd3d 100644
--- a/public/react/src/modules/page/main/CodeRepositoryViewContainer.js
+++ b/public/react/src/modules/page/main/CodeRepositoryViewContainer.js
@@ -101,6 +101,11 @@ class CodeRepositoryViewContainer extends Component {
drawerOpen: open,
})
}
+ loadRepoFiles = () => {
+ if (!this.state.fileTreeData) {
+ this.fetchRepoFiles();
+ }
+ }
componentWillReceiveProps(newProps, oldProps) {
@@ -274,6 +279,7 @@ class CodeRepositoryViewContainer extends Component {
Date: Thu, 5 Sep 2019 19:15:21 +0800
Subject: [PATCH 3/6] =?UTF-8?q?=E5=B7=AEgit=5Furl?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
public/react/src/modules/page/Index.js | 1 +
public/react/src/modules/page/MainContent.js | 10 +-
public/react/src/modules/page/VNCContainer.js | 119 +++++++++++++++++-
.../modules/page/component/SecondDrawer.js | 16 ++-
.../page/component/monaco/TPIMonaco.js | 3 +-
.../modules/page/component/repo/RepoTree.js | 54 ++++++++
.../page/main/CodeRepositoryViewContainer.js | 37 ++++--
7 files changed, 214 insertions(+), 26 deletions(-)
diff --git a/public/react/src/modules/page/Index.js b/public/react/src/modules/page/Index.js
index b2daa27e4..ab0f30e70 100644
--- a/public/react/src/modules/page/Index.js
+++ b/public/react/src/modules/page/Index.js
@@ -219,6 +219,7 @@ class Index extends Component {
praisePlus={context.praisePlus}
+ git_url={context.git_url}
mirror_name={context.mirror_name}
challenge={context.challenge}
myshixun={context.myshixun}
diff --git a/public/react/src/modules/page/MainContent.js b/public/react/src/modules/page/MainContent.js
index 30603370a..d8623d84b 100644
--- a/public/react/src/modules/page/MainContent.js
+++ b/public/react/src/modules/page/MainContent.js
@@ -94,9 +94,13 @@ class MainContent extends Component {
*/}
- { showIframeContent && vnc_url ?
+ { showIframeContent && vnc_url ?
+
+
+
:
diff --git a/public/react/src/modules/page/VNCContainer.js b/public/react/src/modules/page/VNCContainer.js
index 7634fd700..054dc2ce8 100644
--- a/public/react/src/modules/page/VNCContainer.js
+++ b/public/react/src/modules/page/VNCContainer.js
@@ -1,12 +1,24 @@
import React, { Component } from 'react';
+import axios from 'axios'
+import { Spin } from 'antd'
+
import VNCDisplay from './VNCDisplay'
import FloatButton from './component/FloatButton'
import SecondDrawer from './component/SecondDrawer'
-
+import RepoTree from './component/repo/RepoTree'
+import TPIMonaco from './component/monaco/TPIMonaco'
import './VNC.css'
const $ = window.$;
-const firstDrawerWidth = 400;
+const firstDrawerWidth = 260;
class VNCContainer extends Component {
+ constructor(props) {
+ super(props)
+
+ this.state = {
+ fileTreeSelectedKeys: [],
+ repositoryCode: ''
+ }
+ }
componentDidMount() {
@@ -15,10 +27,74 @@ class VNCContainer extends Component {
return $('#game_right_contents').width() - firstDrawerWidth
}
renderSecondDrawerChildren = () => {
- return (
-
-
);
+ const { readingCodeLoading, repositoryCode } = this.state;
+ const height = $(window).height() - 130
+ return (
+
+
+
+
+
+
+ );
+ }
+ fetchReadRepositoryCode = (path) => {
+ const status = 1
+ const fetchRepoCodeUrl = `/tasks/${this.props.game.identifier}/rep_content.json?path=${path}&status=${status}`
+ this.setState({ readingCodeLoading: true });
+ axios.get(fetchRepoCodeUrl, {
+ }).then((fetchReadRepositoryCodeResponse) => {
+
+
+ if (fetchReadRepositoryCodeResponse.data.content || fetchReadRepositoryCodeResponse.data.content == "") {
+ this.setState({
+ repositoryCode: fetchReadRepositoryCodeResponse.data.content,
+ readingCodeLoading: false
+ })
+ } else {
+ this.setState({ readingCodeLoading: false });
+ }
+ // this.setState({ isEditablePath, currentPath: path });
+
+ }).catch(error =>{
+ console.log(error)
+ this.setState({ readingCodeLoading: false });
+ showSnackbar(`服务端异常,请联系管理员!`);
+ })
}
+ onTreeSelect = (selectedKeys, info) => {
+ const isLeaf = info.node.props.isLeaf;
+ if (isLeaf) { // 叶子节点
+ selectedKeys.length && this.setState({
+ fileTreeSelectedKeys: selectedKeys
+ })
+ this.refs["secondDrawer"].showSecondDrawer()
+
+ console.log('leaf clicked')
+ const nodePath = info.node.props.eventKey;
+ if (nodePath) {
+ const filetype = nodePath.split('.').pop().toLowerCase();
+ if (filetype == 'jpg' || filetype == 'png' || filetype == 'gif' || filetype == 'jpeg'
+ || filetype == 'jar'
+ || filetype == 'doc' || filetype == 'pdf' || filetype == 'xsl' || filetype == 'ppt') {
+ showSnackbar(`不支持加载${filetype}类型的文件。`)
+ return;
+ }
+ this.fetchReadRepositoryCode(nodePath);
+ } else {
+ console.error('no eventKey:', info.node)
+ }
+ }
+ }
+ /*
+ selectedKeys={fileTreeSelectedKeys}
+ onSelect={onTreeSelect}
+ */
render() {
const { challenge, vnc_url } = this.props
@@ -26,13 +102,44 @@ class VNCContainer extends Component {
return (
-
+
+
{
+ showSecondDrawer = () => {
this.setState({
childrenDrawer: true
});
@@ -30,7 +30,7 @@ class SecondDrawer extends React.Component {
childrenDrawer: false
});
};
- onCloseInner = () => {};
+
swtichFirstDrawer = () => {
this.setState({
visible: !this.state.visible,
@@ -43,21 +43,25 @@ class SecondDrawer extends React.Component {
});
}
render() {
- const { floatText, maskClosable, children, secondDrawerChildren, firstDrawerWidth, getSecondDrawerWidth } = this.props
+ const { floatText, maskClosable, children, secondDrawerChildren, firstDrawerWidth, getSecondDrawerWidth
+ ,firstDrawerClassName, secondDrawerClassName
+ } = this.props
const secondDrawerWidth = getSecondDrawerWidth();
// 180 不知道为什么会偏移 180px
return (
- */}
{floatText}
{ children }
@@ -68,6 +72,8 @@ class SecondDrawer extends React.Component {
closable={false}
onClose={this.onChildrenDrawerClose}
visible={this.state.childrenDrawer}
+ className={secondDrawerClassName}
+
>
{ secondDrawerChildren }
{/* {
+ loadRepoFiles()
+ }, [])
+
+ if (!fileTreeData || fileTreeData.length === 0) {
+ return ""
+ }
+
+ const onExpand = (expandedKeys) => {
+ // console.log('onExpand', arguments);
+ // if not set autoExpandParent to false, if children expanded, parent can not collapse.
+ // or, you can remove all expanded children keys.
+ setExpandedKeys(expandedKeys)
+ }
+
+ const loop = (data) => {
+ return data.map((item) => {
+ if (item.children) {
+ return {loop(item.children)};
+ }
+ return (
+
+ );
+ });
+ };
+ const treeNodes = loop(fileTreeData);
+
+
+ // selectable={false}
+ return (
+
+ {treeNodes}
+
+ )
+}
diff --git a/public/react/src/modules/page/main/CodeRepositoryViewContainer.js b/public/react/src/modules/page/main/CodeRepositoryViewContainer.js
index 19f6cfd3d..0a5be59e0 100644
--- a/public/react/src/modules/page/main/CodeRepositoryViewContainer.js
+++ b/public/react/src/modules/page/main/CodeRepositoryViewContainer.js
@@ -274,19 +274,34 @@ class CodeRepositoryViewContainer extends Component {
}
// /shixuns/mnf6b7z3/shixun_discuss?challenge_id=88
render() {
-
+
return (
-
+ {this.props.isOnlyContainer == true ?
+ React.Children.map(this.props.children, child => {
+ if(!child) {
+ return ''
+ }
+ return React.cloneElement(child, Object.assign({...this.state}, {
+ loadRepoFiles: this.loadRepoFiles,
+ onTreeSelect: this.onTreeSelect,
+ onLoadData: this.onLoadData,
+ }))
+ })
- >
+ :
+
+ }
+
);
}
}
From b7f88963beda80537353d542572787e0978f1ad0 Mon Sep 17 00:00:00 2001
From: hjm <63528605@qq.com>
Date: Thu, 5 Sep 2019 19:40:44 +0800
Subject: [PATCH 4/6] git_url
---
public/react/src/modules/page/VNCContainer.js | 38 +++++++++++++++----
1 file changed, 31 insertions(+), 7 deletions(-)
diff --git a/public/react/src/modules/page/VNCContainer.js b/public/react/src/modules/page/VNCContainer.js
index 054dc2ce8..8b76c4b74 100644
--- a/public/react/src/modules/page/VNCContainer.js
+++ b/public/react/src/modules/page/VNCContainer.js
@@ -1,6 +1,7 @@
import React, { Component } from 'react';
import axios from 'axios'
import { Spin } from 'antd'
+import ClipboardJS from 'clipboard'
import VNCDisplay from './VNCDisplay'
import FloatButton from './component/FloatButton'
@@ -20,7 +21,13 @@ class VNCContainer extends Component {
}
}
componentDidMount() {
-
+ if (!this.clipboard) {
+ const clipboard = new ClipboardJS('.copybtn');
+ clipboard.on('success', (e) => {
+ this.props.showSnackbar('复制成功')
+ });
+ this.clipboard = clipboard
+ }
}
getSecondDrawerWidth = () => {
@@ -64,7 +71,7 @@ class VNCContainer extends Component {
}).catch(error =>{
console.log(error)
this.setState({ readingCodeLoading: false });
- showSnackbar(`服务端异常,请联系管理员!`);
+ this.props.showSnackbar(`服务端异常,请联系管理员!`);
})
}
onTreeSelect = (selectedKeys, info) => {
@@ -82,7 +89,7 @@ class VNCContainer extends Component {
if (filetype == 'jpg' || filetype == 'png' || filetype == 'gif' || filetype == 'jpeg'
|| filetype == 'jar'
|| filetype == 'doc' || filetype == 'pdf' || filetype == 'xsl' || filetype == 'ppt') {
- showSnackbar(`不支持加载${filetype}类型的文件。`)
+ this.props.showSnackbar(`不支持加载${filetype}类型的文件。`)
return;
}
this.fetchReadRepositoryCode(nodePath);
@@ -96,7 +103,7 @@ class VNCContainer extends Component {
onSelect={onTreeSelect}
*/
render() {
- const { challenge, vnc_url } = this.props
+ const { challenge, vnc_url, git_url } = this.props
const secondDrawerChildren = this.renderSecondDrawerChildren();
return (
@@ -113,27 +120,44 @@ class VNCContainer extends Component {
secondDrawerClassName="codeInDrawer"
>
+
Date: Thu, 5 Sep 2019 20:18:02 +0800
Subject: [PATCH 5/6] =?UTF-8?q?=E5=9B=BE=E6=A0=87?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
public/react/src/modules/page/VNCContainer.js | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/public/react/src/modules/page/VNCContainer.js b/public/react/src/modules/page/VNCContainer.js
index 8b76c4b74..e0e3616e0 100644
--- a/public/react/src/modules/page/VNCContainer.js
+++ b/public/react/src/modules/page/VNCContainer.js
@@ -8,6 +8,8 @@ import FloatButton from './component/FloatButton'
import SecondDrawer from './component/SecondDrawer'
import RepoTree from './component/repo/RepoTree'
import TPIMonaco from './component/monaco/TPIMonaco'
+import notEditablePathImg from '../../images/tpi/notEditablePath.png'
+
import './VNC.css'
const $ = window.$;
const firstDrawerWidth = 260;
@@ -36,10 +38,13 @@ class VNCContainer extends Component {
renderSecondDrawerChildren = () => {
const { readingCodeLoading, repositoryCode } = this.state;
const height = $(window).height() - 130
+
+ const isEditablePath = false;
return (
-
+
Date: Thu, 5 Sep 2019 20:23:20 +0800
Subject: [PATCH 6/6] =?UTF-8?q?=E8=B0=83=E6=95=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/views/student_works/shixun_work_report.json.jbuilder | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/student_works/shixun_work_report.json.jbuilder b/app/views/student_works/shixun_work_report.json.jbuilder
index 0b5e4da45..29a5c1874 100644
--- a/app/views/student_works/shixun_work_report.json.jbuilder
+++ b/app/views/student_works/shixun_work_report.json.jbuilder
@@ -54,7 +54,7 @@ if @shixun
json.passed_time @work.myshixun&.passed_time
# 评阅信息
- json.work_comment @user_course_identity < Course::STUDENT ? @comment&.comment : nil
+ json.work_comment @user_course_identity < Course::STUDENT || !@comment&.is_hidden ? @comment&.comment : nil
json.work_comment_hidden @comment&.is_hidden
# 图形统计