Browse Source

自助注册api

master
xuhuajiao 1 month ago
parent
commit
310bcd1b90
  1. 1
      package.json
  2. 12
      src/api/faceRecognition/index.js
  3. 10
      src/assets/styles/faceMobile.scss
  4. 6
      src/main.js
  5. 150
      src/views/faceRecognition/personInfoManage.vue
  6. 5
      src/views/faceRegisterH5/error.vue
  7. 88
      src/views/faceRegisterH5/index.vue
  8. 10
      src/views/faceRegisterH5/registered.vue
  9. 107
      src/views/faceRegisterH5/selfRegister.vue
  10. 5
      src/views/faceRegisterH5/success.vue

1
package.json

@ -85,6 +85,7 @@
"sortablejs": "1.8.4",
"spark-md5": "^3.0.2",
"v-viewer": "^1.6.4",
"vconsole": "^3.15.1",
"vkbeautify": "^0.99.3",
"vue": "^2.6.14",
"vue-awesome-swiper": "^3.1.3",

12
src/api/faceRecognition/index.js

@ -83,6 +83,15 @@ export function FetchCheckReader(params) {
})
}
// 自助注册 - 编辑人员
export function FetchEditReaderFace(data) {
return request({
url: 'api/person/editReaderFace',
method: 'post',
data
})
}
export default {
add,
edit,
@ -93,5 +102,6 @@ export default {
FetchBatchSavePersonInfos,
FetchSnapshotOperation,
FetchInitReaderCheck,
FetchCheckReader
FetchCheckReader,
FetchEditReaderFace
}

10
src/assets/styles/faceMobile.scss

@ -56,15 +56,23 @@
}
.submit-btn{
display: block;
width: 200px;
height: 80px;
margin: 60px auto 0 auto;
padding-top: 20px;
padding: 0;
color: #fff;
font-size: 16px;
background: url("~@/assets/images/faceH5/btnok.png") no-repeat center center;
background-size: 100% 100%;
text-align: center;
border: none;
line-height: 0;
::v-deep span{
display: inline-block !important;
height: 60px;
padding-top: 20px;
}
}

6
src/main.js

@ -33,6 +33,12 @@ import 'viewerjs/dist/viewer.css'
import Print from 'vue-print-nb'
// import Vconsole from 'vconsole'
// const vConsole = new Vconsole()
// export default vConsole
// 加载用户主题
if (localStorage.getItem('themeValue')) {
window.document.documentElement.setAttribute('data-theme', localStorage.getItem('themeValue'))

150
src/views/faceRecognition/personInfoManage.vue

@ -80,7 +80,26 @@
<input id="upFile" type="file" name="upFile" accept="image/*" @change="changeFile($event)">
<el-button size="small" type="primary"><i class="iconfont icon-shangchuan" />选择上传照片</el-button>
</div>
<el-button type="primary"><i class="iconfont icon-yulan" />摄像头拍摄</el-button>
<el-button type="primary" @click="showCamera = true">
<i class="iconfont icon-yulan" />摄像头拍摄
</el-button>
</div>
<!-- 摄像头拍摄区域 (默认隐藏) -->
<div v-if="showCamera" class="camera-container">
<video
id="video"
autoplay
style="width: 100%; max-width: 400px; border: 1px solid #ccc;"
/>
<canvas
id="canvas"
style="display: none; width: 100%; max-width: 400px;"
/>
<div class="camera-buttons">
<el-button type="warning" @click="takePhoto">拍照</el-button>
<el-button type="info" @click="resetCamera">重拍</el-button>
<el-button type="danger" @click="closeCamera">关闭</el-button>
</div>
</div>
</div>
<div slot="footer" class="dialog-footer">
@ -205,7 +224,13 @@ export default {
filePath: '',
imageUrl: null,
selfRegisterVisible: false,
faceSearchVisible: false
faceSearchVisible: false,
//
showCamera: false,
stream: null,
videoElement: null,
canvasElement: null
}
},
computed: {
@ -214,6 +239,20 @@ export default {
'user'
])
},
watch: {
//
showCamera(val) {
if (val) {
this.openCamera()
} else {
this.stopStream()
}
}
},
beforeDestroy() {
//
this.stopStream()
},
created() {
},
mounted() {
@ -233,6 +272,12 @@ export default {
},
//
[CRUD.HOOK.beforeToAdd](crud, form) {
this.imageUrl = null
Object.keys(crud.form).forEach(key => {
this.$set(crud.form, key, null)
})
this.crud.form.personSex = 1
this.crud.form.personType = 0
},
//
[CRUD.HOOK.beforeToEdit](crud, form) {
@ -266,10 +311,10 @@ export default {
},
//
[CRUD.HOOK.afterValidateCU](crud) {
if (crud.form.personPhotoUrl === '' || crud.form.personPhotoUrl === null) {
this.$message({ message: '请选择上传照片', type: 'error', offset: 8 })
return false
}
// if (crud.form.personPhotoUrl === '' || crud.form.personPhotoUrl === null) {
// this.$message({ message: '', type: 'error', offset: 8 })
// return false
// }
console.log(crud.form)
return true
},
@ -393,6 +438,68 @@ export default {
this.$refs.faceSearchRefs.searchPerson = {}
this.$refs.faceSearchRefs.btnLoading = false
}
},
//
async openCamera() {
try {
//
this.videoElement = document.getElementById('video')
this.canvasElement = document.getElementById('canvas')
//
this.stream = await navigator.mediaDevices.getUserMedia({
video: { width: 400, height: 300 },
audio: false
})
this.videoElement.srcObject = this.stream
} catch (error) {
this.$message.error('无法访问摄像头:' + error.message)
console.error('摄像头访问错误:', error)
}
},
takePhoto() {
if (!this.videoElement || !this.canvasElement) return
//
this.canvasElement.width = this.videoElement.videoWidth
this.canvasElement.height = this.videoElement.videoHeight
//
const context = this.canvasElement.getContext('2d')
context.drawImage(this.videoElement, 0, 0)
// base64
const imageData = this.canvasElement.toDataURL('image/jpeg')
//
this.imageUrl = imageData
this.form.photo = imageData
//
this.stopStream()
},
resetCamera() {
//
this.stopStream()
this.openCamera()
},
closeCamera() {
//
this.stopStream()
this.showCamera = false
},
stopStream() {
if (this.stream) {
this.stream.getTracks().forEach(track => {
track.stop()
})
this.stream = null
}
}
}
}
@ -444,4 +551,35 @@ export default {
border-color: #909399;
color: #909399;
}
.camera-container {
margin-top: 20px;
padding: 15px;
border: 1px solid #e6e6e6;
border-radius: 4px;
}
.camera-buttons {
margin-top: 15px;
display: flex;
gap: 10px;
justify-content: center;
}
.right-user-img {
margin-left: 30px;
text-align: center;
}
.right-user-img img {
width: 200px;
height: 260px;
object-fit: cover;
border: 1px solid #e6e6e6;
margin-bottom: 15px;
}
.upload-btn input {
display: none;
}
</style>

5
src/views/faceRegisterH5/error.vue

@ -20,7 +20,10 @@ export default {
},
methods: {
returnValid() {
this.$router.push({ path: '/faceRegisterH5' })
this.$router.push({
path: '/faceRegisterH5',
query: { 'strLibcode': this.$route.query.strLibcode }
})
}
}
}

88
src/views/faceRegisterH5/index.vue

@ -18,22 +18,27 @@
</el-form-item>
</el-form>
</div>
<div class="submit-btn" @click="submitForm('form')">下一步</div>
<el-button class="submit-btn" :loading="submitLoading" type="primary" @click="submitForm('form')">下一步</el-button>
</div>
</template>
<script>
import { FetchInitReaderCheck, FetchCheckReader } from '@/api/faceRecognition/index'
import { mapGetters } from 'vuex'
export default {
name: 'FaceRegisterH5',
data() {
return {
submitLoading: false,
form: {
readNo: '',
readIdCard: '',
password: '',
readName: ''
readNo: null, //
readIdCard: null, //
password: null, //
readName: null, //
checkReaderIp: null, // IP
checkReaderType: null, //
libraryIp: null, // IP
strFTZNCode: null, // IP
strLibcode: null // licode
},
checkReaderInfo: {},
rules: {
@ -52,32 +57,23 @@ export default {
}
}
},
computed: {
...mapGetters([
'baseApi',
'user'
])
},
watch: {
},
mounted() {
created() {
this.getInitReaderCheck()
},
mounted() {
},
methods: {
getInitReaderCheck() {
// { id: 1, name: '' },
// { id: 2, name: '' },
// { id: 3, name: '' }
FetchInitReaderCheck({ 'libcode': this.user.fonds.fondsNo }).then(res => {
const routeQuery = this.$route.query
FetchInitReaderCheck({ 'libcode': routeQuery.strLibcode }).then(res => {
console.log('res', res)
this.checkReaderInfo = res
// {
// "libraryIp": null,
// "strLibcode": "1201",
// "strFTZNCode": null,
// "checkReaderType": 1,
// "checkReaderIp": null
// }
}).catch(err => {
console.log(err)
})
@ -85,20 +81,42 @@ export default {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
// alert('submit!')
// this.$router.push({ path: '/faceError' })
// this.$router.push({ path: '/faceSuccess' })
// this.$router.push({ path: '/faceRegistered' })
this.$router.push({ path: '/faceSelfRegister' })
const params = {
'strLibcode': this.checkReaderInfo.strLibcode
}
console.log('params', params)
// FetchCheckReader(params).then(res => {
// console.log('res', res)
// }).catch(err => {
// console.log(err)
// })
this.submitLoading = true
this.form.strLibcode = this.checkReaderInfo.strLibcode
this.form.checkReaderType = this.checkReaderInfo.checkReaderType
this.form.checkReaderIp = this.checkReaderInfo.checkReaderIp // IP
this.form.libraryIp = this.checkReaderInfo.libraryIp // IP
this.form.strFTZNCode = this.checkReaderInfo.strFTZNCode // IP
console.log('params', this.form)
FetchCheckReader(this.form).then(res => {
console.log('res', res)
if (res) {
//
localStorage.setItem('personInfo', JSON.stringify(res))
if (res.personPhotoUrl) {
//
this.$router.push({
path: '/faceRegistered',
query: { 'strLibcode': this.checkReaderInfo.strLibcode }
})
} else {
//
this.$router.push({
path: '/faceSelfRegister',
query: { 'strLibcode': this.checkReaderInfo.strLibcode }
})
}
} else {
this.$router.push({
path: '/faceError',
query: { 'strLibcode': this.checkReaderInfo.strLibcode }
})
}
this.submitLoading = false
}).catch(err => {
console.log(err)
this.submitLoading = false
})
} else {
console.log('error submit!!')
return false

10
src/views/faceRegisterH5/registered.vue

@ -23,10 +23,16 @@ export default {
},
methods: {
returnValid() {
this.$router.push({ path: '/faceRegisterH5' })
this.$router.push({
path: '/faceRegisterH5',
query: { 'strLibcode': this.$route.query.strLibcode }
})
},
toSelfRegister() {
this.$router.push({ path: '/faceSelfRegister' })
this.$router.push({
path: '/faceSelfRegister',
query: { 'strLibcode': this.$route.query.strLibcode }
})
}
}
}

107
src/views/faceRegisterH5/selfRegister.vue

@ -12,7 +12,7 @@
<span>2.照片背景干净照片中只有注册者一人</span>
<span>3.不要使用美图类软件做过修饰的照片</span>
<span>4.照片像素 > 600x600</span>
<div v-if="imageUrl" class="clear-img-btn" @click="clearImage">删除照片</div>
<!-- <div v-if="imageUrl" class="clear-img-btn" @click="clearImage">删除照片</div> -->
</div>
</div>
<div class="face-mobile-content register-valid">
@ -20,8 +20,8 @@
<el-form-item label="读者证号" prop="barcode">
<el-input v-model="form.barcode" disabled />
</el-form-item>
<el-form-item label="姓名" prop="name">
<el-input v-model="form.idCard" disabled />
<el-form-item label="姓名" prop="personName">
<el-input v-model="form.personName" disabled />
</el-form-item>
<el-form-item label="身份证号" prop="idCard">
<el-input v-model="form.idCard" disabled />
@ -29,26 +29,33 @@
<el-form-item label="联系方式" prop="phone">
<el-input v-model="form.phone" disabled />
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-input v-model="form.sex" disabled />
<el-form-item label="性别" prop="personSex">
<el-input v-model="form.personSex" disabled />
</el-form-item>
</el-form>
</div>
<div class="submit-btn" @click="submitForm">提交</div>
<!-- <div class="submit-btn" :loading="submitLoading" @click="submitForm">提交</div> -->
<el-button class="submit-btn" :loading="submitLoading" type="primary" @click="submitForm"> </el-button>
</div>
</template>
<script>
import { FetchEditReaderFace } from '@/api/faceRecognition/index'
import { mapGetters } from 'vuex'
import { upload } from '@/utils/upload'
export default {
name: 'SelfRegister',
data() {
return {
submitLoading: false,
personInfo: null,
form: {
barcode: '',
idCard: '',
phone: '',
name: '',
sex: ''
personName: '',
personSex: '',
personPhotoUrl: null
},
imageUrl: '',
rules: {
@ -67,22 +74,75 @@ export default {
}
}
},
computed: {
...mapGetters([
'baseApi',
'user'
])
},
watch: {
},
mounted() {
this.personInfo = JSON.parse(localStorage.getItem('personInfo'))
console.log('personInfo', this.personInfo)
if (this.personInfo) {
if (this.personInfo.personPhotoUrl) {
this.imageUrl = this.baseApi + '/api/fileRelevant/getImg?imgType=3&imgId=' + this.personInfo.personPhotoUrl
} else {
this.imageUrl = require('@/assets/images/user.jpg')
}
this.form = {
barcode: this.personInfo.barcode,
idCard: this.personInfo.idCard,
phone: this.personInfo.phone,
personName: this.personInfo.personName,
personSex: this.personInfo.personSex === 1 ? '男' : '女',
personPhotoUrl: this.personInfo.personPhotoUrl
}
} else {
this.imageUrl = require('@/assets/images/user.jpg')
this.form = {
barcode: '',
idCard: '',
phone: '',
personName: '',
personSex: '',
personPhotoUrl: null
}
}
},
methods: {
submitForm(formName) {
this.$router.push({ path: '/faceSuccess' })
// this.$refs[formName].validate((valid) => {
// if (valid) {
// // alert('submit!')
// // this.$router.push({ path: '/faceError' })
// // this.$router.push({ path: '/faceSuccess' })
// this.$router.push({ path: '/faceRegistered' })
// } else {
// console.log('error submit!!')
// return false
// }
// })
if (!this.form.personPhotoUrl) {
this.$message({ message: '请选择上传照片', type: 'error', offset: 8 })
return false
}
this.submitLoading = true
const params = {
'personId': this.personInfo.personId,
'libcode': this.personInfo.libcode,
'personPhotoUrl': this.form.personPhotoUrl
}
console.log('params', params)
FetchEditReaderFace(params).then(res => {
console.log('res', res)
if (res) {
this.$router.push({
path: '/faceSuccess',
query: { 'strLibcode': this.personInfo.libcode }
})
} else {
this.$router.push({
path: '/faceError',
query: { 'strLibcode': this.personInfo.libcode }
})
}
this.submitLoading = false
}).catch(err => {
console.log(err)
this.submitLoading = false
})
},
openPhotoOptions() {
const input = document.createElement('input')
@ -93,6 +153,12 @@ export default {
const file = e.target.files[0]
if (file) {
this.imageUrl = URL.createObjectURL(file)
upload(this.baseApi + '/api/fileRelevant/uploadFaceImg', file).then(res => {
console.log(res)
if (res.data.code === 200) {
this.form.personPhotoUrl = res.data.data
}
})
}
}
input.click()
@ -100,7 +166,6 @@ export default {
clearImage() {
this.imageUrl = ''
}
}
}
</script>

5
src/views/faceRegisterH5/success.vue

@ -19,7 +19,10 @@ export default {
},
methods: {
returnValid() {
this.$router.push({ path: '/faceRegisterH5' })
this.$router.push({
path: '/faceRegisterH5',
query: { 'strLibcode': this.$route.query.strLibcode }
})
}
}
}

Loading…
Cancel
Save