Handy_Cao 2 سال پیش
والد
کامیت
b69b8a4aa6

+ 45 - 5
src/packages/mobile/views/swap/detail/Index.vue

@@ -24,14 +24,14 @@
                         <span>{{ row.userid }}/{{ row.username }}</span>
                     </template>
                     <template #operate="{ row }">
-                        <Button size="small" type="primary" round @click="onDelisting(row)">
-                            {{ tabIndex === BuyOrSell.Buy ? '卖出' : '买入' }}
+                        <Button size="small" type="primary" :disabled="status(row) === 2 || status(row) === 3 " round @click="onDelisting(row)">
+                            {{ getDelistingButtonTitles(tabIndex, row) }}
                         </Button>
                     </template>
                 </app-list>
             </div>
         </app-pull-refresh>
-        <component ref="componentRef" :is="componentMap.get(componentId)" v-bind="{ selectedRow, tabIndex, item }"
+        <component ref="componentRef" :is="componentMap.get(componentId)" v-bind="{ selectedRow, tabIndex, item, memberUserId }"
             @closed="closeComponent" v-if="componentId" />
     </app-view>
 </template>
@@ -43,11 +43,12 @@ import { useRequest } from '@/hooks/request'
 import { useNavigation } from '@mobile/router/navigation'
 import { useComponent } from '@/hooks/component'
 import { BuyOrSell } from '@/constants/order'
-import { queryTjmdTradeOrderDetail } from '@/services/api/swap'
+import { queryTjmdTradeOrderDetail, queryMdUserSwapProtocol } from '@/services/api/swap'
 import { useFuturesStore } from '@/stores'
 import { useLoginStore, useUserStore } from '@/stores'
 import AppPullRefresh from '@mobile/components/base/pull-refresh/index.vue'
 import AppList from '@mobile/components/base/list/index.vue'
+import { getMemberUserId, getUserId } from '@/services/methods/user'
 
 const Price = defineAsyncComponent(() => import('@mobile/components/modules/quote/price/index.vue'))
 const Chart = defineAsyncComponent(() => import('@mobile/components/modules/quote/chart/index.vue'))
@@ -56,6 +57,7 @@ const Tik = defineAsyncComponent(() => import('@mobile/components/modules/quote/
 const componentMap = new Map<string, unknown>([
     ['delisting', defineAsyncComponent(() => import('./components/delisting/Index.vue'))],
     ['listing', defineAsyncComponent(() => import('./components/listing/Index.vue'))],
+    ['certification-next', defineAsyncComponent(() => import('../../../../tjmd/views/account/certification/components/certification-next/Index.vue'))],
 ])
 
 const pullRefreshRef = shallowRef()
@@ -70,9 +72,22 @@ const futuresStore = useFuturesStore()
 const quote = futuresStore.getGoodsQuote(item.refgoodsid)
 const goodsCode = computed(() => quote.value?.goodscode ?? '')
 const userStore = useUserStore()
+/// 所属机构 ID
+const memberUserId = shallowRef(getMemberUserId())
 
 const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => onTabChange())
 
+/// 查询用户掉期协议签署表
+const { dataList: protocolList} = useRequest(queryMdUserSwapProtocol, {
+    params: {
+        userId: getUserId()
+    }
+})
+
+const status = (row: Model.TjmdTradeOrderDetailRsp) => {
+    return protocolList.value.find((e) => e.areauserid === row.userid)?.protocolstatus ?? 1
+}
+
 const { pageIndex, loading, run, pageCount } = useRequest(queryTjmdTradeOrderDetail, {
     params: {
         pagesize: 20,
@@ -90,6 +105,19 @@ const { pageIndex, loading, run, pageCount } = useRequest(queryTjmdTradeOrderDet
     }
 })
 
+const getDelistingButtonTitles = (tab: number, row: Model.TjmdTradeOrderDetailRsp) => {
+    switch (status(row)) {
+        case 1:
+            return '签署'
+        case 2:
+            return '待审核'
+        case 3:
+            return '待审核'
+        default:
+            return tab === BuyOrSell.Buy ? '卖出' : '买入'
+    }
+}
+
 /// 每隔 30 秒去刷新请求数据信息
 setTimeout(() => {
     // 获取买卖大厅数据
@@ -122,10 +150,22 @@ const onDelisting = (row: Model.TjmdTradeOrderDetailRsp) => {
         showToast('不能与自己成交')
         return
     }
-    openComponent('delisting')
+    switch (status(row)) {
+        case 4: /// 已签署
+            openComponent('delisting')
+            break;
+        case 1:  /// 未签署
+            /// 传对应的机构 ID
+            memberUserId.value = row.userid
+            openComponent('certification-next')
+            break; 
+        default: /// 其他状态
+            break;
+    }
 }
 
 const onListing = () => {
     openComponent('listing')
 }
+
 </script>

+ 10 - 2
src/packages/mobile/views/swap/list/Index.vue

@@ -46,6 +46,7 @@ import { queryQuoteGoodsList } from '@/services/api/swap'
 import { useFuturesStore, useUserStore } from '@/stores'
 import quoteSocket from '@/services/websocket/quote'
 import AppList from '@mobile/components/base/list/index.vue'
+import { showToast } from 'vant'
 
 defineProps({
     showBackButton: {
@@ -106,8 +107,15 @@ const columns: Model.TableColumn[] = [
 ]
 
 const rowClick = (row: Model.QuoteGoodsListRsp) => {
-    setGlobalUrlParams(row)
-    router.push({ name: 'swap-detail' })
+
+    const { hasauth } = userStore.userAccount
+    /// 这里要去判断是否已经实名认证
+    if (hasauth === 1) {
+        setGlobalUrlParams(row)
+        router.push({ name: 'swap-detail' })
+    } else {
+        showToast('未实名认证,请先去实名认证,如果已提交实名认证,请耐心等待审核通过!')
+    }    
 }
 
 onUnmounted(() => subscribe.stop())

+ 1 - 1
src/packages/tjmd/router/index.ts

@@ -118,7 +118,7 @@ const routes: Array<RouteRecordRaw> = [
         path: 'certification',
         name: 'account-certification',
         component: () => import('../views/account/certification/Index.vue'),
-      },
+      }
     ],
   },
   {

+ 7 - 37
src/packages/tjmd/views/account/certification/Index.vue

@@ -38,13 +38,13 @@
                 <Button type="danger" :loading="buttonLoading" @click="onSubmit" round block>提交实名认证</Button>
             </div>
         </template>
-        <component ref="componentRef" v-bind="{ formData }" :is="componentMap.get(componentId)" @closed="closeComponent"
+        <component ref="componentRef" v-bind="{ memberUserId: getMemberUserId() }" :is="componentMap.get(componentId)" @closed="closeComponent"
             v-if="componentId" />
     </app-view>
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, defineAsyncComponent, onMounted, computed } from 'vue'
+import { shallowRef, defineAsyncComponent, onMounted } from 'vue'
 import { CellGroup, Button, Field, Form, FormInstance, showFailToast, FieldRule, Image } from 'vant'
 import { fullloading, dialog } from '@/utils/vant';
 import { getFileUrl } from '@/filters';
@@ -61,7 +61,7 @@ import { useNavigation } from '@mobile/router/navigation'
 import { getUserId, getMemberUserId } from '@/services/methods/user'
 
 const componentMap = new Map<string, unknown>([
-    ['certification-next', defineAsyncComponent(() => import('./components/certification-next/Index.vue'))], // 爱签-实名认证第二步
+    ['certification-next', defineAsyncComponent(() => import('./components/certification-next/Index.vue'))], // 实名认证第二步
 ])
 
 const { router } = useNavigation()
@@ -73,27 +73,14 @@ const { componentRef, componentId, openComponent, closeComponent } = useComponen
     router.back()
 })
 
-const isReadonly = computed(() => userESignRecords.value.some((e) => e.templatetype === 1 && e.recordstatus === 3))
+const isReadonly = false//computed(() => userESignRecords.value.some((e) => e.recordstatus === 3))
 
 /// 查询记录
-const { loading: buttonLoading, dataList: userESignRecords, run: getTencentQianNotice } = useRequest(queryTencentUsereSignRecords, {
-    manual: true,
+const { loading: buttonLoading, dataList: userESignRecords } = useRequest(queryTencentUsereSignRecords, {
     params: {
         userId: getUserId(),
         memberUserId: getMemberUserId()
     },
-    onSuccess: (res) => {
-        const record = res.data.find((e) => e.templatetype === 1 && e.recordstatus === 3)
-        if (record) {
-            const { customername, cardnum, cardfrontphotourl, cardbackphotourl, mobile2, cardtypeid } =  userStore.userInfo
-            formData.username = customername
-            formData.cardnum = cardnum
-            formData.cardbackphotourl = cardfrontphotourl
-            formData.cardbackphotourl = cardbackphotourl
-            formData.cardtype = cardtypeid
-            formData.mobile = mobile2
-        }
-    },
     onError: (err) => {
         showFailToast(err)
     }
@@ -152,29 +139,12 @@ const onCheckCardNum = () => {
         }).then(() => {
             formSubmit().then(() => {
                 hideLoading()
-                /// 查询电子签合同
-                getTencentQianNotice()
                 dialog('提交请求成功').then(() => {
                     /// 进行下一步
                     openComponent('certification-next')
                 })
             }).catch((err) => {
-                switch (err) {
-                    case '100020':
-                        hideLoading('个人三要素信息验证失败', 'fail')
-                        break
-                    case '100021':
-                        hideLoading('用户已存在', 'fail')
-                        break
-                    case '100726':
-                        hideLoading('该条实名记录为核验记录,无法用于添加用户', 'fail')
-                        break
-                    case '100727':
-                        hideLoading('实名认证类型和添加用户类型不匹配', 'fail')
-                        break
-                    default:
-                        hideLoading(err, 'fail')
-                }
+                hideLoading(err, 'fail')
             })
         }).catch((err) => {
             hideLoading(err, 'fail')
@@ -183,7 +153,7 @@ const onCheckCardNum = () => {
 }
 
 const onSubmit = () => {
-    const isInclude = userESignRecords.value.some((e) => e.templatetype === 1 && e.recordstatus === 1)
+    const isInclude = userESignRecords.value.some((e) => e.recordstatus === 1)
     if (!userESignRecords.value.length || isInclude) {
         formRef.value?.submit()
     } else {

+ 42 - 53
src/packages/tjmd/views/account/certification/components/certification-next/Index.vue

@@ -2,24 +2,14 @@
     <app-modal direction="right" height="100%" v-model:show="showModal" :refresh="refresh">
         <app-view class="g-form">
             <template #header>
-                <app-navbar title="实名认证" @back="closed" />
+                <app-navbar title="合同签署" @back="closed" />
             </template>
             <div class="g-form__container">
                 <CellGroup inset>
-                    <Cell title="姓名" :value="formData.username" />
-                    <Cell title="手机号码" :value="formData.mobile" />
-                    <Cell title="证件类型" :value="getAQCertificateTypeListName(formData.cardtype ?? 1)" />
-                    <Cell title="证件号码" :value="formData.cardnum" />
-                    <Cell title="证件正面照片">
-                        <template #value>
-                            <Image fit="contain" :src="cardfrontphotourl" width="100" height="100" />
-                        </template>
-                    </Cell>
-                    <Cell title="证件反面照片">
-                        <template #value>
-                            <Image fit="contain" :src="cardbackphotourl" width="100" height="100" />
-                        </template>
-                    </Cell>
+                    <Cell title="姓名" :value="customername" />
+                    <Cell title="手机号码" :value="mobile2" />
+                    <Cell title="证件号码" :value="decryptAES(cardnum)" />
+                    <Cell title="签署机构" :value="memberUserId" />
                 </CellGroup>
                 <CellGroup inset>
                     <template v-for="(item, index) in dataList" :key="index">
@@ -28,51 +18,71 @@
                     </template>
                 </CellGroup>
             </div>
-            <template #footer>
-                <div class="g-form__footer inset">
-                    <Button type="danger" :disabled="dataList.some((e) => e.recordstatus !== 3)" @click="closed(true)" round
-                        block>提交认证</Button>
-                </div>
-            </template>
         </app-view>
     </app-modal>
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, computed, PropType } from 'vue'
-import { CellGroup, Button, Cell, showFailToast, Image, showToast } from 'vant'
+import { shallowRef } from 'vue'
+import { CellGroup, Cell, showFailToast, showToast } from 'vant'
 import { fullloading } from '@/utils/vant';
-import { getAQCertificateTypeListName } from "@/constants/account";
 import { useRequest } from '@/hooks/request'
-import { queryTencentUsereSignRecords } from '@/services/api/account';
+import { queryTencentUsereSignRecords, requestInitTencentESS } from '@/services/api/account';
 import { useRequestCreateFlowByTemplateDirectly } from '@/business/user/account';
 import plus from '@/utils/h5plus'
 import eventBus from '@/services/bus'
 import { getFileUrl } from '@/filters';
-import AppModal from '@/components/base/modal/index.vue'
-import { getUserId, getMemberUserId } from '@/services/methods/user'
+import { getUserId } from '@/services/methods/user'
 import { useUserStore } from '@/stores'
+import { decryptAES } from '@/services/websocket/package/crypto'
+
+const props = defineProps({
+    memberUserId: {
+        type: Number,
+        required: true,
+    }
+})
 
 const showModal = shallowRef(true)
 // 是否刷新父组件数据
 const refresh = shallowRef(false)
+/// userStore
+const userStore = useUserStore()
 /// 创建电子签合同
 const { createTemplate, templateFormData } = useRequestCreateFlowByTemplateDirectly()
 /// 电子签合同信息
 const dataList = shallowRef<Model.TencentUsereSignRecordsRsq[]>([])
+/// 用户信息
+const { customername, cardnum, mobile2 } =  userStore.userInfo
 /// 查询
 const { run } = useRequest(queryTencentUsereSignRecords, {
     params: {
         userId: getUserId(),
-        memberUserId: getMemberUserId()
+        memberUserId: props.memberUserId
     },
     onSuccess: (res) => {
         if (res.data.length != 0) {
             dataList.value = res.data
+        }  else {
+            /// 创建电子签合同
+            initTencentESS()
         }
     }
 })
 
+/// 创建电子签合同
+const { run: initTencentESS } = useRequest(requestInitTencentESS, {
+    manual: true,
+    params: {
+        userId: getUserId(),
+        memberUserId: props.memberUserId
+    },
+    onSuccess: () => {
+        /// 重新请求
+        run()
+    }
+})
+
 const iconName = (type: number) => {
     switch (type) {
         case 2: return 'info-o'
@@ -82,20 +92,6 @@ const iconName = (type: number) => {
     }
 }
 
-// 正面照
-const cardfrontphotourl = computed(() => {
-    const cardfrontphotourl = props.formData.cardfrontphotourl ?? ''
-    const image = cardfrontphotourl.split(',')[0]
-    return getFileUrl(image)
-})
-
-// 背面照
-const cardbackphotourl = computed(() => {
-    const cardbackphotourl = props.formData.cardbackphotourl ?? ''
-    const image = cardbackphotourl.split(',')[0]
-    return getFileUrl(image)
-})
-
 const openWebview = (url: string) => {
     const ua = window.navigator.userAgent.toLowerCase()
     if (ua.indexOf('micromessenger') !== -1) {
@@ -112,13 +108,6 @@ const openWebview = (url: string) => {
     }
 }
 
-const props = defineProps({
-    formData: {
-        type: Object as PropType<Model.AddAuthReq>,
-        required: true,
-    }
-})
-
 const signer = (item: Model.TencentUsereSignRecordsRsq) => {
     ///  如果是已签署
     if (item.recordstatus === 2) {
@@ -134,13 +123,13 @@ const signer = (item: Model.TencentUsereSignRecordsRsq) => {
             /// 个人信息
             if (userinfotype === 1) {
                 templateFormData.personInfo = {
-                    idCardNumber: props.formData.cardnum,
-                    mobile: props.formData.mobile,
-                    name: props.formData.username
+                    idCardNumber: decryptAES(cardnum),
+                    mobile: mobile2,
+                    name: customername
                 }
             } else {
                 templateFormData.organizationInfo = {
-                    name: props.formData.username
+                    name: customername
                 }
             }
             /// 创建合同

+ 5 - 0
src/packages/tjmd/views/mine/Index.vue

@@ -78,6 +78,11 @@
                         <Iconfont icon="g-icon-sign">签约账户</Iconfont>
                     </template>
                 </Cell>
+                <Cell is-link :to="{ name: 'bank-sign' }" v-if="authStatus === AuthStatus.Certified">
+                    <template #title>
+                        <Iconfont icon="g-icon-sign">合同签署</Iconfont>
+                    </template>
+                </Cell>
                 <Cell is-link :to="{ name: 'mine-profile' }">
                     <template #title>
                         <Iconfont icon="g-icon-profile">个人信息</Iconfont>

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

@@ -253,3 +253,14 @@ export function requestCreateFlowByTemplateDirectly(config: RequestConfig<Model.
         data: config.data,
     }, 'CreateFlowByTemplateDirectly')
 }
+
+/**
+ * 按用户 ID 和机构 ID 创建腾讯电子签业务信息
+ */
+export function requestInitTencentESS(config: RequestConfig<Model.InitTencentESSReq> = {}) {
+    return http.commonRequest<Model.InitTencentESSRsp>({
+        method: 'post',
+        url: '/Tencent/InitTencentESS',
+        data: config.data,
+    })
+}

+ 10 - 0
src/services/api/swap/index.ts

@@ -67,4 +67,14 @@ export function queryTjmdTransferApply(config: RequestConfig<Model.TjmdTransferA
         url: '/Tjmd/QueryTjmdTransferApply',
         params: config.data,
     })
+}
+
+/**
+ * 查询用户掉期协议签署表
+ */
+export function queryMdUserSwapProtocol(config: RequestConfig<Model.MdUserSwapProtocolReq> = {}) {
+    return http.commonRequest<Model.MdUserSwapProtocolRsp[]>({
+        url: '/User/QueryMdUserSwapProtocol',
+        params: config.data,
+    })
 }

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

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

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

@@ -441,6 +441,7 @@ declare namespace Model {
         name?: string
     }
 
+    /// 通过合同名和模板 id 直接发起签署流程 - 请求
     interface OrganizationInfo {
         /// 企业签署方工商营业执照上的企业名称
         name?: string
@@ -453,4 +454,18 @@ declare namespace Model {
         /// 合同签署小程序URL
         signUrl: string
     }
+
+    /// 按用户 ID 和机构 ID 创建腾讯电子签业务信息 - 请求
+    interface InitTencentESSReq {
+        /// 所属会员ID
+        memberUserId?: number
+        /// 用户ID
+        userId?: number
+    }
+
+    /// 按用户 ID 和机构 ID 创建腾讯电子签业务信息 - 回应
+    interface InitTencentESSRsp {
+        /// code
+        code: string
+    }
 }

+ 22 - 0
src/types/model/swap.d.ts

@@ -322,4 +322,26 @@ declare namespace Model {
         /// 市场ID
         marketid: number  
     }
+
+    /** 查询用户掉期协议签署表 请求 */
+    interface MdUserSwapProtocolReq {
+        /// 用户ID
+        userId?: number
+    }
+
+    /** 查询用户掉期协议签署表 响应 */
+    interface MdUserSwapProtocolRsp {
+        /// 掉期服务商ID
+        areauserid: number
+        /// 审核人
+        auditid: number  
+        /// 审核时间
+        audittime: string
+        /// 协议状态 - 1:未签署 2:签署中 3:已签署 4:已审核
+        protocolstatus: number
+        /// 更新时间
+        updatetime: string
+        /// 用户ID
+        userid: number
+    }
 }