From 70d2790f8dc9de57dd229be5466983c495235d6c Mon Sep 17 00:00:00 2001 From: hjm <63528605@qq.com> Date: Mon, 29 Jul 2019 13:55:32 +0800 Subject: [PATCH 01/10] liink --- .../src/modules/courses/exercise/Testpapersettinghomepage.js | 2 +- public/react/src/modules/courses/exercise/new/JudgeDisplay.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/react/src/modules/courses/exercise/Testpapersettinghomepage.js b/public/react/src/modules/courses/exercise/Testpapersettinghomepage.js index ddb448cfc..36b319f5a 100644 --- a/public/react/src/modules/courses/exercise/Testpapersettinghomepage.js +++ b/public/react/src/modules/courses/exercise/Testpapersettinghomepage.js @@ -267,7 +267,7 @@ class Testpapersettinghomepage extends Component{

{this.props.coursedata.name} > - 试卷 + 试卷 > 试卷详情

diff --git a/public/react/src/modules/courses/exercise/new/JudgeDisplay.js b/public/react/src/modules/courses/exercise/new/JudgeDisplay.js index 0f8930a8a..a0d5baf2a 100644 --- a/public/react/src/modules/courses/exercise/new/JudgeDisplay.js +++ b/public/react/src/modules/courses/exercise/new/JudgeDisplay.js @@ -7,7 +7,7 @@ import { } from 'antd'; import axios from 'axios' import { qNameArray } from './common' -import {getUrl, ActionBtn, markdownToHTML} from 'educoder'; +import {getUrl, ActionBtn, markdownToHTML, MarkdownToHtml} from 'educoder'; import QestionDisplayHeader from './QestionDisplayHeader' const { TextArea } = Input; const confirm = Modal.confirm; From 2ac2bbf5d87ead4360956f3967088192b949256a Mon Sep 17 00:00:00 2001 From: p31729568 Date: Tue, 30 Jul 2019 11:56:45 +0800 Subject: [PATCH 02/10] add phone to get user info apig --- app/views/users/get_user_info.json.jbuilder | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/users/get_user_info.json.jbuilder b/app/views/users/get_user_info.json.jbuilder index d9eb736ad..d12b950f9 100644 --- a/app/views/users/get_user_info.json.jbuilder +++ b/app/views/users/get_user_info.json.jbuilder @@ -7,6 +7,7 @@ json.is_teacher @user.user_extension&.teacher? json.user_identity @user.identity json.tidding_count 0 json.user_phone_binded @user.phone.present? +json.phone @user.phone json.profile_completed @user.profile_completed? if @course json.course_identity @course_identity From 275fb7e21c1c02bdcba3e9d4593a22400913e11c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Tue, 30 Jul 2019 13:40:29 +0800 Subject: [PATCH 03/10] b --- public/react/src/AppConfig.js | 2 +- .../PackageIndex/PackageConcent.js | 4 +-- .../PackageIndexNEITaskDetails.js | 27 ++++++++++--------- .../PackageIndexNEITaskDetails/pds.css | 21 +++++++-------- .../PackageIndexNEIBannerConcent.js | 6 ++--- .../PackageIndexNEISubmit.js | 4 +-- public/react/src/modules/tpm/NewHeader.js | 2 +- 7 files changed, 32 insertions(+), 34 deletions(-) diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js index 2ad7df0d5..363ff495d 100644 --- a/public/react/src/AppConfig.js +++ b/public/react/src/AppConfig.js @@ -41,7 +41,7 @@ export function initAxiosInterceptors(props) { // proxy = "http://testbdweb.trustie.net" // proxy = "http://testbdweb.educoder.net" // proxy = "https://testeduplus2.educoder.net" - proxy="http://47.96.87.25:48080/" + proxy="http://47.96.87.25:48080" // 在这里使用requestMap控制,避免用户通过双击等操作发出重复的请求; diff --git a/public/react/src/modules/projectPackages/PackageIndex/PackageConcent.js b/public/react/src/modules/projectPackages/PackageIndex/PackageConcent.js index 46e36f90f..3f31b442e 100644 --- a/public/react/src/modules/projectPackages/PackageIndex/PackageConcent.js +++ b/public/react/src/modules/projectPackages/PackageIndex/PackageConcent.js @@ -157,7 +157,7 @@ class PackageConcent extends Component { enterButton={ 搜索} onSearch={ (value)=>this.setdatafuns(value)} />

@@ -223,7 +223,7 @@ class PackageConcent extends Component {
{item.title}
diff --git a/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js b/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js index 23d7a095c..bec37a59a 100644 --- a/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js +++ b/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js @@ -229,7 +229,8 @@ class PackageIndexNEITaskDetails extends Component { } goback = () => { - window.history.go(-1) + // window.history.go(-1) + window.location.href="/crowdsourcings"; } render() { @@ -251,7 +252,7 @@ class PackageIndexNEITaskDetails extends Component { '} className={"fl"}> {/*{this.props.current_user.username}*/} - 众包创新 + 众包创新 {data&&data.title} @@ -351,7 +352,7 @@ class PackageIndexNEITaskDetails extends Component { 需求详情: {data&&data.status==="pending"&&data&&data.operation.can_select_bidding_user===true?
- 编辑 + 编辑 删除
:""} @@ -393,16 +394,16 @@ class PackageIndexNEITaskDetails extends Component { -
-
-
+
+
+
{data&&data.bidding_users.map((item,key)=>{ return( -
+
{item.status==="bidding_won"?:""} - +

{item.name}

{this.props.current_user&&this.props.current_user.login!=item.login? 头像联系TA @@ -442,15 +443,15 @@ class PackageIndexNEITaskDetails extends Component {
-
-
-
+
+
+
{data&&data.bidding_users.map((item,key)=>{ return( -
this.Clickteacher2(item.id)} key={key}> + ) diff --git a/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/pds.css b/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/pds.css index a6f9e10dc..504a78bed 100644 --- a/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/pds.css +++ b/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/pds.css @@ -1,4 +1,4 @@ -.ysldivhome2{ +.ysldivhome2s{ display: flex; flex-flow: row wrap; align-content:stretch; @@ -6,20 +6,17 @@ margin-bottom: 20px; } -.ysllogin_register_contents{ - display: flex; - margin-top: 20px; - /*justify-content: center;*/ - background: #fff; -} - .ysllogin_register_contentss{ margin-top:0px !important; padding-top: 10px; padding-bottom: 10px; + display: flex; + margin-top: 20px; + /*justify-content: center;*/ + background: #fff; } -.ysldivhomediv1{ +.ysldivhomediv1s{ width: 80px; height: 130px; display: flex; @@ -33,10 +30,10 @@ margin-left: 64px; } -.yslgouxuanimg2{ +.yslgouxuanimg2s{ height: 20px; } -.div1img{ +.div1imgs{ display: flex; justify-content:center; width: 80px; @@ -53,7 +50,7 @@ .ptext{ width: 80px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } -.ysllogin_section { +.ysllogin_sections { display: flex; align-items: center; flex-direction: column; diff --git a/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js b/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js index e7e4b20a2..adde77b64 100644 --- a/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js +++ b/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js @@ -454,7 +454,7 @@ class PackageIndexNEIBannerConcent extends Component { if(type===true){ this.props.setPublicationfun(response.data.id) }else{ - window.location.href="/crowdsourcing/"+response.data.id + window.location.href="/crowdsourcings/"+response.data.id } this.setState({ springtype:false @@ -502,7 +502,7 @@ class PackageIndexNEIBannerConcent extends Component { if(type===true){ this.props.setPublicationfun(response.data.id) }else{ - window.location.href="/crowdsourcing/"+response.data.id + window.location.href="/crowdsourcings/"+response.data.id } this.setState({ springtype:false @@ -836,7 +836,7 @@ class PackageIndexNEIBannerConcent extends Component {

- 姓名: + 姓名: { if(sum===undefined){ - window.location.href="/crowdsourcing/new" + window.location.href="/crowdsourcings/new" }else{ // this.props.history.push("/project_packages/"+sum) - window.location.href="/crowdsourcing/"+sum + window.location.href="/crowdsourcings/"+sum } } diff --git a/public/react/src/modules/tpm/NewHeader.js b/public/react/src/modules/tpm/NewHeader.js index 379c70e27..23330e779 100644 --- a/public/react/src/modules/tpm/NewHeader.js +++ b/public/react/src/modules/tpm/NewHeader.js @@ -718,7 +718,7 @@ submittojoinclass=(value)=>{

  • 教学案例
  • 众包创新
  • 交流问答
  • Date: Tue, 30 Jul 2019 13:48:21 +0800 Subject: [PATCH 04/10] download --- .../courses/busyWork/CommonWorkDetailIndex.js | 46 +++++++++++++++---- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js b/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js index ff8e3e3a2..4f2283499 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js @@ -8,7 +8,7 @@ import { CNotificationHOC } from '../common/CNotificationHOC' import { RouteHOC } from './common' import locale from 'antd/lib/date-picker/locale/zh_CN'; -import { WordsBtn, MarkdownToHtml, trigger, queryString } from 'educoder'; +import { WordsBtn, MarkdownToHtml, trigger, queryString, downloadFile } from 'educoder'; import axios from 'axios'; import Modals from '../../modals/Modals'; import CoursesListType from '../coursesPublic/CoursesListType'; @@ -18,6 +18,8 @@ import '../css/Courses.css' import CBreadcrumb from '../common/CBreadcrumb' import DownloadMessageysl from "../../modals/DownloadMessageysl"; +import { Spin } from 'antd' + //引入对应跳转的组件 //新建分组/普通作业 @@ -64,6 +66,7 @@ class CommonWorkDetailIndex extends Component{ this.state = { DownloadType:false, DownloadMessageval:undefined, + donwloading: false, } } initWorkDetailCommonState = (data) => { @@ -123,7 +126,20 @@ class CommonWorkDetailIndex extends Component{ } }else { this.props.showNotification(`正在下载中`); - window.open("/api"+url, '_blank'); + + this.setState({ donwloading: true }) + downloadFile({ + url: url, + successCallback: (url) => { + this.setState({ donwloading: false }) + console.log('successCallback') + }, + failCallback: (responseHtml, url) => { + this.setState({ donwloading: false }) + console.log('failCallback') + } + }) + // window.open("/api"+url, '_blank'); } }).catch((error) => { console.log(error) @@ -244,7 +260,7 @@ class CommonWorkDetailIndex extends Component{ }
  • - { noTab !== true &&
    + { noTab !== true &&
    this.setState({moduleName: '作品列表'})} @@ -283,18 +299,30 @@ class CommonWorkDetailIndex extends Component{ padding-top: 10px; padding-bottom: 8px; } + + .floatSpinParent .ant-spin-nested-loading { + float: right; + } `} - {this.props.isAdmin()?
  • + {this.props.isAdmin()? +
  • 导出 -
  • :""} + + :""} {/* {isAdmin && 导出作品附件} {isAdmin && 导出成绩} */} From 9400d4a57daef5ec8abf5a6db7e0e7d56c8b3e2e Mon Sep 17 00:00:00 2001 From: jingquan huang Date: Tue, 30 Jul 2019 13:50:06 +0800 Subject: [PATCH 05/10] =?UTF-8?q?users=E8=A1=A8=E6=B7=BB=E5=8A=A0=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/migrate/20190730024112_add_index_to_user.rb | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 db/migrate/20190730024112_add_index_to_user.rb diff --git a/db/migrate/20190730024112_add_index_to_user.rb b/db/migrate/20190730024112_add_index_to_user.rb new file mode 100644 index 000000000..fa198cffa --- /dev/null +++ b/db/migrate/20190730024112_add_index_to_user.rb @@ -0,0 +1,7 @@ +class AddIndexToUser < ActiveRecord::Migration[5.2] + def change + # add_index :users, :login, unique: true + # add_index :users, :mail, unique: true + # add_index :users, :phone, unique: true + end +end From 98ba053ebec9fd049c9d9fa09a5d042b14c5bf9d Mon Sep 17 00:00:00 2001 From: hjm <63528605@qq.com> Date: Tue, 30 Jul 2019 14:08:14 +0800 Subject: [PATCH 06/10] donwloading --- .../src/modules/courses/busyWork/CommonWorkDetailIndex.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js b/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js index 2d3361492..a690fedc0 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js @@ -305,6 +305,9 @@ class CommonWorkDetailIndex extends Component{ .floatSpinParent .ant-spin-nested-loading { float: right; } + .floatSpinParent .ant-spin-nested-loading .ant-spin-spinning{ + top: 10px; + } `} {this.props.isAdmin()?
  • From e1925f40c1a4a74564c89fab7e2d02ece6dabda4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Tue, 30 Jul 2019 14:23:25 +0800 Subject: [PATCH 07/10] =?UTF-8?q?=E4=BC=97=E5=8C=85=E7=A7=BB=E6=A4=8D?= =?UTF-8?q?=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../images/educoder/project_packages/ai.png | Bin 0 -> 1459 bytes .../educoder/project_packages/backend.png | Bin 0 -> 1404 bytes .../cloud_compute_and_big_data.png | Bin 0 -> 1506 bytes .../educoder/project_packages/database.png | Bin 0 -> 1627 bytes .../project_packages/devops_and_test.png | Bin 0 -> 1312 bytes .../educoder/project_packages/front.png | Bin 0 -> 1322 bytes .../educoder/project_packages/mobile.png | Bin 0 -> 1367 bytes .../educoder/project_packages/other.png | Bin 0 -> 1107 bytes .../PackageIndex/PackageConcent.js | 46 +++++++++--------- .../PackageIndexNEITaskDetails.js | 14 +++--- .../PackageIndexNEIBannerConcent.js | 10 ++-- .../projectPackages/packageconcnet.css | 14 ++++++ 12 files changed, 49 insertions(+), 35 deletions(-) create mode 100755 public/images/educoder/project_packages/ai.png create mode 100755 public/images/educoder/project_packages/backend.png create mode 100755 public/images/educoder/project_packages/cloud_compute_and_big_data.png create mode 100755 public/images/educoder/project_packages/database.png create mode 100755 public/images/educoder/project_packages/devops_and_test.png create mode 100755 public/images/educoder/project_packages/front.png create mode 100755 public/images/educoder/project_packages/mobile.png create mode 100755 public/images/educoder/project_packages/other.png diff --git a/public/images/educoder/project_packages/ai.png b/public/images/educoder/project_packages/ai.png new file mode 100755 index 0000000000000000000000000000000000000000..825e75165dc6b016037d6cef82573728f69ffa65 GIT binary patch literal 1459 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 IM6N<$f*J$d*#H0l literal 0 HcmV?d00001 diff --git a/public/images/educoder/project_packages/database.png b/public/images/educoder/project_packages/database.png new file mode 100755 index 0000000000000000000000000000000000000000..2b668e774b5d16b7725469f70309ee0ea285f08e GIT binary patch literal 1627 zcmV-h2Bi6kP)h(#_4@JU@!Y`PtJUbob3tJ$00004bW%=J_Wno)eg_c) z000HzNklAdR#U zNZM@_nN}qrCTyvVW!ZYUJ!dW? zr}wG%);kpIP47^$0CqsuyI0mL>y`D&dS(6pEav$>I|K_L13dcIUtpFV&8 z6&Ca6Pic}w>ZEDrrZwogPovt2^Ml8XKFm0Zl|;(CLYP787$jUYsIL<`?v9n;}cYFlfP=FcHHO`;LC zN3`($RYB-*@sz{p$ny1E5{f;|#2CsKFn2x187LuCN+G3$UxupFj#Rb~CS}l~hSKRX z2MW4Vo~(8D#)PVL$rrHZ{*`9a^uk$pq^@v^to|GWj--E>}t0pib(^@@3x|Ar? zRf9Qn@g0rzYGy2wN2xp?YFPq}$LyJ_@{wH9RlFppGjfM4B$c;_D1(9rlnWeZTEAx5aj`WT88>m&M% zhqCg#3DM2+v*Ug(%FMDZO+!UlTt}!v^j*4=8`57HWz+RDc;Xwxh^>$s7&n=3)a7A4 z_RWWd2PykT7pz|HRi?#6~CZ64Gu*&KY))G!#-n=gC3skycLB52lpsEyoQ0B@PY~?lBXQ;=D zCCk30HNg*K?$6tcbR$U3T0LN{bh{~e5TY|igk6`kFGq=CEmeSl%Dk}yqJoC!0KT_? z1v6Ibjf4eSv1VmMtyzLGuR)i`0(r7nPjhHG;YZC{W2=$s4y{WWrps@BZUO~~ZsIZ= zVvHC3wwl&9`G{)PrD5twT7;+BjSf&H%LK{H+2c7A<3w+|(6!+2Uvvlv5A6kKA6*^` ziQd6++12CPbO_@IhF10V$d`qM<+97oR5X@gTGn3qf)n8K7S<;phRc%v@&u!u4jW7WB|xtO}dPVWMknu;}_;uU&6>-1iMaocN{DMj<5pvyao z%BRNk<}E>|_Z^rnwI*3V*nD+(SI(;4hLxH3yf>ZR;o~6lZRawM@ZNpub^G6ff42Q^ Z!GGbk(Twpgt_lDE002ovPDHLkV1jIHA!q;q literal 0 HcmV?d00001 diff --git a/public/images/educoder/project_packages/devops_and_test.png b/public/images/educoder/project_packages/devops_and_test.png new file mode 100755 index 0000000000000000000000000000000000000000..77b8e6f3b1b9b4b7ea21c6384e1c9638504151fe GIT binary patch literal 1312 zcmV+*1>gFKP)14!N=>7)NnWp|d?Jdp6DJZHSPV`?l!Cpds^xcSv=a{=cOETu+li%zo#k#@@pEUXHCCrZ)=vx8g0)~RSPRzw zkF~O~b@ywd5$oy4*HdB*H(^}{)1vq5Y6I3}I%~LdUYoVjpTT;&-XbeJubtyeRxoJK zD+vE?j};6y+GB-Bt%?PTln2)9wM-* zl)S{9^8427-x4bV7Hj4ee*fU+$fM|vSS2e|-_wJB5Ej223h*kIzmoOkChM#8EC`N& z*j`-lQkGTq8jQ~5kLSrr5N?le9IuGGSyp(3x5=S=`6huuznz@+T`yOxf_0oGJE|o> z=_nch$i1NWWwH6Jo>94#Ez!G5K72G@(n^MJy&ywXBHa>$G&$=RUKx&gdab9)pXzT% z2iebmlJR9;FCEy66@E|lRk!!jGn4av-{h!i#EZ3-j`h)Lke;X)>*@H~EWya7(7mj_Fh z-71!6?Pqz(aZ`BV=3XqD5X90#O}&_!Tt($EzDJHct2`~VW_hhvva;4HDvxJ-p~+lU zZq8wR}pWJ?|b^tAeD(=!GOsJ4&O8AQM!;MVR zYA%c`@8!5wibN!YeNN)mLzF#_s_*y^hXP5I$fP2*k#Ri&t>(fW_k{q9g?h&#ifupB zvYU%|-8~{2D;hV|f)NPwlsFI3^Bxn^7^)RnUQ~~HRy3EN7X*cR$+sEYoCGtPQ+n_F zRYX-&2&2WEWevTBYuwdReLBsLBlccKFs^m)O9eMtj8kV-qncg{mbW~020g0j)$J0~ z_0o$LJ)wKP-rY9QS{h~Lh-0F2pQ2w~im1u%Oh607o(Rr9lQMBJrVq}Y8>`!jsxOfEachn*Jxx8OfK WhLDY%N|dYs0000hZCPO;4`gPsUjnmy^HWHRG(whspb9taUMYHyZ1|5m{f( ztTXG(I6N*4G}^{g^BmjkUOU zdNf^+4yst6m)*L4J6FY;^|R(9vY>|bFR_+y7P7A0QDOb8)#3Ge5*AdjG_t-K*Ix6; zIueWSK5>)<$ofVssL=J)%?dx&<$k4Va#p4m%4IFU73pnOQfR zd|~K*3b~Hu6aN33+((wKW!-eMpwus9-FepA=JUfH7dF6pJfbi=%BrAOwHlK{tJRVq-b4Hcv`pT^NOSYc*heB)Rb%2HCK)OhnX^Z7dOIQIbU!T}S5g`XR+=s9|Q;9wiCc=hTkF7Rw!+Q{7N}_=LQUf(k zQxBE(S+e2Sc!&+WUl(Ozz0a;-vrQO7;6U=lACy#Nk1lHXe*c8#ci@gkN6>{e%06l} z%)$%suED8#Sn)0WK1K^nl%;GD%NM$9B8e$m+obyuZ6{Gxy-(-OvtHG;+OB_ z*7mVFzC0GcTjv@GrBT=^EIB@Dpj+=)a}o$13!C$O$VP-PQ?F28KwyUFS( z3fne^i)j{B^?Tn)IPyf3RPw|XC4_6EOB02 zTfnlJEFKwo8}#RzPEgs~qj@bWG%nyq?>mHUiuN&w8AC9XW~4d$!>ABcsH;(;DMnrj z)a+NeF18Ff5y>r-MQ5>G7gh;$flDOA6GKypws0RM7zRL!l*~&gJgU*fZ^%}zf+}7| zRLqt|yDHwJJ;sI9n=B9<`Jk-)ZJV#)CfP2#=xs-36)elACxu>zaG@;Z)x5bYm)`^x zHyd)D?5cXdH!ibY^I44Ps$*Fd&teFd#k1HnVIwPlub`v}#@o%wx;!k|MHuc}q^g!> z`L;{9Bo$FwpTP3L$VVA%qo_hw-S5hiS4#RRYNLOi{F&|FaQ7m07*qoM6N<$g5QXY-2eap literal 0 HcmV?d00001 diff --git a/public/images/educoder/project_packages/mobile.png b/public/images/educoder/project_packages/mobile.png new file mode 100755 index 0000000000000000000000000000000000000000..cd73520c732c931fcae55531ac837ddd09081c21 GIT binary patch literal 1367 zcmV-d1*rOoP)c=;B$G<{r>vw`T6_$;)2HI_~h;OtKIth>!xbF z5@G-V019+cPE+>(|NsC0|M@b!_SY>F000EWNklJ9>xcEj`eFUB{DC_kg|J@xMj@=e-Z%OZSoo^{_Ko_51#B^_x|x2d>&Acj-vLi%VZUwg}LB!m8sV(sHf&Q?9< zsQIirJw5(7mQq)&#Kt}5r^MPJEPW+zC=eEFJ6D3OW?{^K$+0$1mz`*jVsC4A*@Yc3AWa;bQo&`*A=!la9v_+9qh2JCdJk&*EP1PHLfeNRjmuV zDqABK7PZyB+jhZLRjuzuC)jHL4Wo_Qsx~A)-%8XHD`<;SMY!_W>e{yLHrT3ss2EtT zZ0YVjz`Q%XW~-v9H^ImAZ0XLx{G(WU84DfQ3AVJ3Vo6&SPuBEFfMu}Nd02P7z7l;` z6O^3D#FePK_Wd?VU$g~5S?E6)SE?<`uxJayd1q{xF9{X! zp(|REij{23FQ>sVlrSB)^$EQ4pkN9;q?}#BAEy7Dt%9kzm_QL7RJwD9@BVJ zPKFL*?gag(?6;=M;Ge)~uzXh;R^pz1E57SkP5G+)#_rT>XL!v5CM)q&eLrAJ>H@h8 zA<@?I>*oPm(Fp_^trS~ZhGz?dn>2``H9m{nzXeKGQ57hnZVt=bH3Fn$sc5ohSyttJ`zy)iA+zQh+pTotM7E+-L3uJ2v zjUB>#Tcxo)I(Esy0pWF65PDOU0KDuyWTEQr+q(4a-mYLFX^IA@uXuAjtMSjr?K}S~ Zf&U}?8+Dktk3j$c002ovPDHLkV1haGwgdnG literal 0 HcmV?d00001 diff --git a/public/images/educoder/project_packages/other.png b/public/images/educoder/project_packages/other.png new file mode 100755 index 0000000000000000000000000000000000000000..a700cd5dec4561d0adc46073916d20b6cb58840c GIT binary patch literal 1107 zcmV-Z1g!gsP) zh{FGg!T*WD{)N8#f4cww|Nrp!{h!SK;_&U2hM)id00VSVPE+gk+Qc+V@q(ZEzuVMaYkaxc|j~^XbW#!|MxiAWNmM5 z-9a4oke|L8e;!Y~+nk*@%f!i9^X0T%CQdJ!^LDBD)|@WJY8GUDJ+h9hBkRaIvW~3( zfdxzjx(_Tw4GY?B-}kM37B(SjSpDmIy?*@Yq>jtKYZs53a@OVR!;OmD55xL-6XFev zS^a~3^!8b^t|IGR6tiCZv%iKciG{4oKmOS}p5}NjMHvgW5B^z`P)X}_-PIl}5vFwA3J zd0|g-$2wYFf@QHlIAI@r*rSy$U3!h8Sx&P$iJ$tY_ut%1%8DmO%X*~mMGMl9=kAKcSbGsV|ebEXYm!>Jumw|ksp(SbsZ&E%MMLy7aMl{K#`nF6@Rm{Z@kW?|Fw zx?sY!dx`RwG+PO@2s4I{ASU`s^?#8ZAEOZ@5i^BbP zFr6Ecqy;&P3Wo~YI!9M18TYc1G{Nr0HcyvkiK z@*H7jF5`Po%Dpd)j!(;lt~-~on5|ZvwgTNm(@j31^2!kd1diwx@J?%0+L~HS8F^`ejg3d6F|qC zs=IBvcUtD`fLO%>VlH=-#SK(?=MKZp6 { -// if (item.value === val) { -// vals=item.name -// return true -// } -// } -// ) -// -// return vals -// } +function setcategorylist(val){ + let vals="" + categorylist.some((item,key)=> { + if (item.name === val) { + vals=item.value + return true + } + } + ) + + return vals +} @@ -214,7 +214,7 @@ class PackageConcent extends Component {
    - +
    diff --git a/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js b/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js index bec37a59a..c9fdebc05 100644 --- a/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js +++ b/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js @@ -252,7 +252,7 @@ class PackageIndexNEITaskDetails extends Component { '} className={"fl"}> {/*{this.props.current_user.username}*/} - 众包创新 + 众包创新 {data&&data.title} @@ -281,7 +281,7 @@ class PackageIndexNEITaskDetails extends Component {
    + src={data&&data.creator.image_url} width="70"/>
    {data&&data.creator.name} @@ -291,8 +291,8 @@ class PackageIndexNEITaskDetails extends Component { onMouseOver={this.setover} onMouseOut={this.setout} > - {overtype===false? 头像联系TA: - 头像 头像联系TA: + 头像联系TA}
    }
    @@ -403,9 +403,9 @@ class PackageIndexNEITaskDetails extends Component { return(
    {item.status==="bidding_won"?:""} - +

    {item.name}

    - {this.props.current_user&&this.props.current_user.login!=item.login? + {this.props.current_user&&this.props.current_user.login!=item.login? 头像联系TA :""}
    @@ -451,7 +451,7 @@ class PackageIndexNEITaskDetails extends Component { return(
    this.Clickteacher2(item.id)} key={key}> {item.bool===true?:} - +

    {item.name}

    ) diff --git a/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js b/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js index adde77b64..335f9d27e 100644 --- a/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js +++ b/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js @@ -709,7 +709,7 @@ class PackageIndexNEIBannerConcent extends Component {
    - +

    @@ -724,7 +724,7 @@ class PackageIndexNEIBannerConcent extends Component { {this.state.categorytypes===true?

    请选择类型
    :""}
    - +
    - +

    竞标截止: @@ -833,14 +833,14 @@ class PackageIndexNEIBannerConcent extends Component { {this.state.minmaxtype===true?

    最高费用不能小于最低费用
    :""}

    - +

    姓名: this.onChangeContact_name(e)} /> diff --git a/public/react/src/modules/projectPackages/packageconcnet.css b/public/react/src/modules/projectPackages/packageconcnet.css index 498da9214..74119e2b4 100644 --- a/public/react/src/modules/projectPackages/packageconcnet.css +++ b/public/react/src/modules/projectPackages/packageconcnet.css @@ -344,3 +344,17 @@ color: #4CACFF!important } +.ant-form-item-requireds::before { + display: inline-block; + margin-right: 4px; + color: #f5222d; + font-size: 14px; + font-family: SimSun,sans-serif; + line-height: 1; + content: '*'; +} + +*, *::before, *::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; +} \ No newline at end of file From 1b41c1c00b20debd7d98bfb0004257a6fe6e0909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Tue, 30 Jul 2019 14:46:17 +0800 Subject: [PATCH 08/10] b --- .../projectPackages/PackageIndex/PackageConcent.js | 1 + .../PackageIndexNEITaskDetails.js | 2 +- .../PackageIndexNEIBannerConcent.js | 14 +++++++------- public/react/src/modules/tpm/NewHeader.js | 3 ++- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/public/react/src/modules/projectPackages/PackageIndex/PackageConcent.js b/public/react/src/modules/projectPackages/PackageIndex/PackageConcent.js index 7875c5c46..cfc54bb98 100644 --- a/public/react/src/modules/projectPackages/PackageIndex/PackageConcent.js +++ b/public/react/src/modules/projectPackages/PackageIndex/PackageConcent.js @@ -14,6 +14,7 @@ let categorylist=[ {name:"数据库",value:"database"}, {name:"云计算和大数据",value:"cloud_compute_and_big_data"}, {name:"人工智能",value:"ai"}, + {name:"运维与测试",value:"devops_and_test"}, {name:"其他",value:"other"}, ] // diff --git a/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js b/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js index c9fdebc05..4788a7dc1 100644 --- a/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js +++ b/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js @@ -252,7 +252,7 @@ class PackageIndexNEITaskDetails extends Component { '} className={"fl"}> {/*{this.props.current_user.username}*/} - 众包创新 + 众包创新 {data&&data.title} diff --git a/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js b/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js index 335f9d27e..c9d49e542 100644 --- a/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js +++ b/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js @@ -407,7 +407,7 @@ class PackageIndexNEIBannerConcent extends Component { // } - if(modalCancel===true||this.props.current_user.phone===null){ + if(this.props.current_user&&this.props.current_user.phone===null||modalCancel===true){ if(contact_phone===undefined||contact_phone===null||contact_phone===""){ this.setState({ contact_phonetype:true @@ -445,7 +445,7 @@ class PackageIndexNEIBannerConcent extends Component { min_price:parseInt(min_price), max_price:parseInt(max_price), contact_name: contact_name===null||contact_name===undefined?this.props.current_user.username:contact_name, - contact_phone: contact_phone===undefined?this.props.current_user.phone:contact_phone, + contact_phone: contact_phone===undefined?this.props.current_user&&this.props.current_user.phone:contact_phone, code:code, publish:types } @@ -493,7 +493,7 @@ class PackageIndexNEIBannerConcent extends Component { min_price:parseInt(min_price), max_price:parseInt(max_price), contact_name: contact_name===null||contact_name===undefined?this.props.current_user.username:contact_name, - contact_phone: contact_phone===undefined?this.props.current_user.phone:contact_phone, + contact_phone: contact_phone===undefined?this.props.current_user&&this.props.current_user.phone:contact_phone, code:code, publish:types } @@ -629,7 +629,7 @@ class PackageIndexNEIBannerConcent extends Component { // }) // } // } - if(modalCancel===true||this.props.current_user.phone===null){ + if(this.props.current_user&&this.props.current_user.phone===null||modalCancel===true){ if(e.target.value===undefined||e.target.value===null||e.target.value===""){ this.setState({ contact_phonetype:true @@ -847,12 +847,12 @@ class PackageIndexNEIBannerConcent extends Component { {this.state.contact_nametype===true?

    不能为空
    :""}

    - {modalCancel===false&&this.props.current_user.phone!=null?

    + {this.props.current_user&&this.props.current_user.phone!=null&&modalCancel===false?

    手机号: @@ -861,7 +861,7 @@ class PackageIndexNEIBannerConcent extends Component {

    :""} {/*{this.state.current_userphonetype===true?
    不能为空
    :""}*/} - {modalCancel===true||this.props.current_user.phone===null?

    + {this.props.current_user&&this.props.current_user.phone===null||modalCancel===true?

    {/*未注册才显示!*/} diff --git a/public/react/src/modules/tpm/NewHeader.js b/public/react/src/modules/tpm/NewHeader.js index 23330e779..1798bfca8 100644 --- a/public/react/src/modules/tpm/NewHeader.js +++ b/public/react/src/modules/tpm/NewHeader.js @@ -718,7 +718,7 @@ submittojoinclass=(value)=>{

  • 教学案例
  • 众包创新
  • 交流问答
  • {
  • 我的实训
  • 我的实践课程
  • 我的项目
  • +
  • 我的众包
  • 账号管理
  • {/*
  • this.educoderlogin()} >登入测试接口
  • */} {/*
  • this.trialapplications()} >试用申请
  • */} From 263a809e78f941bbb091b314d432ea42621ff108 Mon Sep 17 00:00:00 2001 From: p31729568 Date: Tue, 30 Jul 2019 14:52:59 +0800 Subject: [PATCH 09/10] fix create project package api bug --- app/services/project_packages/save_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/project_packages/save_service.rb b/app/services/project_packages/save_service.rb index bcfc19a10..caf4cf6c7 100644 --- a/app/services/project_packages/save_service.rb +++ b/app/services/project_packages/save_service.rb @@ -15,7 +15,7 @@ class ProjectPackages::SaveService < ApplicationService is_create = package.new_record? raise Error, '类型不存在' unless ProjectPackageCategory.where(id: params[:category_id]).exists? - params[:project_package_category_id] = params[:category_id].to_i + params[:project_package_category_id] = params.delete(:category_id).to_i raise Error, '竞标截止时间不能小于当前时间' if params[:deadline_at].present? && params[:deadline_at].to_time < Time.now From c90358cdfaa96f47674c751823430288e2a17124 Mon Sep 17 00:00:00 2001 From: p31729568 Date: Tue, 30 Jul 2019 14:57:25 +0800 Subject: [PATCH 10/10] private message feature apis --- app/controllers/concerns/paginate_helper.rb | 2 +- app/controllers/users/base_controller.rb | 17 +++++++- .../private_message_details_controller.rb | 23 +++++++++++ .../users/private_messages_controller.rb | 39 +++++++++++++++++++ .../users/recent_contacts_controller.rb | 8 ++++ .../users/unread_message_infos_controller.rb | 12 ++++++ .../users_for_private_messages_controller.rb | 17 ++++++++ app/decorators/private_message_decorator.rb | 9 +++++ app/models/private_message.rb | 6 +++ app/models/user.rb | 3 +- .../private_messages/create_service.rb | 35 +++++++++++++++++ .../show.json.jbuilder | 11 ++++++ .../private_messages/create.json.jbuilder | 10 +++++ .../private_messages/index.json.jbuilder | 13 +++++++ .../users/recent_contacts/index.json.jbuilder | 2 + .../index.json.jbuilder | 2 + config/routes.rb | 6 +++ 17 files changed, 211 insertions(+), 4 deletions(-) create mode 100644 app/controllers/users/private_message_details_controller.rb create mode 100644 app/controllers/users/private_messages_controller.rb create mode 100644 app/controllers/users/recent_contacts_controller.rb create mode 100644 app/controllers/users/unread_message_infos_controller.rb create mode 100644 app/controllers/users_for_private_messages_controller.rb create mode 100644 app/decorators/private_message_decorator.rb create mode 100644 app/services/private_messages/create_service.rb create mode 100644 app/views/users/private_message_details/show.json.jbuilder create mode 100644 app/views/users/private_messages/create.json.jbuilder create mode 100644 app/views/users/private_messages/index.json.jbuilder create mode 100644 app/views/users/recent_contacts/index.json.jbuilder create mode 100644 app/views/users_for_private_messages/index.json.jbuilder diff --git a/app/controllers/concerns/paginate_helper.rb b/app/controllers/concerns/paginate_helper.rb index 34740eb5d..bbe84a348 100644 --- a/app/controllers/concerns/paginate_helper.rb +++ b/app/controllers/concerns/paginate_helper.rb @@ -1,7 +1,7 @@ module PaginateHelper def paginate(objs, **opts) page = params[:page].to_i <= 0 ? 1 : params[:page].to_i - per_page = params[:per_page].to_i > 0 ? params[:per_page].to_i : opts[:per_page] || 20 + per_page = params[:per_page].to_i > 0 && params[:per_page].to_i < 50 ? params[:per_page].to_i : opts[:per_page] || 20 Kaminari.paginate_array(objs).page(page).per(per_page) end diff --git a/app/controllers/users/base_controller.rb b/app/controllers/users/base_controller.rb index afc03ee13..fd138a182 100644 --- a/app/controllers/users/base_controller.rb +++ b/app/controllers/users/base_controller.rb @@ -26,9 +26,22 @@ class Users::BaseController < ApplicationController render_forbidden end + def page_value + params[:page].to_i <= 0 ? 1 : params[:page].to_i + end + + def per_page_value + params[:per_page].to_i > 0 && params[:per_page].to_i < 50 ? params[:per_page].to_i : 20 + end + alias_method :limit_value, :per_page_value + + def offset_value + (page_value - 1) * limit_value + end + def paginate(objs, **opts) - page = params[:page].to_i <= 0 ? 1 : params[:page].to_i - per_page = params[:per_page].to_i > 0 ? params[:per_page].to_i : 20 + page = page_value + per_page = per_page_value return Kaminari.paginate_array(objs).page(page).per(per_page) unless observed_logged_user? && opts[:special] diff --git a/app/controllers/users/private_message_details_controller.rb b/app/controllers/users/private_message_details_controller.rb new file mode 100644 index 000000000..486d23d7f --- /dev/null +++ b/app/controllers/users/private_message_details_controller.rb @@ -0,0 +1,23 @@ +class Users::PrivateMessageDetailsController < Users::BaseController + before_action :private_user_resources! + + after_action :update_message_status, only: [:show] + + def show + messages = observed_user.private_messages.without_deleted.where(target: target_user) + + @count = messages.count + @messages = messages.order(send_time: :asc).includes(sender: :user_extension) + end + + private + + def target_user + @_target_user ||= User.find(params[:target_id]) + end + + # 置为已读 + def update_message_status + observed_user.private_messages.only_unread.where(target: target_user).update_all(status: 1) + end +end \ No newline at end of file diff --git a/app/controllers/users/private_messages_controller.rb b/app/controllers/users/private_messages_controller.rb new file mode 100644 index 000000000..b80b6152b --- /dev/null +++ b/app/controllers/users/private_messages_controller.rb @@ -0,0 +1,39 @@ +class Users::PrivateMessagesController < Users::BaseController + before_action :private_user_resources! + after_action :update_onclick_time!, only: [:index] + + def index + @count = observed_user.private_messages.without_deleted.group(:target_id).count.count + + subquery = observed_user.private_messages.without_deleted.order(send_time: :desc).to_sql + query = "SELECT subquery.*, COUNT(*) message_count FROM (#{subquery}) subquery "\ + "GROUP BY subquery.target_id ORDER BY subquery.send_time desc LIMIT #{limit_value} OFFSET #{offset_value}" + @messages = PrivateMessage.select('*').from("(#{query}) AS query").includes(target: :user_extension) + end + + def create + receiver = User.find_by(id: params[:target_id]) + return render_error('用户未找到') if receiver.blank? + + @message = PrivateMessages::CreateService.call(observed_user, receiver, create_params) + rescue PrivateMessages::CreateService::Error => ex + render_error(ex.message) + end + + def destroy + message = observed_user.private_messages.without_deleted.find(params[:id]) + message.destroy! + + render_ok + end + + private + + def update_onclick_time! + current_user.onclick_time.touch(:onclick_time) + end + + def create_params + params.permit(:content) + end +end \ No newline at end of file diff --git a/app/controllers/users/recent_contacts_controller.rb b/app/controllers/users/recent_contacts_controller.rb new file mode 100644 index 000000000..bc4b8ea8f --- /dev/null +++ b/app/controllers/users/recent_contacts_controller.rb @@ -0,0 +1,8 @@ +class Users::RecentContactsController < Users::BaseController + before_action :private_user_resources! + + def index + contacts = observed_user.recent_contacts.distinct + @contacts = contacts.order('private_messages.created_at DESC').limit(10).includes(:user_extension) + end +end \ No newline at end of file diff --git a/app/controllers/users/unread_message_infos_controller.rb b/app/controllers/users/unread_message_infos_controller.rb new file mode 100644 index 000000000..7abd36304 --- /dev/null +++ b/app/controllers/users/unread_message_infos_controller.rb @@ -0,0 +1,12 @@ +class Users::UnreadMessageInfosController < Users::BaseController + before_action :private_user_resources! + + def show + click_time = observed_user.click_time + + unread_tiding_count = observed_user.tidings.where('created_at > ?', click_time).count + unread_message_count = observed_user.private_messages.only_unread.group(:target_id).count.count + + render_ok(unread_tiding_count: unread_tiding_count, unread_message_count: unread_message_count) + end +end \ No newline at end of file diff --git a/app/controllers/users_for_private_messages_controller.rb b/app/controllers/users_for_private_messages_controller.rb new file mode 100644 index 000000000..bbd5682a1 --- /dev/null +++ b/app/controllers/users_for_private_messages_controller.rb @@ -0,0 +1,17 @@ +class UsersForPrivateMessagesController < ApplicationController + before_action :require_login, :check_auth + + def index + users = User.active.where.not(id: current_user.id) + + keyword = params[:keyword].to_s.strip + if keyword.blank? + @users = [] + return + end + + users = users.where('LOWER(concat(lastname, firstname, nickname)) LIKE ?', "%#{keyword}%") + + @users = users.limit(10).includes(:user_extension) + end +end \ No newline at end of file diff --git a/app/decorators/private_message_decorator.rb b/app/decorators/private_message_decorator.rb new file mode 100644 index 000000000..6db17acf3 --- /dev/null +++ b/app/decorators/private_message_decorator.rb @@ -0,0 +1,9 @@ +module PrivateMessageDecorator + extend ApplicationDecorator + + display_time_method :send_time + + def unread? + status.zero? + end +end \ No newline at end of file diff --git a/app/models/private_message.rb b/app/models/private_message.rb index 1db4c9f66..640e48db7 100644 --- a/app/models/private_message.rb +++ b/app/models/private_message.rb @@ -1,3 +1,9 @@ class PrivateMessage < ApplicationRecord belongs_to :user + belongs_to :target, class_name: "User" + belongs_to :sender, class_name: "User" + belongs_to :receiver, class_name: "User" + + scope :without_deleted, -> { where.not(status: 2) } + scope :only_unread, -> { where(status: 0) } end diff --git a/app/models/user.rb b/app/models/user.rb index 14d7b2697..ed9d70c00 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -54,7 +54,8 @@ class User < ApplicationRecord has_one :onclick_time, :dependent => :destroy # 新版私信 - has_many :private_messages, :dependent => :destroy + has_many :private_messages, dependent: :destroy + has_many :recent_contacts, through: :private_messages, source: :target has_many :tidings, :dependent => :destroy has_many :games, :dependent => :destroy diff --git a/app/services/private_messages/create_service.rb b/app/services/private_messages/create_service.rb new file mode 100644 index 000000000..560f1a540 --- /dev/null +++ b/app/services/private_messages/create_service.rb @@ -0,0 +1,35 @@ +class PrivateMessages::CreateService < ApplicationService + Error = Class.new(StandardError) + + attr_reader :sender, :receiver, :params + + def initialize(sender, receiver, **params) + @sender = sender + @receiver = receiver + @params = params + end + + def call + validate! + + same_attr = { sender: sender, receiver: receiver, content: content, send_time: Time.now } + + message = nil + ActiveRecord::Base.transaction do + message = sender.private_messages.create!(same_attr.merge(target: receiver, status: 1)) + receiver.private_messages.create!(same_attr.merge(target: sender, status: 0)) + end + message + end + + private + + def content + @_content ||= params[:content].to_s.strip + end + + def validate! + raise Error, '内容不能为空' if content.blank? + raise Error, '内容太长' if content.size > 255 + end +end \ No newline at end of file diff --git a/app/views/users/private_message_details/show.json.jbuilder b/app/views/users/private_message_details/show.json.jbuilder new file mode 100644 index 000000000..065767fb4 --- /dev/null +++ b/app/views/users/private_message_details/show.json.jbuilder @@ -0,0 +1,11 @@ +json.count @count +json.messages do + json.array! @messages.each do |message| + json.extract! message, :id, :user_id, :receiver_id, :sender_id, :content + + json.send_time message.display_send_time + json.sender do + json.partial! 'users/user_simple', user: message.sender + end + end +end \ No newline at end of file diff --git a/app/views/users/private_messages/create.json.jbuilder b/app/views/users/private_messages/create.json.jbuilder new file mode 100644 index 000000000..888cfeff6 --- /dev/null +++ b/app/views/users/private_messages/create.json.jbuilder @@ -0,0 +1,10 @@ +json.status 0 +json.message 'success' +json.private_message do + json.extract! @message, :id, :user_id, :receiver_id, :sender_id, :content + + json.send_time @message.display_send_time + json.sender do + json.partial! 'users/user_simple', user: @message.sender + end +end \ No newline at end of file diff --git a/app/views/users/private_messages/index.json.jbuilder b/app/views/users/private_messages/index.json.jbuilder new file mode 100644 index 000000000..c18a7d209 --- /dev/null +++ b/app/views/users/private_messages/index.json.jbuilder @@ -0,0 +1,13 @@ +json.count @count +json.private_messages do + json.array! @messages.each do |message| + json.extract! message, :id, :content, :message_count + + json.unread message.unread? + json.send_time message.display_send_time + + json.target do + json.partial! 'users/user_simple', user: message.target + end + end +end \ No newline at end of file diff --git a/app/views/users/recent_contacts/index.json.jbuilder b/app/views/users/recent_contacts/index.json.jbuilder new file mode 100644 index 000000000..f2f7f025a --- /dev/null +++ b/app/views/users/recent_contacts/index.json.jbuilder @@ -0,0 +1,2 @@ +json.users @contacts, partial: 'users/user_simple', as: :user +json.count @contacts.size \ No newline at end of file diff --git a/app/views/users_for_private_messages/index.json.jbuilder b/app/views/users_for_private_messages/index.json.jbuilder new file mode 100644 index 000000000..be040e368 --- /dev/null +++ b/app/views/users_for_private_messages/index.json.jbuilder @@ -0,0 +1,2 @@ +json.users @users, partial: 'users/user_simple', as: :user +json.count @users.size \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 6623edd99..2f9eed61b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -53,6 +53,11 @@ Rails.application.routes.draw do resource :grade_records, only: [:show] resource :watch, only: [:create, :destroy] resources :project_packages, only: [:index] + # 私信 + resources :private_messages, only: [:index, :create, :destroy] + resources :recent_contacts, only: [:index] + resource :private_message_details, only: [:show] + resource :unread_message_info, only: [:show] end @@ -91,6 +96,7 @@ Rails.application.routes.draw do end end end + resources :users_for_private_messages, only: [:index] resources :myshixuns, param: :identifier, shallow: true do member do