login.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. <template>
  2. <view class="login">
  3. <Headers></Headers>
  4. <image class="bg" src="/static/images/bg.png"></image>
  5. <view class="ddflex" style="flex-direction: column;">
  6. <view class="register ddflex">
  7. <view class="re-con-pic">
  8. <image src="/static/images/loginBg1.png"></image>
  9. </view>
  10. <view class="re-con">
  11. <view class="re-tit">考生登录</view>
  12. <view class="re-li dflex">
  13. <input v-model="testNumber" type="number" placeholder="准考证号" maxlength="-1" placeholder-class="placeholder" class="re-ipt flex" />
  14. </view>
  15. <uni-data-select
  16. v-model="paperId"
  17. :localdata="range"
  18. @change="changeTestPro"
  19. placeholder="考试项目"
  20. ></uni-data-select>
  21. <view class="re-btn" @click="okLogin()">登录</view>
  22. <view class="re-btn-text" @click="queryScore">考生成绩查询</view>
  23. </view>
  24. </view>
  25. <view class="bottom-content ddflex">
  26. <!-- 考试公告 -->
  27. <view class="note-box">
  28. <view class="note-title ddflex">
  29. <image class="note-title-icon" src="/static/images/ksgg.png"></image>
  30. <view>考试公告</view>
  31. </view>
  32. <view>
  33. <view class="note-item ddflex" v-for="item,index in otherInfo" :key="index" @click="jumpUrl('/pages/contentDetail/contentDetail?id='+item.id)">
  34. <view class="note-item-content">{{item.title}}</view>
  35. <view class="note-item-date">{{dateFormat(item.createDate)}}</view>
  36. </view>
  37. </view>
  38. </view>
  39. <!-- 注意事项 -->
  40. <view class="note-box">
  41. <view class="note-title ddflex">
  42. <image class="note-title-icon" src="/static/images/zysx.png"></image>
  43. <view>注意事项</view>
  44. </view>
  45. <view>
  46. <view class="note-item ddflex" v-for="item,index in noteInfo" :key="index+'zy'" @click="jumpUrl('/pages/contentDetail/contentDetail?id='+item.id)">
  47. <view class="note-item-content">{{item.title}}</view>
  48. <view class="note-item-date">{{dateFormat(item.createDate)}}</view>
  49. </view>
  50. </view>
  51. </view>
  52. </view>
  53. </view>
  54. <uni-popup ref="popup" type="bottom" :is-mask-click='false'>
  55. <view class="popup-box">
  56. <view class="popup-top ddflex">
  57. <view>身份验证</view>
  58. <image src="/static/images/close.png" @click="close()"></image>
  59. </view>
  60. <view class="popup-content">您好!考试前需要进行身份验证,请手持准考证,对准摄像头进行拍照,示例如下</view>
  61. <view style="width: 400px;height: 243px;margin:30px auto;" v-show="!isPhotoing&&!imageUrl">
  62. <img style="width: 100%;height: 100%" src="/static/images/sfyz.png"/>
  63. </view>
  64. <view v-show="isPhotoing" style="width: 400px;height: 243px;margin:30px auto;position: relative;" id="video-box">
  65. <video id="video" style="width: 100%;height: 100%;" object-fit='fill' :autoplay="true" :controls="false" :show-center-play-btn="false"></video>
  66. <canvas id="canvas" style="width: 100%;height: 100%;position: absolute;top:100000px;" canvas-id="canvas"></canvas>
  67. <view style="position: absolute;top: 50%;left: 50%;transform: translate(-50%,-50%);z-index: 100;font-size: 50px;color: #1AA1E6;font-weight: bold;">{{timeText}}</view>
  68. </view>
  69. <view style="width: 400px;height: 243px;margin:30px auto;" v-show="!isPhotoing&&imageUrl">
  70. <img style="width: 100%;height: 100%" :src="imageUrl"/>
  71. </view>
  72. <view class="popup-bottom ddflex">
  73. <view class="popup-btn2" @click="yanzheng" v-show="!isPhotoing">{{imageUrl?'重新验证':'立即验证'}}</view>
  74. <view class="popup-btn2" v-if="imageUrl" @click="yanzhengSubmit">确认</view>
  75. </view>
  76. </view>
  77. </uni-popup>
  78. <Foot :havaBackground='false'></Foot>
  79. </view>
  80. </template>
  81. <script>
  82. const app = getApp();
  83. const req = require('../../utils/request.js');
  84. const utils = require('../../utils/util.js');
  85. const api = require('../../utils/api.js');
  86. export default {
  87. data() {
  88. return {
  89. title: 'Hello',
  90. width: 115,
  91. height: 36,
  92. testNumber: '',
  93. code: '',
  94. isCheckArg: true,
  95. range:[],
  96. otherInfo:[],//考试公告
  97. noteInfo:[],//注意事项
  98. paperId:'',//考试id
  99. isPhotoing:false,//是否正在验证身份
  100. imageUrl:'',
  101. timeText:3,
  102. timeInterval:null
  103. };
  104. },
  105. onLoad() {
  106. var tha = this;
  107. this.getTestProject()
  108. this.getTextOtherInfo()
  109. this.getTextNoteInfo()
  110. },
  111. onShow() {
  112. },
  113. methods: {
  114. jumpUrl(url){
  115. uni.navigateTo({
  116. url:url
  117. })
  118. },
  119. // 考试下拉框
  120. changeTestPro(e){
  121. console.log("e:", e);
  122. },
  123. // 获取考试项目
  124. getTestProject(){
  125. console.log('11')
  126. req.getRequest('/api/v3/exam/user/manager',{},res=>{
  127. console.log('this.range',res)
  128. this.range = res.map(item=>{return {text:item.title,value:item.id}})
  129. console.log(this.range)
  130. })
  131. },
  132. // 考试公告
  133. getTextOtherInfo(){
  134. let form={
  135. code:req.public.ksggCode,
  136. page:1,
  137. limit:3
  138. }
  139. req.getRequest('/api/content/list',form,res=>{
  140. this.otherInfo = res
  141. })
  142. },
  143. // 注意事项
  144. getTextNoteInfo(){
  145. let form={
  146. code:req.public.zysxCode,
  147. page:1,
  148. limit:3
  149. }
  150. req.getRequest('/api/content/list',form,res=>{
  151. this.noteInfo = res
  152. })
  153. },
  154. open() {
  155. this.$refs.popup.open('center')
  156. },
  157. close() {
  158. this.$refs.popup.close()
  159. clearInterval(this.timeInterval)
  160. this.isPhotoing = false
  161. this.imageUrl = ''
  162. },
  163. okLogin() {
  164. if (!this.testNumber) {
  165. return req.msg('请输入准考证号');
  166. }
  167. if (!this.paperId) {
  168. return req.msg('请选择考试项目');
  169. }
  170. var formP = {
  171. admission: this.testNumber,
  172. paperId: this.paperId
  173. };
  174. req.postRequest('/api/admission/login', formP, data => {
  175. if(data){
  176. req.setStorage('userInfo', data);
  177. // 如果进行身份验证
  178. // this.open()
  179. // 直接考试,是否允许考试
  180. req.getRequest(api.get_exam_question + this.paperId,{},quests=>{
  181. if (quests && quests.length > 0) {
  182. uni.navigateTo({
  183. url: '/pages/test/test?paperId='+this.paperId,
  184. success:()=> {
  185. this.close()
  186. }
  187. });
  188. }
  189. })
  190. }
  191. });
  192. },
  193. queryScore(){
  194. if (!this.testNumber) {
  195. return req.msg('请输入准考证号');
  196. }
  197. if (!this.paperId) {
  198. return req.msg('请选择考试项目');
  199. }
  200. var formP = {
  201. admission: this.testNumber,
  202. paperId: this.paperId
  203. };
  204. req.getRequest('/api/v3/exam/user/manager/result', formP, res => {
  205. uni.navigateTo({
  206. url:'/pages/scoreQuery/scoreQuery?paperId='+ this.paperId+'&admissionNo='+this.testNumber
  207. })
  208. });
  209. // req.postRequest('/api/admission/login', formP, data => {
  210. // if(data){
  211. // req.setStorage('userInfo', data);
  212. // req.getRequest('/api/v3/exam/user/manager/result', formP, res => {
  213. // uni.navigateTo({
  214. // url:'/pages/scoreQuery/scoreQuery?paperId='+ this.paperId+'&admissionNo='+this.testNumber
  215. // })
  216. // });
  217. // }
  218. // });
  219. },
  220. // 验证提交
  221. yanzhengSubmit(){
  222. uni.navigateTo({
  223. url: '/pages/test/test?paperId='+this.paperId,
  224. success:()=> {
  225. this.close()
  226. }
  227. });
  228. },
  229. // 时间格式化
  230. dateFormat(date){
  231. return req.dateFormat(date).v5
  232. },
  233. getUserInfo() {
  234. req.getRequest(
  235. '/api/v3/hy/account/userInfo',
  236. {},
  237. data => {
  238. req.setStorage('userInfo', data);
  239. if(data.type==1||data.isStaff){
  240. uni.reLaunch({
  241. url: '/pages/learn/learn'
  242. });
  243. }else{
  244. uni.reLaunch({
  245. url: '/pages/index/index'
  246. });
  247. }
  248. },
  249. true
  250. );
  251. },
  252. // 身份验证
  253. yanzheng(){
  254. this.imageUrl = ''
  255. this.test()
  256. },
  257. takePhoto() {
  258. let _this = this
  259. //获得Canvas对象
  260. const query = uni.createSelectorQuery().in(this);
  261. let video = document.querySelector('video');
  262. let canvas = document.querySelector('canvas')
  263. let ctx = canvas.getContext('2d');
  264. let videoInfo = {}
  265. query.select('video').boundingClientRect(result => {
  266. console.log('videoInfo',result)
  267. videoInfo={
  268. width:result.width,
  269. height:result.height
  270. }
  271. }).exec();
  272. ctx.drawImage(video, 0, 0, videoInfo.width, videoInfo.height);
  273. // console.log(this.dataURLtoBlob(canvas.toDataURL(),'11'))
  274. // req.uploadFile('/api/upload', canvas.toDataURL(), res => {
  275. // req.msg('图片上传成功');
  276. // console.log('图片上传成功',res)
  277. // });
  278. _this.imageUrl = canvas.toDataURL()
  279. _this.isPhotoing = false
  280. // setTimeout(() => {
  281. // uni.canvasToTempFilePath({
  282. // canvasId: 'canvas',
  283. // destWidth: 60,
  284. // destHeight: 40,
  285. // success: function (res) {
  286. // console.log(res.tempFilePath) //图片路径
  287. // // resolve(res.tempFilePath)
  288. // _this.imgUrl = res.tempFilePath
  289. // },
  290. // fail: function (res) {
  291. // console.log(res.errMsg)
  292. // }
  293. // })
  294. // }, 100)
  295. },
  296. dataURLtoBlob(dataurl) {
  297. var arr = dataurl.split(','),
  298. mime = arr[0].match(/:(.*?);/)[1],
  299. bstr = atob(arr[1]),
  300. n = bstr.length,
  301. u8arr = new Uint8Array(n);//8位无符号整数,长度1个字节
  302. console.log(mime)
  303. while (n--) {
  304. u8arr[n] = bstr.charCodeAt(n);
  305. }
  306. // console.log(JSON.stringify(u8arr));
  307. return new Blob([u8arr], {
  308. type: mime
  309. });
  310. },
  311. base64toFile (dataurl, filename){
  312. var arr = dataurl.split(','),
  313. mime = arr[0].match(/:(.*?);/)[1],
  314. bstr = atob(arr[1]),
  315. n = bstr.length,
  316. u8arr = new Uint8Array(n);
  317. while (n--) {
  318. u8arr[n] = bstr.charCodeAt(n);
  319. }
  320. return new File([u8arr], filename, {
  321. type: mime
  322. });
  323. },
  324. test(){
  325. // var video = document.querySelector('video');
  326. const query = uni.createSelectorQuery().in(this);
  327. var video = query.select('#video')
  328. console.log('video',video)
  329. // 兼容代码
  330. window.URL = (window.URL || window.webkitURL || window.mozURL || window.msURL);
  331. // 获取媒体属性,旧版本浏览器可能不支持mediaDevices,我们首先设置一个空对象
  332. if (navigator.mediaDevices === undefined) {
  333. navigator.mediaDevices = {};
  334. }
  335. console.log('navigator.mediaDevices',navigator.mediaDevices)
  336. // 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象
  337. // 使用getUserMedia,因为它会覆盖现有的属性。
  338. // 这里,如果缺少getUserMedia属性,就添加它。
  339. if (navigator.mediaDevices.getUserMedia === undefined) {
  340. navigator.mediaDevices.getUserMedia = function(constraints) {
  341. // 首先获取现存的getUserMedia(如果存在)
  342. var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
  343. // 有些浏览器不支持,会返回错误信息
  344. // 保持接口一致
  345. if (!getUserMedia) { //不存在则报错
  346. return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
  347. }
  348. // 否则,使用Promise将调用包装到旧的navigator.getUserMedia
  349. return new Promise(function(resolve, reject) {
  350. getUserMedia.call(navigator, constraints, resolve, reject);
  351. });
  352. }
  353. }
  354. //摄像头调用配置
  355. var mediaOpts = {
  356. audio: false,
  357. video: { facingMode: "user"}
  358. }
  359. let that=this;
  360. navigator.mediaDevices.getUserMedia(mediaOpts).then(function(stream) {
  361. that.mediaStreamTrack = stream;
  362. video = document.querySelector('video');
  363. console.log('video = document.querySelector(video);',video)
  364. // 旧的浏览器可能没有srcObject
  365. if ("srcObject" in video) {
  366. video.srcObject = stream
  367. } else {
  368. // 避免在新的浏览器中使用它,因为它正在被弃用。
  369. video.src = window.URL && window.URL.createObjectURL(stream) || stream
  370. }
  371. video.play();
  372. that.isPhotoing = true
  373. that.timeText = 3
  374. that.timeInterval = setInterval(()=>{
  375. if(that.timeText>0){
  376. that.timeText--
  377. }else{
  378. clearInterval(that.timeInterval)
  379. that.timeInterval= null
  380. that.takePhoto()
  381. }
  382. },1000)
  383. }).catch(function (err) {
  384. console.log(err)
  385. uni.showModal({
  386. title:'提示',
  387. content:'未找到摄像头',
  388. showCancel:false,
  389. success() {
  390. // uni.navigateBack({
  391. // })
  392. }
  393. })
  394. });
  395. },
  396. }
  397. };
  398. </script>
  399. <style>
  400. @import url('../login/login.css');
  401. </style>