From b50c897f2067b78307ef786ef267ff60751fcf04 Mon Sep 17 00:00:00 2001
From: caishi <1149225589@qq.com>
Date: Mon, 5 Aug 2019 09:00:45 +0800
Subject: [PATCH] =?UTF-8?q?=E6=95=99=E5=AD=A6=E6=A1=88=E4=BE=8B=E8=AF=A6?=
=?UTF-8?q?=E6=83=85=E5=92=8C=E6=96=B0=E5=BB=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.merge_file_a17580 | 529 ++++++++++++++++++
public/react/config/webpack.config.dev.js | 2 +-
public/react/src/common/course/ActionBtn.js | 2 +-
.../react/src/modules/courses/css/Courses.css | 6 +
.../src/modules/moop_cases/CaseDetail.js | 163 ++++++
.../react/src/modules/moop_cases/CaseItem.js | 17 +-
.../react/src/modules/moop_cases/CaseList.js | 134 +++++
.../react/src/modules/moop_cases/CaseNew.js | 381 +++++++++++++
.../react/src/modules/moop_cases/CaseTags.js | 2 +-
.../src/modules/moop_cases/css/moopCases.css | 91 +++
public/react/src/modules/moop_cases/index.js | 186 +++---
11 files changed, 1401 insertions(+), 112 deletions(-)
create mode 100644 .merge_file_a17580
create mode 100644 public/react/src/modules/moop_cases/CaseDetail.js
create mode 100644 public/react/src/modules/moop_cases/CaseList.js
create mode 100644 public/react/src/modules/moop_cases/CaseNew.js
diff --git a/.merge_file_a17580 b/.merge_file_a17580
new file mode 100644
index 000000000..47e471767
--- /dev/null
+++ b/.merge_file_a17580
@@ -0,0 +1,529 @@
+import React, {Component} from 'react';
+import logo from './logo.svg';
+import './App.css';
+import {LocaleProvider} from 'antd'
+import zhCN from 'antd/lib/locale-provider/zh_CN';
+import {
+ BrowserRouter as Router,
+ Route,
+ Switch
+} from 'react-router-dom';
+import axios from 'axios';
+import '@icedesign/base/dist/ICEDesignBase.css';
+
+import '@icedesign/base/index.scss';
+
+import LoginDialog from './modules/login/LoginDialog';
+import Notcompletedysl from './modules/user/Notcompletedysl';
+import Trialapplicationysl from './modules/login/Trialapplicationysl';
+import Trialapplicationreview from './modules/user/Trialapplicationreview';
+import Addcourses from "./modules/courses/coursesPublic/Addcourses";
+import AccountProfile from"./modules/user/AccountProfile";
+
+
+import Trialapplication from './modules/login/Trialapplication'
+
+import NotFoundPage from './NotFoundPage'
+
+import Loading from './Loading'
+
+import Loadable from 'react-loadable';
+
+
+import moment from 'moment'
+
+import {MuiThemeProvider, createMuiTheme} from 'material-ui/styles';
+
+// import './AppConfig'
+
+import history from './history';
+
+import {SnackbarHOC} from 'educoder'
+import {initAxiosInterceptors} from './AppConfig'
+
+
+// !!!tpi需要这个来加载css
+import {TPMIndexHOC} from './modules/tpm/TPMIndexHOC';
+
+
+const theme = createMuiTheme({
+ palette: {
+ primary: {
+ main: '#4CACFF',
+ contrastText: 'rgba(255, 255, 255, 0.87)'
+ },
+ secondary: {main: '#4CACFF'}, // #11cb5f This is just green.A700 as hex.
+ },
+});
+//
+// const Trialapplication= Loadable({
+// loader: () =>import('./modules/login/Trialapplication'),
+// loading:Loading,
+// })
+//登入
+const EducoderLogin = Loadable({
+ loader: () => import('./modules/login/EducoderLogin'),
+ loading: Loading,
+})
+const TestIndex = Loadable({
+ loader: () => import('./modules/test'),
+ loading: Loading,
+})
+
+const IndexWrapperComponent = Loadable({
+ loader: () => import('./modules/page/IndexWrapper'),
+ loading: Loading,
+})
+
+const CommentComponent = Loadable({
+ loader: () => import('./modules/comment/CommentContainer'),
+ loading: Loading,
+})
+
+const TestMaterialDesignComponent = Loadable({
+ loader: () => import('./modules/test/md/TestMaterialDesign'),
+ loading: Loading,
+})
+const TestCodeMirrorComponent = Loadable({
+ loader: () => import('./modules/test/codemirror/TestCodeMirror'),
+ loading: Loading,
+})
+
+const TestComponent = Loadable({
+ loader: () => import('./modules/test/TestRC'),
+ loading: Loading,
+})
+const TestUrlQueryComponent = Loadable({
+ loader: () => import('./modules/test/urlquery/TestUrlQuery'),
+ loading: Loading,
+})
+
+const TPMIndexComponent = Loadable({
+ loader: () => import('./modules/tpm/TPMIndex'),
+ loading: Loading,
+})
+const TPMShixunsIndexComponent = Loadable({
+ loader: () => import('./modules/tpm/shixuns/ShixunsIndex'),
+ loading: Loading,
+})
+
+//实训课程(原实训路径)
+const ShixunPaths = Loadable({
+ loader: () => import('./modules/paths/Index'),
+ loading: Loading,
+})
+
+//在线课堂
+const CoursesIndex = Loadable({
+ loader: () => import('./modules/courses/Index'),
+ loading: Loading,
+})
+const SearchPage = Loadable({
+ loader: () => import('./search/SearchPage'),
+ loading: Loading,
+})
+
+//教学案例
+const MoopCases = Loadable({
+ loader: () => import('./modules/moop_cases/index'),
+ loading: Loading,
+})
+
+// 课堂讨论
+// const BoardIndex = Loadable({
+// loader: () => import('./modules/courses/boards/BoardIndex'),
+// loading:Loading,
+// })
+
+// //课堂普通作业&分组作业
+// const CoursesWorkIndex = Loadable({
+// loader: () => import('./modules/courses/busyWork/Index'),
+// loading:Loading,
+// })
+//
+
+// const TPMShixunchildIndexComponent = Loadable({
+// loader: () => import('./modules/tpm/shixunchild/ShixunChildIndex'),
+// loading: Loading,
+// })
+
+
+// const TPMshixunfork_listIndexComponent = Loadable({
+// loader: () => import('./modules/tpm/shixunchild/Shixunfork_list'),
+// loading: Loading,
+// })
+
+
+const ForumsIndexComponent = Loadable({
+ loader: () => import('./modules/forums/ForumsIndex'),
+ loading: Loading,
+})
+
+// trustie plus forum
+// const TPForumsIndexComponent = Loadable({
+// loader: () => import('./modules/tp-forums/TPForumsIndex'),
+// loading: Loading,
+// })
+
+
+// const TestPageComponent = Loadable({
+// loader: () => import('./modules/page/Index'),
+// loading: Loading,
+// })
+
+
+//新建实训
+const Newshixuns = Loadable({
+ loader: () => import('./modules/tpm/newshixuns/Newshixuns'),
+ loading: Loading,
+})
+
+
+//实训首页
+const ShixunsHome = Loadable({
+ loader: () => import('./modules/home/shixunsHome'),
+ loading: Loading,
+})
+
+
+const CompatibilityPageLoadable = Loadable({
+ loader: () => import('./modules/common/CompatibilityPage'),
+ loading: Loading,
+})
+
+//403页面
+const Shixunauthority = Loadable({
+ loader: () => import('./modules/403/Shixunauthority'),
+ loading: Loading,
+})
+
+
+//404页面
+const Shixunnopage = Loadable({
+ loader: () => import('./modules/404/Shixunnopage'),
+ loading: Loading,
+})
+
+//500页面
+const http500 = Loadable({
+ loader: () => import('./modules/500/http500'),
+ loading: Loading,
+})
+
+// 登录注册
+const LoginRegisterPage = Loadable({
+ loader: () => import('./modules/user/LoginRegisterPage'),
+ loading: Loading,
+})
+const AccountPage = Loadable({
+ loader: () => import('./modules/user/AccountPage'),
+ loading: Loading,
+})
+
+// 个人主页
+const UsersInfo = Loadable({
+ loader: () => import('./modules/user/usersInfo/Infos'),
+ loading: Loading,
+})
+
+// 兴趣页面
+const Interestpage = Loadable({
+ loader: () => import('./modules/login/EducoderInteresse'),
+ loading: Loading,
+})
+
+//众包创新
+const ProjectPackages=Loadable({
+ loader: () => import('./modules/projectPackages/ProjectPackageIndex'),
+ loading: Loading,
+})
+
+class App extends Component {
+ constructor(props) {
+ super(props)
+ // this.state = {
+ // isRenders:false,
+ // }
+
+ }
+
+ componentDidMount() {
+ // force an update if the URL changes
+ history.listen(() => {
+ this.forceUpdate()
+ const $ = window.$
+ // https://www.trustie.net/issues/21919 可能会有问题
+ $("html").animate({ scrollTop: $('html').scrollTop() - 0 })
+ });
+
+ initAxiosInterceptors(this.props)
+
+ //
+ // axios.interceptors.response.use((response) => {
+ // // console.log("response"+response);
+ // if(response!=undefined)
+ // // console.log("response"+response.data.statu);
+ // if (response&&response.data.status === 407) {
+ // this.setState({
+ // isRenders: true,
+ // })
+ // }
+ // return response;
+ // }, (error) => {
+ // //TODO 这里如果样式变了会出现css不加载的情况
+ // });
+ }
+ //修改登录方法
+ Modifyloginvalue=()=>{
+ this.setState({
+ isRender:false,
+ })
+ }
+
+ render() {
+
+
+ return (
+
+
+
+
+ this.Modifyloginvalue()}>
+
+
+
+
+
+ {/*{*/}
+ {/* isRender === true?*/}
+ {/* : ""*/}
+ {/*}*/}
+
+ {/*{*/}
+ {/* isRenders === true?*/}
+ {/**/}
+ {/*:""*/}
+ {/*}*/}
+
+
+
+ {/**/}
+
+ {/*众包创新*/}
+
+ {/*认证*/}
+
+
+ {/*403*/}
+
+
+
+
+ {/*404*/}
+
+
+
+
+
+ ()
+ }>
+ {/**/}
+
+
+
+
+
+
+
+
+
+
+
+ {/*列表页*/}
+
+
+ {/*
+
+
+ */}
+
+ {/**/}
+ {/**/}
+
+
+ {/*实训课程(原实训路径)*/}
+
+
+ ()
+ }
+ >
+
+ {/*课堂*/}
+
+
+ {/* 课堂讨论 */}
+ {/* */}
+
+ {/*
+ */}
+
+ {/* */}
+ {/* 兴趣页面*/}
+ {/**/}
+
+
+
+
+
+
+
+
+ {/* 教学案例 */}
+ ()
+ }/>
+
+ {/* */}
+ {/*列表页*/}
+ {/**/}
+ {/*首页*/}
+
+
+
+ {/**/}
+
+
+
+
+
+ );
+ }
+}
+
+// moment国际化,设置为中文
+moment.defineLocale('zh-cn', {
+ months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
+ monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+ weekdays: '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
+ weekdaysShort: '周日_周一_周二_周三_周四_周五_周六'.split('_'),
+ weekdaysMin: '日_一_二_三_四_五_六'.split('_'),
+ longDateFormat: {
+ LT: 'Ah点mm分',
+ LTS: 'Ah点m分s秒',
+ L: 'YYYY-MM-DD',
+ LL: 'YYYY年MMMD日',
+ LLL: 'YYYY年MMMD日Ah点mm分',
+ LLLL: 'YYYY年MMMD日ddddAh点mm分',
+ l: 'YYYY-MM-DD',
+ ll: 'YYYY年MMMD日',
+ lll: 'YYYY年MMMD日Ah点mm分',
+ llll: 'YYYY年MMMD日ddddAh点mm分'
+ },
+ meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
+ meridiemHour: function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === '凌晨' || meridiem === '早上' ||
+ meridiem === '上午') {
+ return hour;
+ } else if (meridiem === '下午' || meridiem === '晚上') {
+ return hour + 12;
+ } else {
+ // '中午'
+ return hour >= 11 ? hour : hour + 12;
+ }
+ },
+ meridiem: function (hour, minute, isLower) {
+ var hm = hour * 100 + minute;
+ if (hm < 600) {
+ return '凌晨';
+ } else if (hm < 900) {
+ return '早上';
+ } else if (hm < 1130) {
+ return '上午';
+ } else if (hm < 1230) {
+ return '中午';
+ } else if (hm < 1800) {
+ return '下午';
+ } else {
+ return '晚上';
+ }
+ },
+ calendar: {
+ sameDay: function () {
+ return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT';
+ },
+ nextDay: function () {
+ return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT';
+ },
+ lastDay: function () {
+ return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT';
+ },
+ nextWeek: function () {
+ var startOfWeek, prefix;
+ startOfWeek = moment().startOf('week');
+ prefix = this.unix() - startOfWeek.unix() >= 7 * 24 * 3600 ? '[下]' : '[本]';
+ return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm';
+ },
+ lastWeek: function () {
+ var startOfWeek, prefix;
+ startOfWeek = moment().startOf('week');
+ prefix = this.unix() < startOfWeek.unix() ? '[上]' : '[本]';
+ return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm';
+ },
+ sameElse: 'LL'
+ },
+ ordinalParse: /\d{1,2}(日|月|周)/,
+ ordinal: function (number, period) {
+ switch (period) {
+ case 'd':
+ case 'D':
+ case 'DDD':
+ return number + '日';
+ case 'M':
+ return number + '月';
+ case 'w':
+ case 'W':
+ return number + '周';
+ default:
+ return number;
+ }
+ },
+ relativeTime: {
+ future: '%s内',
+ past: '%s前',
+ s: '几秒',
+ m: '1分钟',
+ mm: '%d分钟',
+ h: '1小时',
+ hh: '%d小时',
+ d: '1天',
+ dd: '%d天',
+ M: '1个月',
+ MM: '%d个月',
+ y: '1年',
+ yy: '%d年'
+ },
+ week: {
+ // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
+ dow: 1, // Monday is the first day of the week.
+ doy: 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+export default SnackbarHOC()(App);
\ No newline at end of file
diff --git a/public/react/config/webpack.config.dev.js b/public/react/config/webpack.config.dev.js
index 12d5e437f..15e7e6bef 100644
--- a/public/react/config/webpack.config.dev.js
+++ b/public/react/config/webpack.config.dev.js
@@ -29,7 +29,7 @@ const env = getClientEnvironment(publicUrl);
module.exports = {
// You may want 'eval' instead if you prefer to see the compiled output in DevTools.
// See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s
- devtool: "eval", // 开启调试
+ devtool: "source-map", // 开启调试
// These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle.
// The first two entry points enable "hot" CSS and auto-refreshes for JS.
diff --git a/public/react/src/common/course/ActionBtn.js b/public/react/src/common/course/ActionBtn.js
index 03da0d3e7..e5eeb11a4 100644
--- a/public/react/src/common/course/ActionBtn.js
+++ b/public/react/src/common/course/ActionBtn.js
@@ -1,7 +1,7 @@
import React, { Component } from 'react';
import {Link} from 'react-router-dom'
-const map={"blue":"blueFull","greyBack":"greyBack","grey":"greyWidthFixed","green":"greenBack",
+const map={"blue":"blueFull","greyBack":"greyBack","grey":"greyWidthFixed","green":"greenBack",'greyLine':"greyLine",
'colorBlue': 'colorBlue', // 蓝字白底
}
class ActionBtn extends Component {
diff --git a/public/react/src/modules/courses/css/Courses.css b/public/react/src/modules/courses/css/Courses.css
index 57b1e37f9..47db2f595 100644
--- a/public/react/src/modules/courses/css/Courses.css
+++ b/public/react/src/modules/courses/css/Courses.css
@@ -702,6 +702,12 @@ a.white-btn.use_scope-btn:hover{
.Actionbtn.middle {
padding: 0px 18px;
}
+.greyLine{
+ background: #fff;
+ border:1px solid #eaeaea;
+ color: #999!important;
+ padding:0px 10px;
+}
.colorFF6800{
diff --git a/public/react/src/modules/moop_cases/CaseDetail.js b/public/react/src/modules/moop_cases/CaseDetail.js
new file mode 100644
index 000000000..189744c25
--- /dev/null
+++ b/public/react/src/modules/moop_cases/CaseDetail.js
@@ -0,0 +1,163 @@
+import React,{ Component } from "react";
+import './css/moopCases.css'
+import '../courses/css/Courses.css'
+
+import { getImageUrl , MarkdownToHtml , ActionBtn } from 'educoder';
+
+import Tags from './CaseTags'
+
+import axios from 'axios';
+import Modals from '../modals/Modals'
+
+class CaseDetail extends Component{
+ constructor(props){
+ super(props);
+ this.state={
+ modalsType:"",
+ modalsTopval:"",
+ modalsBottomval:"",
+ modalCancel:"",
+ }
+ }
+
+ componentDidMount =()=>{
+ let caseID = this.props.match.params.caseID;
+ this.props.getDetail(caseID);
+ }
+ // 是否删除
+ delCases=()=>{
+ this.setState({
+ modalsType:true,
+ modalsTopval:"是否确认删除?",
+ modalsBottomval:""
+ })
+ }
+
+ // 取消删除
+ cancelDelClasses=()=>{
+ this.setState({
+ modalsType:false,
+ modalsTopval:"",
+ modalsBottomval:""
+ })
+ }
+ // 确定删除
+ sureDelClasses=()=>{
+ let caseID = this.props.match.params.caseID;
+ let url =`/libraries/${caseID}.json`;
+ axios.delete(url).then((result)=>{
+ if(result){
+ this.props.showNotification("删除成功")
+ this.props.history.push("/moop_cases");
+ }
+ }).catch((error)=>{
+ console.log(error);
+ })
+ }
+
+
+ render(){
+ let { CaseDetail , praise_count , creator , operation , user_praised , tags , attachments }=this.props
+ let {
+ modalsType,
+ modalsTopval,
+ modalsBottomval,
+ } = this.state;
+ return(
+
+
+
+
+ 教学案例 > { CaseDetail && CaseDetail.title}
+
+
+
+ { CaseDetail && CaseDetail.title}
+
+
+
+ 草稿
+
+ 返回
+
+
+
+
+

+
+
+ {creator && creator.name}
+ {
+ operation && operation.can_deletable ? 删除:""
+ }
+
+ {
+ operation && operation.can_editable ? 编辑:""
+ }
+
+
+ {creator && creator.school_name}
+
+ 编码:{CaseDetail && CaseDetail.uuid}
+ 发布时间:{CaseDetail && CaseDetail.published_at}
+
+
+
+
+
+ 作者:{CaseDetail && CaseDetail.author_name}/{CaseDetail && CaseDetail.author_school_name}
+
+
+
+ { CaseDetail && CaseDetail.content && }
+
+ { attachments &&
+
+ {
+ attachments.map((item,key)=>{
+ return(
+
+
+
+
+ {item.title}
+ {item.filesize}
+
+ )
+ })
+ }
+
+ }
+
+ {
+ user_praised ?
+
+ 已赞
+ {praise_count}
+
+ :
+
this.props.praisePoint(this.props.match.params.caseID)} className="pointsBtn">
+
+ {praise_count}
+
+ }
+
+
+
+
+ )
+ }
+}
+export default CaseDetail;
\ No newline at end of file
diff --git a/public/react/src/modules/moop_cases/CaseItem.js b/public/react/src/modules/moop_cases/CaseItem.js
index 45be0b3cb..a5086133b 100644
--- a/public/react/src/modules/moop_cases/CaseItem.js
+++ b/public/react/src/modules/moop_cases/CaseItem.js
@@ -1,5 +1,4 @@
import React,{ Component } from "react";
-import { Spin } from "antd";
import './css/moopCases.css'
import '../courses/css/Courses.css'
@@ -23,16 +22,18 @@ class CaseItem extends Component{
-
- {item.title}
-
+
+ {item.title}
+
-
+
{item.author_name}
{item.author_school_name}
- {item.download_count} 下载
- {item.praise_count} 赞
- {item.visited_count} 浏览
+
+ {item.visited_count} 浏览
+ {item.praise_count} 赞
+ {item.download_count} 下载
+
diff --git a/public/react/src/modules/moop_cases/CaseList.js b/public/react/src/modules/moop_cases/CaseList.js
new file mode 100644
index 000000000..b968cc930
--- /dev/null
+++ b/public/react/src/modules/moop_cases/CaseList.js
@@ -0,0 +1,134 @@
+import React,{ Component } from "react";
+import { Input , Spin , Pagination } from "antd";
+import './css/moopCases.css'
+import '../courses/css/Courses.css'
+
+import { ActionBtn } from 'educoder';
+
+import axios from 'axios'
+
+import NoneData from '../courses/coursesPublic/NoneData'
+
+import mainImg from '../../images/moop_cases/teach_ex.jpg'
+import CaseItem from './CaseItem'
+
+
+const Search = Input.Search;
+class CaseList extends Component{
+ constructor(props){
+ super(props);
+ this.state={
+ type:0,
+ search:undefined,
+ page:1,
+ pageSize:20,
+ libraries:undefined,
+ totalCount:undefined
+ }
+ }
+
+ componentDidMount = () =>{
+ let { type , search , page , pageSize } = this.state;
+ this.InitList(type,search,page,pageSize);
+ }
+
+ // 列表
+ InitList = (type,search,page,pageSize) =>{
+ let url = `/libraries.json`;
+ axios.get(url,{params:{
+ type:type == 0 ? undefined : "mine",
+ keyword:search,
+ page,
+ per_page:pageSize
+ }}).then((result)=>{
+ if(result){
+ this.setState({
+ libraries:result.data.libraries,
+ totalCount:result.data.count
+ })
+ }
+ }).catch((error)=>{
+ console.log(error);
+ })
+ }
+
+ // tab切换
+ changeType = (type) =>{
+ this.setState({
+ type,
+ page:1
+ })
+ let { search , page , pageSize } = this.state;
+ this.InitList(type,search,page,pageSize);
+ }
+
+ // 输入搜索内容
+ inputStudent=(e)=>{
+ this.setState({
+ search:e.target.value
+ })
+ }
+
+ // 搜索
+ searchInfo = () =>{
+ let { type , search , pageSize } = this.state;
+ this.InitList( type , search , 1 , pageSize );
+ }
+
+ // 切换分页
+ onChangePage =(pageNumber)=>{
+ this.setState({
+ page:pageNumber
+ })
+ let { type , search , pageSize } = this.state;
+ this.InitList( type , search , pageNumber , pageSize );
+ }
+
+ render(){
+ let { type , search ,libraries , totalCount ,pageSize ,page } = this.state;
+ return(
+
+
+
+
+
+ 教学案例
+ this.addQuestion(null, Q_TYPE_SINGLE)}>发布案例
+
+
+
+ - this.changeType(0)}>
+ 全部
+
+ - this.changeType(1)}>
+ 我的
+
+
+
+
+
+
+
+ {
+ libraries && libraries.length > 0 &&
+ }
+ {
+ libraries && libraries.length == 0 &&
+ }
+ {
+ totalCount && totalCount > pageSize &&
+
+ }
+
+
+ )
+ }
+}
+export default CaseList
\ No newline at end of file
diff --git a/public/react/src/modules/moop_cases/CaseNew.js b/public/react/src/modules/moop_cases/CaseNew.js
new file mode 100644
index 000000000..a388b482c
--- /dev/null
+++ b/public/react/src/modules/moop_cases/CaseNew.js
@@ -0,0 +1,381 @@
+import React,{ Component } from "react";
+import './css/moopCases.css'
+import '../courses/css/Courses.css'
+import { Form , Input , Upload , Button , Icon , message , Tooltip } from "antd";
+
+import { getImageUrl , MarkdownToHtml , ActionBtn , appendFileSizeToUploadFile , appendFileSizeToUploadFileAll , getUrl , getUploadActionUrl } from 'educoder';
+
+import Tags from './CaseTags'
+
+import axios from 'axios';
+import TPMMDEditor from '../tpm/challengesnew/TPMMDEditor';
+
+const { Dragger } = Upload;
+function beforeUpload(file) {
+ const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
+ if (!isJpgOrPng) {
+ message.error('You can only upload JPG/PNG file!');
+ }
+ const isLt2M = file.size / 1024 / 1024 < 2;
+ if (!isLt2M) {
+ message.error('Image must smaller than 2MB!');
+ }
+ return isJpgOrPng && isLt2M;
+}
+function getBase64(img, callback) {
+ const reader = new FileReader();
+ reader.addEventListener('load', () => callback(reader.result));
+ reader.readAsDataURL(img);
+}
+ const $ = window.$;
+class CaseNew extends Component{
+ constructor(props){
+ super(props);
+ this.DescMdRef = React.createRef();
+
+ this.state={
+ goldCases:false,
+ bankCases:false,
+ contentFileList:[],
+ imageUrl:undefined,
+ loading: false,
+ checkTag:false,
+ coverID:undefined
+ }
+ }
+
+ // 上传附件-删除确认框
+ onAttachmentRemove = (file, stateName) => {
+ this.props.confirm({
+ content: '是否确认删除?',
+ onOk: () => {
+ this.deleteAttachment(file, stateName)
+ },
+ onCancel() {
+ console.log('Cancel');
+ },
+ });
+ return false;
+ }
+
+ // 上传附件-确认删除
+ deleteAttachment = (file, stateName) => {
+ // 初次上传不能直接取uid
+ const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
+ axios.delete(url, {
+ }).then((response) => {
+ if (response.data) {
+ const { status } = response.data;
+ if (status == 0) {
+ console.log('--- success')
+
+ this.setState((state) => {
+ const index = state[stateName].indexOf(file);
+ const newFileList = state[stateName].slice();
+ newFileList.splice(index, 1);
+ return {
+ [stateName]: newFileList,
+ };
+ });
+ }
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ }
+ // 上传附件-change
+ handleContentUploadChange = (info) => {
+ let contentFileList = info.fileList;
+ this.setState({ contentFileList: appendFileSizeToUploadFileAll(contentFileList)});
+ }
+
+ // 上传封面图-change
+ handleChange = (info) => {
+ if (info.file.status === 'uploading') {
+ this.setState({ loading: true });
+ return;
+ }
+ if (info.file.status === 'done') {
+ // Get this url from response in real world.
+ getBase64(info.file.originFileObj, imageUrl =>
+ this.setState({
+ imageUrl,
+ loading: false
+ }),
+ );
+ console.log(info.file);
+ this.setState({
+ coverID:info.file.response && info.file.response.id
+ })
+ }
+ };
+
+ // 编辑时加载数据
+ componentDidMount=()=>{
+ if(this.props.match.params.caseID){
+ this.InitEditData();
+ }
+ }
+
+ componentDidUpdate=(prevState)=>{
+ if(this.props.CaseDetail && prevState.CaseDetail != this.props.CaseDetail){
+ this.props.form.setFieldsValue({
+ caseTitle:this.props.CaseDetail.title,
+ userName:this.props.CaseDetail.author_name,
+ userUnit:this.props.CaseDetail.author_school_name,
+ })
+ this.setState({
+ contentFileList:this.props.CaseDetail.attachments.map(item => {
+ return {
+ id: item.id,
+ uid: item.id,
+ name: appendFileSizeToUploadFile(item),
+ url: item.url,
+ filesize: item.filesize,
+ status: 'done'
+ }
+ }),
+ coverID:this.props.cover && this.props.cover.id,
+ imageUrl:this.props.CaseDetail.cover && getImageUrl(this.props.CaseDetail.cover.url)
+ })
+ this.props.tags.map((item)=>{
+ if(item.name=="入库案例"){
+ this.setState({bankCases:true})
+ }else{
+ this.setState({goldCases:true})
+ }
+ })
+ }
+ }
+
+ InitEditData=()=>{
+ let caseID = this.props.match.params.caseID;
+ this.props.getDetail(caseID);
+ }
+
+ // 申请提交和保存
+ handleSubmit = (type) => {
+ console.log(type);
+ this.props.form.validateFieldsAndScroll((err, values) => {
+ let { goldCases , bankCases } = this.state;
+ if(!goldCases && !bankCases){
+ $("html").animate({ scrollTop: $("#tagFormItem").offset().top - 100 });
+ this.setState({
+ checkTag:true
+ })
+ return;
+ }
+ const mdContnet = this.DescMdRef.current.getValue().trim();
+ console.log(values);
+ let url=`/libraries/:id.json`;
+ // axios.put(())
+ })
+ }
+
+ // 选择标签
+ changeType=(type)=>{
+ let { goldCases , bankCases } = this.state;
+ if(type=="gold"){
+ this.setState({
+ goldCases:!goldCases
+ })
+ }else{
+ this.setState({
+ bankCases:!bankCases
+ })
+ }
+ if(!goldCases == true || !bankCases == true){
+ this.setState({checkTag:false})
+ }
+ }
+
+ render(){
+ let { caseID } = this.props.match.params;
+ let { CaseDetail } = this.props;
+ let { goldCases , bankCases , contentFileList , imageUrl , checkTag } = this.state;
+ const {getFieldDecorator} = this.props.form;
+
+
+ // 上传附件点击事件
+ const uploadProps = {
+ width: 600,
+ multiple: true,
+ fileList:contentFileList,
+ action: `${getUploadActionUrl()}`,
+ onChange: this.handleContentUploadChange,
+ onRemove: (file) => this.onAttachmentRemove(file, 'contentFileList'),
+ beforeUpload: (file) => {
+ const isLt150M = file.size / 1024 / 1024 < 150;
+ if (!isLt150M) {
+ message.error('文件大小必须小于150MB!');
+ }
+ return isLt150M;
+ }
+ };
+ // 上传封面图-html
+ const uploadButton = (
+
+
+
+ );
+ // 上传封面图点击事件
+ const uploadCover = {
+ listType:"picture-card",
+ className:"avatar-uploader",
+ showUploadList:false,
+ action:`${getUploadActionUrl()}`,
+ onChange:this.handleChange,
+ }
+ return(
+
+
+
+ 教学案例 > { caseID ? "编辑" : "新建" }
+
+
上传教学案例
+
+
+
+
+
+ )
+ }
+}
+const WrappedCoursesNewApp = Form.create({name: 'CaseNew'})(CaseNew);
+export default WrappedCoursesNewApp;
\ No newline at end of file
diff --git a/public/react/src/modules/moop_cases/CaseTags.js b/public/react/src/modules/moop_cases/CaseTags.js
index 0826b8645..4b4f0670c 100644
--- a/public/react/src/modules/moop_cases/CaseTags.js
+++ b/public/react/src/modules/moop_cases/CaseTags.js
@@ -14,7 +14,7 @@ class CaseTags extends Component{
{
tags && tags.map((item,key)=>{
return(
- {item}
+ {item.name}
)
})
}
diff --git a/public/react/src/modules/moop_cases/css/moopCases.css b/public/react/src/modules/moop_cases/css/moopCases.css
index 95e539c7b..a840d0682 100644
--- a/public/react/src/modules/moop_cases/css/moopCases.css
+++ b/public/react/src/modules/moop_cases/css/moopCases.css
@@ -41,10 +41,101 @@
border: 1px solid #FC2B6A;
line-height: 17px;
}
+.edu-activity-green {
+ background-color: green;
+ color: #fff!important;
+ cursor: pointer;
+ border: 1px solid green;
+ line-height: 17px;
+}
.edu-activity-blue {
background-color: #4CACFF;
color: #fff!important;
cursor: pointer;
border: 1px solid #4CACFF;
line-height: 17px;
+}
+
+.pointsBtn {
+ width: 70px;
+ height: 70px;
+ background-color: #4cacff;
+ border-radius: 50%;
+ color: #fff;
+ text-align: center;
+ margin: 0 auto;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ padding: 2px 0;
+ cursor: pointer;
+ line-height: 22px;
+ padding-top: 12px;
+}
+.pointedBtn{
+ background: #BCD1E3;
+ cursor: default
+}
+.pointsBtn span{
+ display: block;
+}
+.upload_Title {
+ position: relative;
+ margin-right: 20px;
+ float: left;
+ line-height: 35px;
+ font-size: 16px;
+ width: 56px;
+ color:rgba(0, 0, 0, 0.85);
+ text-align: center
+}
+.upload_Title.must:before {
+ display: inline-block;
+ margin-right: 4px;
+ color: #f5222d;
+ font-size: 14px;
+ font-family: SimSun, sans-serif;
+ line-height: 1;
+ content: '*';
+}
+.upload_Title:after{
+ content: ':';
+ position: relative;
+ top: -0.5px;
+ margin: 0 8px 0 2px;
+}
+.libraries_tab li {
+ width: 120px;
+ height: 35px;
+ line-height: 33px;
+ border-radius: 18px;
+ border: 1px solid #4C98FF;
+ color: #4C98FF;
+ cursor: pointer;
+ margin-right: 30px;
+ float: left;
+ text-align: center;
+}
+.libraries_tab li.active {
+ background: #4C98FF;
+ color: #fff;
+}
+.librariesField .ant-upload{
+ width: 100%;
+ background: #F2F9FF;
+ justify-content: center;
+ align-items: center;
+ display: -webkit-flex;
+ text-align: center;
+ height: 120px!important;
+ border-radius: 4px;
+ border: 1px dashed #4cacff!important;
+ display: block;
+ cursor: pointer;
+}
+.uploadImage .ant-upload.ant-upload-select-picture-card{
+ width:120px;
+ height: 90px;
+}
+.uploadImage .ant-upload.ant-upload-select-picture-card > .ant-upload{
+ padding:0px!important;
}
\ No newline at end of file
diff --git a/public/react/src/modules/moop_cases/index.js b/public/react/src/modules/moop_cases/index.js
index f35925388..91c3557b8 100644
--- a/public/react/src/modules/moop_cases/index.js
+++ b/public/react/src/modules/moop_cases/index.js
@@ -1,133 +1,117 @@
import React,{ Component } from "react";
-import { Input , Spin , Pagination } from "antd";
import './css/moopCases.css'
import '../courses/css/Courses.css'
-import { SnackbarHOC , ActionBtn , WordsBtn } from 'educoder';
+import { SnackbarHOC } from 'educoder';
+
import { TPMIndexHOC } from '../tpm/TPMIndexHOC';
import { CNotificationHOC } from '../courses/common/CNotificationHOC'
-import axios from 'axios'
+import {BrowserRouter as Router,Route,Switch} from 'react-router-dom';
+import Loading from '../../Loading';
+import Loadable from 'react-loadable';
+
+import axios from 'axios';
-import NoneData from '../courses/coursesPublic/NoneData'
+const CaseList = Loadable({
+ loader: () => import('./CaseList'),
+ loading:Loading,
+})
+const CaseDetail = Loadable({
+ loader: () => import('./CaseDetail'),
+ loading:Loading,
+})
+const CaseNew = Loadable({
+ loader: () => import('./CaseNew'),
+ loading:Loading,
+})
-import mainImg from '../../images/moop_cases/teach_ex.jpg'
-import CaseItem from './CaseItem'
-const Search = Input.Search;
class Index extends Component{
constructor(props){
super(props);
this.state={
- type:0,
- search:undefined,
- page:1,
- pageSize:20,
- libraries:undefined,
- totalCount:undefined
+ praise_count:0,
+ CaseDetail:undefined,
+ cover:undefined,
+ creator:undefined,
+ operation:undefined,
+ tags:undefined,
+ attachments:undefined,
+ user_praised:true,
}
}
-
- componentDidMount = () =>{
- let { type , search , page , pageSize } = this.state;
- this.InitList(type,search,page,pageSize);
- }
-
- // 列表
- InitList = (type,search,page,pageSize) =>{
- let url = `/libraries.json`;
- axios.get(url,{params:{
- type:type == 0 ? undefined : "mine",
- keyword:search,
- page,
- per_page:pageSize
- }}).then((result)=>{
+ // 获取案例详情
+ getDetail = (caseID) =>{
+ let url=`/libraries/${caseID}.json`
+ axios.get(url).then((result)=>{
if(result){
this.setState({
- libraries:result.data.libraries,
- totalCount:result.data.count
+ CaseDetail:result.data,
+ praise_count:result.data.praise_count,
+ cover:result.data.cover,
+ creator:result.data.creator,
+ operation:result.data.operation,
+ user_praised:result.data.operation.user_praised,
+ tags:result.data.tags,
+ attachments:result.data.attachments
})
}
}).catch((error)=>{
console.log(error);
})
}
-
- // tab切换
- changeType = (type) =>{
- this.setState({
- type,
- page:1
- })
- let { search , page , pageSize } = this.state;
- this.InitList(type,search,page,pageSize);
- }
-
- // 输入搜索内容
- inputStudent=(e)=>{
- this.setState({
- search:e.target.value
- })
- }
-
- // 搜索
- searchInfo = () =>{
- let { type , search , pageSize } = this.state;
- this.InitList( type , search , 1 , pageSize );
- }
-
- // 切换分页
- onChangePage =(pageNumber)=>{
- this.setState({
- page:pageNumber
- })
- let { type , search , pageSize } = this.state;
- this.InitList( type , search , pageNumber , pageSize );
+ // 点赞
+ praisePoint=(caseID)=>{
+ let { praise_count }=this.state;
+ let url =`/praise_tread/like.json`;
+ axios.post(url,{
+ object_id:caseID,
+ object_type:"library"
+ }).then((result)=>{
+ if(result){
+ this.setState({
+ praise_count: parseInt(praise_count)+1,
+ user_praised:true
+ })
+ }
+ }).catch((error)=>{
+ console.log(error);
+ })
}
render(){
- let { type , search ,libraries , totalCount ,pageSize ,page } = this.state;
+
return(
-

-
-
-
- 教学案例
- this.addQuestion(null, Q_TYPE_SINGLE)}>发布案例
-
-
-
- - this.changeType(0)}>
- 全部
-
- - this.changeType(1)}>
- 我的
-
-
-
-
-
-
-
- {
- libraries && libraries.length > 0 &&
- }
- {
- libraries && libraries.length == 0 &&
- }
- {
- totalCount && totalCount > pageSize &&
-
- }
-
+
+
+ ()
+ }
+ >
+
+ ()
+ }
+ >
+
+ ()
+ }
+ >
+
+
+ ()
+ }
+ >
+
+
)
}