login.vue 13 KB

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