zhb 11 месяцев назад
Родитель
Сommit
1fbbf55c5d

+ 8 - 9
src/App.vue

@@ -2,12 +2,7 @@
     <div class="wrap">
         <PageHeader :title="headerTitle" :show-back="!showBack" />
         <router-view v-slot="{ Component }" class="app body" :class="{ 'is-tab': routeIsTab }">
-            <transition
-                v-if="!globalLoading"
-                :name="transitionName"
-                @before-enter="handleBeforeEnter"
-                @after-enter="handleAfterEnter"
-            >
+            <transition v-if="!globalLoading" :name="transitionName" @before-enter="handleBeforeEnter" @after-enter="handleAfterEnter">
                 <keep-alive :include="cacheComponents">
                     <component :is="Component" />
                 </keep-alive>
@@ -40,7 +35,7 @@ defineOptions({
 })
 const { t } = useI18n()
 const { route, globalStore } = useGlobal()
-const { globalLoading, routerLoading, requestLoading, fullScreenLoading } = storeToRefs(globalStore)
+const { globalLoading, routerLoading, requestLoading, fullScreenLoading, theme } = storeToRefs(globalStore)
 // setTimeout(() => {
 //     globalStore.setGlobalLoading(false)
 // }, 200)
@@ -83,6 +78,11 @@ const headerTitle = computed(() => {
     key = slashToDash(key)
     return t(`${key}.title`) || ''
 })
+onMounted(() => {
+    console.log(theme, 12)
+
+    document.documentElement.classList.toggle('dark', theme.value === 'dark')
+})
 </script>
 
 <style scoped lang="scss">
@@ -93,7 +93,7 @@ const headerTitle = computed(() => {
     font-family: 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
 }
 .page {
-    padding: 0 20px 120px 20px;
+    padding: 0 16px 120px 16px;
     box-sizing: border-box;
     min-height: 100vh;
     background: var(--main-bg);
@@ -106,6 +106,5 @@ const headerTitle = computed(() => {
     z-index: 9999;
     background: rgba(0, 0, 0, 1);
     padding: 12px;
-    border-radius: 8px;
 }
 </style>

+ 1 - 1
src/api/user.ts

@@ -31,7 +31,7 @@ export const userApi = {
     },
     // 获取用户信息
     getUserSingle: () => {
-        return $api.post<UserInfo>('/custom/search/single')
+        return $api.post<UserInfo>('/ucard/api/merchant/user/single')
     },
     //退出登录
     logout: () => {

BIN
src/assets/images/logo.png


+ 29 - 1
src/assets/scss/global/global.scss

@@ -10,12 +10,41 @@
 
     // 兼容最小宽度
     --min-window: #{$vmMinWindow};
+    --main-bg: #fff;
+    --card-bg: #222;
+    --action-bg: #fff;
+    --main-yellow:  #EA002A;
+    --lable:  #454745;
+    --main-yellow-dark: rgb(15 120 71);
+    --white: #000;
+    --gray: #aaa;
+    --border: #868685;
+    --black: #fff;
+    --black1: #343434;
+    --font-size-10: 10px;
+    --font-size-12: 12px;
+    --font-size-13: 13px;
+    --font-size-14: 14px;
+    --font-size-15: 15px;
+    --font-size-16: 16px;
+    --font-size-18: 18px;
+    --font-size-20: 20px;
+    --font-size-22: 22px;
+    --font-size-24: 24px;
+    --font-size-26: 26px;
+    --font-size-28: 28px;
+    --font-size-32: 32px;
+    --font-size-36: 36px;
+    --font-size-40: 40px;
+}
+.dark{
     --main-bg: #181a1b;
     --card-bg: #222;
     --action-bg: #232323;
     --main-yellow:  rgb(6 255 139);
     --main-yellow-dark: rgb(15 120 71);
     --white: #fff;
+    --lable:  #aaa;
     --gray: #aaa;
     --border: #333;
     --black: #000;
@@ -152,7 +181,6 @@ body {
     align-items: center;
     padding: 16px 24px;
     background: rgba(0, 0, 0, 0.88);
-    border-radius: 12px;
     backdrop-filter: blur(4px);
     box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
     animation: fadeIn 0.2s ease-in-out;

+ 0 - 14
src/components.d.ts

@@ -13,13 +13,11 @@ declare module 'vue' {
     CustomTabbar: typeof import('./components/CustomTabbar.vue')['default']
     EmptyComponents: typeof import('./components/empty-components.vue')['default']
     EmptyState: typeof import('./components/EmptyState.vue')['default']
-    ImgList: typeof import('./components/img-list.vue')['default']
     JsxComponents: typeof import('./components/jsx-components.tsx')['default']
     PageHeader: typeof import('./components/PageHeader.vue')['default']
     RemitInput: typeof import('./components/RemitInput.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
-    SelectCard: typeof import('./views/select-card.vue')['default']
     ULoadmore: typeof import('./components/u-loadmore.vue')['default']
     VanButton: typeof import('vant/es')['Button']
     VanCalendar: typeof import('vant/es')['Calendar']
@@ -28,28 +26,16 @@ declare module 'vue' {
     VanCheckbox: typeof import('vant/es')['Checkbox']
     VanDatePicker: typeof import('vant/es')['DatePicker']
     VanDialog: typeof import('vant/es')['Dialog']
-    VanDropdownItem: typeof import('vant/es')['DropdownItem']
-    VanDropdownMenu: typeof import('vant/es')['DropdownMenu']
     VanField: typeof import('vant/es')['Field']
     VanForm: typeof import('vant/es')['Form']
-    VanGrid: typeof import('vant/es')['Grid']
-    VanGridItem: typeof import('vant/es')['GridItem']
     VanIcon: typeof import('vant/es')['Icon']
     VanImage: typeof import('vant/es')['Image']
     VanImagePreview: typeof import('vant/es')['ImagePreview']
-    VanList: typeof import('vant/es')['List']
     VanLoading: typeof import('vant/es')['Loading']
-    VanNavBar: typeof import('vant/es')['NavBar']
     VanPicker: typeof import('vant/es')['Picker']
     VanPopup: typeof import('vant/es')['Popup']
-    VanPullRefresh: typeof import('vant/es')['PullRefresh']
-    VanSkeleton: typeof import('vant/es')['Skeleton']
     VanSwipe: typeof import('vant/es')['Swipe']
     VanSwipeItem: typeof import('vant/es')['SwipeItem']
-    VanTab: typeof import('vant/es')['Tab']
-    VanTabbar: typeof import('vant/es')['Tabbar']
-    VanTabbarItem: typeof import('vant/es')['TabbarItem']
-    VanTabs: typeof import('vant/es')['Tabs']
     VanUploader: typeof import('vant/es')['Uploader']
     VirtualCard: typeof import('./components/VirtualCard.vue')['default']
   }

+ 1 - 1
src/components/CustomTabbar.vue

@@ -64,7 +64,7 @@
     right: 0;
     bottom: 0;
     height: 60px;
-    background: #181a1b;
+    background: var(--main-bg);
     border-radius: 18px 18px 0 0;
     display: flex;
     justify-content: space-around;

+ 42 - 25
src/components/PageHeader.vue

@@ -1,10 +1,13 @@
 <template>
-  <div class="page-header">
-    <div class="header">
-      <van-icon v-if="showBack" name="arrow-left" class="back-icon" @click="handleBack" />
-      <span>{{ title }}</span>
+    <div class="page-header">
+        <div class="header">
+            <span class="back" v-if="showBack">
+                <van-icon  name="down" class="back-icon" @click="handleBack" />
+            </span>
+
+            <span>{{ title }}</span>
+        </div>
     </div>
-  </div>
 </template>
 
 <script setup lang="ts">
@@ -14,34 +17,48 @@ import { Icon as VanIcon } from 'vant'
 const router = useRouter()
 
 defineProps<{
-  title: string
-  showBack?: boolean
+    title: string
+    showBack?: boolean
 }>()
 
 const handleBack = () => {
-  router.back()
+    router.back()
 }
 </script>
 
 <style scoped lang="scss">
 .page-header {
-  .header {
-    position: relative;
-    text-align: center;
-    font-size: var(--font-size-18);
-    color: var(--white);
-    font-weight: bold;
-    margin: 0 0 20px 0;
-    padding-top: 20px;
-
-    .back-icon {
-      position: absolute;
-      left: 16px;
-      top: 50%;
-      transform: translateY(-50%, -50%);
-      font-size: var(--font-size-20);
-      cursor: pointer;
+    .header {
+        position: relative;
+        text-align: left;
+        font-size: var(--font-size-22);
+        color: var(--white);
+        font-weight: 700;
+        margin: 10px 0 10px 16px;
+        height: 40px;
+        display: flex;
+        align-items: center;
+        line-height: 40px;
+
+
+
+        .back {
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            width: 36px;
+            height: 36px;
+            background: rgba(22, 51, 0, 0.08);
+            border-radius: 50%;
+            margin-right: 20px;
+        }
+
+        .back-icon {
+            line-height: 36px;
+            font-size: var(--font-size-20);
+            cursor: pointer;
+            transform: rotate(90deg);
+        }
     }
-  }
 }
 </style>

+ 41 - 30
src/components/RemitInput.vue

@@ -3,10 +3,11 @@
         <label class="form-label" v-if="label"
             ><span>{{ required ? '*' : '' }}</span> {{ label }}
         </label>
-        <template v-if="type === 'text'">
+        <template v-if="type === 'text' || type == 'password'">
             <van-field
                 class="form-input"
                 v-model="inputValueDoc"
+                :type="type"
                 :placeholder="placeholder"
                 :readonly="readonly"
                 :disabled="disabled"
@@ -18,12 +19,16 @@
                 @blur="handleBlur"
                 @focus="handleFocus"
                 @clear="handleClear"
-            />
+            >
+                <template #left-icon> <slot name="left-icon1"></slot> </template>
+                <template #right-icon> <slot name="right-icon1"></slot> </template>
+            </van-field>
         </template>
         <template v-if="type === 'number'">
             <van-field
                 class="form-input"
                 v-model="inputValueDoc"
+                type="number"
                 :placeholder="placeholder"
                 :readonly="readonly"
                 :disabled="disabled"
@@ -35,7 +40,8 @@
                 @blur="handleBlur"
                 @focus="handleFocus"
                 @clear="handleClear"
-            />
+                ><slot></slot
+            ></van-field>
         </template>
         <template v-if="type === 'select'">
             <van-field
@@ -50,7 +56,8 @@
                 is-link
                 @click="!disabled && (showPicker = true)"
                 @clear="handleClear"
-            />
+                ><slot></slot
+            ></van-field>
             <van-popup v-model:show="showPicker" destroy-on-close round position="bottom">
                 <van-field
                     v-if="showSearch"
@@ -115,14 +122,19 @@ const afterRead = async (file) => {
         message: '上传中...',
         forbidClick: true,
     })
-    const result = await uploadApi.uploadFile(file.file)
-    closeToast()
-    inputValueDoc.value = result.data
-    showToast('上传成功')
+    try {
+        const result = await uploadApi.uploadFile(file.file)
+        closeToast()
+        inputValueDoc.value = result.data
+        showToast('上传成功')
+        setTimeout(()=>{isUploading.value = false},100)
+    } catch (error) {
+        showToast('上传失败')
+    }
 }
 
 const props = defineProps({
-    type: { type: String, default: 'text', validator: (v) => ['text', 'number', 'select', 'date'].includes(v) },
+    type: { type: String, default: 'text', validator: (v) => ['text', 'password', 'number', 'select', 'date'].includes(v) },
     label: String,
     fkey: String,
     showSearch: { type: Boolean, default: false },
@@ -159,9 +171,7 @@ const filteredColumns = computed(() => {
 watch(
     () => inputValueDoc.value,
     (newVal) => {
-        if (!newVal) {
-            return
-        }
+        if (!newVal) return
         if (props.type === 'text' || props.type === 'number') {
             inputValue.value = newVal
             emit('update:value', newVal)
@@ -186,9 +196,7 @@ watch(
 watch(
     () => props.value,
     (newVal) => {
-        if (!newVal) {
-            return
-        }
+        if (!newVal || isUploading.value) return
         if (props.type === 'date') {
             inputValueDoc.value = newVal ? dayjs(newVal).format('YYYY-MM-DD') : ''
             inputValue.value = newVal
@@ -197,8 +205,8 @@ watch(
             inputValueDoc.value = matched?.text || ''
             inputValue.value = matched?.value || ''
             selectedValue.value = [matched?.value]
-        } else if(props.type === 'upload'){
-            uploader.value=[{url:props.value}]
+        } else if (props.type === 'upload') {
+            uploader.value = [{ url: props.value }]
             inputValueDoc.value = props.value
         } else {
             inputValueDoc.value = newVal
@@ -244,14 +252,16 @@ const onDateConfirm = (value) => {
 <style scoped lang="scss">
 .form-group {
     width: 100%;
-    margin-bottom: 18px;
+    margin-bottom: 8px;
 }
 
 .form-label {
-    color: #fff;
-    font-size: 15px;
-    margin-bottom: 8px;
-    display: block;
+    font-family: 'Inter';
+    font-style: normal;
+    font-size: var(--font-size-14);
+    line-height: 22px;
+    letter-spacing: 1px;
+    color: var(--lable);
     span {
         color: red;
     }
@@ -259,17 +269,14 @@ const onDateConfirm = (value) => {
 
 .form-input {
     width: 100%;
-    background: #181818 !important;
-    border: 1px solid var(--main-yellow) !important;
+    border: 1px solid var(--border) !important;
     border-radius: 10px !important;
-    color: #fff !important;
     font-size: 16px !important;
     margin-top: 4px;
 
     ::v-deep .van-field__control {
-        color: #fff !important;
         &::placeholder {
-            color: #bdbdbd !important;
+            color: var(--lable) !important;
         }
     }
 }
@@ -287,13 +294,17 @@ const onDateConfirm = (value) => {
     background: #181818 !important;
 }
 ::v-deep .van-field__right-icon {
-    color: var(--main-yellow) !important;
+    color: var(--black1) !important;
 }
 ::v-deep .van-field {
-    background: var(--action-bg);
+    background: transparent;
+    color: var(--white);
+}
+::v-deep .van-field__control {
+    color: var(--white);
 }
 ::v-deep .van-uploader__upload {
-    background: #181818;
+    /* background: #181818; */
 }
 ::v-deep .van-calendar {
     background: var(--action-bg);

+ 5 - 35
src/components/VirtualCard.vue

@@ -4,7 +4,7 @@
             <div class="steps-top">
                 <div class="step">
                     <div class="step-circle">1</div>
-                    <div class="step-label">上传KYC附件</div>
+                    <div class="step-label">选择卡片类型</div>
                 </div>
                 <div class="step-dash"></div>
                 <div class="step">
@@ -129,37 +129,8 @@ onMounted(() => {
 })
 </script>
 
-<style scoped>
-.apply-card-header {
-    font-size: 20px;
-    color: #fff;
-    font-weight: 600;
-    margin-bottom: 18px;
-}
-.apply-card-img {
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    margin-bottom: 18px;
-}
-.apply-card-visual {
-    position: relative;
-    width: 90px;
-    height: 60px;
-    background: transparent;
-    border-radius: 12px;
-    box-shadow: 0 2px 8px rgba(214, 255, 0, 0.1);
-}
-.chip {
-    position: absolute;
-    right: 12px;
-    top: 22px;
-    width: 22px;
-    height: 16px;
-    background: #eaeaea;
-    border-radius: 4px;
-    border: 1.5px solid #bbb;
-}
+<style scoped lang="scss">
+
 .apply-card-steps {
     width: 100%;
     margin-bottom: 52px;
@@ -187,7 +158,6 @@ onMounted(() => {
 .step-circle {
     width: 28px;
     height: 28px;
-    background: #232323;
     color: var(--main-yellow);
     border-radius: 50%;
     font-size: 14px;
@@ -212,7 +182,7 @@ onMounted(() => {
     top: -16px;
 }
 .step-label {
-    color: var(--main-yellow);
+    color: var(--white);
     font-size: 14px;
     font-weight: 500;
     text-align: center;
@@ -222,7 +192,7 @@ onMounted(() => {
     width: 90%;
     max-width: 320px;
     background: var(--main-yellow);
-    color: #232323;
+    color: var(--black);
     border: none;
     border-radius: 24px;
     font-size: 17px;

+ 6 - 5
src/i18n/locales/cn.ts

@@ -44,7 +44,7 @@ export default {
         logout: '确认退出登录吗?',
     },
     language: {
-        title: '语言设置',
+        title: 'Sell USDT',
         selectLang: '选择语言',
         cn: '中文简体',
         zh: '中文繁体',
@@ -101,10 +101,10 @@ export default {
     },
     'find-password': {
         title: '找回密码',
-        desc: '请上传签名照片',
-        input: '请输入验证码',
-        getCode: '获取验证码',
-        nextStep: '下一步',
+        desc: '签名照片',
+        nextStep: '提交',
+        success: '设置成功',
+        error: '设置失败'
     },
     'freeze-card': {
         title: '冻结卡片',
@@ -606,5 +606,6 @@ export default {
         "p31": "扩展字段",
         "p32": "取消",
         "p33": "提交",
+        'kycSuccess':'完善成功'
     }
 }

+ 1 - 0
src/stores/pinia.types.ts

@@ -8,4 +8,5 @@ export interface GlobalState {
     ISPRE: boolean
     ISPROD: boolean
     isPageSwitching: boolean
+    theme: string
 }

+ 6 - 0
src/stores/use-global-store.ts

@@ -11,8 +11,13 @@ const useStore = defineStore('globalStore', () => {
         ISPRE: import.meta.env.VITE_APP_ENV === 'pre-release',
         ISPROD: import.meta.env.VITE_APP_ENV === 'production',
         isPageSwitching: false,
+        // theme: 'light',
+        theme: 'dark',
     })
 
+    const setGlobalTheme = (payload: string) => {
+        state.theme = payload
+    }
     const setGlobalLoading = (payload: boolean) => {
         state.globalLoading = payload
     }
@@ -29,6 +34,7 @@ const useStore = defineStore('globalStore', () => {
     return {
         ...toRefs(state),
         setGlobalLoading,
+        setGlobalTheme,
         setRouterLoading,
         setRequestLoading,
         setFullScreenLoading,

+ 2 - 1
src/views/cards.vue

@@ -386,7 +386,8 @@ function goToFindPassword() {
     router.push({
         path: '/find/password',
         query: {
-            id: currentCard.value?.id,
+            cardNo: currentCard.value?.cardNo,
+            cardTypeId: currentCard.value?.cardTypeId,
         },
     })
 }

+ 1 - 1
src/views/eur.vue

@@ -10,7 +10,7 @@
                 <button class="action-btn" @click="goToGlobalRemit">{{ t('eur.globalRemit') }}</button>
             </div>
             <div class="balance-chart">
-                <img src="../assets/img/remit.png" alt="chart" class="chart-img" />
+                <!-- <img src="../assets/img/remit.png" alt="chart" class="chart-img" /> -->
             </div>
         </div>
         <div class="record-title">{{ t('eur.transactionRecord') }}</div>

+ 54 - 155
src/views/find-password.vue

@@ -1,183 +1,82 @@
 <template>
-    <div class="page find-password-page">
+    <div class="page">
         <div class="find-form">
-            <div class="upload-label">{{ t('find-password.desc') }}</div>
-            <div class="upload-box" @click="triggerFileInput">
-                <input ref="fileInput" type="file" accept="image/png, image/jpeg" style="display: none" @change="handleFileChange" />
-                <div v-if="!previewUrl" class="upload-placeholder">
-                    <span class="plus">+</span>
-                </div>
-                <img v-else :src="previewUrl" class="preview-img" />
+            <remit-input
+                v-model:value="kycForm.signaturePhoto"
+                type="upload"
+                fkey="signaturePhoto"
+                :label="t('find-password.desc')"
+                @change="handleChange"
+            />
+            <div class="find-button">
+                <van-button type="primary" block @click="handleNext1">{{ t('find-password.nextStep') }}</van-button>
             </div>
-            <div class="tip">{{ t('find-password.tip') }}</div>
-            <button class="confirm-btn" :disabled="!file" @click="handleConfirm">{{ t('find-password.nextStep') }}</button>
         </div>
     </div>
 </template>
 
 <script setup lang="ts">
-import { showToast } from 'vant'
+import { useRouter } from 'vue-router'
 import { useI18n } from 'vue-i18n'
-import { $Api } from '@/api'
-import { useRoute } from 'vue-router'
+import { showToast } from 'vant'
 import { ucardApi } from '@/api/ucard'
-import type { CardInfo } from '@/api/ucard'
-const { t } = useI18n()
+import useUserStore from '@/stores/use-user-store'
+const userStore = useUserStore()
+const userInfo = computed(() => userStore.userInfo)
 const route = useRoute()
-const { id } = route.query as { id: string }
-const cardInfo = ref<CardInfo | null>(null)
-const file = ref<File | null>(null)
-const previewUrl = ref('')
-const signaturePhoto = ref('')
-const fileInput = ref<HTMLInputElement | null>(null)
-function triggerFileInput() {
-    fileInput.value?.click()
-}
-const getCardInfo = async () => {
-    const res = await ucardApi.cardSingle({ id })
-    cardInfo.value = res.data
-}
-onMounted(() => {
-    getCardInfo()
+const { t } = useI18n()
+const router = useRouter()
+const kycForm = ref({
+    signaturePhoto: '',
+    data: '',
+    uniqueId: '',
 })
+const { cardNo, cardTypeId } = route.query as { cardNo: string; cardTypeId: string }
+const formData = ref<typeof kycForm.value>({ cardNo: cardNo, cardTypeId: cardTypeId } as any)
 
-function handleFileChange(e: Event) {
-    const target = e.target as HTMLInputElement
-    if (target.files && target.files[0]) {
-        const f = target.files[0]
-        if (!['image/png', 'image/jpeg'].includes(f.type)) {
-            showToast('仅支持PNG、JPG格式')
-            return
+const handleNext1 = async () => {
+    if (formData.value.signaturePhoto) {
+        formData.value.uniqueId = userInfo.value?.customInfo?.uniqueId
+        const res = await ucardApi.ucardResetPassword(formData.value as any)
+        if (res.code === 200) {
+            showToast(t('find-password.success'))
+            router.push('/cards')
+        } else {
+            showToast(t('find-password.error'))
         }
-        file.value = f
-        previewUrl.value = URL.createObjectURL(f)
     }
 }
-const isUploading = ref(false)
-async function handleConfirm() {
-    if (!file.value) {
-        showToast('请上传签名照片')
-        return
-    }
-    try {
-        isUploading.value = true
-        showLoadingToast({
-            message: '上传中...',
-            forbidClick: true,
-        })
-        const result = await $Api.upload.uploadFile(file.value)
-        closeToast()
-        showToast('上传成功')
-        signaturePhoto.value = result.data
-        try {
-            await $Api.ucard.ucardResetPassword({
-                signaturePhoto: result.data,
-                ...cardInfo.value,
-            })
-            showToast('重置密码成功')
-        } catch (error) {
-            showToast('重置密码失败,请重试')
-        }
-    } catch (error) {
-        closeToast()
-        showToast('上传失败,请重试')
-    } finally {
-        isUploading.value = false
-    }
+const handleChange = (value: any) => {
+    formData.value = { ...formData.value, [value.key]: value.value }
 }
 </script>
 
 <style scoped lang="scss">
-.find-password-page {
-    min-height: 100vh;
-    background: linear-gradient(135deg, #232323 0%, #2a2a2a 100%);
-    display: flex;
-    align-items: center;
-    justify-content: center;
-}
 .find-form {
     width: 100%;
-    max-width: 340px;
-    margin: 0 auto;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    background: rgba(24, 24, 24, 0.92);
+    max-width: 350px;
     border-radius: 20px;
-    box-shadow: 0 4px 32px 0 rgba(214, 255, 0, 0.08);
-    padding: 36px 20px 32px 20px;
-}
-.upload-label {
-    color: #fff;
-    font-size: 18px;
-    font-weight: 500;
-    margin-bottom: 22px;
-    letter-spacing: 1px;
-}
-.upload-box {
-    width: 140px;
-    height: 140px;
-    background: #181818;
-    border-radius: 16px;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    margin-bottom: 12px;
-    cursor: pointer;
-    border: 2px dashed var(--main-yellow);
-    transition: border-color 0.2s;
-    overflow: hidden;
-    box-shadow: 0 2px 12px 0 rgba(214, 255, 0, 0.04);
-    &:hover {
-        border-color: #fff200;
-    }
-}
-.upload-placeholder {
+    padding-top: 28px;
     display: flex;
     flex-direction: column;
-    align-items: center;
-    justify-content: center;
-    width: 100%;
-    height: 100%;
-}
-.plus {
-    font-size: 48px;
-    color: var(--main-yellow);
-    margin-bottom: 0;
-    font-weight: bold;
-}
-.tip {
-    color: #bdbdbd;
-    font-size: 13px;
-    margin-bottom: 18px;
-    margin-top: 2px;
-    text-align: center;
+    gap: 18px;
 }
-.preview-img {
-    width: 100%;
-    height: 100%;
-    object-fit: cover;
-    border-radius: 16px;
-    border: 1.5px solid var(--main-yellow);
-    box-shadow: 0 2px 8px 0 rgba(214, 255, 0, 0.08);
-}
-.confirm-btn {
-    width: 100%;
-    height: 48px;
-    background: linear-gradient(90deg, var(--main-yellow) 0%, var(--main-yellow-dark) 100%);
-    color: #232323;
-    border: none;
-    border-radius: 24px;
-    font-size: 20px;
-    font-weight: bold;
-    margin-top: 30px;
-    cursor: pointer;
-    box-shadow: 0 2px 12px 0 rgba(73, 247, 166, 0.1);
-    letter-spacing: 2px;
-    transition: background 0.2s, box-shadow 0.2s;
-}
-.confirm-btn:disabled {
-    opacity: 0.5;
-    cursor: not-allowed;
+.find-button {
+    margin-top: 18px;
+    ::v-deep {
+        .van-button {
+            height: 44px;
+            border-radius: 24px;
+            background: var(--main-yellow);
+            border: none;
+            color: #232323;
+            font-size: var(--font-size-16);
+            font-weight: bold;
+
+            &:active {
+                opacity: 0.9;
+            }
+        }
+    }
 }
 </style>

+ 25 - 63
src/views/improve-info.vue

@@ -1,6 +1,6 @@
 <template>
     <div class="page">
-        <div class="kyc-form" v-if="isShow">
+        <div class="kyc-form" v-if="isShow && countryOptions.length > 0">
             <remit-input
                 v-model:value="infoForm.lastName"
                 fkey="lastName"
@@ -28,6 +28,7 @@
             />
             <remit-input
                 v-model:value="infoForm.areaCode"
+                v-if="phoneCodes.length > 0"
                 fkey="areaCode"
                 :required="true"
                 type="select"
@@ -105,42 +106,6 @@
                 :label="t('improve-info.p30')"
                 @change="handleChange"
             />
-            <!-- <div class="form-item phone-input">
-                <div :class="{ 'phone-code': true, 'phone-code-active': form.phoneCode }">
-                    <van-field
-                        is-link
-                        readonly
-                        @click="showPicker = true"
-                        v-model="form.phoneCode"
-                        :placeholder="t('improve-info.phoneCode')"
-                        :rules="[{ required: true, message: t('improve-info.phoneCode') }]"
-                        autocomplete="off"
-                    />
-                    <van-popup v-model:show="showPicker" destroy-on-close round position="bottom">
-                        <van-picker
-                            v-model="form.phoneCode1"
-                            :visible-option-num="8"
-                            show-toolbar
-                            :title="t('improve-info.country')"
-                            :columns="[phoneCodes]"
-                            :cancel-button-text="t('common.cancel')"
-                            :confirm-button-text="t('common.confirm')"
-                            @cancel="showPicker = false"
-                            @confirm="onConfirm"
-                        />
-                    </van-popup>
-                </div>
-                <div class="phone-divider"></div>
-                <div class="phone-number">
-                    <van-field
-                        v-model="form.phone"
-                        :placeholder="t('improve-info.phone')"
-                        :rules="[{ required: true, message: t('improve-info.phone') }]"
-                        autocomplete="off"
-                    />
-                </div>
-            </div> -->
-
             <div class="kyc-button">
                 <van-button type="primary" block @click="kycSubmit">{{ t('improve-info.p33') }}</van-button>
             </div>
@@ -160,10 +125,11 @@ const userStore = useUserStore()
 const userInfo = computed(() => userStore.userInfo)
 const { t } = useI18n()
 const router = useRouter()
-
+const route = useRoute()
+const { type } = route.query as { type: string }
 const sexOptions = ref([
-    { text: t('improve-info.p15'), value: 1 },
-    { text: t('improve-info.p16'), value: 2 },
+    { text: t('improve-info.p15'), value: '1' },
+    { text: t('improve-info.p16'), value: '2' },
 ])
 const idTypeOptions = ref([
     { text: t('improve-info.p25'), value: 'EUROPEAN_ID' },
@@ -229,7 +195,6 @@ const getCityListForSelect = async (countryCode: string) => {
                 value: item.code,
             }))
             cityOptions.value = cityList
-            isShow.value = true
         }
     } catch (error) {
         cityOptions.value = []
@@ -254,18 +219,17 @@ const kycSubmit = async () => {
         return
     }
     let res
-
     if (formData.value.uniqueId) {
         res = await ucardApi.merchantUpdate(formData.value as any)
         if (res.code === 200) {
             showToast(t('improve-info.kycSuccess'))
+            router.push('/mine')
         }
     } else {
         res = await ucardApi.merchantRegister(formData.value as any)
         if (res.code === 200) {
             showToast(t('improve-info.kycSuccess'))
             userInfo.value.customInfo.uniqueId = res.data
-            console.log(userInfo.value)
             userStore.saveUserInfo(userInfo.value)
             router.push('/')
         }
@@ -307,16 +271,16 @@ const getInfoForm = () => {
     for (const key of fields) {
         data[key] = customInfo[key] ?? undefined
     }
-    for (const key of fields) {
-        data[key] = formDatas.value[key] ?? undefined
-        console.log(data[key],formDatas.value,112);
+    if (customInfo.uniqueId) {
+        for (const key of fields) {
+            data[key] = formDatas.value[key] ?? undefined
+        }
     }
-
-
     data.lastName = convertToPinyin(data.lastName)
     data.firstName = convertToPinyin(data.firstName)
     infoForm.value = { ...data }
     formData.value = { ...formData.value, ...data }
+    console.log(formData.value, 1222)
 }
 const getUserInfo = async () => {
     if (!userToken.value) {
@@ -325,26 +289,24 @@ const getUserInfo = async () => {
     }
     try {
         const res = await userApi.getUserSingle()
-
-        if (res.code === 200) {
-            console.log(res,1111);
+        if (res.code === 200 && res.data.uniqueId) {
             formDatas.value = res.data
             getInfoForm()
-            // userStore.saveUserInfo(res.data)
         }
-    } catch (error: any) {
-        showToast(error.message || '失败')
-    } finally {
-    }
+    } catch (error: any) {}
 }
-onMounted(() => {
-    getUserInfo()
-    // getInfoForm()
+onMounted(async () => {
+    if (type == '1') {
+        getUserInfo()
+    } else {
+        getInfoForm()
+    }
     isShow.value = false
-    getCountryListForSelect()
-    getCountry()
+    await getCountry()
+    await getCountryListForSelect()
     if (infoForm.value.nationality) {
-        getCityListForSelect(infoForm.value.nationality)
+        await getCityListForSelect(infoForm.value.nationality)
+        isShow.value = true
     } else {
         isShow.value = true
     }
@@ -380,7 +342,7 @@ onMounted(() => {
     width: 100%;
     max-width: 350px;
     border-radius: 20px;
-    padding: 28px 18px 18px 18px;
+    /* padding: 28px 18px 18px 18px; */
     display: flex;
     flex-direction: column;
     gap: 18px;

+ 1 - 1
src/views/kyc.vue

@@ -265,8 +265,8 @@ const handleNext1 = async () => {
 const kycSubmit = async () => {
     const res = await ucardApi.kycSubmit(formData.value as any)
     if (res.code === 200) {
-        // router.push('/kyc/success')
         showToast(t('kyc.kycSuccess'))
+        router.push('/cards')
     }
 }
 onMounted(() => {

+ 6 - 5
src/views/language.vue

@@ -24,17 +24,18 @@ function changeLang(langValue: string) {
 
 <style scoped lang="scss">
 .title {
-    font-size: var(--font-size-22);
+    font-size: var(--font-size-18);
+    color: var(--white);
     font-weight: bold;
-    margin-bottom: 24px;
+    margin: 24px 0;
 }
 .lang-item {
     background: var(--main-bg);
     border-radius: 14px;
     padding: 18px 18px;
-    font-size: var(--font-size-18);
+    font-size: var(--font-size-16);
     margin-bottom: 16px;
-    color: var(--main-yellow);
+    color: var(--white);
     display: flex;
     align-items: center;
     cursor: pointer;
@@ -48,6 +49,6 @@ function changeLang(langValue: string) {
 .check {
     margin-left: auto;
     color: var(--main-bg);
-    font-size: var(--font-size-18);
+    font-size: var(--font-size-16);
 }
 </style>

+ 54 - 65
src/views/login.vue

@@ -5,34 +5,51 @@
         </div>
         <div class="login-container">
             <div class="login-header">
-                <h2>欢迎登录</h2>
-                <p>请使用您的账号密码登录</p>
+                <img src="../assets/images/logo.png" alt="" srcset="" />
+                <!-- <h2>欢迎登录</h2>
+                <p>请使用您的账号密码登录</p> -->
             </div>
 
             <div class="login-form">
-                <div class="form-item">
-                    <van-field v-model="loginName" autocomplete="off" placeholder="请输入账号" :rules="[{ required: true, message: '请输入账号' }]">
-                        <template #left-icon>
-                            <van-icon name="user-o" />
-                        </template>
-                    </van-field>
-                </div>
-
-                <div class="form-item">
-                    <van-field v-model="password" :type="showPassword ? 'text' : 'password'" autocomplete="off" placeholder="请输入密码" :rules="[{ required: true, message: '请输入密码' }]">
-                        <template #left-icon>
-                            <van-icon name="lock" />
-                        </template>
-                        <template #right-icon>
-                            <van-icon name="eye-o" @click="showPassword = !showPassword" />
-                        </template>
-                    </van-field>
-                </div>
+                <remit-input
+                    v-model:value="loginName"
+                    type="text"
+                    fkey="loginName"
+                    label="邮箱"
+                    :clearable="true"
+                    @change="handleChange"
+                    placeholder="请输入邮箱"
+                    :rules="[{ required: true, message: '请输入邮箱' }]"
+                >
+                    <!-- <template #left-icon1> <van-icon name="user-o" /> </template> -->
+                </remit-input>
+                <remit-input
+                    v-model:value="password"
+                    :type="showPassword ? 'text' : 'password'"
+                    fkey="password"
+                    :clearable="true"
+                    label="密码"
+                    @change="handleChange"
+                    placeholder="请输入密码"
+                    :rules="[{ required: true, message: '请输入密码' }]"
+                >
+                    <!-- <template #left-icon1>
+                        <van-icon name="lock" />
+                    </template> -->
+                    <template #right-icon1>
+                        <van-icon name="eye-o" @click="showPassword = !showPassword" />
+                    </template>
+                </remit-input>
 
                 <div class="form-options">
                     <van-checkbox v-model="rememberPassword" shape="square" icon-size="16px"> 记住密码 </van-checkbox>
                     <span class="forgot-password" @click="handleForgotPassword">忘记密码?</span>
                 </div>
+                <div class="form-options">
+                    <van-checkbox v-model="rememberPassword1" shape="square" icon-size="16px">
+                        By registering, you accept our Privacy Policy and Terms of Service
+                    </van-checkbox>
+                </div>
 
                 <div class="login-button">
                     <van-button type="primary" block :loading="loading" @click="handleLogin"> 登录 </van-button>
@@ -64,6 +81,7 @@ const userStore = useUserStore()
 const loginName = ref('')
 const password = ref('')
 const rememberPassword = ref(false)
+const rememberPassword1 = ref(false)
 const loading = ref(false)
 const showPassword = ref(false)
 const handleLogin = async () => {
@@ -77,7 +95,7 @@ const handleLogin = async () => {
             password: password.value,
             rememberPassword: true,
         })
-    }else {
+    } else {
         userStore.saveAccountInfo({
             loginName: '',
             password: '',
@@ -87,7 +105,7 @@ const handleLogin = async () => {
     try {
         const res = await userApi.login({
             loginName: loginName.value,
-            password: password.value
+            password: password.value,
         })
         if (res.code === 200) {
             userToken.value = res.data
@@ -98,6 +116,14 @@ const handleLogin = async () => {
     } catch (error) {}
 }
 
+const handleChange = (value: any) => {
+    if (value.key == 'loginName') {
+        loginName.value = value.value
+    } else {
+        password.value = value.value
+    }
+}
+
 const getUserInfo = async () => {
     if (!userToken.value) {
         showToast('请先登录')
@@ -107,9 +133,9 @@ const getUserInfo = async () => {
         const res = await userApi.getUserInfo()
         userStore.saveUserInfo(res.data)
         if (res.code === 200) {
-            if(res.data.customInfo.uniqueId){
+            if (res.data.customInfo.uniqueId) {
                 router.push('/')
-            }else {
+            } else {
                 router.push('/improve/info')
             }
             showToast('登录成功')
@@ -174,7 +200,7 @@ onMounted(() => {
     }
 
     .login-header {
-        text-align: center;
+        /* text-align: center; */
         margin-bottom: 40px;
 
         h2 {
@@ -189,31 +215,6 @@ onMounted(() => {
         }
     }
 
-    .login-form {
-        .form-item {
-            margin-bottom: 20px;
-
-            .van-field {
-                background: var(--action-bg);
-                border-radius: 12px;
-                padding: 12px 16px;
-
-                .van-field__left-icon {
-                    margin-right: 12px;
-                    color: var(--main-yellow);
-                }
-
-                .van-field__control {
-                    color: var(--white);
-
-                    &::placeholder {
-                        color: var(--gray);
-                    }
-                }
-            }
-        }
-    }
-
     .form-options {
         display: flex;
         justify-content: space-between;
@@ -225,25 +226,12 @@ onMounted(() => {
                 color: var(--gray);
                 font-size: var(--font-size-14);
             }
-
-            .van-checkbox__icon {
-                border-color: var(--main-yellow);
-
-                &--checked {
-                    background-color: var(--main-yellow);
-                    border-color: var(--main-yellow);
-                }
-            }
         }
 
         .forgot-password {
             color: var(--main-yellow);
             font-size: var(--font-size-14);
         }
-        .van-checkbox__label {
-            color: var(--main-yellow);
-            font-size: var(--font-size-14);
-        }
     }
 
     .login-button {
@@ -341,7 +329,8 @@ onMounted(() => {
 }
 ::v-deep .van-checkbox__icon--checked .van-icon-success {
     border-color: var(--main-yellow) !important;
-    background: var(--main-yellow) !important;
-    color: var(--black) !important;
+    background: transparent !important;
+    color: var(--main-yellow) !important;
+    border-radius: 2px;
 }
 </style>

+ 3 - 2
src/views/mine.vue

@@ -27,7 +27,7 @@
                 <i class="i-mdi-lock-reset"></i>
                 <span>{{ t('language.i2') }}</span>
             </div>
-            <div class="group-item" @click="$router.push('/improve/info')">
+            <div class="group-item" @click="$router.push('/improve/info?type=1')">
                 <i class="i-mdi-shield-lock-outline"></i>
                 <span>{{ t('language.i3') }}</span>
             </div>
@@ -109,10 +109,11 @@ const handleLogout = async (action: string) => {
     margin-bottom: 6px;
 }
 .user-info .phone {
-    color: #333;
+    color: var(--black);
     font-size: var(--font-size-18);
     font-weight: bold;
 }
+
 .group {
     background: var(--action-bg);
     border-radius: 16px;

+ 26 - 77
src/views/reset-password.vue

@@ -2,21 +2,21 @@
     <div class="page">
         <div class="reset-container">
             <div class="reset-form">
-                <div class="form-item">
-                    <van-field
-                        v-model="form.email"
-                        autocomplete="off"
-                        placeholder="请输入邮箱"
-                        :rules="[
-                            { required: true, message: '请输入邮箱' },
-                            { pattern: config.Pattern.Email, message: '请输入正确的邮箱格式' },
-                        ]"
-                    >
-                        <template #left-icon>
-                            <van-icon name="envelop-o" />
-                        </template>
-                    </van-field>
-                </div>
+                <remit-input
+                    v-model:value="email"
+                    type="text"
+                    fkey="email"
+                    label="邮箱"
+                    :clearable="true"
+                    @change="handleChange"
+                    placeholder="请输入邮箱"
+                    :rules="[
+                        { required: true, message: '请输入邮箱' },
+                        { pattern: config.Pattern.Email, message: '请输入正确的邮箱格式' },
+                    ]"
+                >
+                    <template #left-icon1> <van-icon name="envelop-o" /> </template>
+                </remit-input>
                 <div class="reset-button">
                     <van-button type="primary" block :loading="loading" @click="handleReset"> {{ t('reset-password.reset') }} </van-button>
                 </div>
@@ -37,20 +37,20 @@ import config from '@/config'
 const { t } = useI18n()
 const router = useRouter()
 const loading = ref(false)
-const form = ref({ email: '' })
+const email = ref('')
 const handleReset = async () => {
-    if (!form.value.email) {
+    if (!email.value) {
         showToast(t('reset-password.emailRequired'))
         return
     }
-    if (!config.Pattern.Email.test(form.value.email)) {
+    if (!config.Pattern.Email.test(email.value)) {
         showToast(t('reset-password.emailError'))
         return
     }
 
     loading.value = true
     try {
-        const res = await userApi.updatePassword(form.value)
+        const res = await userApi.updatePassword({ email: email.value })
         showToast(res.msg)
         router.push('/login')
     } catch (error: any) {
@@ -59,6 +59,12 @@ const handleReset = async () => {
         loading.value = false
     }
 }
+const handleChange = (value: any) => {
+    if (value.key == 'email') {
+        email.value = value.value
+    }
+}
+
 const handleLogin = () => {
     router.push('/login')
 }
@@ -66,64 +72,7 @@ const handleLogin = () => {
 
 <style scoped lang="scss">
 .reset-container {
-    padding: 40px 20px;
-}
-
-.reset-header {
-    text-align: center;
-    margin-bottom: 40px;
-
-    h2 {
-        font-size: var(--font-size-24);
-        color: var(--main-yellow);
-        margin-bottom: 8px;
-    }
-
-    p {
-        font-size: var(--font-size-14);
-        color: var(--gray);
-    }
-}
-
-.reset-form {
-    .form-item {
-        margin-bottom: 20px;
-
-        .van-field {
-            background: var(--action-bg);
-            border-radius: 12px;
-            padding: 12px 16px;
-
-            :deep(.van-field__left-icon) {
-                margin-right: 12px;
-                color: var(--main-yellow);
-            }
-
-            :deep(.van-field__control) {
-                color: var(--white);
-
-                &::placeholder {
-                    color: var(--gray);
-                }
-            }
-
-            .van-field__button {
-                .van-button {
-                    height: 32px;
-                    padding: 0 12px;
-                    background: var(--main-yellow);
-                    border: none;
-                    color: var(--black);
-                    font-size: var(--font-size-14);
-                    border-radius: 8px;
-
-                    :deep(&--disabled) {
-                        opacity: 0.5;
-                    }
-                }
-            }
-        }
-    }
+    padding: 40px 0;
 }
 
 .reset-button {

+ 1 - 3
src/views/select-card.vue

@@ -93,12 +93,10 @@ onMounted(() => {
 ::v-deep {
     .van-swipe__track {
         width: 100% !important;
-        background: linear-gradient(145deg, #1a1a1a, #181818);
     }
 }
 .select-card-content {
     min-height: 100vh;
-    background: #111;
     color: #fff;
     display: flex;
     flex-direction: column;
@@ -144,7 +142,6 @@ onMounted(() => {
 
 .card-box {
     flex: 0 0 80%;
-    background: linear-gradient(145deg, #1a1a1a, #181818);
     border: 2px solid var(--main-yellow);
     border-radius: 20px;
     padding: 28px 14px;
@@ -246,6 +243,7 @@ onMounted(() => {
 .label {
     width: 160px;
     line-height: 1.5;
+
 }
 
 .card-list li:hover {