|
@@ -1,165 +1,35 @@
|
|
|
<script setup lang="ts">
|
|
|
+import NavHomeSelect from '@/assets/images/nav-home.select.png?url';
|
|
|
import { Notify, Toast } from '@/platform';
|
|
|
|
|
|
import {
|
|
|
- type FieldKey,
|
|
|
getCaptchaMethod,
|
|
|
processMethod,
|
|
|
registerAccountMethod,
|
|
|
registerFieldsMethod,
|
|
|
- scanAccountMethod, searchAccountMethod,
|
|
|
-} from '@/request/api';
|
|
|
-
|
|
|
-import { useVisitor } from '@/stores';
|
|
|
-import { useRouteQuery } from '@vueuse/router';
|
|
|
-
|
|
|
-import { useCaptcha, useForm, useRequest, useWatcher } from 'alova/client';
|
|
|
+ searchAccountMethod,
|
|
|
+} from '@/request/api';
|
|
|
+import type { Fields, RegisterModel } from '@/request/model';
|
|
|
+import { useRouteQuery } from '@vueuse/router';
|
|
|
|
|
|
-import type { FieldRule, FormInstance, NumberKeyboardProps, PasswordInputProps } from 'vant';
|
|
|
-import { RadioGroup as vanRadioGroup } from 'vant';
|
|
|
+import { useCaptcha, useRequest, useSerialRequest } from 'alova/client';
|
|
|
|
|
|
-import NavHomeSelect from '@/assets/images/nav-home.select.png?url';
|
|
|
+import type { FormInstance } from 'vant';
|
|
|
+import { RadioGroup as vanRadioGroup } from 'vant';
|
|
|
|
|
|
-interface Field {
|
|
|
- control: {
|
|
|
- label: string; placeholder?: string;
|
|
|
- type?: string; min?: number; max?: number; minlength?: number; maxlength?: number;
|
|
|
- clearable?: boolean; border?: boolean; readonly?:boolean;
|
|
|
- };
|
|
|
- component?: |
|
|
|
- { name: 'radio', options: { label: string; value: string; }[] } |
|
|
|
- { name: 'code', props?: Partial<PasswordInputProps> };
|
|
|
- keyboard?: { show: boolean; } & Partial<NumberKeyboardProps>;
|
|
|
- suffix?: string;
|
|
|
- rules?: FieldRule[];
|
|
|
-}
|
|
|
|
|
|
-const Fields: Record<FieldKey, Field> = {
|
|
|
- height: {
|
|
|
- control: {
|
|
|
- label: '身高', placeholder: '请输入身高',
|
|
|
- type: 'number', min: 1, max: 300, clearable: true, readonly: true,
|
|
|
- maxlength: 5,
|
|
|
- },
|
|
|
- keyboard: { show: false, title: '身高', extraKey:'.', closeButtonText: '完成' },
|
|
|
- suffix: 'cm',
|
|
|
- },
|
|
|
- weight: {
|
|
|
- control: {
|
|
|
- label: '体重', placeholder: '请输入体重',
|
|
|
- type: 'number', min: 1, max: 300, clearable: true, readonly: true,
|
|
|
- maxlength: 5,
|
|
|
- },
|
|
|
- keyboard: { show: false, title: '体重', extraKey:'.', closeButtonText: '完成' },
|
|
|
- suffix: 'kg',
|
|
|
- },
|
|
|
- age: {
|
|
|
- control: {
|
|
|
- label: '年龄', placeholder: '请输入年龄',
|
|
|
- type: 'digit', min: 0, max: 300, clearable: true, readonly: true,
|
|
|
- maxlength: 3,
|
|
|
- },
|
|
|
- keyboard: { show: false, title: '年龄', closeButtonText: '完成' },
|
|
|
- suffix: '岁',
|
|
|
- },
|
|
|
- sex: {
|
|
|
- control: { label: '性别', border: false },
|
|
|
- component: {
|
|
|
- name: 'radio' as const,
|
|
|
- options: [
|
|
|
- { label: '男', value: '0' },
|
|
|
- { label: '女', value: '1' },
|
|
|
- ],
|
|
|
- },
|
|
|
- },
|
|
|
- isEasyAllergy: {
|
|
|
- control: { label: '容易过敏', border: false },
|
|
|
- component: {
|
|
|
- name: 'radio' as const,
|
|
|
- options: [
|
|
|
- { label: '是', value: 'Y' },
|
|
|
- { label: '否', value: 'N' },
|
|
|
- ],
|
|
|
- },
|
|
|
- },
|
|
|
- name: {
|
|
|
- control: {
|
|
|
- label: '姓名', placeholder: '请输入姓名',
|
|
|
- type: 'text', maxlength: 10, clearable: true,
|
|
|
- },
|
|
|
- },
|
|
|
- cardno: {
|
|
|
- control: {
|
|
|
- label: '身份证号', placeholder: '请输入身份证号',
|
|
|
- type: 'text', maxlength: 18, minlength: 18, clearable: true, readonly: true,
|
|
|
- },
|
|
|
- keyboard: { show: false, title: '身份证号', extraKey: 'X', closeButtonText: '完成' },
|
|
|
- rules: [
|
|
|
- { required: true, message: '请输入身份证号' },
|
|
|
- {
|
|
|
- validator: (value: string) => value && value.length === 18,
|
|
|
- message: '请输入正确的身份证',
|
|
|
- trigger: 'onBlur',
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- phone: {
|
|
|
- control: {
|
|
|
- label: '手机号码', placeholder: '请输入手机号码',
|
|
|
- type: 'tel', maxlength: 11, minlength: 11, clearable: true, readonly: true,
|
|
|
- },
|
|
|
- keyboard: { show: false, title: '手机号码', closeButtonText: '完成' },
|
|
|
- rules: [
|
|
|
- { required: true, message: '请输入手机号码' },
|
|
|
- {
|
|
|
- validator: (value: string) => value && value.length === 11,
|
|
|
- message: '请输入正确的手机号码',
|
|
|
- trigger: 'onBlur',
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- code: {
|
|
|
- control: {
|
|
|
- label: '验证码', placeholder: '请输入验证码',
|
|
|
- type: 'digit', maxlength: 6, minlength: 6, clearable: true,
|
|
|
- border: false,
|
|
|
- },
|
|
|
- component: {
|
|
|
- name: 'code' as const,
|
|
|
- props: { mask: false },
|
|
|
- },
|
|
|
- keyboard: { show: false, title: '验证码', closeButtonText: '完成' },
|
|
|
- rules: [
|
|
|
- { required: true, message: '请输入验证码' },
|
|
|
- {
|
|
|
- validator: (value: string) => value && value.length === 6,
|
|
|
- message: '请输入验证码',
|
|
|
- trigger: [ 'onChange', 'onBlur' ],
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
-};
|
|
|
+const { data: fields, loading } = useRequest(registerFieldsMethod);
|
|
|
|
|
|
-
|
|
|
-const fields = ref<( Field & { name: FieldKey } )[]>([]);
|
|
|
-const { loading } = useRequest(registerFieldsMethod).onSuccess(({ data }) => {
|
|
|
- fields.value = data.map(name => {return { ...Fields[ name ], name };});
|
|
|
-});
|
|
|
-
|
|
|
-const Visitor = useVisitor();
|
|
|
const formRef = useTemplateRef<FormInstance>('register-form');
|
|
|
-const { form: modelRef, loading: submitting, send: submit } = useForm(data => registerAccountMethod(data), {
|
|
|
- initialForm: { code: '' } as Record<string, any>,
|
|
|
-}).onSuccess(async ({ data }) => {
|
|
|
- Visitor.patientId = data;
|
|
|
- Toast.success(`操作成功`);
|
|
|
- try {
|
|
|
- submitting.value = true;
|
|
|
- await handle();
|
|
|
- } finally {
|
|
|
- submitting.value = false;
|
|
|
- }
|
|
|
-});
|
|
|
+const modelRef = ref<Partial<RegisterModel>>({ code: '' });
|
|
|
+
|
|
|
+const router = useRouter();
|
|
|
+const { loading: submitting, send: submit } = useSerialRequest([
|
|
|
+ data => registerAccountMethod(data),
|
|
|
+ () => processMethod(),
|
|
|
+], { immediate: false })
|
|
|
+ .onSuccess(({ data }) => {router.replace(data);})
|
|
|
+ .onError(({ error }) => Notify.warning(error.message));
|
|
|
|
|
|
const { loading: searching, send: search } = useRequest((data) => searchAccountMethod(data), {
|
|
|
immediate: false,
|
|
@@ -195,7 +65,7 @@ const searchHandle = async (key: 'cardno' | 'code') => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-function onKeyboardBlur(field: Field & { name: FieldKey }) {
|
|
|
+function onKeyboardBlur(field: Fields[number]) {
|
|
|
if ( field?.name === 'phone' && !captchaLoaded ) { getCaptchaHandle(); }
|
|
|
if ( field?.name === 'cardno' ) { searchHandle('cardno'); }
|
|
|
if ( field?.name === 'code' ) { searchHandle('code'); }
|
|
@@ -205,47 +75,21 @@ function onSubmitHandle() {
|
|
|
submit(toValue(modelRef));
|
|
|
}
|
|
|
|
|
|
-const router = useRouter();
|
|
|
-const { send: handle } = useRequest(
|
|
|
- () => processMethod('/register'),
|
|
|
- { immediate: false },
|
|
|
-).onSuccess(
|
|
|
- ({ data }) => {
|
|
|
- if ( data ) {
|
|
|
- router.replace(data);
|
|
|
- } else {
|
|
|
- Notify.warning(`[路由] 配置异常无法解析正确路径,请联系管理员`);
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
-function fix(key: FieldKey) {
|
|
|
+function fix(key: string) {
|
|
|
for ( const field of fields.value ) {
|
|
|
if (field.keyboard?.show && field.name !== key ) field.keyboard.show = false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const scan = useRouteQuery<string>('scan');
|
|
|
-useWatcher(
|
|
|
- () => scanAccountMethod(sessionStorage.getItem(`scan_${ scan.value }`)!),
|
|
|
- [ scan ],
|
|
|
- {
|
|
|
- immediate: true,
|
|
|
- async middleware(_, next) {
|
|
|
- if ( scan.value ) {
|
|
|
- let scanToastRef: any;
|
|
|
- try {
|
|
|
- scanToastRef = Toast.loading(100, { message: '加载中' });
|
|
|
- await next();
|
|
|
- } catch ( error ) {} finally {
|
|
|
- scanToastRef?.close?.();
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
- },
|
|
|
-).onSuccess(({ data }) => {
|
|
|
- Toast.success('扫码成功');
|
|
|
- modelRef.value = { ...modelRef.value, ...data };
|
|
|
-});
|
|
|
+watch(scan, key => {
|
|
|
+ if ( key ) {
|
|
|
+ try {
|
|
|
+ const { model } = JSON.parse(sessionStorage.getItem(`scan_${ key }`) ?? '');
|
|
|
+ modelRef.value = { ...modelRef.value, ...model };
|
|
|
+ } catch ( e: any ) {}
|
|
|
+ }
|
|
|
+}, { immediate: true });
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
for ( let i = 0; i < sessionStorage.length; i++ ) {
|
|
@@ -319,7 +163,7 @@ onBeforeUnmount(() => {
|
|
|
</van-form>
|
|
|
<div class="m-4">
|
|
|
<div class="m-auto size-16 cursor-pointer">
|
|
|
- <van-loading v-if="submitting" type="spinner" size="64" color="#38ff6e" />
|
|
|
+ <van-loading v-if="submitting || loading" type="spinner" size="64" color="#38ff6e" />
|
|
|
<img v-else class="size-full"
|
|
|
src="@/assets/images/next-step.svg" alt="提交" @click="formRef?.submit()"
|
|
|
>
|