Commit bb463d63 by zhanghaozhe

Merge branch 'intelligent-recommend' into pre

# Conflicts:
#	build/asset-manifest.json
#	build/index.html
#	build/mrstatic/js/65.eec31f7c.chunk.js.map
#	build/mrstatic/js/BargainMiddlePage.b3e90217.chunk.js.map
#	build/mrstatic/js/main.c3c8406b.chunk.js.map
#	build/mrstatic/js/python-class.43c9fac3.chunk.js.map
#	build/service-worker.js
parents 23c92358 9e0b8956
This source diff could not be displayed because it is too large. You can view the blob instead.
!function(e){function r(r){for(var a,n,f=r[0],d=r[1],i=r[2],s=0,b=[];s<f.length;s++)n=f[s],o[n]&&b.push(o[n][0]),o[n]=0;for(a in d)Object.prototype.hasOwnProperty.call(d,a)&&(e[a]=d[a]);for(u&&u(r);b.length;)b.shift()();return c.push.apply(c,i||[]),t()}function t(){for(var e,r=0;r<c.length;r++){for(var t=c[r],a=!0,n=1;n<t.length;n++){var d=t[n];0!==o[d]&&(a=!1)}a&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var a={},n={36:0},o={36:0},c=[];function f(r){if(a[r])return a[r].exports;var t=a[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.e=function(e){var r=[];n[e]?r.push(n[e]):0!==n[e]&&{1:1,3:1,4:1,5:1,6:1,7:1,8:1,9:1,10:1,11:1,12:1,14:1,16:1,17:1,18:1,19:1,20:1,21:1,22:1,23:1,24:1,25:1,26:1,27:1,28:1,30:1,31:1,32:1,33:1,34:1,35:1,37:1,38:1,39:1,40:1,41:1,42:1,43:1,44:1,47:1,48:1,49:1,50:1,51:1,52:1,53:1,54:1,55:1,57:1,58:1,59:1,60:1,62:1,63:1,64:1,65:1}[e]&&r.push(n[e]=new Promise(function(r,t){for(var a="mrstatic/css/"+({5:"Activity",6:"BargainMiddlePage",7:"Classify",8:"Country",9:"CourseList",10:"DrawDocument",11:"Examination",12:"Invite",13:"MyEdit",14:"Order",15:"Orderinfo",16:"PayOrder",17:"Preferential",18:"SearchResult",19:"ShareCourse",20:"ShopCart",21:"aist-share",22:"blessing-getPrize",23:"blessing-preheat",24:"blessing-rank",25:"coupons",26:"deposit-order",27:"deposit-pay-order",28:"detail",30:"myorders",31:"newyear-2019-landing",32:"newyear-yearIndex",33:"prize-winner-list",34:"purchased",35:"python-class",37:"search",38:"shareposter",39:"study",40:"system-notices",41:"togroup",42:"treasure-box-home",43:"treasure-box-mybox",44:"video"}[e]||e)+"."+{0:"31d6cfe0",1:"bff22cf8",2:"31d6cfe0",3:"5ed15c7e",4:"0dc24c6e",5:"a74b39fb",6:"31cef199",7:"f2f19957",8:"16a64650",9:"47812ac6",10:"2e7d81ca",11:"f2cc3163",12:"361dc1a3",13:"31d6cfe0",14:"35f475a1",15:"31d6cfe0",16:"e5315535",17:"18d20d0c",18:"bb7c3056",19:"278ad3b1",20:"3a4dbb7a",21:"ca49c1cb",22:"951fd27d",23:"715eb28a",24:"b92d0394",25:"c10ecc19",26:"6f3a01ca",27:"219bad3d",28:"975c864b",30:"3c41b358",31:"b0d930fa",32:"fe0d87a6",33:"55e46fc9",34:"f583a040",35:"087d6571",37:"38c3e634",38:"f09a5959",39:"e406d228",40:"08df3d15",41:"49988cae",42:"742fb589",43:"b84e2e84",44:"e2426591",46:"31d6cfe0",47:"50547718",48:"bd362b42",49:"17c0e036",50:"2471f477",51:"0bb224f2",52:"ecbb6f9a",53:"9f46e45e",54:"ee45d0b0",55:"4723f76a",56:"31d6cfe0",57:"ab7f5e40",58:"4c85e85c",59:"470b9744",60:"10a4034d",61:"31d6cfe0",62:"697fa90d",63:"eb90513f",64:"5fba4ed0",65:"e51ea0fc"}[e]+".chunk.css",o=f.p+a,c=document.getElementsByTagName("link"),d=0;d<c.length;d++){var i=(u=c[d]).getAttribute("data-href")||u.getAttribute("href");if("stylesheet"===u.rel&&(i===a||i===o))return r()}var s=document.getElementsByTagName("style");for(d=0;d<s.length;d++){var u;if((i=(u=s[d]).getAttribute("data-href"))===a||i===o)return r()}var b=document.createElement("link");b.rel="stylesheet",b.type="text/css",b.onload=r,b.onerror=function(r){var a=r&&r.target&&r.target.src||o,c=new Error("Loading CSS chunk "+e+" failed.\n("+a+")");c.request=a,delete n[e],b.parentNode.removeChild(b),t(c)},b.href=o,document.getElementsByTagName("head")[0].appendChild(b)}).then(function(){n[e]=0}));var t=o[e];if(0!==t)if(t)r.push(t[2]);else{var a=new Promise(function(r,a){t=o[e]=[r,a]});r.push(t[2]=a);var c,d=document.createElement("script");d.charset="utf-8",d.timeout=120,f.nc&&d.setAttribute("nonce",f.nc),d.src=function(e){return f.p+"mrstatic/js/"+({5:"Activity",6:"BargainMiddlePage",7:"Classify",8:"Country",9:"CourseList",10:"DrawDocument",11:"Examination",12:"Invite",13:"MyEdit",14:"Order",15:"Orderinfo",16:"PayOrder",17:"Preferential",18:"SearchResult",19:"ShareCourse",20:"ShopCart",21:"aist-share",22:"blessing-getPrize",23:"blessing-preheat",24:"blessing-rank",25:"coupons",26:"deposit-order",27:"deposit-pay-order",28:"detail",30:"myorders",31:"newyear-2019-landing",32:"newyear-yearIndex",33:"prize-winner-list",34:"purchased",35:"python-class",37:"search",38:"shareposter",39:"study",40:"system-notices",41:"togroup",42:"treasure-box-home",43:"treasure-box-mybox",44:"video"}[e]||e)+"."+{0:"e278c735",1:"8ccb3ba2",2:"b3ec967c",3:"846255e3",4:"2cbd2115",5:"7ec7f2b9",6:"b3e90217",7:"9026b6f9",8:"87d90b89",9:"b9772b84",10:"749c0360",11:"db75562e",12:"03ba786f",13:"4751204d",14:"8ed15331",15:"2de132f2",16:"6fb43349",17:"40f0edaf",18:"d96f36a5",19:"4c634bea",20:"1727e020",21:"aa06950a",22:"b3da729d",23:"ff4bbf80",24:"c392e4f0",25:"000af26b",26:"3ae30112",27:"284eb346",28:"681ee242",30:"2f01329e",31:"d13568be",32:"51653ba5",33:"c127a088",34:"148df373",35:"43c9fac3",37:"2aee0468",38:"3c664772",39:"be29f8a9",40:"3b3e0b79",41:"0ebabd0d",42:"d7397e33",43:"420feb62",44:"48b188d9",46:"26572008",47:"9aa693c2",48:"30bc711f",49:"15508182",50:"feb9bfd4",51:"f1e8d0d1",52:"5b89cb08",53:"ed8fa7d4",54:"0621bfa4",55:"2f33452a",56:"81962ecf",57:"965079f4",58:"1583e048",59:"f9091165",60:"72a77810",61:"b36c1038",62:"185f011f",63:"56faee3e",64:"a1498af9",65:"eec31f7c"}[e]+".chunk.js"}(e),c=function(r){d.onerror=d.onload=null,clearTimeout(i);var t=o[e];if(0!==t){if(t){var a=r&&("load"===r.type?"missing":r.type),n=r&&r.target&&r.target.src,c=new Error("Loading chunk "+e+" failed.\n("+a+": "+n+")");c.type=a,c.request=n,t[1](c)}o[e]=void 0}};var i=setTimeout(function(){c({type:"timeout",target:d})},12e4);d.onerror=d.onload=c,document.head.appendChild(d)}return Promise.all(r)},f.m=e,f.c=a,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"===typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var a in e)f.d(t,a,function(r){return e[r]}.bind(null,a));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/",f.oe=function(e){throw console.error(e),e};var d=window.webpackJsonp=window.webpackJsonp||[],i=d.push.bind(d);d.push=r,d=d.slice();for(var s=0;s<d.length;s++)r(d[s]);var u=i;t()}([]);
//# sourceMappingURL=runtime~main.2d297271.js.map
\ No newline at end of file
(window.webpackJsonp=window.webpackJsonp||[]).push([[39],{1188:function(e,t,a){"use strict";a.r(t);var c=a(3),s=a(5),n=a(4),r=a(6),i=a(7),o=a(0),l=a.n(o),m=(a(679),a(14)),u=a(46),d=a(461),p=(a(680),a(1191)),h=a(1176),v=a(20),f=a(79),E=a(503),g=a.n(E),b=a(38),y=a(23);var N=l.a.memo(function(e){var t=e.addCourseClick;return l.a.createElement("div",{className:"add-course"},l.a.createElement("button",{className:"add",onClick:t},"\u6dfb\u52a0\u8bfe\u7a0b+"))});function _(e){var t=e.record,a=t.seconds,c=t.lesson_name,s="";if(c){var n=/\u7b2c[\s\S]+?\u8bfe/.exec(c);s+=n&&n[0]?n[0]:""}if(a){var r=function(e){return{hour:Math.floor(e/3600),min:Math.floor(e/60)%60,sec:e%60}}(a);s+=(r.hour?String(r.hour).padStart(2,"0")+":":"")+(r.min?String(r.min).padStart(2,"0")+":":"")+(r.sec?String(r.sec).padStart(2,"0"):"")}return l.a.createElement("span",{className:"record"},s.length?"\u5b66\u4e60\u5230".concat(s):null)}var C=l.a.memo(function(e){var t=e.item;if(t.ago||t.seconds){var a=new Date(1e3*t.ago),c=Object(p.a)(a)?Object(h.a)(a,"HH\u65f6mm\u5206"):Object(h.a)(a,"MM\u6708dd\u65e5");return l.a.createElement("div",{className:"des"},l.a.createElement("span",{className:"time"},c),l.a.createElement(_,{record:t}))}return l.a.createElement("button",{className:"start-learn"},"\u5f00\u59cb\u5b66\u4e60")}),k=function(e){function t(){var e,a;Object(c.a)(this,t);for(var s=arguments.length,i=new Array(s),o=0;o<s;o++)i[o]=arguments[o];return(a=Object(n.a)(this,(e=Object(r.a)(t)).call.apply(e,[this].concat(i)))).state={isLoading:!0},a.handleClick=function(e,t){var c=a.props.history,s=t.mode,n=t.course_id;s&&6==s?c.push("/python?id=".concat(n)):c.push("/play/video?id=".concat(e))},a.addCourseClick=function(){a.props.history.push("/classify")},a.loadFunc=Object(b.debounce)(function(){a.props.courseList.length%10===0&&a.props.fetchCoursesListIfNeeded()},200),a}return Object(i.a)(t,e),Object(s.a)(t,[{key:"componentDidMount",value:function(){this.props.switchTab(!1),this.props.fetchCoursesListIfNeeded()}},{key:"componentWillUnmount",value:function(){this.props.switchTab(!0)}},{key:"render",value:function(){var e=this,t=this.props,a=t.courseList,c=t.user;return l.a.createElement(y.f,{isLoading:this.props.isLoading},a&&0!==a.length?l.a.createElement(l.a.Fragment,null,l.a.createElement("div",{className:"my-course-uid"},"\u52a0\u7fa4\u8bf7\u5907\u6ce8\u60a8\u7684\u5b66\u53f7\uff1a".concat(!c.hasError&&this.props.user.data.uid)),l.a.createElement(g.a,{pageStart:0,hasMore:!0,loadMore:this.loadFunc,useWindow:!1},l.a.createElement("ul",{ref:function(t){return e.list=t}},a.map(function(t,a){var c=l.a.createElement("div",{className:"info"},l.a.createElement("div",{className:"title"},t.course_title),!t.is_restricted&&t.is_aist&&l.a.createElement("div",{className:"contact"},"\u52a9\u6559\u5fae\u4fe1\uff1a",t.assist_weixin),!t.is_restricted&&!t.is_aist&&1==t.contact_type&&t.course_qq&&l.a.createElement("div",{className:"contact"},"QQ\u7fa4\uff1a",t.course_qq),!t.is_restricted&&!t.is_aist&&2==t.contact_type&&t.course_qq&&l.a.createElement("div",{className:"contact"},"\u73ed\u4e3b\u4efb\u5fae\u4fe1\uff1a",t.course_qq),t.is_aist&&t.aist_schedule&&l.a.createElement("div",{className:"process-status"},l.a.createElement("div",{className:"process-wrapper"},l.a.createElement("div",{className:"process-bar",style:{width:"".concat(parseFloat(t.aist_schedule),"%")}})),l.a.createElement("div",{className:"process-text"},t.aist_schedule)),l.a.createElement(C,{item:t})),s=t.is_aist?l.a.createElement("span",{className:"status"},"\u8fd4\u73b0"):t.course_expire?l.a.createElement("span",{className:"course-expire"},t.course_expire):null;return l.a.createElement(d.a,Object.assign({img:t.image_name,handleClick:e.handleClick},t,{key:a,info:c,status:s,item:t,id:t.v_course_id}))}))),a.length%10!==0?l.a.createElement(N,{addCourseClick:this.addCourseClick}):null):l.a.createElement("div",{className:"empty"},l.a.createElement("p",null,l.a.createElement("i",{className:"iconfont iconfish"})),l.a.createElement("p",{className:"empty-prompt"},"\u60a8\u8fd8\u6ca1\u6709\u8bfe\u7a0b\u54e6\uff0c\u8d76\u5feb\u53bb\u9009\u8bfe\u5427~"),l.a.createElement("p",null,l.a.createElement(m.b,{className:"select-course",to:"/classify"},"\u53bb\u9009\u8bfe"))))}}]),t}(o.Component),j=Object(v.b)(function(e){return{courseList:e.myCourses.courseList,user:e.user,isLoading:e.myCourses.isLoading}},{fetchCoursesListIfNeeded:f.e,switchTab:f.f})(k),w=(a(37),a(10)),O=a.n(w),L=(a(681),function(e){return l.a.createElement("li",{className:"course-base-item ".concat(e.className),onClick:e.handleClick.bind(void 0,e.id)},e.top,l.a.createElement("img",{src:e.img,alt:""}),l.a.createElement("p",{className:"course-title"},e.title),e.bottom)}),M=a(2),S=a(17),F=a.n(S),x=(a(87),a(682),function(e){return l.a.createElement("div",{className:"bottom"},l.a.createElement(y.i,{className:e.className},e.text),l.a.createElement("span",null,e.audience,"\u4eba\u89c2\u770b"))}),q=function(e){function t(){var e,a;Object(c.a)(this,t);for(var s=arguments.length,i=new Array(s),o=0;o<s;o++)i[o]=arguments[o];return(a=Object(n.a)(this,(e=Object(r.a)(t)).call.apply(e,[this].concat(i)))).page=1,a.num=10,a.state={courses:[],live:[],page:1,hasMore:!1},a.handleClick=function(e){a.props.history.push("/play/video?id=".concat(e))},a.getFreeCourses=function(){return M.e.get("".concat(API.home,"/m/free_course/").concat(a.page++,"/").concat(a.num))},a.getFreeLive=function(){return M.e.get("".concat(API.home,"/m/live/free_list"))},a.toLive=function(e){var t=e.room_id;e.live_status?window.location.assign("http://www.julyedu.com/live/m_room/".concat(t)):O.a.info("\u76f4\u64ad\u5373\u5c06\u5f00\u59cb\uff0c\u656c\u8bf7\u671f\u5f85",2,null,!1)},a.loadFunc=function(){a.state.hasMore&&a.setState({hasMore:a.state.courses.length%10===0},function(){a.getFreeCourses().then(function(e){var t=e.data;200==t.code?Array.isArray(t.data)&&a.setState({courses:a.state.courses.concat(t.data),hasMore:t.data.length%10===0}):O.a.info(t.msg)})})},a}return Object(i.a)(t,e),Object(s.a)(t,[{key:"componentDidMount",value:function(){var e=this;this.getFreeCourses().then(function(t){var a=t.data;200==a.code?e.setState({courses:a.data,hasMore:!0}):O.a.info(a.msg)}),this.getFreeLive().then(function(t){var a=t.data;200==a.code?e.setState({live:Object(b.isEmpty)(a.data)?[]:a.data}):O.a.info(a.msg,2,null,!1)})}},{key:"render",value:function(){var e=this;return l.a.createElement(g.a,{pageStart:0,loadMore:this.loadFunc,useWindow:!1,className:"free-courses",element:"ul",hasMore:this.state.hasMore,threshold:250},this.state.live.map(function(t,a){var c=l.a.createElement("div",{className:"bottom"},l.a.createElement("div",{className:"animation-box"},new Array(4).fill("a").map(function(e,t){return l.a.createElement("i",{key:t,className:F()("column","column-".concat(t+1))})})),l.a.createElement("div",{className:"time"},"".concat(t.live_start_time))),s=0==t.live_status?l.a.createElement(y.i,{className:"tag-soon top"},"\u5373\u5c06\u5f00\u59cb"):l.a.createElement(y.i,{className:"tag-playing top"},"\u6b63\u5728\u76f4\u64ad");return l.a.createElement(L,{img:t.live_cover,title:t.live_title,top:s,bottom:c,key:t.live_id,className:"live",handleClick:e.toLive.bind(e,t),id:a})}),this.state.courses.map(function(t,a){return l.a.createElement(L,{img:t.logo,title:t.video_course_name,handleClick:e.handleClick,bottom:l.a.createElement(x,{audience:t.play_times,className:"tag-category",text:t.category}),id:t.v_course_id,key:a,className:"course-item"})}))}}]),t}(o.PureComponent),A=a(150),I=a(143),D=a(24),P=function(e){function t(){var e,a;Object(c.a)(this,t);for(var s=arguments.length,i=new Array(s),o=0;o<s;o++)i[o]=arguments[o];return(a=Object(n.a)(this,(e=Object(r.a)(t)).call.apply(e,[this].concat(i)))).state={position:{}},a}return Object(i.a)(t,e),Object(s.a)(t,[{key:"render",value:function(){var e=this.props.match;return l.a.createElement("section",{id:"study"},l.a.createElement("div",{className:"tab"},l.a.createElement("div",null,l.a.createElement(m.c,{to:"".concat(e.url,"/my-course"),replace:!0,activeClassName:"active"},"\u6211\u7684\u8bfe\u7a0b")),l.a.createElement("div",null,l.a.createElement(m.c,{to:"".concat(e.url,"/free-course"),replace:!0,activeClassName:"active"},"\u514d\u8d39\u8bfe\u7a0b"))),l.a.createElement("div",{className:"study-container"},l.a.createElement(u.d,null,l.a.createElement(u.a,{exact:!0,from:"/study",to:"study/my-course"}),l.a.createElement(u.b,{path:"".concat(this.props.match.path,"/my-course"),component:j}),l.a.createElement(u.b,{path:"".concat(this.props.match.path,"/free-course"),component:q}))))}}]),t}(o.Component);t.default=Object(D.d)(I.a,A.a)(P)},461:function(e,t,a){"use strict";var c=a(0),s=a.n(c);a(462);t.a=function(e){return s.a.createElement("li",{className:"v-list-base-item",onClick:e.handleClick.bind(void 0,e.id,e.item)},s.a.createElement("div",{className:"content"},s.a.createElement("div",{className:"cover"},e.status,s.a.createElement("img",{src:e.img,alt:""})),e.info),e.tab)}},462:function(e,t,a){},679:function(e,t,a){},680:function(e,t,a){},681:function(e,t,a){},682:function(e,t,a){}}]);
//# sourceMappingURL=study.be29f8a9.chunk.js.map
\ No newline at end of file
......@@ -29,7 +29,7 @@ class App extends Component {
super(props)
this.state = {
isShowActivityEntry: 0,
isShowChannel: 0
isShowChannel: 0,
}
this.globalEntry = null
}
......@@ -72,7 +72,6 @@ class App extends Component {
const {history} = this.props
this.setNavigationRecord(this.props.location, this.props.history.action)
this.setPreviousLocation()
......@@ -96,9 +95,9 @@ class App extends Component {
from: {
pathname: this.previousLocation.pathname,
search: this.previousLocation.search,
hash: this.previousLocation.hash
}
}
hash: this.previousLocation.hash,
},
},
}
} else {
this.removeShareCodeCookie()
......@@ -115,7 +114,7 @@ class App extends Component {
// treasure_stage,宝箱阶段,0-不在活动时间,1-活动时间内
this.setState({
isShowActivityEntry: data.treasure_stage,
isShowChannel: data.is_show_site_window_by_channel
isShowChannel: data.is_show_site_window_by_channel,
}, () => {
data.treasure_stage && this.bindGlobalEntry()
})
......@@ -143,13 +142,12 @@ class App extends Component {
const {pathname, search, hash} = location
let isLastRecord = location.pathname === (this.records.length && this.records[this.records.length - 1].pathname)
let needHistoryMutation = location.pathname !== this.previousLocation.pathname
switch (action) {
case 'POP':
if (needHistoryMutation) {
this.firstLoad ? this.records.push({pathname, search, hash}) : this.records.pop()
} else {
this.records[this.records.length - 1] = location
this.records.length ? (this.records[this.records.length - 1] = location) : this.records = [location]
}
break
case 'REPLACE':
......@@ -161,8 +159,10 @@ class App extends Component {
location.state && location.state.records
? (location.state.records = this.records)
: location.state ? location.state = {...location.state, records: this.records}
: (location.state = {records: this.records})
: location.state ? location.state = {
...location.state,
records: this.records,
} : (location.state = {records: this.records})
}
......@@ -172,7 +172,7 @@ class App extends Component {
if (zhihu_cb) {
let data = {
'zhihu_cb': zhihu_cb
'zhihu_cb': zhihu_cb,
}
http.post(`${API['home']}/sys/zhihu/firstRecord`, data)
......@@ -254,8 +254,8 @@ class App extends Component {
user_name: username,
is_vip: isVIP,
uid,
code
}
code,
},
} = res.data
payload = {
......@@ -266,15 +266,15 @@ class App extends Component {
isVIP,
avatar,
uid,
code
}
code,
},
}
} else {
payload = {
hasError: true,
msg: res.data.msg,
code: res.data.code,
data: {}
data: {},
}
}
return payload
......@@ -285,7 +285,7 @@ class App extends Component {
if (data.errno == 200) {
//移除红包统计cookie
this.removeShareCodeCookie()
let {uid, token, avatar_file: avatar, uname: username,} = data.data
let {uid, token, avatar_file: avatar, uname: username} = data.data
return {
hasError: false,
......@@ -293,9 +293,9 @@ class App extends Component {
uid,
token,
avatar,
username
username,
},
msg: data.msg
msg: data.msg,
}
} else {
let {code, msg} = data.data
......@@ -303,7 +303,7 @@ class App extends Component {
code,
msg,
hasError: true,
data: {}
data: {},
}
}
}
......@@ -339,7 +339,7 @@ class App extends Component {
closeGlobalEntry = () => {
localStorage.setItem('globalEntryClosedTime', Date.now().toString())
this.setState({
isShowActivityEntry: 0
isShowActivityEntry: 0,
})
}
......@@ -375,7 +375,7 @@ class App extends Component {
export default compose(
connect(
state => ({user: state.user}),
{setCurrentUser, startFetchUser}
{setCurrentUser, startFetchUser},
),
withRouter
withRouter,
)(App)
......@@ -17,7 +17,7 @@ import AllCourseNavigation from "./all-course"
// const animateTypes = Swiper.animateTypes
@connect(state => ({
user: state.user
user: state.user,
}))
class Index extends Component {
constructor(props) {
......@@ -33,28 +33,28 @@ class Index extends Component {
{
'src': require('./image/freeclass_icon.png'),
'name': '公开课',
'href': '/study/free-course'
'href': '/study/free-course',
},
{
'src': require('./image/jingpin_icon.png'),
'name': '精品特惠',
'href': '/preferential'
'href': '/preferential',
},
{
'src': require('./image/zjxj_icon.png'),
'name': '赚奖学金',
'href': '/scholarship'
'href': '/scholarship',
},
{
'src': require('./image/mryt_icon.png'),
'name': '每日一题',
'href': '/examination'
'href': '/examination',
},
{
'src': require('./image/shequ_icon.png'),
'name': '社区',
'href': 'https://ask.julyedu.com'
}
'href': 'https://ask.julyedu.com',
},
],
}
}
......@@ -72,7 +72,7 @@ class Index extends Component {
this.setState({
banner: data.banner,
lives: data.lives,
modules
modules,
})
} else {
Toast.info(res.data.msg, 2)
......@@ -93,7 +93,7 @@ class Index extends Component {
this.setState({
isShow: true,
islive: true,
roomMess: item
roomMess: item,
})
} else {
window.location.href = `${window.location.href.includes('pre') ? 'http://www-pre.julyedu.com' : 'http://www.julyedu.com'}/live/m_room/${item.room_id}`
......@@ -119,15 +119,23 @@ class Index extends Component {
src="http://julyedu-img-public.oss-cn-beijing.aliyuncs.com/Public/img/index/logo.png"
alt=""
/>
<CallApp
{/* <CallApp
className='to-app'
text='在APP打开'
/>
/>*/}
<div className="right">
<Link to={'/intelligent-recommend'}>
<span className={'intelligent-recommend-entry'}>
<i className={'mind-icon'}></i>
智能选课
</span>
</Link>
<i
className='iconfont iconiconfront- search'
onClick={this.toSearch.bind(this)}
/>
</div>
</div>
<div className='zw_height'></div>
......
......@@ -34,6 +34,29 @@
vertical-align: top;
}
.right {
float: right;
height: 100%;
}
.intelligent-recommend-entry {
float: left;
margin-right: 20px;
font-size: 14px;
color: #09f;
line-height: 24px;
.mind-icon {
display: inline-block;
width: 16px;
height: 16px;
margin-right: 4px;
background: url("./image/mind-icon.png") no-repeat;
background-size: contain;
vertical-align: middle;
}
}
.search {
font-size: 22px !important;
float: right;
......@@ -88,6 +111,7 @@
.category {
width: 100%;
padding: 20px 15px 15px 15px;
.swiper-container {
height: 106px !important;
margin-top: 15px;
......@@ -263,7 +287,6 @@
}
/*
横向滚动
*/
......
import React, {Component} from 'react'
import {HeaderBar} from '@/common'
import {http} from '@/utils'
import React, { Component } from 'react'
import { HeaderBar } from '@/common'
import { getParam, http } from '@/utils'
import './index.scss'
import QRCode from 'qrcode'
import html2canvas from 'html2canvas'
import scoreIconL from '@assets/image/score_icon-l.png'
import scoreIconR from '@assets/image/score_icon-r.png'
import scoreReportBg from '@assets/image/scoreReport_bg.png'
import {connect} from "react-redux"
import { connect } from "react-redux"
@connect(state => ({
user: state.user,
......@@ -23,7 +23,7 @@ class scoreReport extends Component {
myRankList: '',
imgUrl: '',
codeSrc: '',
avatar_file: ''
avatar_file: '',
}
}
......@@ -37,14 +37,14 @@ class scoreReport extends Component {
}
shouldComponentUpdate(nextProps, nextState, nextContext) {
if (this.props.user.data.avatar !== nextProps.user.data.avatar) {
this.getCanvas()
return false
}
return true
}
// shouldComponentUpdate(nextProps, nextState, nextContext) {
// if (this.props.user.data.avatar !== nextProps.user.data.avatar) {
// this.getCanvas()
// return false
// }
// return true
// }
//
getCanvas() {
document.documentElement.scrollTop = 0
......@@ -89,24 +89,23 @@ class scoreReport extends Component {
}
handleFetchInfo = (index) => {
http.get(`${API.home}/sys/at/user_score/${index}`).then(res => {
http.get(`${API.home}/sys/at/user_score/${index}/${getParam('uid') ? getParam('uid') : 0}`).then(res => {
const {code, data} = res.data
if (code === 200) {
const {user, history} = this.props
if (user.hasError) {
history.push('/passport')
return
}
this.setState({
myRankList: data
myRankList: data,
})
let avatar = this.props.user && this.props.user.data.avatar
let avatar = data.avatar_file
this.getBase64(avatar)
setTimeout(() => {
this.getCanvas()
}, 500)
} else if (code === 4030) {
const {user, history} = this.props
if (user.hasError) {
history.push('/passport')
}
}
})
}
......@@ -213,7 +212,7 @@ class scoreReport extends Component {
<div className="comment text-overflow-4">
<img className={'avatar_file'} src={avatar_file} alt=""/>
{myRankList && myRankList.title && myRankList.title.comment}
<span dangerouslySetInnerHTML={{__html: myRankList.title}}></span>
</div>
<div className="code">
......
......@@ -2,6 +2,7 @@
width: 100%;
background-color: #09f;
}
.score-report {
width: 100%;
padding: 30px 12px 45px 12px;
......@@ -115,6 +116,10 @@
font-size: 14px;
line-height: 21px;
margin: 15px 33px 0;
em {
text-decoration: line-through;
}
}
.code {
......
......@@ -6,6 +6,7 @@ import storage from 'store2'
import { html } from '@/utils'
import { compareDesc } from "date-fns";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
class Scores extends Component {
......@@ -48,9 +49,19 @@ class Scores extends Component {
componentDidMount() {
this.getInitialData()
this.getRankList(null, 0)
if (!this.props.user.hasError) {
this.getUserScores(0)
this.getUserAddress()
}
}
componentDidUpdate(prevProps, prevState) {
if (this.props.user.hasError !== prevProps.user.hasError) {
this.getUserScores(0)
this.getUserAddress()
}
}
handleChange = (e) => {
const isNeverSHow = e.target.checked
......@@ -95,7 +106,7 @@ class Scores extends Component {
}
getUserScores = (type) => {
http.get(`${API.home}/sys/at/user_score/${type}`)
http.get(`${API.home}/sys/at/user_score/${type}/0`)
.then(res => {
const {code, msg, data} = res.data
......@@ -171,6 +182,7 @@ class Scores extends Component {
userAddress,
entryButtonInRule,
} = this.state
const {user, history} = this.props
const _rankList = Array.isArray(rankList) ? isExpandRankList ? rankList : rankList.slice(0, 10) : []
return (
<div className={'scores'}>
......@@ -202,7 +214,14 @@ class Scores extends Component {
</tr>
</thead>
<tbody>
<tr>
{
user.hasError
? <tr>
<td>--</td>
<td>--</td>
<td>--</td>
</tr>
: <tr>
{
userScore.score === '-' ? '-' :
<td>{userScore.score} <Link to={`/ai-test/analysis/${userScore.r_id}`}>解析</Link></td>
......@@ -212,6 +231,7 @@ class Scores extends Component {
userScore.rank === '-' ? '-' : <td>{userScore.rank}</td>
}
</tr>
}
</tbody>
</table>
</div>
......@@ -231,9 +251,13 @@ class Scores extends Component {
<div>
<span>仅显示前50</span>
<a href="javascript:void(0);" onClick={() => {
if (user.hasError) {
history.push('/passport')
} else {
this.setState({
isShowUserAddress: true,
})
}
}}>收货地址</a>
</div>
</div>
......@@ -386,4 +410,7 @@ function Rule({neverShow, isNeverShow, rule, close, startTest, entryButtonInRule
}
export default Scores;
\ No newline at end of file
export default connect(
({user}) => ({user}),
null,
)(Scores);
\ No newline at end of file
......@@ -50,6 +50,10 @@
background-color: $blue-bg;
}
th{
width: 33.333333%;
}
}
th {
......
import React, { Component } from 'react';
import './index.scss'
import { Link } from "react-router-dom";
import { browser, getParam, http } from "@/utils"
import { Toast } from "antd-mobile";
import { connect } from "react-redux";
import { WithFullSize } from "@/HOCs"
import { isEmpty } from "lodash";
import { addMessage, addResult, reselect } from './store'
const messageType = {
SYSTEM_MESSAGE: 1,
USER_MESSAGE: 2,
OPTIONS: 3,
}
class IntelligentRecommend extends Component {
state = {
showAnalyzing: false,
systemAvatar: 'https://julyedu-img-public.oss-cn-beijing.aliyuncs.com/Public/Image/home/avatar_20191104.png',
options: {
data: [],
messageId: 0,
},
next: {
oid: 0,
rid: 0,
},
}
componentDidMount() {
const {user, intelligentRecommend, history, reselect} = this.props
if (user.hasError) {
return history.push('/passport')
}
if (isEmpty(intelligentRecommend.result)) {
reselect()
this.getMessage()
}
}
handleSelect = (item) => {
this.props.addMessage({type: messageType.USER_MESSAGE, content: item.describe, id: item.id})
this.setState(state => ({
options: {data: [], messageId: 0},
next: {
...state.next,
oid: item.id,
},
}), () => {
this.getMessage()
})
}
getMessage = () => {
const {oid, rid} = this.state.next
http.get(`${API.home}/sys/icc/communicate/${oid}/${rid}`)
.then(res => {
const {data, code, msg} = res.data
if (code === 200) {
if (data.answer_type === 1) {
this.setState({
showAnalyzing: true,
}, () => {
setTimeout(() => {
this.setState({showAnalyzing: false})
this.props.addResult({...data})
}, Math.random() * 500 + 1000)
})
} else {
const message = {
type: messageType.SYSTEM_MESSAGE,
content: data.contents.find(item => item.is_question),
}
const optionsData = data.contents.filter(item => !item.is_question)
this.props.addMessage(message)
this.setState({
options: {
messageId: message.content.id,
data: optionsData,
},
next: {rid: data.rid},
})
}
} else {
Toast.fail(msg)
}
})
}
consult = (e) => {
e.preventDefault()
http.post(`${API.home}/sys/icc/consult`, {
rid: this.state.result.rid,
}).finally(() => {
window.location.href = e.target.getAttribute('href')
})
}
goBack = () => {
const {state} = this.props.location
if (browser.isWeixin && getParam('code') && getParam('state')) {
window.history.go(-2)
}
if (state.records && state.records.length > 1) {
window.history.go(-1);
} else if (state.from && state.from.pathname) {
location.replace(`${state.from.pathname}${state.from.search}`)
} else {
window.location.href = window.location.origin
}
}
render() {
const {showAnalyzing, systemAvatar, options} = this.state
const {user, intelligentRecommend: {result, processing}, reselect} = this.props
const recommends = result.contents
return (
<div id={'intelligent-recommend'}>
<div className="head">
<div>
<div className="go-back">
<i className='iconfont iconiconfront-68' onClick={this.goBack}></i>
</div>
<div className={'title'}>七月在线智能选课</div>
</div>
<button onClick={() => {
this.setState({
next: {oid: 0, rid: 0},
options: {messageId: 0, data: []},
}, () => {
reselect()
this.getMessage()
});
}}>重新选课
</button>
</div>
<div className="dialog-box">
{
!!processing.length && processing.map((item, index) => {
switch (item.type) {
case messageType.SYSTEM_MESSAGE:
return (
<React.Fragment key={index}>
<Message text={item.content.describe} identity={'system'} avatar={systemAvatar}/>
{
options.messageId === item.content.id &&
<Options options={options.data} handleSelect={this.handleSelect}/>
}
</React.Fragment>
)
case messageType.USER_MESSAGE:
return <Message text={item.content} identity={'user'} avatar={user.data.avatar} key={index + 2}/>
}
})
}
{
showAnalyzing && <div className="analyzing">努力分析中...</div>
}
</div>
{
!isEmpty(recommends) && <div className="result">
<div className="title">根据您目前的情况,推荐结果如下</div>
<div className="obtained">
<div className={'subtitle'} dangerouslySetInnerHTML={{__html: recommends.skill_title}}></div>
<div className={'skill'} dangerouslySetInnerHTML={{__html: recommends.skill_desc}}></div>
</div>
<div className="obtained">
<div className={'subtitle'} dangerouslySetInnerHTML={{__html: recommends.project_title}}></div>
<div className={'skill project'} dangerouslySetInnerHTML={{__html: recommends.project_desc}}></div>
{/*<ul>
<li className={'skill project'}>·技能描述、技能描述</li>
<li className={'skill project'}>·工作及项目描述、工作及项目描述、项目描述</li>
</ul>*/}
</div>
<div className={'salary-section'}>
<div className={'subtitle'} dangerouslySetInnerHTML={{__html: recommends.salary_title}}></div>
<div className={'salary'} dangerouslySetInnerHTML={{__html: recommends.salary_desc}}></div>
</div>
<div className="recommends">
<div>想获得以上技能,向您推荐:</div>
<ul className={'courses'}>
{
!!recommends.courses.length && recommends.courses.map(item => {
return <li className={'course'} key={item.course_id} onClick={(e) => {
if (e.target.nodeName.toLowerCase() !== 'a') {
if (item.course_id) {
this.props.history.push(`/detail?id=${item.course_id}`)
} else {
this.props.history.push(`/play?id=${item.v_course_id}`)
}
}
}}>
<div className="cover">
<img src={item.img_url}
alt=""/>
</div>
<div className="info">
<div className={'title'}>{item.recmd_title}</div>
<div className={'des'}>{item.recmd_desc}</div>
<div className="bar">
{
item.c_type === 1 && <React.Fragment key={item.course_id}>
<div className="prices">
<span className={'price'}>{item.price_sale}</span>
<span className={'old-price'}>{item.price_original}</span>
</div>
<Link className={'register'} to={`/detail?id=${item.course_id}`}>{item.second_btn}</Link>
</React.Fragment>
}
{
item.c_type === 2 && <React.Fragment key={item.course_id}>
<a href="http://q.url.cn/s/Vbkup6m?_type=wpa" className={'contact'}
onClick={this.consult.bind(this, item.rid)}>{item.consult}</a>
<Link className={'register'} to={`/detail?id=${item.course_id}`}>{item.second_btn}</Link>
</React.Fragment>
}
{
item.c_type === 0 &&
<Link className={'study'} to={`/play?id=${item.v_course_id}`}>{item.second_btn}</Link>
}
</div>
</div>
</li>
})
}
</ul>
</div>
</div>
}
</div>
);
}
}
function Message({text, avatar, identity}) {
return <div className={`message clearfix ${identity}`}>
<div className="avatar">
<img src={avatar} alt=""/>
</div>
<div className={`text`}>{text}</div>
</div>
}
function Options({options, handleSelect}) {
return <ul className={'options'}>
{
!!options.length && options.map(item => {
return <li onClick={() => handleSelect(item)} key={item.id}>
{item.describe}
</li>
})
}
</ul>
}
export default connect(
({user, intelligentRecommend}) => ({user, intelligentRecommend}),
{addMessage, addResult, reselect},
)(WithFullSize(IntelligentRecommend));
\ No newline at end of file
#intelligent-recommend {
background: linear-gradient(to right, #F1F0F6, #EBF4F9);
padding: 59px 10px 18px;
min-height: 100%;
.clearfix {
&::after {
content: ".";
visibility: hidden;
display: block;
height: 0;
clear: both;
}
}
.head {
position: fixed;
top: 0;
left: 0;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 44px;
padding: 0 15px;
background: #fff;
z-index: 100;
& > div {
display: flex;
align-items: center;
}
.iconfont {
font-size: 16px;
color: #222;
font-weight: 600;
}
.title {
margin-left: 10px;
font-size: 15px;
color: #2b2b2b;
}
button {
width: 84px;
height: 30px;
border: 1px solid #09f;
border-radius: 15px;
color: #09f;
font-size: 13px;
outline: 0;
background-color: transparent;
-webkit-appearance: none;
}
}
.dialog-box {
padding: 20px 15px 20px;
margin-bottom: 20px;
background: rgba(242, 247, 250, 1);
border: 1px solid #5CF9FF;
border-radius: 8px;
.analyzing {
color: #4f5c66;
font-size: 12px;
line-height: 48px;
text-align: center;
}
}
.message {
.avatar {
display: inline-block;
margin-right: 14px;
img {
width: 30px;
height: 30px;
border-radius: 50%;
}
}
.text {
position: relative;
padding: 0 16px;
height: 40px;
display: inline-block;
background: rgba(255, 255, 255, 1);
border-radius: 4px;
font-size: 16px;
color: #333;
text-align: center;
line-height: 40px;
}
$angleSize: 8px;
@mixin pseudo {
content: '';
position: absolute;
top: 50%;
transform: translateY(-50%);
display: block;
border-color: transparent;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
}
&.system {
.text::before {
@include pseudo;
left: -$angleSize;
border-right: $angleSize solid #fff;
}
}
&.user {
.avatar {
float: right;
}
.text {
float: right;
margin-right: 15px;
background-color: #0036FF;
color: #fff;
&::after {
@include pseudo;
right: -$angleSize;
border-left: $angleSize solid #0036FF;
}
}
}
}
.message + .message {
margin-top: 30px;
}
.options {
position: relative;
padding-top: 18px;
margin-top: 15px;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 8px;
background: url("./images/options-divide-line.png") no-repeat;
background-size: contain;
}
li {
width: 126px;
height: 33px;
margin: 0 auto 15px;
background: linear-gradient(90deg, rgba(0, 153, 255, 1) 0%, rgba(77, 184, 255, 1) 100%);
border-radius: 17px;
font-size: 16px;
color: #fff;
text-align: center;
line-height: 33px;
}
}
.result {
padding: 0 15px 30px;
background: rgba(255, 255, 255, 1);
border: 1px solid rgba(0, 153, 255, 1);
border-radius: 8px;
color: #333;
& > .title {
position: relative;
color: #09f;
font-size: 16px;
text-align: center;
line-height: 62px;
@mixin pseudo {
content: '';
position: absolute;
top: 50%;
transform: translateY(-50%);
display: block;
width: 11px;
height: 11px;
background: url("./images/title-decorator.png") no-repeat;
background-size: contain;
}
&::before {
@include pseudo;
left: 5%;
}
&::after {
@include pseudo;
right: 5%;
transform: translateY(-50%) scale(-1);
}
}
.subtitle {
font-size: 12px;
}
.skill {
font-size: 18px;
line-height: 36px;
font-weight: 600;
&.project {
font-size: 14px;
}
}
.salary {
font-size: 18px;
line-height: 2em;
font-weight: 500;
color: #FF2A00;
}
.obtained {
margin-bottom: 20px;
}
.salary-section {
margin-bottom: 20px;
}
.recommends {
& > div:nth-child(1) {
margin-bottom: 12px;
font-size: 12px;
color: #09f;
}
.cover {
flex: 0 0 auto;
width: 125px;
height: 90px;
margin-right: 10px;
img {
width: 100%;
height: 100%;
}
}
.course {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
.info {
flex: 1 1 auto;
position: relative;
}
.title {
width: 190px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 8px;
font-size: 16px;
line-height: 16px;
font-weight: 500;
color: #333;
}
.des {
display: -webkit-box;
/* autoprefixer: ignore next */
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
margin-bottom: 5px;
overflow: hidden;
font-size: 11px;
color: #4F5C66;
}
.bar {
position: absolute;
left: 0;
bottom: 0;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 24px;
font-size: 0;
a {
display: inline-block;
box-sizing: border-box;
padding: 6px 14px;
text-align: center;
font-size: 12px;
line-height: 12px;
border-radius: 12px;
}
.contact {
color: #fff;
background-color: #09f;
margin-right: 6px;
}
.register {
color: #FF0000;
border: 1px solid #FF0000;
}
.price {
font-size: 15px;
color: #FF2121;
margin-right: 5px;
}
.old-price {
font-size: 11px;
color: #999;
text-decoration: line-through;
}
.study {
background-color: #09f;
color: #fff;
font-size: 12px;
}
}
}
}
}
}
\ No newline at end of file
export const ADD_MESSAGE = 'ADD_MESSAGE'
export const ADD_RESULT = 'ADD_RESULT'
export const RESELECT = 'RESELECT'
export const addMessage = payload => {
return {
type: ADD_MESSAGE,
payload,
}
}
export const addResult = payload => {
return {
type: ADD_RESULT,
payload,
}
}
export const reselect = () => {
return {
type: RESELECT
}
}
const initialState = {
processing: [],
result: {},
}
export default function intelligentRecommend(state = initialState, action) {
switch (action.type) {
case ADD_MESSAGE:
return {
processing: [...state.processing, action.payload],
result: state.result,
}
case ADD_RESULT:
return {
processing: state.processing,
result: action.payload,
}
case RESELECT:
return initialState
default:
return state
}
}
\ No newline at end of file
......@@ -55,7 +55,7 @@ function Record({record: {seconds, lesson_name}}) {
const Bottom = React.memo(({item}) => {
if (item.ago || item.seconds) {
let date = new Date(item.ago * 1000)
let time = isToday(date) ? format(date, 'HH时mm分') : format(date, 'MM月DD日')
let time = isToday(date) ? format(date, 'HH时mm分') : format(date, 'MM月dd日')
return (
<div className="des">
<span className='time'>{time}</span>
......
......@@ -324,15 +324,20 @@ export default [
{
path: '/ml',
exact: true,
component: loadable(() => import(/* ml */'@/components/ml')),
component: loadable(() => import(/* webpackChunkName: 'ml' */'@/components/ml')),
},
{
path: '/mlShare',
component: loadable(() => import('@/components/mlShare')),
component: loadable(() => import(/* webpackChunkName: 'mlShare' */'@/components/mlShare')),
},
//ai水平测试
{
path: '/ai-test',
component: loadable(() => import('@/components/ai-test')),
component: loadable(() => import(/* webpackChunkName: 'ai-test' */'@/components/ai-test')),
},
//智能选课
{
path: '/intelligent-recommend',
component: loadable(() => import(/* webpackChunkName: 'intelligent-recommend' */'@/components/intelligent-recommend')),
},
]
......@@ -3,13 +3,15 @@ import myCourses from '@/components/study/myCourses/reducers'
import courseInfo from '@/components/detail/reducers'
import user from './userReducer'
import country from '@/components/country/countryRedux'
import intelligentRecommend from "@components/intelligent-recommend/store"
const reducer = combineReducers({
myCourses,
courseInfo,
user,
country
country,
intelligentRecommend
});
export default reducer;
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment