166 lines
4.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="cam-page">
<!-- 顶部自定义导航 -->
<view class="cam-nav" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="cam-nav-back" @click="goBack">
<u-icon name="arrow-left" color="#fff" size="40"></u-icon>
</view>
<view class="cam-nav-title">{{ title }}</view>
<view class="cam-nav-right"></view>
</view>
<!-- 拍摄态相机取景 -->
<block v-if="!captured">
<camera class="cam-view" :device-position="'back'" :flash="'auto'" @error="onCamError"></camera>
<!-- 取景框遮罩 -->
<view class="cam-overlay">
<view class="cam-frame" :class="orientation === 'landscape' ? 'frame-landscape' : 'frame-portrait'">
<view class="cam-corner tl"></view>
<view class="cam-corner tr"></view>
<view class="cam-corner bl"></view>
<view class="cam-corner br"></view>
</view>
<view class="cam-tip">{{ frameTip }}</view>
</view>
<!-- 横版/竖版切换 -->
<view class="cam-orient">
<view class="orient-item" :class="{ active: orientation === 'landscape' }" @click="orientation = 'landscape'">横版</view>
<view class="orient-item" :class="{ active: orientation === 'portrait' }" @click="orientation = 'portrait'">竖版</view>
</view>
<!-- 底部操作相册 / 拍照 -->
<view class="cam-actions">
<view class="cam-action-side" @click="pickFromAlbum">
<u-icon name="photo" color="#fff" size="44"></u-icon>
<text>相册</text>
</view>
<view class="cam-shutter" @click="takePhoto"></view>
<view class="cam-action-side cam-action-placeholder"></view>
</view>
</block>
<!-- 预览态重拍 / 提交 -->
<block v-else>
<image class="cam-preview" :src="tempPath" mode="aspectFit"></image>
<view class="cam-preview-actions">
<view class="prev-btn prev-retake" @click="retake">重拍</view>
<view class="prev-btn prev-submit" @click="confirmUse">提交</view>
</view>
</block>
</view>
</template>
<script>
export default {
data() {
return {
statusBarHeight: 20,
target: 'license', // license / idFront / idBack / industry
orientation: 'landscape',
captured: false,
tempPath: '',
cameraCtx: null,
}
},
computed: {
title() {
const map = {
license: '拍摄营业执照',
idFront: '拍摄身份证人像面',
idBack: '拍摄身份证国徽面',
industry: '拍摄行业资质',
}
return map[this.target] || '拍摄证件'
},
frameTip() {
const map = {
license: '请将营业执照完整置于取景框内',
idFront: '请将身份证人像面置于取景框内',
idBack: '请将身份证国徽面置于取景框内',
industry: '请将资质证件完整置于取景框内',
}
return map[this.target] || '请将证件完整置于取景框内'
}
},
onLoad(options) {
if (options && options.target) this.target = options.target
// 身份证默认横版,营业执照/资质默认竖版
this.orientation = (this.target === 'idFront' || this.target === 'idBack') ? 'landscape' : 'portrait'
try {
const sys = uni.getSystemInfoSync()
this.statusBarHeight = sys.statusBarHeight || 20
} catch (e) {}
},
onReady() {
// #ifndef H5
this.cameraCtx = uni.createCameraContext()
// #endif
},
methods: {
goBack() {
uni.navigateBack()
},
onCamError(e) {
console.error('相机错误:', e)
uni.showModal({
title: '无法使用相机',
content: '请检查是否已授予相机权限,或改用相册上传。',
showCancel: false
})
},
takePhoto() {
if (!this.cameraCtx) {
// H5 等不支持 camera 组件的环境,回退到系统拍照
this.pickFromCamera()
return
}
this.cameraCtx.takePhoto({
quality: 'high',
success: (res) => {
this.tempPath = res.tempImagePath
this.captured = true
},
fail: () => {
uni.showToast({ title: '拍照失败,请重试', icon: 'none' })
}
})
},
pickFromCamera() {
uni.chooseImage({
count: 1, sizeType: ['compressed'], sourceType: ['camera'],
success: (res) => {
const fp = res.tempFilePaths && res.tempFilePaths[0]
if (!fp) return
this.tempPath = fp
this.captured = true
}
})
},
pickFromAlbum() {
uni.chooseImage({
count: 1, sizeType: ['compressed'], sourceType: ['album'],
success: (res) => {
const fp = res.tempFilePaths && res.tempFilePaths[0]
if (!fp) return
this.tempPath = fp
this.captured = true
}
})
},
retake() {
this.captured = false
this.tempPath = ''
},
confirmUse() {
if (!this.tempPath) return
// 把拍摄结果通过事件总线回传给入驻表单页,由其负责上传 + OCR
uni.$emit('shopEnter:capture', { target: this.target, filePath: this.tempPath })
uni.navigateBack()
}
}
}
</script>
<style>
@import url("./index.css");
</style>