From 4018789af622dbfbc5811d205c456e11d07039d2 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 23 Mar 2020 09:15:06 +0800 Subject: [PATCH] register --- test_client/src/views/crm/consumer.vue | 77 ++++++----- test_mini/app.js | 6 + test_mini/images/sologan.png | Bin 0 -> 34398 bytes test_mini/images/wave.png | Bin 0 -> 7682 bytes test_mini/pages/cuoti/index.js | 5 +- test_mini/pages/index/index.js | 1 - test_mini/pages/index/index.wxml | 3 - test_mini/pages/index/index.wxss | 4 - test_mini/pages/lianxi/index.js | 6 +- test_mini/pages/login/login.js | 130 ++++++++++-------- test_mini/pages/login/login.wxml | 39 +++++- test_mini/pages/login/login.wxss | 22 ++- test_mini/pages/subject/index.js | 38 ++++- test_mini/pages/subject/index.wxml | 5 +- test_mini/utils/request.js | 7 +- test_server/crm/authentication.py | 6 +- .../crm/migrations/0008_auto_20200322_2113.py | 33 +++++ test_server/crm/models.py | 39 +++--- test_server/crm/serializers.py | 13 +- test_server/crm/urls.py | 3 +- test_server/crm/views.py | 106 +++++++++++--- test_server/crm/zhenzismsclient.py | 39 ++++++ test_server/question/views.py | 3 + test_server/rbac/models.py | 37 ++++- 24 files changed, 448 insertions(+), 174 deletions(-) create mode 100644 test_mini/images/sologan.png create mode 100644 test_mini/images/wave.png create mode 100644 test_server/crm/migrations/0008_auto_20200322_2113.py create mode 100644 test_server/crm/zhenzismsclient.py diff --git a/test_client/src/views/crm/consumer.vue b/test_client/src/views/crm/consumer.vue index 3b9b216..805c741 100644 --- a/test_client/src/views/crm/consumer.vue +++ b/test_client/src/views/crm/consumer.vue @@ -99,10 +99,9 @@ @@ -156,14 +155,27 @@ - - + + + + + +
取消 @@ -181,6 +193,7 @@ import { updateConsumer, importConsumer } from "@/api/crm"; +import { getSubjectAll } from "@/api/question" import { getCompanyList } from "@/api/crm"; import { genTree, deepClone } from "@/utils"; import checkPermission from "@/utils/permission"; @@ -192,10 +205,8 @@ const defaultConsumer = { id: "", name: "", username: "", - company: { - id:0, - name:'' - }, + company: null, + subjects:[] }; const listQuery = { page: 1, @@ -237,13 +248,15 @@ export default { }, filterOrgText: "", treeLoding: false, - companyData: [] + companyData: [], + subjectData: [], }; }, computed: {}, created() { this.getList(); this.getCompanyList(); + this.getSubjectAll(); }, methods: { checkPermission, @@ -292,6 +305,11 @@ export default { this.treeLoding = false; }); }, + getSubjectAll() { + // getSubjectAll().then(response => { + // this.subjectData = genTree(response.data); + // }); + }, resetFilter() { this.listQuery = { page: 1, @@ -346,18 +364,18 @@ export default { const isEdit = this.dialogType === "edit"; if (isEdit) { let consumer = this.consumer - consumer.company = consumer.company.id updateConsumer(this.consumer.id, consumer).then(() => { - for (let index = 0; index < this.consumerList.length; index++) { - if (this.consumerList[index].id === this.consumer.id) { - this.consumerList.splice( - index, - 1, - Object.assign({}, this.consumer) - ); - break; - } - } + // for (let index = 0; index < this.consumerList.length; index++) { + // if (this.consumerList[index].id === this.consumer.id) { + // this.consumerList.splice( + // index, + // 1, + // Object.assign({}, this.consumer) + // ); + // break; + // } + // } + this.getList() this.dialogVisible = false; this.$notify({ title: "成功", @@ -367,9 +385,6 @@ export default { }); }); } else { - this.consumer.company.id = this.consumer.company.id.pop(); - let consumer = this.consumer - consumer.company = consumer.company.id createConsumer(consumer).then(res => { // this.consumer = res.data // this.consumerList.unshift(this.consumer) diff --git a/test_mini/app.js b/test_mini/app.js index 6400235..684abc4 100644 --- a/test_mini/app.js +++ b/test_mini/app.js @@ -15,6 +15,12 @@ App({ if(res.code==200){ this.globalData.token = res.data.token this.globalData.userInfo = res.data.userinfo + if(res.data.userinfo.username == null){ + //匿名用户 + wx.reLaunch({ + url: '/pages/login/login', + }) + } } }) } diff --git a/test_mini/images/sologan.png b/test_mini/images/sologan.png new file mode 100644 index 0000000000000000000000000000000000000000..ba0482c85b50c25bdaff0568e81796f302ed36ad GIT binary patch literal 34398 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ν0F4VLoyR^ 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 Q#(g3+C9NkF3NM5I4?b8$r~m)} literal 0 HcmV?d00001 diff --git a/test_mini/images/wave.png b/test_mini/images/wave.png new file mode 100644 index 0000000000000000000000000000000000000000..f3d1ce7842d41160da0e278df42e922ade43aceb GIT binary patch literal 7682 zcmeHMc{r5syMM-LEHRQ~FWs;p#-#^Z|&il_ZpZ9*=`+lB#`#kSEVR|}hjP#uJ002hy z^UC@FFvkHvMN12Z?zCqL|AdA-J*|r>(75!!;nEpG_d#owa@E%{0CSG(D+L@ZWOG!E zUgpU&c$~)9_+F{46q@Ex!X;u&u1)95zmIsUe0H;>rd)wV)YHGlFbM>SsEE`9z}=~? ztZ>oe^X%}TR}$t>@HNEouLxL7IBf+9^MYN{W!t^?jP=G6pKfe7$eY(rks|N1kFkj#Xcd0UHDL30&ez-XST+od za7Nu%k~XspzBM;=p3T|}ae7UX@ouOosWW2hb`Jm0Cjj&!woDZ=H=~covqqWkf0wM1 z6;Co;mwPhB{Z^O63c#W#`f!MS3Wv96oLn(X>nejJbBkNCg0?W0lcVdW9sq>xW%6CI zoU=Y&YrTUyMu|`N`SE?f&YV0v)b#b%)8)>cDRNQ6S6@!s##eW!IEy`IIuLX8_7Rp+ z0DQ910&)3)Ukp|b@IP;U{J^X-EkRY=9bV|DYl*4Jk_97Qcv_;8w1v@~U0$b(!{5$F zwXu|{drThe0N~jId{ZVR|s=e}+pf5(XKTWvQ#(Sb$L;9)G1r8&ig zvBt-2dbKy(URTL22?lz;4Q!?8@!&&v%c~Awx)W*@ga=upgMW*;eJVg8Am05 zc_zYymG_O{p78y^V@p&YE~2{)K#oDimg##*9`h@y`NMsIc((P^ce%7aI~({Feskaj z86V>-rzY)>O}r0!yh3XT+4^MEyz{^bp2m9nDy+tmV)LV(r2(RJzR9^>04)ECeXPah zxb#X^ zvs4Lu6Z&gfBpnZDBv=%AFqD3B^=M5Fx4*3CMq;Zpg>5wPu?GS;Io279$ufN^Np(FA z_bp%1aj6WWAp_u_33+}kiJZ`D$ircndALJk&IpB_6q{lI6^W|4_O|%Ykn0W_74c_e zMI_KCq0W%b(&%&I&i)=dG2+Fq0=+7iND%^a9-1gPsCY>3eO0&?Wr3a|>U&OD+0-vF zfRW4%?7r>x$sb8>{_`_34kw1GVnYsRu3-pWT@)< zJmE8^rL)wv=eJvP{hIO<;Rd(FsW#8OCcs=Ncic}K`_0NQCV1WgIKsN=mx4$K{60#9 z*tTszqXMiw``?a`nHTkH5p)nD|x({1?et^xn7B9I|t(KuCANXU3W9-$&GpB zeT1>N*zk}ybt)|5m24zou`sUhjq8fxEs5uaMfm{iQ}#XmR7hOMmG+rYqkKz+YfUE4 zMH3}RZ3gw#w58~S?r}~NzND@oZDlKvL7UgMPttO_uGS=RK4G-fX0!QrQMua(Zdq`s z^$dHL0DDlA@HTsD{z-tD*Gq4*Zj6Yv;&k-TJT4oNQa1R-n-RD~Suj+wr+V_s!oh1b z-_vzPCq&4k4_RJ>+8J`al0g5 zHR&L0OH)8cjWf|KSKxNmpfkGg?Z!kB7(q=_n4Sn>uOp8dUKO4XmMKzkx0-k>S98Sz ztf~*+p&T&2oAiyPQ(?C7Nbt{47|6+MqbRbrOmsL1v#Zyz_T-kzs3n7ux3x9xGcUvt zuQL-`g*ktWs=`2C8(PE0KoxEGR6g38dg`Z~k+fBVRYjv&@7+Lt@cR-5G6%D@JXqG0yFAfiY zRQkvE>)k@9^uBYDwYz>?%LS;3&kkTt!J2)70{hWEUzW(KUaq}NOEq;Zqvs4UOA;*>4kXszMb9U zYVXZ4h65(klswvV#OaD$A;u$fk=0WCIfK}?v;gVP=w}mkD)4PWJqK@VH~9jKPs+^w z!OmM1-Ej#26K>x_(6?yV49~*OIQ2HBAlHLy3AW))Uvgb%W{}FU>!@deOeN;uko3eX zGt=PxWhVQ~rZCj0ZHL$6M$q^qt)DbmioQpj-|LVi`&94ySS`T%{W9I8uwyjH&_Mju z&Hj872gZfcz6KFhNqiE{KCjI{u>YQ-bnzRjtK#oW=3g2SBMR)Os+29eOLXbn3d|Pn z;gjfL=m9(_hc8PMNgzBta5{iKyx`?S-V$mV>G4gHF~&D9m?MihWSD}I`j)oR_7ho> zzJqHw z4oAlHV@6s|nbZ(dY0W*1mR+&Zf9oLo)%}lTD5*KV=-}eU2#Pv|+cFj=R7xeZ(^ zG@IAM_oqrH)IV^FN+a*v4(4q;rNRR2`$alKT^%J`njk-GRy< zZ-3Ei>QNVa{e6)jHvw-B&4=(M^85ZXUdeY14e%26>EYZkrB_GItEp z%HUdi$A@*HNEl*|}7#B!BD_HgI>rA6H!=a0>-lXK4J}2w>tWy@_t_FN%k%Qlp zJgWV2Ea(y^^_dPF!KKi+fI*(&>CMdn2&z;I-$k(aa<`t=sh7 z7kDmV@icF%AWi99-i}l;z`w-Z@g$w{HTK|!&PKEG+>$trL5?m}p^2>p;m#loa}IPs z-N}d#)xnOu(eK^KTTf(LU4VQ@$r8632SHF&`K5;jm)jVT(Rs8l2-K#5d z<+Xqe!OaV~FNZAM2sUDtBWXYQ`=m-ft@I=raO%-|A-!5#p(m)sj?v0-pitGsi^WVX zxMQ8zc5FGc26{W0W73f9q)k)xwIdS%HYqbHlMJb1W@o;8&lqoPt>x3lK%GO*AQw2r z!4%INJ1=vp%C>4lVvUARu}w%o-YWG8!vTZdbS`E--==L52E36B=HXI`emnLoHVzgj ze(e0iC=sNiC_VJo4l^VM|=Mu-~!E3$yW(p>-Vv z{__uIaA_=3@>Zje$U;JOv~J1ztJ@ODPt{jo^$RversBS7xi@=Gx(j`b9(r z`J-kVU0M#q0oE?==e>S)KJ$ExBP{X)XT5YJAmh@B6PJqB)10AyYk?jE2RJ7iQg895`9QwJu1`4aw;S-+IUoRnM$kk#sRa1~0o&Jn&S! zvR+YXv8OdTcxfV&yXMs^M-3)tg^`^|o@`jQLK`-R%-5`ssMl~FF_`2=#Ro+NN#IwLhVtRz4$zdSO z2tHUJPN%evcPa%slD}1zJ%44@C6cxdA32{Eay~6cA2Bi~ad>LM*+KuSWcQP&!~BWE z6=q0+^>@_5u5zN0XN+5Mspaj_q5JaPSqj*mB3Tvq$h|SosCukkBN)S!Gx*LGt($Ad zC#2f@IJ=LhqJhi#v?i>yf)M;bu%r3Yo*ySRLc1)N(Xl3Op=a?No)b(sOg+{U*#>Pb zu<#(gYAy#=F$7l8W?ee21p(PEsxhCJ%qGS`|W4>9U{f_Y=ym%x|ErO zojBadZ%ig54n{lp^vk8s+GktD2SWTzfAr!<>5|?v;;3TC1d$)}_A=Ij^n?-xrN&G; z_+J*%xxvaMum0{|-Ezz=lOj5g_CNF^X%@(De-_t_gH^b^cYVWiG346zRQO>B65iQ= zXhx!Kp*&1;Kd?xHXE6}&YWKII4QM%{1_1#@qs)Qp zU6*Lk9aOl)T{mE`l#W*MzwhR3SnT!5FDCej4^Oin6_}9WZ3OSsR$}p%(*6bEmr@^f zpiS}e$`?4SmP?Fgli#CI_Vc{~pEv+Yye*(QObq-yv!B1q=MXXX{xj_5$Qj|VCbOl% znh>`1Cv3wng-7|+TkptUHb@u@_bmQ&;U#PLl0=9CtpciPF%q>(dN zbXZf7CvxGg;Lhg}r^MZ%9g)QVA%f-ZfZ+-igAho7%tDtvv{dLa<=-8kVt@mJh}-OA z1oY;9E!w{?wxk-y0YG{j44Nevz5C4Gfe0SCTu8A6`xt4NZ^;}3Sp}HbT_a4{JB!{M zKvgtgvOK`(X=l6JP>%H?;c8$ld|bKV1j(cr78@;GED-O!f${%eiSm>IkCs z)idh-Bpd@ycQ=5C&O^ZhdkJczc)B2!q72^`ybi95@IqEI)OU^0=iiR~yEUI`9v)p+DK^pQ6{_>Zsj+hsgJcQ33c@e*Ud3 zY;Z-x{waF>FI=}*jQSft|G`Fk$*8~a^KW%DS&f4ZJ$uBcxZn8s-*fvP$ZO~i5~y?j y;ky5)*Z(mK|5iu;7wEO%U(ffuCzJn{Ug2X>MMBqCG&*-Wueyqka*?7%;C}#W7d%-2 literal 0 HcmV?d00001 diff --git a/test_mini/pages/cuoti/index.js b/test_mini/pages/cuoti/index.js index e0e1bb7..3f01ce3 100644 --- a/test_mini/pages/cuoti/index.js +++ b/test_mini/pages/cuoti/index.js @@ -10,7 +10,8 @@ Page({ ctms: [], tm_index: 0, isright:false, - answerP:false + answerP:false, + tmtotal:0 }, radioChange: function (e) { var that = this @@ -26,7 +27,7 @@ Page({ /** * 生命周期函数--监听页面加载 */ - onLoad: function (options) { + onLoad: function () { var that = this wx.showLoading({}) try { diff --git a/test_mini/pages/index/index.js b/test_mini/pages/index/index.js index 3fba5f8..177d47e 100644 --- a/test_mini/pages/index/index.js +++ b/test_mini/pages/index/index.js @@ -4,7 +4,6 @@ const app = getApp() Page({ data: { - motto: 'Hello World', userInfo: {}, hasUserInfo: false, canIUse: wx.canIUse('button.open-type.getUserInfo') diff --git a/test_mini/pages/index/index.wxml b/test_mini/pages/index/index.wxml index 0243bda..d79c207 100644 --- a/test_mini/pages/index/index.wxml +++ b/test_mini/pages/index/index.wxml @@ -7,7 +7,4 @@ {{userInfo.nickName}} - - {{motto}} - diff --git a/test_mini/pages/index/index.wxss b/test_mini/pages/index/index.wxss index 8435be5..fab9dee 100644 --- a/test_mini/pages/index/index.wxss +++ b/test_mini/pages/index/index.wxss @@ -15,7 +15,3 @@ .userinfo-nickname { color: #aaa; } - -.usermotto { - margin-top: 20px; -} \ No newline at end of file diff --git a/test_mini/pages/lianxi/index.js b/test_mini/pages/lianxi/index.js index ee138f8..05e9f9c 100644 --- a/test_mini/pages/lianxi/index.js +++ b/test_mini/pages/lianxi/index.js @@ -20,10 +20,12 @@ Page({ this.setData({ questioncatId: value.id }) + } else{ + wx.switchTab({ + url: '/pages/main/main', + }) } } catch (e) { - wx.navigateBack({ - }) } }, diff --git a/test_mini/pages/login/login.js b/test_mini/pages/login/login.js index 6d0e5fe..fbf4f6d 100644 --- a/test_mini/pages/login/login.js +++ b/test_mini/pages/login/login.js @@ -1,66 +1,86 @@ -// pages/login/login.js +//index.js +//获取应用实例 +const app = getApp() +const api = require("../../utils/request.js"); Page({ - - /** - * 页面的初始数据 - */ data: { - + userInfo: {}, + hasUserInfo: false, + canIUse: wx.canIUse('button.open-type.getUserInfo') }, - - /** - * 生命周期函数--监听页面加载 - */ - onLoad: function (options) { - + //事件处理函数 + bindViewTap: function () { + wx.navigateTo({ + url: '../logs/logs' + }) }, - - /** - * 生命周期函数--监听页面初次渲染完成 - */ - onReady: function () { - + phoneChange: function (e) { + this.data.phone = e.detail.value }, - - /** - * 生命周期函数--监听页面显示 - */ - onShow: function () { - + codeChange: function (e) { + this.data.code = e.detail.value }, - - /** - * 生命周期函数--监听页面隐藏 - */ - onHide: function () { - + onLoad: function () { + wx.hideHomeButton() + if (app.globalData.userInfo) { + this.setData({ + userInfo: app.globalData.userInfo, + hasUserInfo: true + }) + } else if (this.data.canIUse) { + // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 + // 所以此处加入 callback 以防止这种情况 + app.userInfoReadyCallback = res => { + this.setData({ + userInfo: res.userInfo, + hasUserInfo: true + }) + } + } else { + // 在没有 open-type=getUserInfo 版本的兼容处理 + wx.getUserInfo({ + success: res => { + app.globalData.userInfo = res.userInfo + this.setData({ + userInfo: res.userInfo, + hasUserInfo: true + }) + } + }) + } }, - - /** - * 生命周期函数--监听页面卸载 - */ - onUnload: function () { - + getUserInfo: function (e) { + app.globalData.userInfo = e.detail.userInfo + this.setData({ + userInfo: e.detail.userInfo, + hasUserInfo: true + }) }, - - /** - * 页面相关事件处理函数--监听用户下拉动作 - */ - onPullDownRefresh: function () { - + sendMsg : function (e){ + api.request('crm/consumer/sendcode', 'GET', {phone:this.data.phone}).then(res => { + wx.showToast({ + title: '验证码发送成功!', + icon:'none' + }) + }) }, - - /** - * 页面上拉触底事件的处理函数 - */ - onReachBottom: function () { - + onGetInfo : function (e){ + this.setData({ + userInfo: e.detail.userInfo + }) + this.denglu() }, - - /** - * 用户点击右上角分享 - */ - onShareAppMessage: function () { - + goMain: function (){ + wx.reLaunch({ + url: '/pages/main/main', + }) + }, + denglu: function () { + api.request('crm/consumer/register/', 'POST', { phone: this.data.phone, code: this.data.code }).then(res => { + getApp().onLaunch() + }) + wx.switchTab({ + url: '/pages/main/main', + }) } -}) \ No newline at end of file +}) diff --git a/test_mini/pages/login/login.wxml b/test_mini/pages/login/login.wxml index 2f17a4e..ec2ae6e 100644 --- a/test_mini/pages/login/login.wxml +++ b/test_mini/pages/login/login.wxml @@ -1,2 +1,37 @@ - -pages/login/login.wxml + + + 开启学习之旅 + 为了更好的为您服务,请注册! + + + 注册 + + + + 手机号 + + + + + + 获取验证码 + + + + + 验证码 + + + + + + + + + 浏览进入 + + + + Copyright © 2018-2020 国检集团 + 中存大数据提供技术支持 + \ No newline at end of file diff --git a/test_mini/pages/login/login.wxss b/test_mini/pages/login/login.wxss index 4827a66..8435be5 100644 --- a/test_mini/pages/login/login.wxss +++ b/test_mini/pages/login/login.wxss @@ -1 +1,21 @@ -/* pages/login/login.wxss */ \ No newline at end of file +/**index.wxss**/ +.userinfo { + display: flex; + flex-direction: column; + align-items: center; +} + +.userinfo-avatar { + width: 128rpx; + height: 128rpx; + margin: 20rpx; + border-radius: 50%; +} + +.userinfo-nickname { + color: #aaa; +} + +.usermotto { + margin-top: 20px; +} \ No newline at end of file diff --git a/test_mini/pages/subject/index.js b/test_mini/pages/subject/index.js index 740cfce..3814950 100644 --- a/test_mini/pages/subject/index.js +++ b/test_mini/pages/subject/index.js @@ -1,5 +1,6 @@ // pages/subject/index.js const api = require("../../utils/request.js"); + Page({ /** @@ -14,11 +15,19 @@ Page({ */ onLoad: function (options) { api.request('question/subject/', 'GET').then(res => { - if (res.code == 200) { + var subjectData = res.data + api.request('crm/consumer/subjectpaid', 'GET').then(res => { + for(var i=0;i所有学科 - +

{{item.name}}

- 已购买 + 已购买 +
购买
diff --git a/test_mini/utils/request.js b/test_mini/utils/request.js index 9453cb4..75a647b 100644 --- a/test_mini/utils/request.js +++ b/test_mini/utils/request.js @@ -12,15 +12,16 @@ function request(url, method, data) { }, success: (res => { wx.hideLoading(); - if (res.data.code >= 400) { + if (res.data.code >= 200 && res.data.code < 400) { + resolve(res.data); + } + else { wx.showToast({ title: JSON.stringify(res.data.msg), icon: 'none', duration: 1000 }) } - resolve(res.data); - }), fail: (res => { diff --git a/test_server/crm/authentication.py b/test_server/crm/authentication.py index 67dc882..5e76228 100644 --- a/test_server/crm/authentication.py +++ b/test_server/crm/authentication.py @@ -10,14 +10,14 @@ class ConsumerTokenAuthentication(JSONWebTokenAuthentication): """ 返回登陆消费者 """ - username = payload['username'] + id = payload['user_id'] - if not username: + if not id: msg = _('签名有误.') raise exceptions.AuthenticationFailed(msg) try: - consumer = Consumer.objects.get(username=username) + consumer = Consumer.objects.get(id=id) except Consumer.DoesNotExist: msg = _('消费者不存在') raise exceptions.AuthenticationFailed(msg) diff --git a/test_server/crm/migrations/0008_auto_20200322_2113.py b/test_server/crm/migrations/0008_auto_20200322_2113.py new file mode 100644 index 0000000..bbba513 --- /dev/null +++ b/test_server/crm/migrations/0008_auto_20200322_2113.py @@ -0,0 +1,33 @@ +# Generated by Django 3.0.4 on 2020-03-22 13:13 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('crm', '0007_auto_20200320_1726'), + ] + + operations = [ + migrations.CreateModel( + name='SendCode', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')), + ('is_delete', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), + ('phone', models.CharField(max_length=11, verbose_name='发送号码')), + ('code', models.CharField(max_length=4, verbose_name='验证码')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AlterField( + model_name='consumer', + name='username', + field=models.CharField(blank=True, max_length=11, null=True, unique=True, verbose_name='手机号码'), + ), + ] diff --git a/test_server/crm/models.py b/test_server/crm/models.py index 1fa0aa2..93e611e 100644 --- a/test_server/crm/models.py +++ b/test_server/crm/models.py @@ -5,34 +5,34 @@ from question.models import Questioncat # Create your models here. class Company(SoftCommonModel): - """ + ''' 客户企业 - """ - name = models.CharField(max_length=60, verbose_name="名称", unique=True) - pid = models.ForeignKey("self", null=True, blank=True, on_delete=models.SET_NULL, verbose_name="父") + ''' + name = models.CharField(max_length=60, verbose_name='名称', unique=True) + pid = models.ForeignKey('self', null=True, blank=True, on_delete=models.SET_NULL, verbose_name='父') class Meta: - verbose_name = "客户企业" + verbose_name = '客户企业' verbose_name_plural = verbose_name def __str__(self): return self.name class Consumer(SoftCommonModel): - """ + ''' 学员 - """ - name = models.CharField(max_length=200, verbose_name="姓名") - username = models.CharField(max_length=11, default="", verbose_name="手机号码/邮箱", unique=True) - company = models.ForeignKey("Company", null=True, blank=True, on_delete=models.SET_NULL, verbose_name="所属单位") - openid = models.CharField(max_length=200, verbose_name="openid", null=True, blank=True, unique=True) - avatar = models.CharField(default="/media/default/avatar.png",max_length=1000, null=True, blank=True, verbose_name="头像") - nickname = models.CharField(max_length=200, verbose_name="昵称", null=True, blank=True) - subjects = models.ManyToManyField(Questioncat, verbose_name="付费学科", through="PaySubject") + ''' + name = models.CharField(max_length=200, verbose_name='姓名') + username = models.CharField(max_length=11, verbose_name='手机号码', unique=True, null=True, blank=True) + company = models.ForeignKey('Company', null=True, blank=True, on_delete=models.SET_NULL, verbose_name='所属单位') + openid = models.CharField(max_length=200, verbose_name='openid', null=True, blank=True, unique=True) + avatar = models.CharField(default='/media/default/avatar.png',max_length=1000, null=True, blank=True, verbose_name='头像') + nickname = models.CharField(max_length=200, verbose_name='昵称', null=True, blank=True) + subjects = models.ManyToManyField(Questioncat, verbose_name='付费学科', through='PaySubject') class Meta: - verbose_name = "客户" + verbose_name = '客户' verbose_name_plural = verbose_name def __str__(self): @@ -43,4 +43,11 @@ class PaySubject(CommonModel): 付费学科关联表 ''' consumer = models.ForeignKey(Consumer, on_delete=models.CASCADE) - subject = models.ForeignKey(Questioncat, on_delete=models.CASCADE) \ No newline at end of file + subject = models.ForeignKey(Questioncat, on_delete=models.CASCADE) + +class SendCode(CommonModel): + ''' + 验证码发送记录 + ''' + phone = models.CharField(max_length=11, verbose_name='发送号码') + code = models.CharField(max_length=4, verbose_name= '验证码') \ No newline at end of file diff --git a/test_server/crm/serializers.py b/test_server/crm/serializers.py index d439e61..f9a874b 100644 --- a/test_server/crm/serializers.py +++ b/test_server/crm/serializers.py @@ -20,18 +20,7 @@ class ConsumerSerializer(serializers.ModelSerializer): create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) company_name = serializers.StringRelatedField(source='company') - - class Meta: - model = Consumer - fields = '__all__' - depth = 1 - -class ConsumerCUSerializer(serializers.ModelSerializer): - """ - 客户新增编辑序列化 - """ - create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) - update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) + subjects_name = serializers.StringRelatedField(source='subjects', many=True) class Meta: model = Consumer diff --git a/test_server/crm/urls.py b/test_server/crm/urls.py index c59ac8f..e61718d 100644 --- a/test_server/crm/urls.py +++ b/test_server/crm/urls.py @@ -1,5 +1,5 @@ from django.urls import path,include -from .views import CompanyViewSet, ConsumerViewSet, ConsumerMPLoginView +from .views import CompanyViewSet, ConsumerViewSet, ConsumerMPLoginView, ConsumerRegister from rest_framework import routers @@ -9,5 +9,6 @@ router.register('company', CompanyViewSet, basename="company") urlpatterns = [ path('consumer/mplogin/', ConsumerMPLoginView.as_view()), + path('consumer/register/', ConsumerRegister.as_view()), path('', include(router.urls)), ] diff --git a/test_server/crm/views.py b/test_server/crm/views.py index 8ebf927..7d5330a 100644 --- a/test_server/crm/views.py +++ b/test_server/crm/views.py @@ -9,18 +9,48 @@ from rest_framework import status from django_filters.rest_framework import DjangoFilterBackend from openpyxl import Workbook, load_workbook import requests -from rest_framework_jwt.serializers import jwt_encode_handler, jwt_payload_handler +from rest_framework_jwt.serializers import jwt_encode_handler import json +import random +from rest_framework_jwt.settings import api_settings +from calendar import timegm +from datetime import datetime +import warnings + + from utils.custom import CommonPagination from rbac.permission import RbacPermission -from .models import Company, Consumer, PaySubject -from .serializers import CompanySerializer, ConsumerSerializer, ConsumerCUSerializer +from crm.authentication import ConsumerTokenAuthentication +from .models import Company, Consumer, PaySubject, SendCode +from .serializers import CompanySerializer, ConsumerSerializer from server import settings from question.models import Questioncat +from crm.zhenzismsclient import ZhenziSmsClient appid = 'wx5c39b569f01c27db' secret = '68762892f8df2b4a0b1940c5250a8dc0' +sms_appid = '104951' +sms_appsecret = '3d0ccaf9-f680-47e3-ad93-9e83093c5a04' +sms_url = 'https://sms_developer.zhenzikj.com' + +def jwt_payload_handler(user): + payload = { + 'user_id': user.pk, + 'exp': datetime.utcnow() + api_settings.JWT_EXPIRATION_DELTA + } + if api_settings.JWT_ALLOW_REFRESH: + payload['orig_iat'] = timegm( + datetime.utcnow().utctimetuple() + ) + + if api_settings.JWT_AUDIENCE is not None: + payload['aud'] = api_settings.JWT_AUDIENCE + + if api_settings.JWT_ISSUER is not None: + payload['iss'] = api_settings.JWT_ISSUER + + return payload class CompanyViewSet(ModelViewSet): """ @@ -69,23 +99,34 @@ class ConsumerViewSet(ModelViewSet): serializer_class = ConsumerSerializer pagination_class = CommonPagination ordering_fields = ('id',) - ordering = ['id'] + ordering = ['company'] filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter] filterset_fields = ('company',) search_fields = ('^name',) - - def get_serializer_class(self): - if self.action == 'list': - return ConsumerSerializer - else: - return ConsumerCUSerializer - def destroy(self, request, *args, **kwargs): #逻辑删除 - instance = self.get_object() - # self.perform_destroy(instance) - instance.is_delete = True - instance.save() - return Response(status=status.HTTP_204_NO_CONTENT) + @action(methods=['get'], detail=False, permission_classes=[], authentication_classes=[ConsumerTokenAuthentication], + url_path='subjectpaid', url_name='subject_paid') + def has_paid(self, request): + """ + 当前登陆消费者已付费的学科 + """ + queryset = PaySubject.objects.filter(consumer = request.user) + data = queryset.values_list('subject__id',flat=True) + return Response(data) + + @action(methods=['get'], detail=False, permission_classes=[], authentication_classes=[], + url_path='sendcode', url_name='code_send') + def sendcode(self, request): + client = ZhenziSmsClient(sms_url, sms_appid, sms_appsecret) + code = random.randint(1000,9999) + phone = request.query_params.get('phone') + params = {'message':'您的验证码为:' + str(code) +',5分钟内有效', 'number': phone} + result = json.loads(client.send(params)) + if result['code'] == 0: + SendCode.objects.create(phone=phone, code=code) + return Response(status=status.HTTP_200_OK) + else: + return Response({'error':result['data']}) @action(methods=['post'], detail=False, permission_classes=[IsAuthenticated], url_path='import', url_name='import_consumer') @@ -155,11 +196,8 @@ class ConsumerMPLoginView(APIView): info = json.loads(info) openid = info['openid'] session_key = info['session_key'] - try: - consumer = Consumer.objects.get(openid = openid) - serializer = ConsumerSerializer(instance=consumer) - except: - return Response("匿名用户",status=status.HTTP_401_UNAUTHORIZED) + consumer = Consumer.objects.get_or_create(openid = openid)[0] + serializer = ConsumerSerializer(instance=consumer) payload = jwt_payload_handler(consumer) token = jwt_encode_handler(payload) return Response({"token":token,"session_key":session_key, "openid":openid, "userinfo":serializer.data}) @@ -168,4 +206,28 @@ class ConsumerLogoutView(APIView): authentication_classes = () permission_classes = () def get(self, request, *args, **kwargs): - return Response(status=status.HTTP_200_OK) \ No newline at end of file + return Response(status=status.HTTP_200_OK) + +class ConsumerRegister(APIView): + ''' + 验证码登陆和注册 + ''' + authentication_classes = [ConsumerTokenAuthentication] + permission_classes = [] + def post(self, request, *args, **kwargs): + data = request.data + phone = data.get('phone', None) + code = data.get('code', None) + if phone and code: + obj = SendCode.objects.filter(phone=phone).last() + if code == obj.code: # 验证通过 + consumer_queryset = Consumer.objects.filter(username=phone) + if consumer_queryset.exists(): # 是否存在 + consumer = consumer_queryset.first() + openid = request.user.openid + request.user.delete(soft=False) # 彻底删除 + consumer.openid = openid + consumer.save() + return Response(status=status.HTTP_200_OK) + else: + return Response({'error':'验证码错误!'}) \ No newline at end of file diff --git a/test_server/crm/zhenzismsclient.py b/test_server/crm/zhenzismsclient.py new file mode 100644 index 0000000..32d1711 --- /dev/null +++ b/test_server/crm/zhenzismsclient.py @@ -0,0 +1,39 @@ +import requests +from requests.packages.urllib3.exceptions import InsecureRequestWarning + +class ZhenziSmsClient(object): + def __init__(self, apiUrl, appId, appSecret): + self.apiUrl = apiUrl + self.appId = appId + self.appSecret = appSecret + + def send(self, params): + data = params; + data['appId'] = self.appId; + data['appSecret'] = self.appSecret; + requests.packages.urllib3.disable_warnings(InsecureRequestWarning); + response = requests.post(self.apiUrl+'/sms/send.do', data=data, verify=False); + result = str(response.content,'utf-8'); + return result; + + + def balance(self): + data = { + 'appId': self.appId, + 'appSecret': self.appSecret + } + requests.packages.urllib3.disable_warnings(InsecureRequestWarning); + response = requests.post(self.apiUrl+'/account/balance.do', data=data, verify=False); + result = str(response.content,'utf-8'); + return result; + + def findSmsByMessageId(self, messageId): + data = { + 'appId': self.appId, + 'appSecret': self.appSecret, + 'messageId': messageId + } + requests.packages.urllib3.disable_warnings(InsecureRequestWarning); + response = requests.post(self.apiUrl+'/smslog/findSmsByMessageId.do', data=data, verify=False); + result = str(response.content,'utf-8'); + return result; diff --git a/test_server/question/views.py b/test_server/question/views.py index b0d3778..804165f 100644 --- a/test_server/question/views.py +++ b/test_server/question/views.py @@ -16,6 +16,7 @@ from .models import Questioncat, Question from .serializers import QuestioncatSerializer, QuestionSerializer, SubjectSerializer from server import settings from crm.authentication import ConsumerTokenAuthentication +from crm.models import PaySubject class SubjectViewSet(ModelViewSet): @@ -54,6 +55,8 @@ class SubjectViewSet(ModelViewSet): if self.request.method == 'GET': self.permission_classes = [] return [permission() for permission in self.permission_classes] + + class QuestioncatViewSet(ModelViewSet): """ diff --git a/test_server/rbac/models.py b/test_server/rbac/models.py index 5acf02a..91217a3 100644 --- a/test_server/rbac/models.py +++ b/test_server/rbac/models.py @@ -3,17 +3,35 @@ from django.contrib.auth.models import AbstractUser import django.utils.timezone as timezone from django.db.models.query import QuerySet -class SoftDeleteQuerySet(QuerySet): +# 自定义软删除查询基类 +class SoftDeletableQuerySetMixin(object): + """ + QuerySet for SoftDeletableModel. Instead of removing instance sets + its ``is_deleted`` field to True. + """ + def delete(self): + """ + Soft delete objects from queryset (set their ``is_deleted`` + field to True) + """ self.update(is_delete=True) -class SoftDeletManager(models.Manager): - ''' - 仅返回删除的实例 - ''' + +class SoftDeletableQuerySet(SoftDeletableQuerySetMixin, QuerySet): + pass + + +class SoftDeletableManagerMixin(object): + """ + Manager that limits the queryset by default to show only not deleted + instances of model. + """ + _queryset_class = SoftDeletableQuerySet + def get_queryset(self): """ - 在这里处理一下QuerySet, 然后返回没被标记位is_delete的QuerySet + Return queryset limited to not deleted entries. """ kwargs = {'model': self.model, 'using': self._db} if hasattr(self, '_hints'): @@ -21,6 +39,10 @@ class SoftDeletManager(models.Manager): return self._queryset_class(**kwargs).filter(is_delete=False) + +class SoftDeletableManager(SoftDeletableManagerMixin, models.Manager): + pass + class SoftCommonModel(models.Model): create_time = models.DateTimeField(default=timezone.now, verbose_name='创建时间', help_text='创建时间') update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间', help_text='修改时间') @@ -29,7 +51,7 @@ class SoftCommonModel(models.Model): class Meta: abstract = True - objects = SoftDeletManager() + objects = SoftDeletableManager() def delete(self, using=None, soft=True, *args, **kwargs): """ @@ -39,6 +61,7 @@ class SoftCommonModel(models.Model): self.is_delete = True self.save(using=using) else: + return super(SoftCommonModel, self).delete(using=using, *args, **kwargs) class CommonModel(models.Model):