身份认证页面

This commit is contained in:
wkj 2024-05-17 22:12:55 +08:00
parent b7c95671a5
commit 085ec63909
12 changed files with 208 additions and 67 deletions

View File

@ -1,16 +1,11 @@
/** index.wxss **/
@import "../../../config/styles/mp/index.less";
@import "../../../config/styles/mp/mixins.less";
.page-body { .page-body {
height: 100vh; height: 100%;
display: flex; display: flex;
flex: 1; flex: 1;
flex-direction: column; flex-direction: column;
box-sizing: border-box; box-sizing: border-box;
align-items: stretch; align-items: stretch;
background-color: @oak-bg-color-page;
.safe-area-inset-bottom();
} }
.container { .container {

View File

@ -1,3 +1,4 @@
import { OakUserDisabledException } from '../../../types/Exception';
export default OakComponent({ export default OakComponent({
entity: 'mobile', entity: 'mobile',
@ -11,7 +12,6 @@ export default OakComponent({
filters: [ filters: [
{ {
filter() { filter() {
// const token = this.features.token.getToken();
const userId = this.features.token.getUserId(); const userId = this.features.token.getUserId();
return { return {
userId, userId,
@ -34,26 +34,50 @@ export default OakComponent({
deleteIdx: undefined, deleteIdx: undefined,
}, },
properties: { properties: {
showBack: false, onFinish: undefined as (() => void) | undefined
}, },
methods: { methods: {
async onRefreshMobile(e: any) { async onRefreshMobile(e: WechatMiniprogram.Touch) {
const { onFinish } = this.props;
this.setState({ this.setState({
refreshing: true, refreshing: true,
}); });
try { try {
const { code, errMsg } = e.detail; const { code, errMsg } = e.detail;
if (errMsg !== 'getPhoneNumber:ok') { if (errMsg !== 'getPhoneNumber:ok') {
console.error(errMsg); // 用户拒绝不用管
console.warn(errMsg);
if (errMsg !== 'getPhoneNumber:fail user deny') {
this.setMessage({ this.setMessage({
title: '获取手机号失败', content: '获取手机号失败',
type: 'warning', type: 'warning',
}); });
} else { return;
await this.features.token.getWechatMpUserPhoneNumber(code);
} }
} catch (err) { } else {
// await this.features.token.getWechatMpUserPhoneNumber(code);
if (onFinish) {
onFinish();
}
else if (process.env.OAK_PLATFORM === 'wechatMp') {
this.triggerEvent('finish', {})
}
}
} catch (err: any) {
console.error(err); console.error(err);
if (err instanceof OakUserDisabledException) {
this.setMessage({
content: err?.message,
type: 'error',
});
}
else {
this.setMessage({
content: err?.message || '获取手机号错误',
type: 'error',
});
}
} }
this.setState({ this.setState({
refreshing: false, refreshing: false,
@ -61,13 +85,8 @@ export default OakComponent({
}, },
goAddMobile() { goAddMobile() {
const eventLoggedIn = `mobile:me:login:${Date.now()}`;
this.subEvent(eventLoggedIn, () => {
this.navigateBack();
});
this.navigateTo({ this.navigateTo({
url: '/mobile/login', url: '/mobile/login',
eventLoggedIn,
}); });
}, },

View File

@ -24,7 +24,7 @@
</view> </view>
</block> </block>
<l-button type="default" block size="long" open-type="getPhoneNumber" bindgetphonenumber="onRefreshMobile"> <l-button type="default" block size="long" loading="{{ refreshing }}" open-type="getPhoneNumber" bindgetphonenumber="onRefreshMobile">
授权手机号 授权手机号
</l-button> </l-button>
</view> </view>

View File

@ -14,7 +14,6 @@ export default function render(
{ {
mobiles?: EntityDict['mobile']['OpSchema'][]; mobiles?: EntityDict['mobile']['OpSchema'][];
allowRemove: boolean; allowRemove: boolean;
showBack: boolean;
tokenMobileId?: string; tokenMobileId?: string;
}, },
{ {
@ -22,10 +21,9 @@ export default function render(
} }
> >
) { ) {
const { mobiles, allowRemove, tokenMobileId, showBack = false } = props.data; const { mobiles, allowRemove, tokenMobileId } = props.data;
const { goAddMobile, removeItem, recoverItem, execute } = props.methods; const { goAddMobile, removeItem, recoverItem, execute } = props.methods;
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const eventLoggedIn = `user:info:login:${Date.now()}`;
return ( return (
<> <>

View File

@ -18,6 +18,10 @@ export default OakComponent({
type: 1, type: 1,
entity: 1, entity: 1,
entityId: 1, entityId: 1,
fileType: 1,
sort: 1,
isBridge: 1,
uploadState: 1,
}, },
isList: true, isList: true,
formData({ data: rows, features }) { formData({ data: rows, features }) {
@ -42,8 +46,6 @@ export default OakComponent({
); );
} }
console.log(file1, file2)
return { return {
file1, file1,
file2, file2,

View File

@ -1,5 +1,5 @@
<block wx:if="{{ idCardType === 'ID-Card' }}" >
<view class="card-box"> <view class="card-box">
<view class="card" bindtap="onPickMp" data-tag2="file1"> <view class="card" bindtap="onPickMp" data-tag2="file1">
<block wx:if="{{file1Url}}"> <block wx:if="{{file1Url}}">
@ -39,3 +39,4 @@
</view> </view>
</view> </view>
</block>

View File

@ -3,6 +3,7 @@
"l-loading": "@oak-frontend-base/miniprogram_npm/lin-ui/loading/index", "l-loading": "@oak-frontend-base/miniprogram_npm/lin-ui/loading/index",
"l-input": "@oak-frontend-base/miniprogram_npm/lin-ui/input/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",
"l-button": "@oak-frontend-base/miniprogram_npm/lin-ui/button/index",
"idCard": "./idCard/index" "idCard": "./idCard/index"
} }
} }

View File

@ -1,7 +1,22 @@
@import '../../../config/styles/mp/index.less'; @import '../../../config/styles/mp/index.less';
.container { .page-body {
background-color: #fff; height: 100%;
padding: 20rpx 20rpx; display: flex;
flex: 1;
flex-direction: column;
box-sizing: border-box;
align-items: stretch;
}
.container {
flex: 1;
display: flex;
flex-direction: column;
}
.inner {
background-color: #fff;
padding: 20rpx 0rpx;
} }

View File

@ -1,6 +1,12 @@
import { EntityDict } from '../../../oak-app-domain'; import { EntityDict } from '../../../oak-app-domain';
import { generateNewId } from 'oak-domain/lib/utils/uuid'; import { generateNewId } from 'oak-domain/lib/utils/uuid';
import {
isIdCardNumber,
isHkCardNumber,
isTwCardNumber,
isAmCardNumber,
isPassportNumber,
} from 'oak-domain/lib/utils/validator';
export default OakComponent({ export default OakComponent({
entity: 'user', entity: 'user',
@ -32,11 +38,32 @@ export default OakComponent({
// }, // },
isList: false, isList: false,
formData({ data: row, features }) { formData({ data: row, features }) {
let file1;
let file2;
const idCardType = row?.idCardType;
if (idCardType === 'ID-Card') {
file1 = row?.extraFile$entity?.find(
(ele) =>
!ele.$$deleteAt$$ &&
ele.tag1 === idCardType &&
ele.tag2 === 'file1'
);
file2 = row?.extraFile$entity?.find(
(ele) =>
!ele.$$deleteAt$$ &&
ele.tag1 === idCardType &&
ele.tag2 === 'file2'
);
}
return { return {
name: row?.name, name: row?.name,
idNumber: row?.idNumber, idNumber: row?.idNumber,
idCardType: row?.idCardType, idCardType: row?.idCardType,
idState: row?.idState, idState: row?.idState,
file1,
file2,
}; };
}, },
data: { data: {
@ -84,5 +111,77 @@ export default OakComponent({
idNumber: value, idNumber: value,
}); });
}, },
async onConfirm() {
const { name, idCardType, idNumber, idState } = this.state;
if (!name) {
this.setMessage({
type: 'warning',
content: '请输入姓名',
});
return;
}
if (!idCardType) {
this.setMessage({
type: 'warning',
content: '请输入证件类型',
});
return;
}
if (!idNumber) {
this.setMessage({
type: 'warning',
content: '请输入证件号码',
});
return;
}
if (idCardType === 'ID-Card' && !isIdCardNumber(idNumber)) {
this.setMessage({
type: 'warning',
content: '身份证号输入不合法',
});
return;
}
if (idCardType === 'passport' && !isPassportNumber(idNumber)) {
this.setMessage({
type: 'warning',
content: '护照输入不合法',
});
return;
}
if (
idCardType === 'Mainland-passport' &&
!(
isHkCardNumber(idNumber) ||
isTwCardNumber(idNumber) ||
isAmCardNumber(idNumber)
)
) {
this.setMessage({
type: 'warning',
content: '港澳台通行证输入不合法',
});
return;
}
if (idCardType === 'ID-Card') {
const { file1, file2 } = this.state;
if (!file1) {
this.setMessage({
type: 'warning',
content: '请上传身份证人像面',
});
return;
} else if (!file2) {
this.setMessage({
type: 'warning',
content: '请上传身份证国徽面',
});
return;
}
}
// this.execute();
},
}, },
}); });

View File

@ -1,13 +1,18 @@
<view class="page-body">
<view class="container"> <view class="container">
<view class="inner">
<l-input required value="{{ name }}" label="{{ t('user:attr.name') }}" placeholder="{{ t('please input name') }}" bind:lininput="setNameMp" /> <l-input required value="{{ name }}" label="{{ t('user:attr.name') }}" placeholder="{{ t('please input name') }}" bind:lininput="setNameMp" />
<l-picker required label="{{ t('user:attr.idCardType') }}" placeholder="{{ t('please choose idCardType') }}" range="{{ idCardTypeArr }}" rangeKey="label" value="{{idCardType}}" bind:linchange="setIdCardTypeMp" /> <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" /> <l-input required value="{{ idNumber }}" disabled="{{!idCardType}}" type="idcard" label="{{ t('user:attr.idNumber') }}" placeholder="{{ t('please input idNumber') }}" bind:lininput="setIdNumberMp" />
<block wx:if="{{oakId && idCardType}}">
<block wx:if="{{oakId}}">
<idCard entity="user" entityId="{{oakId}}" origin="{{origin}}" idCardType="{{idCardType}}" oakPath="{{ oakFullpath + '.extraFile$entity' }}" /> <idCard entity="user" entityId="{{oakId}}" origin="{{origin}}" idCardType="{{idCardType}}" oakPath="{{ oakFullpath + '.extraFile$entity' }}" />
</block> </block>
</view>
</view>
<l-button type="default" block size="long" bind:lintap="onConfirm">
提交认证
</l-button>
</view> </view>

View File

@ -6,5 +6,6 @@
"Identity national emblem profile": "身份证国徽面", "Identity national emblem profile": "身份证国徽面",
"Real name verification passed": "已通过实名验证", "Real name verification passed": "已通过实名验证",
"please upload identity witness profile": "请上传身份证人像面", "please upload identity witness profile": "请上传身份证人像面",
"please upload identity national emblem profile": "请上传身份证国徽面" "please upload identity national emblem profile": "请上传身份证国徽面",
"commit": "提交认证"
} }

View File

@ -44,14 +44,19 @@ export const UserActionDef: ActionDef<UserAction, UserState> = {
export type Action = UserAction | IdAction; export type Action = UserAction | IdAction;
export const entityDesc: EntityDesc<Schema, Action, '', { export const entityDesc: EntityDesc<
Schema,
Action,
'',
{
userState: UserState; userState: UserState;
idState: IdState; idState: IdState;
gender: Required<Schema>['gender']; gender: Required<Schema>['gender'];
idCardType: Required<Schema>['idCardType']; idCardType: Required<Schema>['idCardType'];
}> = { }
> = {
locales: { locales: {
"zh_CN": { zh_CN: {
name: '用户', name: '用户',
attr: { attr: {
name: '姓名', name: '姓名',
@ -65,7 +70,7 @@ export const entityDesc: EntityDesc<Schema, Action, '', {
ref: '指向用户', ref: '指向用户',
files: '相关文件', files: '相关文件',
userState: '用户状态', userState: '用户状态',
idState: '身份验证状态', idState: '证状态',
codes: '微信分享二维码', codes: '微信分享二维码',
isRoot: '是否超级用户', isRoot: '是否超级用户',
addresses: '收货地址', addresses: '收货地址',
@ -73,7 +78,7 @@ export const entityDesc: EntityDesc<Schema, Action, '', {
action: { action: {
activate: '激活', activate: '激活',
accept: '同意', accept: '同意',
verify: '证', verify: '证',
reject: '拒绝', reject: '拒绝',
enable: '启用', enable: '启用',
disable: '禁用', disable: '禁用',
@ -88,21 +93,21 @@ export const entityDesc: EntityDesc<Schema, Action, '', {
merged: '已被合并', merged: '已被合并',
}, },
idState: { idState: {
unverified: '未证', unverified: '未证',
verifying: '证中', verifying: '证中',
verified: '已证', verified: '已证',
}, },
gender: { gender: {
male: '男', male: '男',
female: '女', female: '女',
}, },
idCardType: { idCardType: {
"ID-Card": '身份证', 'ID-Card': '身份证',
passport: '护照', passport: '护照',
"Mainland-passport": '港澳台通行证', 'Mainland-passport': '港澳台通行证',
},
},
}, },
}
}
}, },
indexes: [ indexes: [
{ {
@ -122,12 +127,12 @@ export const entityDesc: EntityDesc<Schema, Action, '', {
}, },
{ {
name: 'nickname', name: 'nickname',
} },
], ],
config: { config: {
type: 'fulltext', type: 'fulltext',
parser: 'ngram', parser: 'ngram',
} },
}, },
{ {
name: 'index_userState_refId', name: 'index_userState_refId',
@ -137,8 +142,8 @@ export const entityDesc: EntityDesc<Schema, Action, '', {
}, },
{ {
name: 'ref', name: 'ref',
} },
] ],
}, },
], ],
style: { style: {
@ -171,8 +176,8 @@ export const entityDesc: EntityDesc<Schema, Action, '', {
idCardType: { idCardType: {
'ID-Card': '#E0FFFF', 'ID-Card': '#E0FFFF',
'Mainland-passport': '#2E8B57', 'Mainland-passport': '#2E8B57',
'passport': '#2F4F4F', passport: '#2F4F4F',
},
},
}, },
}
}
}; };