身份图片组件

This commit is contained in:
Wang Kejun 2024-05-17 00:34:43 +08:00
parent 8960c72b76
commit c7b10aa173
9 changed files with 284 additions and 187 deletions

View File

@ -41,8 +41,9 @@
"antd-mobile": ">=5.33.0",
"antd-mobile-icons": ">=0.3.0",
"react": ">=18.2.0",
"react-dom": ">=18.1.0",
"react-dom": ">=18.2.0",
"react-native": ">=0.72.7",
"react-router": ">=6.3.0",
"react-router-dom": ">=6.3.0"
},
"devDependencies": {

View File

@ -0,0 +1,3 @@
{
"usingComponents": {}
}

View File

@ -0,0 +1,70 @@
@import '../../../../config/styles/mp/index.less';
.card-box {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
border-radius: 5px;
background: rgba(245, 245, 245, 1);
padding: 20rpx 20rpx;
margin-top: 20rpx;
.card {
width: 158px;
height: 100px;
opacity: 1;
border-radius: 5px;
background: rgba(255, 255, 255, 1);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.image {
width: 158px;
height: 100px;
}
.card-add {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.icon {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 10px;
width: 20px;
height: 20px;
background: @oak-color-primary;
color: #fff;
font-weight: bold;
}
.text {
/** 文本1 */
font-size: 14px;
font-weight: 400;
letter-spacing: 0px;
line-height: 20.27px;
color: rgba(128, 128, 128, 1);
margin-top: 18rpx;
}
}
}
}

View File

@ -0,0 +1,157 @@
import { EntityDict } from '../../../../oak-app-domain';
import { generateNewId } from 'oak-domain/lib/utils/uuid';
type Tag2 = 'file1' | 'file2'
export default OakComponent({
entity: 'extraFile',
projection: {
id: 1,
tag1: 1,
tag2: 1,
origin: 1,
bucket: 1,
objectId: 1,
filename: 1,
extra1: 1,
extension: 1,
type: 1,
entity: 1,
entityId: 1,
},
isList: true,
formData({ data: rows, features }) {
let file1;
let file1Url;
let file2;
let file2Url;
const { idCardType } = this.props;
if (idCardType === 'ID-Card') {
file1 = rows?.find(
(ele) => !ele.$$deleteAt$$ && ele.tag1 === idCardType && ele.tag2 === 'file1'
);
file1Url = features.extraFile.getUrl(
file1 as EntityDict['extraFile']['OpSchema']
);
file2 = rows?.find(
(ele) => !ele.$$deleteAt$$ && ele.tag1 === idCardType && ele.tag2 === 'file2'
);
file2Url = features.extraFile.getUrl(
file2 as EntityDict['extraFile']['OpSchema']
);
}
console.log(file1, file2)
return {
file1,
file2,
file1Url,
file2Url
};
},
data: {},
properties: {
origin: 'qiniu',
idCardType: '',
entityId: '',
entity: 'user'
},
methods: {
async onPickMp(e: WechatMiniprogram.Touch) {
const tag2 = e.currentTarget.dataset.tag2 as Tag2;
try {
const { errMsg, tempFiles } = await wx.chooseMedia({
count: 1,
mediaType: ['image'],
sourceType: ['album', 'camera'],
});
if (errMsg !== 'chooseMedia:ok') {
this.setMessage({
type: 'warning',
content: errMsg,
});
} else {
await Promise.all(
tempFiles.map(async (tempExtraFile) => {
const {
tempFilePath,
thumbTempFilePath,
fileType,
size,
} = tempExtraFile;
const filePath = tempFilePath || thumbTempFilePath;
const fileFullName = filePath.match(/[^/]+(?!.*\/)/g)![0];
this.pushExtraFile({
name: fileFullName,
fileType,
size,
extra1: filePath,
}, tag2);
})
);
}
} catch (err: any) {
console.error(err);
if (err.errMsg !== 'chooseMedia:fail cancel') {
this.setMessage({
type: 'error',
content: err.errMsg,
});
}
}
},
async pushExtraFile(options: {
name: string;
extra1: any;
fileType: string;
size: number;
}, tag2: Tag2) {
const { entity, entityId, autoUpload = false, origin = 'qiniu', idCardType } = this.props;
const { name, extra1, fileType, size } = options;
const extension = name.substring(name.lastIndexOf('.') + 1);
const filename = name.substring(0, name.lastIndexOf('.'));
const applicationId = this.features.application.getApplicationId();
const id = generateNewId();
const updateData = {
applicationId,
origin,
type: 'image',
tag1: idCardType,
tag2,
objectId: generateNewId(),
filename,
size,
extension,
fileType,
id,
entityId,
entity,
sort: 1000,
uploadState: 'uploading'
} as EntityDict['extraFile']['CreateSingle']['data'];
const _file = this.state[tag2]; //取出file1、file2
// 如果autoUpload
if (autoUpload) {
await this.features.extraFile.autoUpload(
updateData as EntityDict['extraFile']['OpSchema'],
extra1
);
if (_file) {
this.removeItem(_file.id as string);
await this.execute();
}
} else {
this.addItem(updateData);
if (_file) {
this.removeItem(_file.id as string);
}
this.features.extraFile.addLocalFile(id, extra1);
}
},
},
});

View File

@ -0,0 +1,41 @@
<view class="card-box">
<view class="card" bindtap="onPickMp" data-tag2="file1">
<block wx:if="{{file1Url}}">
<image src="{{file1Url}}" class="image" mode="aspectFit" />
</block>
<block wx:else>
<view class="card-add" >
<view class="icon">
+
</view>
<view class="text">
身份证人像面
</view>
</view>
</block>
</view>
<view class="card" bindtap="onPickMp" data-tag2="file2">
<block wx:if="{{file2Url}}">
<image src="{{file2Url}}" class="image" mode="aspectFit" />
</block>
<block wx:else>
<view class="card-add" >
<view class="icon">
+
</view>
<view class="text">
身份证国徽面
</view>
</view>
</block>
</view>
</view>

View File

@ -2,6 +2,7 @@
"usingComponents": {
"l-loading": "@oak-frontend-base/miniprogram_npm/lin-ui/loading/index",
"l-input": "@oak-frontend-base/miniprogram_npm/lin-ui/input/index",
"l-picker": "@oak-frontend-base/miniprogram_npm/lin-ui/picker/index"
"l-picker": "@oak-frontend-base/miniprogram_npm/lin-ui/picker/index",
"idCard": "./idCard/index"
}
}

View File

@ -5,65 +5,3 @@
background-color: #fff;
padding: 20rpx 20rpx;
}
.card-box {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
border-radius: 5px;
background: rgba(245, 245, 245, 1);
padding: 20rpx 20rpx;
margin-top: 20rpx;
.card {
width: 158px;
height: 100px;
opacity: 1;
border-radius: 5px;
background: rgba(255, 255, 255, 1);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.card-add {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.icon {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 10px;
width: 20px;
height: 20px;
background: @oak-color-primary;
color: #fff;
font-weight: bold;
}
.text {
/** 文本1 */
font-size: 14px;
font-weight: 400;
letter-spacing: 0px;
line-height: 20.27px;
color: rgba(128, 128, 128, 1);
margin-top: 18rpx;
}
}
}
}

View File

@ -1,6 +1,7 @@
import { EntityDict } from '../../../oak-app-domain';
import { generateNewId } from 'oak-domain/lib/utils/uuid';
export default OakComponent({
entity: 'user',
// projection: {
@ -39,7 +40,6 @@ export default OakComponent({
};
},
data: {
uploading: false,
idCardTypeArr: [
{
value: 'ID-Card',
@ -55,7 +55,9 @@ export default OakComponent({
},
] as { label: string; value: string }[],
},
properties: {},
properties: {
origin: 'qiniu',
},
methods: {
setNameMp(e: WechatMiniprogram.Input) {
const {
@ -82,96 +84,5 @@ export default OakComponent({
idNumber: value,
});
},
async handleUpload(file: any) {
const {
name,
size,
type: fileType,
originFileObj,
lastModified,
} = file;
const md5 = name! + size! + lastModified;
const extension = name.substring(name.lastIndexOf('.') + 1);
const filename = name.substring(0, name.lastIndexOf('.'));
const entity: keyof EntityDict = 'user';
const origin = 'qiniu';
const updateData = {
origin,
type: 'image',
tag1: 'IDCard',
objectId: generateNewId(),
entity,
filename,
size,
extension,
fileType,
id: generateNewId(),
entityId: this.props.oakId,
md5,
} as EntityDict['extraFile']['CreateSingle']['data'];
try {
await this.features.extraFile.autoUpload(
updateData as EntityDict['extraFile']['OpSchema'],
originFileObj!
);
} catch (error) {
//todo 保存extraFile失败 需要remove七牛图片
throw error;
}
},
prevImg(file: any, id: string) {
const reader = new FileReader();
const preViewContainer = document.getElementById(id);
reader.onload = (e) => {
const imgEle = document.createElement('img');
imgEle.src = e.target!.result as string;
imgEle.style.position = 'absolute';
imgEle.style.top = '0px';
imgEle.style.left = '0px';
imgEle.style.width = '100%';
imgEle.style.height = '100%';
imgEle.style.objectFit = 'contain';
preViewContainer?.appendChild(imgEle);
};
reader.readAsDataURL(file);
},
// 身份证校验要使用专业的身份验证库, 当前不做校验
async commit(file1: any, file2: any) {
if (!file1) {
this.setMessage({
content: this.t('please upload identity witness profile'),
type: 'warning',
});
return;
}
if (!file2) {
this.setMessage({
content: this.t(
'please upload identity national emblem profile'
),
type: 'warning',
});
return;
}
this.setState({
uploading: true,
});
try {
await this.handleUpload(file1);
await this.handleUpload(file2);
this.setState({
uploading: false,
});
this.execute('accept');
} catch (err) {
this.setState({
uploading: false,
});
}
},
},
});

View File

@ -4,35 +4,10 @@
<l-picker required label="{{ t('user:attr.idCardType') }}" placeholder="{{ t('please choose idCardType') }}" range="{{ idCardTypeArr }}" rangeKey="label" value="{{idCardType}}" bind:linchange="setIdCardTypeMp" />
<l-input required disabled="{{!idCardType}}" type="idcard" label="{{ t('user:attr.idNumber') }}" placeholder="{{ t('please input idNumber') }}" bind:lininput="setIdNumberMp" />
<view class="card-box">
<view class="card" >
<view class="card-add" bindtap="onPickMp" data-type="card1">
<view class="icon">
+
</view>
<view class="text">
身份证人像面
</view>
</view>
</view>
<view class="card">
<view class="card-add" bindtap="onPickMp" data-type="card2">
<view class="icon">
+
</view>
<view class="text">
身份证国徽面
</view>
</view>
</view>
</view>
<block wx:if="{{oakId}}">
<idCard entity="user" entityId="{{oakId}}" origin="{{origin}}" idCardType="{{idCardType}}" oakPath="{{ oakFullpath + '.extraFile$entity' }}" />
</block>
</view>