index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <style>
  2. </style>
  3. <template>
  4. <div style='height: 100%;'>
  5. <div id='import-header'>
  6. <img src='../assets/images/nav_images.png' alt=''>照片批量上传工具
  7. <button id='exit-btn' @click='logout' title="退出"></button>
  8. </div>
  9. <div id='import-body'>
  10. <div id='import-div'>
  11. <a href='javascript:;' class='file'>
  12. <!-- webkitdirectory-->
  13. <input id='photos' :disabled='uploadDisabled' multiple="true" title=' ' name='files' type='file' v-on:change='importPhotos'/>
  14. <button id='import-btn'>
  15. 上传照片
  16. </button>
  17. </a>
  18. <div id='progressDiv'>
  19. <span>
  20. 成功:
  21. <span style="color:green;">{{successNum}}</span>/{{allNum}}
  22. </span>
  23. <span>
  24. 失败:<span style="color:red;">{{errorNum}}</span>/{{allNum}}
  25. </span>
  26. <span v-show="completeShow" style="color: green;font-weight: bold;">全部处理完成</span>
  27. <span v-show="!completeShow&&(successNum>0||errorNum>0)" style="color: red;font-weight: bold;">处理中...</span>
  28. </div>
  29. </div>
  30. <div id='progress-div'>
  31. <div id='console-panel'>
  32. <div v-for='msgInfo in returnMsgList'>
  33. <p class='console-line' v-if='msgInfo.success'>
  34. <span><img src='../assets/images/icon_sucess.png'></span>
  35. <span>{{msgInfo.fileName}}:{{msgInfo.msg}}</span>
  36. </p>
  37. <p class='console-line' v-if='!msgInfo.success'>
  38. <span><img src='../assets/images/icon_failed.png'></span>
  39. <span>{{msgInfo.fileName}}:{{msgInfo.msg}}</span>
  40. </p>
  41. </div>
  42. </div>
  43. </div>
  44. </div>
  45. </div>
  46. </template>
  47. <script>
  48. const CryptoJS = require('crypto-js');
  49. const Base64 = require('js-base64').Base64;
  50. export default {
  51. data() {
  52. return {
  53. photoQuantityLimit:10000,//单次上传限制
  54. photoList:[],//总的照片队列
  55. photoLine:[],//正在处理的照片队列
  56. concurrency:8,//同时处理的照片数量
  57. returnMsgList:[],//返回信息
  58. successNum:0, //成功数量
  59. errorNum:0, //失败数量
  60. allNum:0, //总数
  61. completeShow:false,
  62. uploadDisabled:false,
  63. seconds:0 // 耗时 秒
  64. }
  65. },
  66. methods: {
  67. init(){
  68. this.photoList = [];
  69. this.photoLine = [];
  70. this.returnMsgList = [];
  71. this.successNum = 0;
  72. this.errorNum = 0;
  73. this.allNum = 0;
  74. this.completeShow = false;
  75. },
  76. importPhotos() {
  77. this.init();
  78. var photos = document.getElementById('photos');
  79. for(var i = 0;i<photos.files.length;i++){
  80. this.photoList.push(photos.files[i]);
  81. }
  82. this.allNum = this.photoList.length;
  83. if(this.allNum > this.photoQuantityLimit){
  84. alert("单次上传文件数量不能大于"+this.photoQuantityLimit+",当前数量为"+photoQuantity);
  85. photos.files = null;
  86. return;
  87. }
  88. this.photoLine = this.photoList.splice(0, this.concurrency);
  89. for(var i = 0;i<this.photoLine.length;i++){
  90. this.processStudentPhoto(this.photoLine[i]);
  91. }
  92. var _this = this;
  93. var uploadTime = setInterval(function(){
  94. //检查photoLine中是否有已经完成的
  95. for (let i = 0; i < _this.photoLine.length; i++) {
  96. if (_this.photoLine[i].finished) {
  97. if (_this.photoList.length > 0) {
  98. _this.photoLine[i] = _this.photoList.shift();
  99. _this.processStudentPhoto(_this.photoLine[i]);
  100. }
  101. }
  102. }
  103. if (_this.photoList.length < 1) {
  104. //检查看是否全部完成了
  105. console.log('photoList处理完毕');
  106. clearInterval(uploadTime);
  107. }
  108. },500);
  109. },
  110. processStudentPhoto(photo) {
  111. let photoNameArr = photo.name.split('.');
  112. let fileName = photoNameArr[0];//文件名就是身份证号码
  113. let fileSuffix = photoNameArr[1];//文件后缀
  114. //生成新名称
  115. let md5Hash = CryptoJS.MD5(Base64.encode(photo.name+new Date().getTime())).toString();
  116. let rootOrgId = localStorage.getItem('rootOrgId');
  117. //根据身份证号码查询学生信息
  118. this.$http.get('/api/ecs_core/studentFaceInfo/identityNumber?orgId='+rootOrgId+'&identityNumber='+fileName, {})
  119. .then((response) => {
  120. var studentFaceInfo = response.body;
  121. if (studentFaceInfo.student && studentFaceInfo.student.id) {
  122. this.detectFace(photo).then((res)=>{
  123. if(res.body.faces.length>=1){
  124. let face_token = res.body.faces[0].face_token;
  125. this.getFaceSetToken().then((res)=>{
  126. var face_set_token = res.bodyText;
  127. //var face_set_token = 'ee564a7abbde7f1287f668ddd945ccfa';
  128. this.addFaceToSet(face_set_token, face_token).then((res)=>{
  129. this.saveStudentFaceInfo({
  130. 'studentFaceInfoId':studentFaceInfo.id,
  131. 'studentId':studentFaceInfo.student.id,
  132. 'face_set_token':face_set_token,
  133. 'face_token':face_token,
  134. 'fileName':fileName,
  135. 'file':photo,
  136. 'fileSuffix':fileSuffix,
  137. 'photoNewName':md5Hash+'.'+fileSuffix
  138. });
  139. },(err)=>{
  140. this.finishOne(false,fileName,'addFaceToSet失败',photo);
  141. });
  142. },(err)=>{
  143. this.finishOne(false,fileName,'获取FaceSetToken失败',photo);
  144. });
  145. }else{
  146. this.finishOne(false,fileName,'face++没有检测到人脸',photo);
  147. }
  148. },(err)=>{
  149. this.finishOne(false,fileName,'调用face++检测人脸失败',photo);
  150. });
  151. }else{
  152. this.finishOne(false,fileName,'查询身份证不存在',photo);
  153. }
  154. },(error)=>{
  155. this.finishOne(false,fileName,'根据身份证号码查询失败',photo);
  156. });
  157. },
  158. //保存照片信息
  159. saveStudentFaceInfo(photoInfo){
  160. this.saveImageToUpyun(photoInfo).then((res)=>{
  161. //调用core后台接口,对数据进行保存
  162. if(!photoInfo.studentFaceInfoId){
  163. this.saveStudentFaceInfoByPost(photoInfo);
  164. }else{
  165. this.saveStudentFaceInfoByPut(photoInfo);
  166. }
  167. },(err)=>{
  168. this.finishOne(false,photoInfo.fileName,'saveImageToUpyun失败',photoInfo.file);
  169. });
  170. },
  171. //保存文件至又拍云
  172. saveImageToUpyun(photoInfo){
  173. var url = process.env.VUE_APP_UPYUN_BUCKETURL+'/student_base_photo/'+photoInfo.fileName+'/'+photoInfo.photoNewName;
  174. var authorization = 'Basic '+Base64.encode(process.env.VUE_APP_UPYUN_OPERATOR+':'+process.env.VUE_APP_UPYUN_PASSWORD);
  175. var headers = {headers:{'Authorization':authorization,'Content-Type': 'image/jpeg'}};
  176. return this.$http.put(url,photoInfo.file,headers);
  177. },
  178. //获取faceSetToken
  179. getFaceSetToken(){
  180. return this.$http.get('/api/ecs_core/faceSet/enableFaceSet');
  181. },
  182. //faceToken加入faceSetToken
  183. addFaceToSet(faceset_token,face_token){
  184. let formData_addface = new FormData();
  185. formData_addface.append('api_key', process.env.VUE_APP_FACEPP_API_KEY);
  186. formData_addface.append('api_secret',process.env.VUE_APP_FACEPP_API_SECRET);
  187. formData_addface.append('faceset_token', faceset_token);
  188. formData_addface.append('face_tokens', face_token);
  189. return this.$http.post('/facepp/v3/faceset/addface', formData_addface);
  190. },
  191. //face++分析人脸
  192. detectFace(file){
  193. let fileBlob = new Blob([file]);
  194. let formData_face_token = new FormData();
  195. formData_face_token.append('api_key',process.env.VUE_APP_FACEPP_API_KEY);
  196. formData_face_token.append('api_secret',process.env.VUE_APP_FACEPP_API_SECRET);
  197. formData_face_token.append('image_file', fileBlob);
  198. return this.$http.post('/facepp/v3/detect', formData_face_token);
  199. },
  200. saveStudentFaceInfoByPost(photoInfo){
  201. this.$http.post('/api/ecs_core/studentFaceInfo', {
  202. 'faceSetToken': photoInfo.face_set_token,
  203. 'faceToken': photoInfo.face_token,
  204. 'photoMD5': photoInfo.photoNewName,
  205. 'student': {
  206. 'id': photoInfo.studentId
  207. },
  208. 'createUser':localStorage.getItem('userName'),
  209. 'updateUser':localStorage.getItem('userName'),
  210. 'createType':'IMPORT_TOOL'
  211. }).then((res)=>{
  212. this.finishOne(true,photoInfo.fileName,'处理成功',photoInfo.file);
  213. },(err)=>{
  214. this.finishOne(false,photoInfo.fileName,'saveStudentFaceInfoByPost失败',photoInfo.file);
  215. });
  216. },
  217. saveStudentFaceInfoByPut(photoInfo){
  218. this.$http.put('/api/ecs_core/studentFaceInfo', {
  219. 'faceSetToken': photoInfo.face_set_token,
  220. 'faceToken': photoInfo.face_token,
  221. 'photoMD5': photoInfo.photoNewName,
  222. 'student': {
  223. 'id': photoInfo.studentId
  224. },
  225. 'createUser':localStorage.getItem('userName'),
  226. 'updateUser':localStorage.getItem('userName'),
  227. 'createType':'IMPORT_TOOL'
  228. }).then((res)=>{
  229. this.finishOne(true,photoInfo.fileName,'处理成功',photoInfo.file);
  230. },(err)=>{
  231. this.finishOne(false,photoInfo.fileName,'saveStudentFaceInfoByPut失败',photoInfo.file);
  232. });
  233. },
  234. //成功或失败处理
  235. finishOne(isSuccess,fileName,msg,file){
  236. file.finished = true;
  237. this.returnMsgList.push({'success':isSuccess,'fileName':fileName,'msg':msg});
  238. if(isSuccess){
  239. this.successNum++;
  240. }else{
  241. this.errorNum++;
  242. //如果存在nodejs环境
  243. if(typeof(nodeRequire) != "undefined"){
  244. var fs = nodeRequire("fs");
  245. if(fs){
  246. var errorfilePath = file.path.substring(0,file.path.lastIndexOf("\\"))+"\\errorfiles";
  247. if (!fs.existsSync(errorfilePath)) {
  248. fs.mkdirSync(errorfilePath);
  249. }
  250. var readStream = fs.createReadStream(file.path);
  251. var writeStream = fs.createWriteStream(errorfilePath+"\\"+file.name);
  252. readStream.pipe(writeStream);
  253. fs.appendFile(errorfilePath+'\\errorPhotos.txt',fileName+":"+msg+'\n',function (){});
  254. }
  255. }
  256. }
  257. if(this.errorNum+this.successNum == this.allNum){
  258. var photos = document.getElementById('photos');
  259. photos.files = null;
  260. this.completeShow = true;
  261. }
  262. },
  263. logout() {
  264. localStorage.removeItem("rootOrgId");
  265. localStorage.removeItem("userName");
  266. localStorage.removeItem("user_token");
  267. this.$router.push({path:'/login'});
  268. }
  269. }
  270. };
  271. </script>