Handy_Cao 2 rokov pred
rodič
commit
d144c04cfa

+ 1 - 1
public/config/appconfig.json

@@ -1,6 +1,6 @@
 {
   "version": "1.0.0",
   "versionCode": "100000",
-  "apiUrl": "http://192.168.31.204:8080/cfg?key=test_204",
+  "apiUrl": "http://192.168.31.202:8080/cfg?key=test_202",
   "appName": "多元世纪"
 }

+ 58 - 2
src/business/user/account.ts

@@ -1,6 +1,6 @@
-import { shallowRef, reactive } from 'vue'
+import { shallowRef, reactive, computed } from 'vue'
 import { useLoginStore, useAccountStore } from '@/stores'
-import { investorDel, modifyPassword, requestAddAuth } from '@/services/api/account'
+import { investorDel, modifyPassword, requestAddAuth, requestAddUser, requestCreateContractAndAddSigner } from '@/services/api/account'
 import cryptojs from 'crypto-js'
 
 const loginStore = useLoginStore()
@@ -33,6 +33,33 @@ export function addAuthReq() {
     }
 }
 
+// 实名认证添加用户(爱签)
+export function adddUserReq() {
+    const loading = shallowRef(false)
+
+    const formData = reactive<Model.AddUserReq>({
+        idCardType: 1
+    })
+
+    const formSubmit = async () => {
+        try {
+            loading.value = true
+            await requestAddUser ({
+                data: formData
+            })
+        } finally {
+            loading.value = false
+        }
+    }
+
+    return {
+        loading,
+        formData,
+        formSubmit
+    }
+}
+
+
 // 修改密码
 export function useAccountPassword(ModifyPwdType: 0 | 1 | 2) {
     const loading = shallowRef(false)
@@ -90,4 +117,33 @@ export function useAccountCancellation() {
         loading,
         formSubmit,
     }
+}
+
+/**
+ * 上传待签署文件和添加签署方
+ */
+export function  useRequestCreateContractAndAddSigner() {
+    const loading = shallowRef(false)
+
+    /// 合同编号
+    const templateNoFormData = reactive<Model.ContractAndAddSignerReq>({ })
+
+    const createSigner = async () => {
+        try {
+            loading.value = true
+            return await requestCreateContractAndAddSigner({
+                data: {
+                    ...templateNoFormData,
+                }
+            })
+        } finally {
+            loading.value = false
+        }
+    }
+
+    return {
+        loading,
+        createSigner,
+        templateNoFormData
+    }
 }

+ 28 - 0
src/constants/account.ts

@@ -13,6 +13,14 @@ export enum AuthStatus {
 }
 
 /**
+ * 爱签实名认证状态
+ */
+export enum AQCertificateType {
+    /// 身份证
+    Identity = 1
+}
+
+/**
  * 实名认证状态列表
  * @returns 
  */
@@ -35,6 +43,26 @@ export function getAuthStatusName(value: number) {
 }
 
 /**
+ * 获取对应的爱签证件类型列表
+ * @returns 
+ */
+export function getAQCertificateTypeList() {
+    return [
+        { label: '身份证', value: AQCertificateType.Identity },
+    ]
+}
+
+/**
+ * 获取对应的爱签证件类型列表
+ * @returns 
+ */
+export function getAQCertificateTypeListName(value: number) {
+    const enums = getAQCertificateTypeList()
+    return getEnumTypeName(enums, value)
+}
+
+
+/**
  * 获取对应的证件类型列表
  * @returns 
  */

+ 68 - 26
src/packages/qxst/views/account/certification/Index.vue

@@ -3,23 +3,25 @@
         <template #header>
             <app-navbar title="实名认证" />
         </template>
-        <Form ref="formRef" class="g-form__container" @submit="onSubmit">
+        <Form ref="formRef" class="g-form__container" @submit="onSubmit" :loading="loading">
             <CellGroup inset>
-                <Field v-model="formData.username" name="username" label="姓名" placeholder="请输入用户姓名"
-                    :rules="formRules.username" />
-                <Field name="cardtype" label="证件类型" :rules="formRules.cardtype" is-link>
+                <Field v-model="formData.name" name="name" label="姓名" placeholder="请输入用户姓名"
+                    :rules="formRules.name" />
+                <Field v-model="formData.mobile" name="mobile" label="手机号码" placeholder="请输入手机号码"
+                    :rules="formRules.mobile" />
+                <Field name="idCardType" label="证件类型" :rules="formRules.idCardType" is-link>
                     <template #input>
-                        <app-select v-model="formData.cardtype" placeholder="请选择证件类型" :options="enums" />
+                        <app-select v-model="formData.idCardType" placeholder="请选择证件类型" :options="enums" />
                     </template>
                 </Field>
-                <Field v-model="formData.cardnum" name="cardnum" label="证件号码" placeholder="请输入证件号码"
-                    :rules="formRules.cardnum" />
-                <Field name="cardfrontphotourl" label="证件正面照片" :rules="formRules.cardfrontphotourl">
+                <Field v-model="formData.idCard" name="cardnum" label="证件号码" placeholder="请输入证件号码"
+                    :rules="formRules.idCard" />
+                <Field name="idCardPhoto" label="证件正面照片" :rules="formRules.idCardPhoto">
                     <template #input>
                         <app-uploader @success="b_afterRead" />
                     </template>
                 </Field>
-                <Field name="cardbackphotourl" label="证件反面照片" :rules="formRules.cardbackphotourl">
+                <Field name="idCardPhotoBackURL" label="证件反面照片" :rules="formRules.idCardPhotoBackURL">
                     <template #input>
                         <app-uploader @success="f_afterRead" />
                     </template>
@@ -29,53 +31,92 @@
         <img src="../../../assets/images/certification.png" />
         <template #footer>
             <div class="g-form__footer inset">
-                <Button type="danger" @click="formRef?.submit" round block>提交实名认证</Button>
+                <Button type="danger" @click="formRef?.submit" :disabled="!canAdd" round block>提交实名认证</Button>
             </div>
         </template>
+        <component ref="componentRef" v-bind="{ formData }" :is="componentMap.get(componentId)" @closed="closeComponent" v-if="componentId" />
     </app-view>
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, computed } from 'vue'
+import { shallowRef, computed, defineAsyncComponent } from 'vue'
 import { CellGroup, Button, Field, Form, FormInstance, showFailToast, FieldRule } from 'vant'
-import { addAuthReq } from '@/business/user'
 import { fullloading, dialog } from '@/utils/vant';
-import { getCertificateTypeList } from "@/constants/account";
+import { getAQCertificateTypeList } from "@/constants/account";
+import { useRequest } from '@/hooks/request'
+import { queryUserESignRecord } from '@/services/api/account';
+import { adddUserReq } from '@/business/user/account';
+import { validateRules } from '@/constants/regex';
+import { useComponent } from '@/hooks/component'
 import AppSelect from '../../../components/base/select/index.vue'
-import { useNavigation } from '../../../router/navigation'
 import AppUploader from '../../../components/base/uploader/index.vue'
 
 const formRef = shallowRef<FormInstance>()
-const { formData, formSubmit } = addAuthReq()
-const { router } = useNavigation()
+const { formData, formSubmit } = adddUserReq()
+const error = shallowRef(false)
+const canAdd = shallowRef(false)
+const { componentRef, componentId, openComponent, closeComponent } = useComponent()
+
+const componentMap = new Map<string, unknown>([
+    ['certification-next', defineAsyncComponent(() => import('./components/certification-next/Index.vue'))], // 爱签-实名认证第二步
+])
+
+/// 查询记录
+const { loading  } = useRequest(queryUserESignRecord, {
+    onSuccess: (res) => {
+        res.data.map(obj => {
+            if (obj.templatetype === 1 && obj.recordstatus === 1) {
+                canAdd.value = true
+            }
+        })
+    },
+    onError: () => {
+        error.value = true
+    }
+})
 
 /// 获取对应的证件枚举类型
-const enums = computed(() => { return getCertificateTypeList().map(obj => { return { label: obj.label, value: obj.value } }) })
+const enums = computed(() => { return getAQCertificateTypeList().map(obj => { return { label: obj.label, value: obj.value } }) })
 
 const b_afterRead = (filePath: string) => {
-    formData.cardfrontphotourl = filePath
+    formData.idCardPhoto = filePath
 }
 
 const f_afterRead = (filePath: string) => {
-    formData.cardbackphotourl = filePath
+    formData.idCardPhotoBackURL = filePath
 }
 
 // 表单验证规则
-const formRules: { [key in keyof Model.AddAuthReq]?: FieldRule[] } = {
-    username: [{
+const formRules: { [key in keyof Model.AddUserReq]?: FieldRule[] } = {
+    name: [{
         required: true,
         message: '请输入用户姓名',
     }],
-    cardnum: [{
+    mobile: [{
+        required: true,
+        message: '请输入手机号码',
+        validator: (val) => {
+            if (validateRules.phone.validate(val)) {
+                return true
+            }
+            return validateRules.phone.message
+        }
+    }],
+    idCard: [{
         required: true,
         message: '请输入证件号码',
-
+        validator: (val) => {
+            if (validateRules.cardno.validate(val)) {
+                return true
+            }
+            return validateRules.cardno.message
+        }
     }],
-    cardbackphotourl: [{
+    idCardPhotoBackURL: [{
         required: true,
         message: '请上传证件背面照片',
     }],
-    cardfrontphotourl: [{
+    idCardPhoto: [{
         required: true,
         message: '请上传证件正面照片',
     }],
@@ -86,7 +127,8 @@ const onSubmit = () => {
         formSubmit().then(() => {
             hideLoading()
             dialog('实名认证提交请求成功').then(() => {
-                router.back()
+                /// 进行下一步
+                openComponent('certification-next')
             })
         }).catch((err) => {
             showFailToast(err)

+ 150 - 0
src/packages/qxst/views/account/certification/components/certification-next/Index.vue

@@ -0,0 +1,150 @@
+<template>
+    <app-modal direction="right" height="100%" v-model:show="showModal" :refresh="refresh">
+        <app-view class="g-form account-certification">
+            <template #header>
+                <app-navbar title="实名认证" />
+            </template>
+            <CellGroup inset>
+                <Cell title="姓名" :value="formData.name" />
+                <Cell title="手机号码" :value="formData.mobile" />
+                <Cell title="证件类型" :value="getAQCertificateTypeListName(formData.idCardType ?? 1)" />
+                <Cell title="证件号码" :value="formData.idCard" />
+                <Field name="idCardPhoto" label="证件正面照片">
+                    <template #input>
+                        <image :src="idCardPhoto"></image>
+                    </template>
+                </Field>
+                <Field name="idCardPhotoBackURL" label="证件反面照片">
+                    <template #input>
+                        <image :src="idCardPhotoBackURL"></image>
+                    </template>
+                </Field>
+            </CellGroup>
+            <CellGroup inset>
+                <Cell v-for="(item, index) in dataList" :key="index" @click="signer(item)">
+                    <template #title>
+                        <Icon :name="iconName(item.recordstatus)"></Icon>
+                        <Button :disable="item.recordstatus === 2">{{ item.templatename }}</Button>
+                    </template>
+                </Cell>
+            </CellGroup>
+            <template #footer>
+                <div class="g-form__footer inset">
+                    <Button type="danger" :disable="!canAdd" @click="formRef?.submit" round block>提交认证</Button>
+                </div>
+            </template>
+        </app-view>
+    </app-modal>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, computed, PropType} from 'vue'
+import { CellGroup, Button, Cell, Field, Icon, FormInstance, showFailToast } from 'vant'
+import { fullloading, dialog } from '@/utils/vant';
+import { getAQCertificateTypeListName } from "@/constants/account";
+import { useRequest } from '@/hooks/request'
+import { queryUserESignRecord } from '@/services/api/account';
+import { useRequestCreateContractAndAddSigner } from '@/business/user/account';
+import AppModal from '@/components/base/modal/index.vue'
+import plus from '@/utils/h5plus'
+import { onMounted } from 'vue';
+import { getFileUrl } from '@/filters';
+
+const formRef = shallowRef<FormInstance>()
+const error = shallowRef(false)
+const showModal = shallowRef(true)
+// 是否刷新父组件数据
+const refresh = shallowRef(false)
+const dataList = shallowRef<Model.UserESignRecordRsq[]>([])
+const { createSigner, templateNoFormData} = useRequestCreateContractAndAddSigner()
+/// 可以认证
+const canAdd = shallowRef(false)
+
+const iconName = (type: number) => {
+    switch (type) {
+        case 1:
+            return 'circle'
+        case 2:
+            return 'circle'
+        case 3:
+            return 'passed'
+        default:
+            return 'close'
+    }
+}
+
+// 正面照
+const idCardPhoto = computed(() => {
+    const idCardPhoto = props.formData.idCardPhoto ?? ''
+    return idCardPhoto.split(',').map((path) => getFileUrl(path))
+})
+
+// 背面照
+const idCardPhotoBackURL = computed(() => {
+    const idCardPhotoBackURL = props.formData.idCardPhotoBackURL ?? ''
+    return idCardPhotoBackURL.split(',').map((path) => getFileUrl(path))
+})
+
+const openURL = (url: string) => {
+    plus.openURL(url)
+}
+
+const props = defineProps({
+    formData: {
+        type: Object as PropType<Model.AddUserReq>,
+        required: true,
+    }
+})
+
+const onSubmit = () => {
+    fullloading((hideLoading) => {
+        // formSubmit().then(() => {
+        //     hideLoading()
+        //     dialog('实名认证提交请求成功').then(() => {
+        //         // router.back()
+        //     })
+        // }).catch((err) => {
+        //     showFailToast(err)
+        // })
+    })
+}
+
+const signer = (item: Model.UserESignRecordRsq) => {
+    ///  如果是已签署
+    if (item.recordstatus === 3) { 
+        if (item.contractfileaddr != '') {
+            openURL(item.contractfileaddr)
+        } else {
+            showFailToast('已签署文件地址错误')
+        }
+    } else {
+        fullloading((hideLoading) => {
+            templateNoFormData.templateNo = item.templateno
+            /// 创建合同
+            createSigner().then((res) => {
+                hideLoading()
+                openURL(res.data.data)
+            }).catch((err) => {
+                showFailToast(err)
+            })
+        })
+    }
+}
+
+onMounted(() => {
+    /// 查询
+    useRequest(queryUserESignRecord, {
+        onSuccess: (res) => {
+            if (res.data.length != 0) {
+                dataList.value = res.data
+            }
+
+            /// 只有全部签署才可以进行下一步
+            canAdd.value = res.data.some(obj => { [1, 2, 4].includes(obj.recordstatus) })
+        },
+        onError: () => {
+            error.value = true
+        }
+    })
+})
+</script>

+ 33 - 0
src/services/api/account/index.ts

@@ -140,4 +140,37 @@ export function modifyPassword(config: RequestConfig<Proto.ModifyPwdReq>) {
         requestCode: 'ModifyPwdReq',
         responseCode: 'ModifyPwdRsp',
     })
+}
+
+/**
+ * 实名认证添加用户
+ */
+export function requestAddUser(config: RequestConfig<Model.AddUserReq> = {}) {
+    return http.goRequest<Model.AddUserRsp>({
+        method: 'post',
+        url: '/Account/AddUser',
+        data: config.data,
+    })
+}
+
+/**
+ * 查询用户电子签记录表
+ */
+export function queryUserESignRecord(config: RequestConfig<Model.UserESignRecordReq> = {}) {
+    return http.goRequest<Model.UserESignRecordRsq[]>({
+        method: 'get',
+        url: '/Account/QueryUserESignRecord',
+        data: config.data,
+    })
+}
+
+/**
+ * 上传待签署文件和添加签署方
+ */
+export function requestCreateContractAndAddSigner(config: RequestConfig<Model.ContractAndAddSignerReq> = {}) {
+    return http.goRequest<Model.ContractAndAddSignerRsq>({
+        method: 'post',
+        url: '/Account/CreateContractAndAddSigner',
+        data: config.data,
+    })
 }

+ 1 - 1
src/services/http/index.ts

@@ -156,7 +156,7 @@ export default new (class {
      * @returns 
      */
     async goRequest<T>(config: AxiosRequestConfig, errMsg?: string) {
-        const baseUrl = service.getConfig('goAccess')
+        const baseUrl = 'http://192.168.30.172:8888/api'//service.getConfig('goAccess')
         config.url = baseUrl + config.url
         const res = await this.request<CommonResult<T>>(config, errMsg)
         switch (res.code) {

+ 85 - 0
src/types/model/bank.d.ts

@@ -282,4 +282,89 @@ declare namespace Model {
         // 交易模式
         trademode: number
     }
+
+
+    // 查询用户电子签记录表请求
+    interface UserESignRecordReq {
+        /// 页数
+        page?: number
+        /// 条数
+        size?: number
+    }
+
+    // 查询用户电子签记录表回应
+    interface UserESignRecordRsq {
+        // 认证信息
+        authinfo: string
+        // 合同签署文件地址
+        contractfileaddr: string
+        // 合同编号
+        contractno: string
+        // 创建时间
+        createtime: string
+        // 创建人
+        creatorid: number
+        // 显示顺序
+        orderindex: number
+        // 记录ID(SEQ_USERESIGNRECORD)
+        recordid: number
+        // 记录状态 - 1:未签署 2:签署中 3:已签署 4:签署拒绝
+        recordstatus: number
+        // 签署备注
+        signremark: string
+        // 合同签署URL(三方URL)
+        signurl: string
+        // 模板配置ID
+        templateconfigid: number
+        // 模板名称
+        templatename: string
+        // 模板编号(电子签类型对应的模板编号)
+        templateno: string
+        // 模板类型 - 1:实名认证 2:开户协议
+        templatetype: number
+        // 更新时间
+        updatetime: string
+        // 用户ID
+        userid: number
+    }
+
+    /// 实名认证添加用户请求
+    interface AddUserReq {
+        // 证件号码
+        idCard?: string
+        // 证件照正面
+        idCardPhoto?: string
+        // 证件照背面
+        idCardPhotoBackURL?: string
+        // 证件类型(默认1):1-居民身份证 2-台湾居民来往内地通行证 3-港澳居民往来内地通行证 10-武装警察身份证 11-军人身份证 15-警察(警官)证 21-外国人永久居留证 23-护照
+        idCardType?: number
+        // 手机号码
+        mobile?: string
+        // 用户姓名
+        name?: string
+    }
+
+    /// 实名认证添加用户回应
+    interface AddUserRsp {
+        // 返回码
+        code: string
+        // 返回信息
+        msg: string
+    }
+
+    /// 上传待签署文件和添加签署方-请求
+    interface ContractAndAddSignerReq {
+        /// 合同模板编号
+        templateNo?: string
+    }
+
+    /// 上传待签署文件和添加签署方-回应
+    interface ContractAndAddSignerRsq {
+        /// code
+        code: number
+        /// data
+        data: string
+        /// msg
+        msg: string
+    }
 }

+ 0 - 1
src/types/proto/bank.d.ts

@@ -1,5 +1,4 @@
 import { IMessageHead } from './proto'
-import Long from 'long'
 
 declare global {
     namespace Proto {