Parcourir la source

完成认证服务页面重构

yuanmingze il y a 4 mois
Parent
commit
4882bf59ef

+ 347 - 0
src/pages-auth/certification-service/index.vue

@@ -0,0 +1,347 @@
+<template>
+  <view class="certification-service">
+    <scroll-view scroll-y class="certification-service__scroll">
+      <view class="info-card">
+        <view class="card-title">账户信息</view>
+
+        <view v-for="item in accountItems" :key="item.label" class="info-row">
+          <text class="info-row__label">{{ item.label }}</text>
+          <text class="info-row__value">{{ item.value || '-' }}</text>
+        </view>
+      </view>
+
+      <view class="info-card">
+        <view class="card-header">
+          <view class="card-title">身份信息</view>
+
+          <view class="card-actions">
+            <view :class="['status-tag', identityStatusClass]">
+              {{ identityStatusText }}
+            </view>
+
+            <button class="action-btn" :class="identityStatusClass" @click="handleGoIdentityAuth">
+              {{ isIdentityVerified ? '更新' : '编辑并认证' }}
+            </button>
+          </view>
+        </view>
+
+        <view class="id-card-image-list">
+          <view v-for="item in idCardImageList" :key="item.label" class="id-card-image">
+            <image v-if="item.url" class="id-card-image__img" :src="item.url" mode="aspectFill" />
+
+            <view v-else class="id-card-image__empty">
+              {{ item.label }}
+            </view>
+          </view>
+        </view>
+
+        <view v-for="item in identityItems" :key="item.label" class="info-row">
+          <text class="info-row__label">{{ item.label }}</text>
+          <text class="info-row__value">{{ item.value || '-' }}</text>
+        </view>
+      </view>
+
+      <view class="info-card">
+        <view class="card-header">
+          <view class="card-title">银行卡信息</view>
+
+          <view class="card-actions">
+            <view :class="['status-tag', bankStatusClass]">
+              {{ bankStatusText }}
+            </view>
+
+            <button class="action-btn" :class="bankStatusClass" @click="handleGoBankAuth">
+              {{ isBankVerified ? '更新' : '编辑并认证' }}
+            </button>
+          </view>
+        </view>
+
+        <view v-for="item in bankItems" :key="item.label" class="info-row">
+          <text class="info-row__label">{{ item.label }}</text>
+          <text class="info-row__value">{{ item.value || '-' }}</text>
+        </view>
+      </view>
+    </scroll-view>
+  </view>
+</template>
+
+<script setup lang="ts">
+import { computed, ref } from 'vue'
+
+import { onShow } from '@dcloudio/uni-app'
+
+import { getAuthInfoApi } from '@/services/modules/auth'
+import type { GetAuthInfoResponse } from '@/services/modules/auth/type'
+
+import { useUserStore } from '@/stores/modules/user'
+
+const AUTH_SUCCESS_STATUS = 1
+
+const IDENTITY_AUTH_URL = '/pages-sub-verify/auth/identity'
+const BANK_AUTH_URL = '/pages-sub-verify/auth/bank'
+
+const userStore = useUserStore()
+
+const authInfo = ref<GetAuthInfoResponse | null>(null)
+
+const currentUserInfo = computed(() => userStore.currentUserInfo)
+
+const idCardInfo = computed(() => authInfo.value?.idCardInfo ?? null)
+const faceAuthInfo = computed(() => authInfo.value?.faceAuthInfo ?? null)
+const bankAccountInfo = computed(() => authInfo.value?.bankAccountInfo ?? null)
+
+const isIdentityVerified = computed(() => faceAuthInfo.value?.authStatus === AUTH_SUCCESS_STATUS)
+const isBankVerified = computed(() => bankAccountInfo.value?.authStatus === AUTH_SUCCESS_STATUS)
+
+const identityStatusClass = computed(() =>
+  isIdentityVerified.value ? 'is-verified' : 'is-unverified'
+)
+const bankStatusClass = computed(() => (isBankVerified.value ? 'is-verified' : 'is-unverified'))
+
+const identityStatusText = computed(() => (isIdentityVerified.value ? '已认证' : '未认证'))
+const bankStatusText = computed(() => (isBankVerified.value ? '已认证' : '未认证'))
+
+const accountItems = computed(() => [
+  {
+    label: '姓名',
+    value: currentUserInfo.value?.realname ?? authInfo.value?.name ?? '',
+  },
+  {
+    label: '手机号码',
+    value: currentUserInfo.value?.phone ?? authInfo.value?.loginAuthInfo?.phone ?? '',
+  },
+])
+
+const identityItems = computed(() => [
+  {
+    label: '姓名',
+    value: idCardInfo.value?.name ?? authInfo.value?.name ?? '',
+  },
+  {
+    label: '身份证号',
+    value: idCardInfo.value?.idCardNumber ?? authInfo.value?.idCardNumber ?? '',
+  },
+])
+
+const bankItems = computed(() => [
+  {
+    label: '银行卡号',
+    value: bankAccountInfo.value?.bankCardNumber ?? '',
+  },
+  {
+    label: '开户行',
+    value: bankAccountInfo.value?.bankName ?? '',
+  },
+  {
+    label: '预留手机',
+    value: bankAccountInfo.value?.bankPhone ?? '',
+  },
+])
+
+const idCardImageList = computed(() => [
+  {
+    label: '身份证正面',
+    url: idCardInfo.value?.idCardImgFront ?? '',
+  },
+  {
+    label: '身份证反面',
+    url: idCardInfo.value?.idCardImgEnd ?? '',
+  },
+])
+
+const handleGoIdentityAuth = () => {
+  uni.navigateTo({
+    url: IDENTITY_AUTH_URL,
+  })
+}
+
+const handleGoBankAuth = () => {
+  if (!isIdentityVerified.value) {
+    uni.showToast({
+      title: '请先完成身份信息认证',
+      icon: 'none',
+      duration: 3000,
+    })
+    return
+  }
+
+  uni.navigateTo({
+    url: BANK_AUTH_URL,
+  })
+}
+
+const getAuthInfo = async () => {
+  try {
+    const res = await getAuthInfoApi()
+    authInfo.value = res?.data ?? null
+  } catch (error) {
+    authInfo.value = null
+
+    console.error('获取认证信息失败', error)
+
+    uni.showToast({
+      title: '获取认证信息失败',
+      icon: 'none',
+    })
+  }
+}
+
+onShow(() => {
+  getAuthInfo()
+})
+</script>
+
+<style lang="scss" scoped>
+.certification-service {
+  min-height: 100vh;
+  background: #f5f5f5;
+}
+
+.certification-service__scroll {
+  height: 100vh;
+  padding: 20rpx;
+  box-sizing: border-box;
+}
+
+.info-card {
+  margin-bottom: 24rpx;
+  padding: 0 32rpx;
+  overflow: hidden;
+  border-radius: 18rpx;
+  background: #ffffff;
+  box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.04);
+  box-sizing: border-box;
+}
+
+.card-title {
+  display: flex;
+  align-items: center;
+  min-height: 88rpx;
+  color: #333333;
+  font-size: 32rpx;
+  font-weight: 600;
+  line-height: 1.4;
+  border-bottom: 1rpx solid #eeeeee;
+}
+
+.card-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  min-height: 88rpx;
+  border-bottom: 1rpx solid #eeeeee;
+
+  .card-title {
+    min-height: auto;
+    border-bottom: none;
+  }
+}
+
+.card-actions {
+  display: flex;
+  align-items: center;
+  gap: 14rpx;
+  flex-shrink: 0;
+}
+
+.status-tag {
+  height: 42rpx;
+  padding: 0 16rpx;
+  border-radius: 8rpx;
+  font-size: 24rpx;
+  line-height: 42rpx;
+  white-space: nowrap;
+
+  &.is-verified {
+    background: #e8f5e9;
+    color: #4caf50;
+  }
+
+  &.is-unverified {
+    background: #fef0f0;
+    color: #f56c6c;
+  }
+}
+
+.action-btn {
+  height: 56rpx;
+  margin: 0;
+  padding: 0 28rpx;
+  border-radius: 28rpx;
+  background: #ffffff;
+  font-size: 26rpx;
+  line-height: 56rpx;
+
+  &::after {
+    border: none;
+  }
+
+  &.is-verified {
+    border: 1rpx solid #faad14;
+    color: #faad14;
+  }
+
+  &.is-unverified {
+    border: 1rpx solid #1890ff;
+    color: #1890ff;
+  }
+}
+
+.info-row {
+  display: flex;
+  align-items: center;
+  min-height: 96rpx;
+  border-bottom: 1rpx solid #eeeeee;
+
+  &:last-child {
+    border-bottom: none;
+  }
+}
+
+.info-row__label {
+  width: 200rpx;
+  flex-shrink: 0;
+  color: #666666;
+  font-size: 28rpx;
+}
+
+.info-row__value {
+  flex: 1;
+  color: #333333;
+  font-size: 28rpx;
+  line-height: 1.5;
+  text-align: right;
+  word-break: break-all;
+}
+
+.id-card-image-list {
+  display: grid;
+  grid-template-columns: repeat(2, minmax(0, 1fr));
+  gap: 24rpx;
+  padding: 24rpx 0;
+  border-bottom: 1rpx solid #eeeeee;
+}
+
+.id-card-image {
+  height: 210rpx;
+  overflow: hidden;
+  border: 1rpx solid #eeeeee;
+  border-radius: 12rpx;
+  background: #f7f7f7;
+  box-sizing: border-box;
+}
+
+.id-card-image__img {
+  width: 100%;
+  height: 100%;
+}
+
+.id-card-image__empty {
+  display: flex;
+  height: 100%;
+  align-items: center;
+  justify-content: center;
+  color: #999999;
+  font-size: 28rpx;
+}
+</style>

+ 12 - 0
src/pages.json

@@ -85,6 +85,18 @@
           }
         }
       ]
+    },
+    {
+      "root": "pages-auth",
+      "pages": [
+        {
+          "path": "certification-service/index",
+          "style": {
+            "navigationBarTitleText": "认证服务",
+            "navigationStyle": "default"
+          }
+        }
+      ]
     }
   ],
   "globalStyle": {

+ 1 - 1
src/pages/login/index.vue

@@ -86,7 +86,7 @@ import { onMounted, reactive, ref } from 'vue'
 import projectConfig from '@/config/presets'
 import { debounce } from '@/plugins/debounce'
 
-import { getAuthTokenApi, getMobileCodeApi } from '@/services/modules/auth'
+import { getAuthTokenApi, getMobileCodeApi } from '@/services/modules/login'
 
 import { useCodeCountdown } from '@/composables/useCodeCountdown'
 import { useFormValidator } from '@/composables/useFormValidator'

+ 14 - 6
src/pages/mine-page/index.vue

@@ -50,7 +50,7 @@
               </view>
 
               <view class="user-card-meta">
-                <text>{{ getRolesName(currentUserInfo?.roles) }}</text>
+                <text>{{ getRolesName(currentUserInfo?.roles || []) }}</text>
               </view>
             </view>
           </view>
@@ -59,7 +59,7 @@
     </view>
     <view class="mine-page-content">
       <view class="auth card">
-        <view class="auth-item">
+        <view class="auth-item" @click="navigateToAuth">
           <view class="auth-item-content">
             <image
               class="auth-item-icon"
@@ -73,7 +73,7 @@
           </view>
           <view class="auth-item-action">
             <text class="auth-item-action-text">去认证</text>
-            <wd-icon name="arrow-right" color="#3FA3F1" size="36rpx" />
+            <wd-icon name="right" color="#3FA3F1" size="36rpx" />
           </view>
         </view>
 
@@ -88,7 +88,7 @@
 
           <view class="auth-item-action">
             <text class="auth-item-action-text">去签约</text>
-            <wd-icon name="arrow-right" color="#3FA3F1" size="36rpx" />
+            <wd-icon name="right" color="#3FA3F1" size="36rpx" />
           </view>
         </view>
       </view>
@@ -100,7 +100,7 @@
           </view>
 
           <view class="menu-item-arrow">
-            <wd-icon name="arrow-right" color="#333333" size="32rpx" />
+            <wd-icon name="right" color="#333333" size="32rpx" />
           </view>
         </view>
       </view>
@@ -151,7 +151,7 @@ import { computed, ref } from 'vue'
 
 import { useUserStore } from '@/stores/modules/user'
 
-import { functionList, menuList, rolesList } from './mine.config.ts'
+import { functionList, menuList, rolesList } from './mine.config'
 
 const userStore = useUserStore()
 
@@ -193,6 +193,14 @@ const handleCompanyConfirm = (curr: { item: { name: string; color: string }; ind
   userStore.setCurrentUserInfoIndex(index)
 }
 
+const navigateToAuth = () => {
+  console.log('cqwe')
+
+  uni.navigateTo({
+    url: '/pages-auth/certification-service/index',
+  })
+}
+
 const handleLogoutClick = () => {
   uni.showModal({
     title: '提示',

+ 1 - 1
src/pages/reset-password/index.vue

@@ -66,7 +66,7 @@ import { reactive } from 'vue'
 
 import { debounce } from '@/plugins/debounce'
 
-import { getPwdCodeForNoAuthApi, updUserPwdApi } from '@/services/modules/auth/index'
+import { getPwdCodeForNoAuthApi, updUserPwdApi } from '@/services/modules/login/index'
 
 import { useCodeCountdown } from '@/composables/useCodeCountdown'
 import { useFormValidator } from '@/composables/useFormValidator'

+ 3 - 65
src/services/modules/auth/index.ts

@@ -1,68 +1,6 @@
 import http from '../../index'
-import type {
-  AuthTokenRequest,
-  CheckBlacklistRequest,
-  CheckBlacklistResponse,
-  LoginRequest,
-  UpdUserPwdRequest,
-} from './type'
-import type { UserInfoResponse } from './userInfo'
+import type { GetAuthInfoResponse } from './type'
 
-//  账号密码校验
-export const getAuthTokenApi = (data: AuthTokenRequest) => {
-  const passwordUrl = encodeURIComponent(data.password)
-  return http.postRaw(
-    `/auth/oauth/token?username=${data.username + '@mp'}&password=${passwordUrl}&grant_type=password&scope=server&mp=wechat`
-  )
-}
-
-// 登录
-export const getTokenBySmsApi = (data: LoginRequest) => {
-  return http.postRaw(
-    `/auth/mobile/token/sms?code=${data.code}&mobile=SMS@${data.username}&grant_type=mobile`,
-    {},
-    {
-      loading: true,
-      loadingText: '登录中...',
-    }
-  )
-}
-// 通过微信 code 获取用户信息
-export const getUserInfoByCodeApi = (wxCode: string, avatar?: string) => {
-  return http.get<UserInfoResponse>(`/admin/api/getUserInfoByCode?code=${wxCode}&avatar=${avatar}`)
-}
-
-//校验是否是黑名单
-
-export const checkBlacklistApi = (data: CheckBlacklistRequest) => {
-  return http.get<CheckBlacklistResponse>(`/admin/user/blacklist/check`, data)
-}
-
-export const getMobileCodeApi = (phone: string) => {
-  return http.get<boolean>(
-    `/admin/mobile/${phone}`,
-    {},
-    {
-      loading: true,
-      loadingText: '发送中...',
-    }
-  )
-}
-
-export const getPwdCodeForNoAuthApi = (username: string) => {
-  return http.get<boolean>(
-    `/admin/mobile/for-pwd-noauth?username=${username}`,
-    {},
-    {
-      loading: true,
-      loadingText: '发送中...',
-    }
-  )
-}
-
-export const updUserPwdApi = (data: UpdUserPwdRequest) => {
-  return http.post<boolean>('/admin/user/upd-for-app', data, {
-    loading: true,
-    loadingText: '发送中...',
-  })
+export const getAuthInfoApi = () => {
+  return http.get<GetAuthInfoResponse>(`/admin/api/member/auth/get-auth-info`)
 }

+ 33 - 21
src/services/modules/auth/type.d.ts

@@ -1,30 +1,42 @@
-export interface LoginRequest {
-  username: string
-  code: string
+export interface GetAuthInfoResponse {
+  idCardNumber: string
+  name: string
+  bankAccountInfo: BankAccountInfo | null
+  faceAuthInfo: FaceAuthInfo | null
+  idCardInfo: IdCardInfo | null
+  loginAuthInfo: LoginAuthInfo | null
 }
 
-export interface AuthTokenRequest {
-  username: string
-  password: string
-}
-export interface UpdUserPwdRequest {
-  username: string
-  code: string
-  password: string
+export interface BankAccountInfo {
+  authStatus: number
+  authTime: string
+  bankCardNumber: string
+  bankName: string
+  bankPhone: string
+  phoneStatus: number
 }
 
-export interface CheckBlacklistRequest {
-  phoneNumber: string
-  idCardNumber: string
+export interface FaceAuthInfo {
+  authStatus: number
+  authTime: string
+  expireTime: string
+  faceImg: string
+  faceSerialNo: string
 }
 
-export interface CheckBlacklistResponse {
-  idCardNumberStatus: boolean
-  phoneNumberStatus: boolean
+export interface IdCardInfo {
+  address: string
+  gender: string
+  idCardEndDate: string
+  idCardImgEnd: string
+  idCardImgFront: string
+  idCardNumber: string
+  idCardStartDate: string
+  name: string
 }
 
-export interface LoginActionResult<T = void> {
-  success: boolean
-  message?: string
-  data?: T
+export interface LoginAuthInfo {
+  authStatus: number
+  authTime: string
+  phone: string
 }

+ 68 - 0
src/services/modules/login/index.ts

@@ -0,0 +1,68 @@
+import http from '../../index'
+import type {
+  AuthTokenRequest,
+  CheckBlacklistRequest,
+  CheckBlacklistResponse,
+  LoginRequest,
+  UpdUserPwdRequest,
+} from './type'
+import type { UserInfoResponse } from './userInfo'
+
+//  账号密码校验
+export const getAuthTokenApi = (data: AuthTokenRequest) => {
+  const passwordUrl = encodeURIComponent(data.password)
+  return http.postRaw(
+    `/auth/oauth/token?username=${data.username + '@mp'}&password=${passwordUrl}&grant_type=password&scope=server&mp=wechat`
+  )
+}
+
+// 登录
+export const getTokenBySmsApi = (data: LoginRequest) => {
+  return http.postRaw(
+    `/auth/mobile/token/sms?code=${data.code}&mobile=SMS@${data.username}&grant_type=mobile`,
+    {},
+    {
+      loading: true,
+      loadingText: '登录中...',
+    }
+  )
+}
+// 通过微信 code 获取用户信息
+export const getUserInfoByCodeApi = (wxCode: string, avatar?: string) => {
+  return http.get<UserInfoResponse>(`/admin/api/getUserInfoByCode?code=${wxCode}&avatar=${avatar}`)
+}
+
+//校验是否是黑名单
+
+export const checkBlacklistApi = (data: CheckBlacklistRequest) => {
+  return http.get<CheckBlacklistResponse>(`/admin/user/blacklist/check`, data)
+}
+
+export const getMobileCodeApi = (phone: string) => {
+  return http.get<boolean>(
+    `/admin/mobile/${phone}`,
+    {},
+    {
+      loading: true,
+      loadingText: '发送中...',
+    }
+  )
+}
+
+export const getPwdCodeForNoAuthApi = (username: string) => {
+  return http.get<boolean>(
+    `/admin/mobile/for-pwd-noauth?username=${username}`,
+    {},
+    {
+      loading: true,
+      loadingText: '发送中...',
+    }
+  )
+}
+
+export const updUserPwdApi = (data: UpdUserPwdRequest) => {
+  return http.post<boolean>('/admin/user/upd-for-app', data, {
+    loading: true,
+    loadingText: '发送中...',
+  })
+}

+ 30 - 0
src/services/modules/login/type.d.ts

@@ -0,0 +1,30 @@
+export interface LoginRequest {
+  username: string
+  code: string
+}
+
+export interface AuthTokenRequest {
+  username: string
+  password: string
+}
+export interface UpdUserPwdRequest {
+  username: string
+  code: string
+  password: string
+}
+
+export interface CheckBlacklistRequest {
+  phoneNumber: string
+  idCardNumber: string
+}
+
+export interface CheckBlacklistResponse {
+  idCardNumberStatus: boolean
+  phoneNumberStatus: boolean
+}
+
+export interface LoginActionResult<T = void> {
+  success: boolean
+  message?: string
+  data?: T
+}

+ 0 - 0
src/services/modules/auth/userInfo.d.ts → src/services/modules/login/userInfo.d.ts


+ 6 - 6
src/services/modules/pointsPackageRecord/index.ts

@@ -1,18 +1,18 @@
 import http from '../../index'
 import type {
-  getUserScorePackageListRequst,
-  getUserScorePackageListResponse,
-  pkgWithdrawRequest,
+  GetUserScorePackageListRequst,
+  GetUserScorePackageListResponse,
+  PkgWithdrawRequest,
 } from './type'
 
-export const getUserScorePackageListApi = (params: getUserScorePackageListRequst) => {
-  return http.get<getUserScorePackageListResponse>(`/admin/api/getUserScorePackageList2`, params, {
+export const getUserScorePackageListApi = (params: GetUserScorePackageListRequst) => {
+  return http.get<GetUserScorePackageListResponse>(`/admin/api/getUserScorePackageList2`, params, {
     loading: true,
     loadingText: '加载中...',
   })
 }
 
-export const pkgWithdrawApi = (data: pkgWithdrawRequest) => {
+export const pkgWithdrawApi = (data: PkgWithdrawRequest) => {
   return http.post(
     `/admin/api/pkg/withdraw?packageStatusId=${data.packageStatusId}`,
     {},

+ 3 - 3
src/services/modules/pointsPackageRecord/type.d.ts

@@ -1,4 +1,4 @@
-export interface getUserScorePackageListRequst {
+export interface GetUserScorePackageListRequst {
   current: number
   size: number
   selType: 2
@@ -7,7 +7,7 @@ export interface getUserScorePackageListRequst {
   activeId: string
 }
 
-export interface getUserScorePackageListResponse {
+export interface GetUserScorePackageListResponse {
   current: number
   hitCount: boolean
   optimizeCountSql: boolean
@@ -53,6 +53,6 @@ export interface ScorePackageRecordItem {
   waitApprovalTaskNum: number
 }
 
-export interface pkgWithdrawRequest {
+export interface PkgWithdrawRequest {
   packageStatusId: string
 }

+ 2 - 2
src/services/modules/task/package/index.ts

@@ -1,12 +1,12 @@
 import http from '../../../index'
 import type {
   getUserScorePackageListRequest,
-  getUserScorePackageListResponse,
+  GetUserScorePackageListResponse,
   pickupPackageRequest,
 } from './type'
 
 export const getUserScorePackageListApi = (params: getUserScorePackageListRequest) => {
-  return http.get<getUserScorePackageListResponse>(`/admin/api/getUserScorePackageList2`, params, {
+  return http.get<GetUserScorePackageListResponse>(`/admin/api/getUserScorePackageList2`, params, {
     loading: true,
     loadingText: '加载中...',
   })

+ 1 - 1
src/services/modules/task/package/type.d.ts

@@ -6,7 +6,7 @@ export interface getUserScorePackageListRequest {
   packageName: string
 }
 
-export interface getUserScorePackageListResponse {
+export interface GetUserScorePackageListResponse {
   current: number
   size: number
   total: number

+ 3 - 3
src/stores/modules/user.ts

@@ -2,13 +2,13 @@ import { defineStore } from 'pinia'
 
 import { getWXLoginCode } from '@/lib/wechatService'
 
-import { checkBlacklistApi, getTokenBySmsApi, getUserInfoByCodeApi } from '@/services/modules/auth'
+import { checkBlacklistApi, getTokenBySmsApi, getUserInfoByCodeApi } from '@/services/modules/login'
 import type {
   CheckBlacklistRequest,
   LoginActionResult,
   LoginRequest,
-} from '@/services/modules/auth/type'
-import type { UserInfoItem } from '@/services/modules/auth/userInfo'
+} from '@/services/modules/login/type'
+import type { UserInfoItem } from '@/services/modules/login/userInfo'
 import { resetUnauthorizedHandled } from '@/services/request'
 
 import { pinia } from '@/stores/index'