ソースを参照

Merge branch 'master' of http://git.izouma.com/xiongzhu/paimaide

panhui 3 年 前
コミット
0e000c00a3

+ 1 - 1
android/app/build.gradle

@@ -6,7 +6,7 @@ android {
         applicationId "com.bigauction.mobile"
         minSdkVersion rootProject.ext.minSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
-        versionCode 29
+        versionCode 36
         versionName "1.0.0"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         aaptOptions {

BIN
android/app/src/main/assets/cdvasset.manifest


+ 2 - 2
ios/App/App.xcodeproj/project.pbxproj

@@ -352,7 +352,7 @@
 				CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO;
 				CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 29;
+				CURRENT_PROJECT_VERSION = 36;
 				DEFINES_MODULE = NO;
 				DEVELOPMENT_TEAM = 72P5Y6N578;
 				INFOPLIST_FILE = App/Info.plist;
@@ -377,7 +377,7 @@
 				CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO;
 				CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 29;
+				CURRENT_PROJECT_VERSION = 36;
 				DEFINES_MODULE = NO;
 				DEVELOPMENT_TEAM = 72P5Y6N578;
 				INFOPLIST_FILE = App/Info.plist;

+ 168 - 2
src/App.vue

@@ -4,13 +4,39 @@
             <ion-router-outlet />
         </ion-app>
     </vant-config-provider>
-    <!-- <img id="btn-customer" src="@/assets/icon_custumer.png" @click="onClick" /> -->
+    <img id="btn-customer" src="@/assets/icon_custumer.png" @click="customer" />
+    <div class="customer-modal">
+        <transition name="fade">
+            <div class="dim" @click="showCustmer = false" v-if="showCustmer"></div>
+        </transition>
+        <transition name="popup">
+            <div class="modal-content" v-if="showCustmer">
+                <div class="head">
+                    <div class="text">{{ $t('common.customerService') }}</div>
+                    <div class="icon" @click="showCustmer = false">
+                        <ion-icon :icon="closeOutline"></ion-icon>
+                    </div>
+                </div>
+                <div class="item" v-for="(item, i) in customers" :key="i">
+                    <img class="bg" src="@/assets/bg_customer.png" />
+                    <div class="item-content">
+                        <img src="@/assets/icon_customer.png" class="icon" />
+                        <div class="info" @click="copyText(item.phone)">
+                            <div class="name">{{ $t('common.customerService') }}</div>
+                            <div class="num">WhatsApp: {{ item.phone }}</div>
+                        </div>
+                        <div class="btn-open" @click="open(item.phone)">{{ $t('common.open') }}</div>
+                    </div>
+                </div>
+            </div>
+        </transition>
+    </div>
 </template>
 
 <script setup>
 import { ConfigProvider as VantConfigProvider, showConfirmDialog } from 'vant'
 import { useBackButton, useIonRouter } from '@ionic/vue'
-import { onMounted, onBeforeUnmount } from 'vue'
+import { onMounted, onBeforeUnmount, ref } from 'vue'
 import { useRoute } from 'vue-router'
 import { useSystemStore } from './stores/system'
 import { App } from '@capacitor/app'
@@ -18,11 +44,18 @@ import { useSettingsStore } from '@/stores/settings'
 import { useI18n } from 'vue-i18n'
 import { emitter } from '@/utils/eventBus'
 import taost from '@/utils/toast'
+import { http } from '@/plugins/http'
+import { closeOutline } from 'ionicons/icons'
+import { Clipboard as NativeClipboard } from '@capacitor/clipboard'
+import { Capacitor } from '@capacitor/core'
+import { useClipboard } from '@vueuse/core'
+import { AppLauncher } from '@capacitor/app-launcher'
 
 const store = useSettingsStore()
 const { t } = useI18n()
 const ionRouter = useIonRouter()
 const route = useRoute()
+const customers = ref([])
 
 const promptLogin = async () => {
     const confirm = await showConfirmDialog({
@@ -33,7 +66,13 @@ const promptLogin = async () => {
         ionRouter.push({ name: 'login' })
     }
 }
+let ts = 0
 const promptExit = () => {
+    if (new Date().getTime() - ts < 2000) {
+        App.exitApp()
+        return
+    }
+    ts = new Date().getTime()
     taost(t('common.exitApp'))
 }
 useBackButton(-1, () => {
@@ -46,10 +85,43 @@ useBackButton(-1, () => {
 onMounted(() => {
     useSystemStore().getSysConfigs()
     emitter.on('promptLogin', promptLogin)
+    http.get('/sysConfig/get/CUSTOMER_SERVICE').then(res => {
+        customers.value = res.value
+            .replace(/:/g, ':')
+            .replace(/,/g, ',')
+            .split(',')
+            .map(i => {
+                if (i.includes(':')) {
+                    const [name, phone] = i.split(':')
+                    return { name, phone }
+                } else {
+                    return { name: t('common.customerService'), phone: i }
+                }
+            })
+    })
 })
 onBeforeUnmount(() => {
     emitter.off('promptLogin', promptLogin)
 })
+const showCustmer = ref(false)
+function customer() {
+    showCustmer.value = true
+}
+
+const { copy } = useClipboard({ legacy: true })
+async function copyText(text) {
+    if (Capacitor.isNativePlatform()) {
+        await NativeClipboard.write({
+            string: text
+        })
+    } else {
+        copy(text)
+    }
+    taost(t('common.copied'))
+}
+async function open(phone) {
+    await AppLauncher.openUrl({ url: `whatsapp://send?phone=${phone}` })
+}
 </script>
 <style lang="less" scoped>
 .consult {
@@ -82,4 +154,98 @@ onBeforeUnmount(() => {
     height: 48px;
     bottom: calc(var(--ion-safe-area-bottom) + 68px);
 }
+
+.customer-modal {
+    position: absolute;
+    height: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    .dim {
+        position: fixed;
+        bottom: 0;
+        top: 0;
+        left: 0;
+        right: 0;
+        background-color: rgba(0, 0, 0, 0.5);
+    }
+    .modal-content {
+        position: fixed;
+        bottom: 0;
+        left: 0;
+        right: 0;
+        background: var(--ion-background-color);
+        border-radius: 16px 16px 0px 0px;
+        padding-bottom: env(safe-area-inset-bottom, 20px);
+        .head {
+            height: 60px;
+            .f();
+            color: #ffffff;
+            font-size: 16px;
+            .text {
+                flex-grow: 1;
+                font-weight: bold;
+                margin-left: 16px;
+            }
+            .icon {
+                width: 38px;
+                height: 38px;
+                margin-right: 8px;
+                .f();
+                justify-content: center;
+            }
+        }
+        .item {
+            position: relative;
+            margin: 0 16px 10px 16px;
+            .f();
+            .bg {
+                width: 100%;
+                height: auto;
+            }
+            .item-content {
+                position: absolute;
+                top: 0;
+                left: 0;
+                right: 0;
+                bottom: 0;
+                .f();
+                padding-left: 18px;
+                .icon {
+                    width: 40px;
+                    height: 40px;
+                }
+            }
+            .info {
+                .f-col();
+                flex: 1 1 0;
+                height: 40px;
+                justify-content: space-around;
+                margin-left: 10px;
+
+                .name {
+                    color: #121325;
+                    font-weight: bold;
+                    font-size: 14px;
+                }
+                .num {
+                    color: #386459;
+                    font-size: 12px;
+                }
+            }
+            .btn-open {
+                width: 60px;
+                height: 24px;
+                background: #121325;
+                border-radius: 12px;
+                margin-right: 18px;
+                font-size: 12px;
+                color: #ffffff;
+                font-weight: bold;
+                .f();
+                justify-content: center;
+            }
+        }
+    }
+}
 </style>

BIN
src/assets/bg_customer.png


BIN
src/assets/icon_customer.png


+ 1 - 1
src/components/TutorialModal.vue

@@ -42,7 +42,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, defineExpose } from 'vue'
+import { ref, onMounted } from 'vue'
 import {
     createAnimation,
     IonButtons,

+ 279 - 262
src/locales/en.json

@@ -1,185 +1,92 @@
 {
-  "balance": {
-    "availableWidthdrawAmount": "Amount that can be withdrawn",
-    "balance": "Account Balance",
-    "chooseAmount": "select amount",
-    "confirmWithdraw": "Confirm withdrawal",
-    "inputCustomAmount": "Please enter a custom amount",
-    "realReceipt": "Actual account",
-    "recharge": "recharge",
-    "record": {
-      "commission": "commission",
-      "pay": "to pay",
-      "receipt": "collect money",
-      "recharge": "recharge",
-      "withdraw": "withdraw"
+    "balance": {
+        "availableWidthdrawAmount": "Amount that can be withdrawn",
+        "balance": "Account Balance",
+        "chooseAmount": "select amount",
+        "confirmWithdraw": "Confirm withdrawal",
+        "inputCustomAmount": "Please enter a custom amount",
+        "realReceipt": "Actual account",
+        "recharge": "recharge",
+        "record": {
+            "commission": "commission",
+            "pay": "to pay",
+            "receipt": "collect money",
+            "recharge": "recharge",
+            "withdraw": "withdraw"
+        },
+        "symbol": "$",
+        "totalWithdraw": "Cumulative withdrawal",
+        "unit": "PHP",
+        "withdraw": "withdraw",
+        "withdrawAmount": "Withdrawal Amount",
+        "withdrawAmountError": "Please enter the correct withdrawal amount",
+        "withdrawFee": "Withdrawal fee",
+        "withdrawFeeTip0": "Note: 1/3 of the total transaction fee for the purchase is",
+        "withdrawFeeTip1": ", the excess handling fee",
+        "withdrawInputTip": "Please enter the withdrawal amount",
+        "withdrawModalTitle": "Apply for withdrawal",
+        "withdrawSuccess": "Successful withdrawal",
+        "withdrawing": "Withdrawing",
+        "rechargeMax": "The maximum recharge amount is {value}",
+        "rechargeMin": "The minimum recharge amount is {value}"
     },
-    "symbol": "$",
-    "totalWithdraw": "Cumulative withdrawal",
-    "unit": "PHP",
-    "withdraw": "withdraw",
-    "withdrawAmount": "Withdrawal Amount",
-    "withdrawAmountError": "Please enter the correct withdrawal amount",
-    "withdrawFee": "Withdrawal fee",
-    "withdrawFeeTip0": "Note: 1/3 of the total transaction fee for the purchase is",
-    "withdrawFeeTip1": ", the excess handling fee",
-    "withdrawInputTip": "Please enter the withdrawal amount",
-    "withdrawModalTitle": "Apply for withdrawal",
-    "withdrawSuccess": "Successful withdrawal",
-    "withdrawing": "Withdrawing",
-    "rechargeMax": "The maximum recharge amount is {value}",
-    "rechargeMin": "The minimum recharge amount is {value}"
-  },
-  "cancel": "Cancel",
-  "common": {
-    "alert": "hint",
     "cancel": "Cancel",
-    "confirm": "Sure",
-    "eula": "Platform",
-    "guide": "Tutorial",
-    "home": "Home",
-    "loadFinish": "download finished",
-    "loading": "Loading",
-    "mine": "Mine",
-    "more": "More",
-    "news": "News",
-    "pullRefresh": "Pull down to refresh",
-    "rank": "leaderboard",
-    "register": "register",
-    "updateSuccess": "update completed",
-    "profit": "Commission",
-    "noRecords": "No records",
-    "notAvailable": "Not available",
-    "wait": "stay tuned",
-    "save": "Save",
-    "saving": "Saving",
-    "saveSuccess": "Saved successfully",
-    "saveFail": "Save failed",
-    "exitApp": "Press again to exit the app",
-    "close": "close",
-    "saveFailed": "save failed",
-    "skip": "Exit"
-  },
-  "delegate": {
-    "tip": "The consignment sale has not started yet, it will start today at ${time}",
-    "title": "Consignment",
-    "increase": "mark up",
-    "originalPrice": "original price",
-    "payServiceCharge": "pay processing fees",
-    "sellPrice": "selling price",
-    "tip1": "Note: entrusting the platform to sell services, the maximum price of the product can be increased by {riseRatePercent}% each time, and the platform will charge {serviceCharge}% of the custody service fee"
-  },
-  "distribution": {
-    "commission": "commission",
-    "joinTeamAt": "time to join the team",
-    "myInvitor": "my recommender",
-    "myProfit": "Income",
-    "orderNum": "number of order",
-    "profitDetails": "Revenue Details",
-    "qrCode": "my promo code",
-    "teamNum": "Team size",
-    "totalProfit": "Total revenue",
-    "viewDetail": "view details",
-    "viewTeam": "view team",
-    "saveImg": "save Picture",
-    "empty": "no yet",
-    "invite": "To invite"
-  },
-  "home": {
-    "all": "All"
-  },
-  "login": "Log in",
-  "loginPage": {
-    "agreement": "User Agreement",
-    "codePla": "please enter verification code",
-    "goRegister": "Sign up now",
-    "invitorPla": "Invitation code (optional)",
-    "isRead": "have read and agreed",
-    "loginByCode": "Verification code login",
-    "loginNow": "Already have an account, log in now",
-    "loginPwd": "password login",
-    "loginSuceess": "login successful",
-    "noAcount": "No account yet?",
-    "noAgree": "Please read and agree to the registration agreement",
-    "phone": "phone number",
-    "phoneError": "Wrong format of phone number",
-    "phonePla": "Please enter phone number",
-    "username": "Username",
-    "enterUsername": "Enter your username",
-    "psd": "password",
-    "psdAgainError": "The two passwords entered are inconsistent",
-    "psdAgainPla": "please enter password again",
-    "psdPla": "please enter password",
-    "register": "Register an account",
-    "registerSuccess": "registration success",
-    "sendCode": "Send code",
-    "sended": "Sented",
-    "psdEorror": "Wrong format of password",
-    "nameError": "Account length 6-20, can only contain numbers, letters and underscores, not pure numbers"
-  },
-  "mine": {
-    "address": "Address",
-    "avatar": "Avatar",
-    "bankCard": "Bank Account",
-    "bindPhone": "Bind Phone",
-    "female": "Female",
-    "logout": "sign out",
-    "male": "male",
-    "newProfit": "new income",
-    "nickname": "Nick Name",
-    "noBind": "Not added",
-    "noLogin": "not logged in",
-    "noSetting": "not set",
-    "settings": "Settings",
-    "sex": "Gender",
-    "user": "User",
-    "common": "Common Functions",
-    "nickPlac": "Please enter a nickname",
-    "sure": "Confirm the changes"
-  },
-  "news": {
-    "newsNull": "There is no news~"
-  },
-  "order": {
-    "buyNow": "Buy Now",
-    "createSuccess": "Order successfully created",
-    "createdAt": "order time",
-    "detail": "order details",
-    "id": "order number",
-    "my": "My Order",
-    "payInfo": "Payment Information",
-    "payMethod": "payment method",
-    "payMethodName": {
-      "balance": "balance payment"
+    "common": {
+        "alert": "hint",
+        "cancel": "Cancel",
+        "confirm": "Sure",
+        "eula": "Platform",
+        "guide": "Tutorial",
+        "home": "Home",
+        "loadFinish": "download finished",
+        "loading": "Loading",
+        "mine": "Mine",
+        "more": "More",
+        "news": "News",
+        "pullRefresh": "Pull down to refresh",
+        "rank": "leaderboard",
+        "register": "register",
+        "updateSuccess": "update completed",
+        "profit": "Commission",
+        "noRecords": "No records",
+        "notAvailable": "Not available",
+        "wait": "stay tuned",
+        "save": "Save",
+        "saving": "Saving",
+        "saveSuccess": "Saved successfully",
+        "saveFail": "Save failed",
+        "exitApp": "Press again to exit the app",
+        "close": "close",
+        "saveFailed": "save failed",
+        "skip": "Exit",
+        "customerService": "Customer Service",
+        "open": "Open",
+        "copied": "Copied"
     },
-    "payNow": "pay immediately",
-    "processing": "Processing",
-    "status": {
-      "ALL": "all",
-      "CANCELED": "Cancelled",
-      "CONFIRMED": "For Sale",
-      "NOT_CONFIRMED": "Waiting for the seller to confirm receipt",
-      "NOT_PAID": "Pending",
-      "NOT_SHIPPED": "to be delivered",
-      "RECEIVED": "received",
-      "SELLING": "Selling",
-      "SHIPPED": "Shipped",
-      "SOLD": "Sold",
-      "SOLD_NOT_CONFIRMED": "To be confirmed receipt",
-      "SOLD_NOT_PAID": "pending buyer payment"
+    "delegate": {
+        "tip": "The consignment sale has not started yet, it will start today at ${time}",
+        "title": "Consignment",
+        "increase": "mark up",
+        "originalPrice": "original price",
+        "payServiceCharge": "pay processing fees",
+        "sellPrice": "selling price",
+        "tip1": "Note: entrusting the platform to sell services, the maximum price of the product can be increased by {riseRatePercent}% each time, and the platform will charge {serviceCharge}% of the custody service fee"
     },
-    "statusDesc": {
-      "CANCELED": "The order has been cancelled, if you have any questions, please contact customer service",
-      "CONFIRMED": "To be entrusted, it will be put on the shelves within 24 hours after entrusting",
-      "NOT_CONFIRMED": "Waiting for the seller to confirm receipt",
-      "NOT_PAID": "Please pay as soon as possible, overtime unpaid orders will be automatically canceled",
-      "NOT_SHIPPED": "to be delivered",
-      "RECEIVED": "received",
-      "SELLING": "In entrustment, if you have any questions, please contact customer service",
-      "SHIPPED": "Shipped",
-      "SOLD": "Sold, please contact customer service if you have any questions",
-      "SOLD_NOT_CONFIRMED": "To be confirmed receipt",
-      "SOLD_NOT_PAID": "pending buyer payment"
+    "distribution": {
+        "commission": "commission",
+        "joinTeamAt": "time to join the team",
+        "myInvitor": "my recommender",
+        "myProfit": "Income",
+        "orderNum": "number of order",
+        "profitDetails": "Revenue Details",
+        "qrCode": "my promo code",
+        "teamNum": "Team size",
+        "totalProfit": "Total revenue",
+        "viewDetail": "view details",
+        "viewTeam": "view team",
+        "saveImg": "save Picture",
+        "empty": "no yet",
+        "invite": "To invite"
     },
     "total": "Total",
     "totalPayment": "actual payment",
@@ -194,89 +101,199 @@
     "second": "Second",
     "stopSale": "Suspension of sale",
     "paySuccess": "Payment successful",
-    "paying": "Payment in progress"
-  },
-  "product": {
-    "dailyEarning": "Daily Income",
-    "detail": "Product Details",
-    "hot": "Hot snapping up…",
-    "nowPrice": "Current",
-    "owner": "Product Holder",
-    "search": "search",
-    "searchNo": "No products were found~",
-    "searchPla": "Enter search keywords",
-    "start": "back grab",
-    "tomorrowBuy": "Available",
-    "priceNow": "Current",
-    "riseDesc": "Daily Income",
-    "tag": "Digital Artwork"
-  },
-  "rank": {
-    "inviteNum": "New recruits",
-    "profitInfo": "Earnings information",
-    "rank": "Ranking",
-    "rankByInvite": "Invite Ranking",
-    "rankByProfit": "Revenue Ranking",
-    "userInfo": "User Info",
-    "withdrawRechargeRate": "Recharge revenue ratio"
-  },
-  "settings": {
-    "darkMode": "Dark Mode",
-    "checkUpdate": "Check for update",
-    "checkingUpdate": "Checking for update",
-    "upToDate": "Already up to date",
-    "updating": "Updating"
-  },
-  "title": {
-    "balanceRecord": "Transaction details",
-    "distribution": "revenue center",
-    "myTeam": "my team"
-  },
-  "user": {
-    "notLogin": "User is not logged in, do you want to log in now?",
-    "profile": "Edit Information",
-    "wallet": "My purse"
-  },
-  "blf": {
-    "has": "Remaining places",
-    "pic": "illustrate",
-    "tips": "Pledge your balance, and enjoy today's dividends through the platform's overall pledge balance ratio, and the highest daily chemical income can get 1%",
-    "buy": "snap up now",
-    "buying": "snapped up, income",
-    "computing": "Income calculation",
-    "finish": "sold out",
-    "pending": "Coming soon",
-    "sucess": "successful purchase",
-    "not": "no activity yet"
-  },
-  "tutorial": {
-    "step1": "Step 1: Scan the QR code of the recommender, fill in the registration information, and click register to complete the registration",
-    "step2": "Step 2: After registration, save the QR code and share it with more users to register",
-    "step3": "Step 3: Log in to the app, click on the wallet recharge amount",
-    "step4": "Step 4: Select or enter the amount to be recharged for recharge",
-    "step5": "Step 5: Select the session, click home, and select the initial session. Each user of the primary session is limited to two collections per day, the intermediate session is open from 4:00 pm to 5:00 pm every day, and the advanced session is open from 3:00 pm to 4:00 pm every day.",
-    "step6": "Step 6: Purchase collections, if the wallet balance is insufficient, you need to recharge the wallet balance",
-    "step7": "Step 7: When entrusting the collection to be put on the shelves in the order, you need to pay the platform a commission fee of 4%, and the collection range corresponding to the collection is 6% of the time of purchase.",
-    "step8": "Step 8: If the amount is sufficient, you can directly purchase the collection and then entrust it to be put on the shelf",
-    "step9": "Note: After purchasing 2 pieces, the primary field cannot purchase collections next time, and each user is limited to purchase 2 pieces per day"
-  },
-  "bank": {
-    "bank": "Bank",
-    "addBankCard": "Add Bank Account",
-    "editBankCard": "Edit Bank Account",
-    "deleteBankCard": "Delete Bank Account",
-    "account": "Account",
-    "name": "Name",
-    "phone": "Phone Number",
-    "mail": "Mail",
-    "saveBankCard": "Save Bank Account",
-    "selectBank": "Select Bank",
-    "invalidCard": "Invalid Card Number",
-    "invalidName": "Invalid Name",
-    "invalidPhone": "Invalid Phone Number",
-    "invalidMail": "Invalid Mail",
-    "invalidBank": "Invalid Bank",
-    "deletePrompt": "Are you sure you want to delete this bank account?",
-    "deleteSuccess": "Bank account deleted successfully"
-  }
+    "paying": "Payment in progress",
+    "product": {
+        "dailyEarning": "Daily Income",
+        "detail": "Product Details",
+        "hot": "Hot snapping up…",
+        "nowPrice": "Current",
+        "owner": "Product Holder",
+        "search": "search",
+        "searchNo": "No products were found~",
+        "searchPla": "Enter search keywords",
+        "start": "back grab",
+        "tomorrowBuy": "Available",
+        "priceNow": "Current",
+        "riseDesc": "Daily Income",
+        "tag": "Digital Artwork"
+    },
+    "rank": {
+        "inviteNum": "New recruits",
+        "profitInfo": "Earnings information",
+        "rank": "Ranking",
+        "rankByInvite": "Invite Ranking",
+        "rankByProfit": "Revenue Ranking",
+        "userInfo": "User Info",
+        "withdrawRechargeRate": "Recharge revenue ratio"
+    },
+    "settings": {
+        "darkMode": "Dark Mode",
+        "checkUpdate": "Check for update",
+        "checkingUpdate": "Checking for update",
+        "upToDate": "Already up to date",
+        "updating": "Updating"
+    },
+    "title": {
+        "balanceRecord": "Transaction details",
+        "distribution": "revenue center",
+        "myTeam": "my team"
+    },
+    "user": {
+        "notLogin": "User is not logged in, do you want to log in now?",
+        "profile": "Edit Information",
+        "wallet": "My purse"
+    },
+    "blf": {
+        "has": "Remaining places",
+        "pic": "illustrate",
+        "tips": "Pledge your balance, and enjoy today's dividends through the platform's overall pledge balance ratio, and the highest daily chemical income can get 1%",
+        "buy": "snap up now",
+        "buying": "snapped up, income",
+        "computing": "Income calculation",
+        "finish": "sold out",
+        "pending": "Coming soon",
+        "sucess": "successful purchase",
+        "not": "no activity yet"
+    },
+    "tutorial": {
+        "step1": "Step 1: Scan the QR code of the recommender, fill in the registration information, and click register to complete the registration",
+        "step2": "Step 2: After registration, save the QR code and share it with more users to register",
+        "step3": "Step 3: Log in to the app, click on the wallet recharge amount",
+        "step4": "Step 4: Select or enter the amount to be recharged for recharge",
+        "step5": "Step 5: Select the session, click home, and select the initial session. Each user of the primary session is limited to two collections per day, the intermediate session is open from 4:00 pm to 5:00 pm every day, and the advanced session is open from 3:00 pm to 4:00 pm every day.",
+        "step6": "Step 6: Purchase collections, if the wallet balance is insufficient, you need to recharge the wallet balance",
+        "step7": "Step 7: When entrusting the collection to be put on the shelves in the order, you need to pay the platform a commission fee of 4%, and the collection range corresponding to the collection is 6% of the time of purchase.",
+        "step8": "Step 8: If the amount is sufficient, you can directly purchase the collection and then entrust it to be put on the shelf",
+        "step9": "Note: After purchasing 2 pieces, the primary field cannot purchase collections next time, and each user is limited to purchase 2 pieces per day"
+    },
+    "bank": {
+        "bank": "Bank",
+        "addBankCard": "Add Bank Account",
+        "editBankCard": "Edit Bank Account",
+        "deleteBankCard": "Delete Bank Account",
+        "account": "Account",
+        "name": "Name",
+        "phone": "Phone Number",
+        "mail": "Mail",
+        "saveBankCard": "Save Bank Account",
+        "selectBank": "Select Bank",
+        "invalidCard": "Invalid Card Number",
+        "invalidName": "Invalid Name",
+        "invalidPhone": "Invalid Phone Number",
+        "invalidMail": "Invalid Mail",
+        "invalidBank": "Invalid Bank",
+        "deletePrompt": "Are you sure you want to delete this bank account?",
+        "deleteSuccess": "Bank account deleted successfully"
+    },
+    "home": {
+        "all": "All"
+    },
+    "login": "Log in",
+    "loginPage": {
+        "agreement": "User Agreement",
+        "codePla": "please enter verification code",
+        "goRegister": "Sign up now",
+        "invitorPla": "Invitation code (optional)",
+        "isRead": "have read and agreed",
+        "loginByCode": "Verification code login",
+        "loginNow": "Already have an account, log in now",
+        "loginPwd": "password login",
+        "loginSuceess": "login successful",
+        "noAcount": "No account yet?",
+        "noAgree": "Please read and agree to the registration agreement",
+        "phone": "phone number",
+        "phoneError": "Wrong format of phone number",
+        "phonePla": "Please enter phone number",
+        "username": "Username",
+        "enterUsername": "Enter your username",
+        "psd": "password",
+        "psdAgainError": "The two passwords entered are inconsistent",
+        "psdAgainPla": "please enter password again",
+        "psdPla": "please enter password",
+        "register": "Register an account",
+        "registerSuccess": "registration success",
+        "sendCode": "Send code",
+        "sended": "Sented",
+        "psdEorror": "Wrong format of password",
+        "nameError": "Account length 6-20, can only contain numbers, letters and underscores, not pure numbers"
+    },
+    "mine": {
+        "address": "Address",
+        "avatar": "Avatar",
+        "bankCard": "Bank Account",
+        "bindPhone": "Bind Phone",
+        "female": "Female",
+        "logout": "sign out",
+        "male": "male",
+        "newProfit": "new income",
+        "nickname": "Nick Name",
+        "noBind": "Not added",
+        "noLogin": "not logged in",
+        "noSetting": "not set",
+        "settings": "Settings",
+        "sex": "Gender",
+        "user": "User",
+        "common": "Common Functions",
+        "nickPlac": "Please enter a nickname",
+        "sure": "Confirm the changes"
+    },
+    "news": {
+        "newsNull": "There is no news~"
+    },
+    "order": {
+        "buyNow": "Buy Now",
+        "createSuccess": "Order successfully created",
+        "createdAt": "order time",
+        "detail": "order details",
+        "id": "order number",
+        "my": "My Order",
+        "payInfo": "Payment Information",
+        "payMethod": "payment method",
+        "payMethodName": {
+            "balance": "balance payment"
+        },
+        "payNow": "pay immediately",
+        "processing": "Processing",
+        "status": {
+            "ALL": "all",
+            "CANCELED": "Cancelled",
+            "CONFIRMED": "For Sale",
+            "NOT_CONFIRMED": "Waiting for the seller to confirm receipt",
+            "NOT_PAID": "Pending",
+            "NOT_SHIPPED": "to be delivered",
+            "RECEIVED": "received",
+            "SELLING": "Selling",
+            "SHIPPED": "Shipped",
+            "SOLD": "Sold",
+            "SOLD_NOT_CONFIRMED": "To be confirmed receipt",
+            "SOLD_NOT_PAID": "pending buyer payment"
+        },
+        "statusDesc": {
+            "CANCELED": "The order has been cancelled, if you have any questions, please contact customer service",
+            "CONFIRMED": "To be entrusted, it will be put on the shelves within 24 hours after entrusting",
+            "NOT_CONFIRMED": "Waiting for the seller to confirm receipt",
+            "NOT_PAID": "Please pay as soon as possible, overtime unpaid orders will be automatically canceled",
+            "NOT_SHIPPED": "to be delivered",
+            "RECEIVED": "received",
+            "SELLING": "In entrustment, if you have any questions, please contact customer service",
+            "SHIPPED": "Shipped",
+            "SOLD": "Sold, please contact customer service if you have any questions",
+            "SOLD_NOT_CONFIRMED": "To be confirmed receipt",
+            "SOLD_NOT_PAID": "pending buyer payment"
+        },
+        "total": "Total",
+        "totalPayment": "actual payment",
+        "walletPay": "wallet payment",
+        "applyShip": "Apply for delivery",
+        "confirmReceipt": "confirm the receipt of goods",
+        "countDown": "Automatically cancel the order when the payment countdown expires",
+        "hasProblem": "Encounter problems?",
+        "payAt": "Payment time",
+        "viewOrder": "check order",
+        "mint": "Minute",
+        "second": "Second",
+        "stopSale": "Suspension of sale",
+        "paySuccess": "Payment successful",
+        "paying": "Payment in progress"
+    }
 }

+ 4 - 1
src/locales/zh.json

@@ -32,7 +32,10 @@
         "saveFailed": "保存失败",
         "exitApp": "再按一次退出应用",
         "close": "关闭",
-        "skip": "跳过"
+        "skip": "跳过",
+        "customerService": "咨询客服",
+        "open": "打开",
+        "copied": "已复制"
     },
     "order": {
         "id": "订单编号",

+ 14 - 3
src/main.js

@@ -84,8 +84,7 @@ const checkUpdate = async () => {
         .sync(
             {
                 updateDialog: false,
-                installMode:
-                    localStorage.getItem('firstRun') === '1' ? InstallMode.IMMEDIATE : InstallMode.ON_NEXT_RESTART,
+                installMode: InstallMode.IMMEDIATE,
                 ignoreFailedUpdates: false
             },
             downloadProgress => {
@@ -126,7 +125,13 @@ const initAF = () => {
         })
     AppsFlyer.addListener(AFConstants.CONVERSION_CALLBACK, event => {
         if (event.callbackName === AFConstants.onConversionDataSuccess) {
-            console.log('ConversionData: ', event.data)
+            console.log('ConversionData: ', event)
+            setTimeout(() => {
+                console.log('ConversionData: ', event)
+            }, 30000)
+            setTimeout(() => {
+                console.log('ConversionData: ', event)
+            }, 60000)
             if (event.data.invitor) {
                 localStorage.setItem('invitor', event.data.invitor)
             }
@@ -140,6 +145,9 @@ const initAF = () => {
     AppsFlyer.addListener(AFConstants.UDL_CALLBACK, event => {
         if (event.status === 'FOUND') {
             console.log('udl found: ', event.deepLink)
+            if (event.invitor) {
+                localStorage.setItem('invitor', event.invitor)
+            }
         } else if (event.status === 'ERROR') {
             console.log('udl error: ', event.error)
         }
@@ -202,3 +210,6 @@ document.addEventListener('deviceready', () => {
 if (useStorage('showConsole', 0).value > new Date().getTime()) {
     initEruda()
 }
+if (location.origin.includes('http://192.168')) {
+    initEruda()
+}

+ 21 - 2
src/styles/main.less

@@ -88,7 +88,7 @@ ion-modal.dialog {
 }
 .van-button--plain {
     background: transparent;
-    --van-button-primary-background: #39F3BB;
+    --van-button-primary-background: #39f3bb;
 }
 .van-button {
     --van-button-normal-font-size: 14px;
@@ -121,8 +121,27 @@ input:-webkit-autofill {
     .eruda-js-input {
         height: 54px !important;
         padding-bottom: 30px !important;
-        &.eruda-active{
+        &.eruda-active {
             height: 100% !important;
         }
     }
 }
+.fade-enter-active,
+.fade-leave-active {
+    transition: opacity 0.3s ease;
+}
+
+.fade-enter-from,
+.fade-leave-to {
+    opacity: 0;
+}
+
+.popup-enter-active,
+.popup-leave-active {
+    transition: transform 0.3s ease;
+}
+
+.popup-enter-from,
+.popup-leave-to {
+    transform: translateY(100%);
+}

+ 3 - 3
src/version.json

@@ -1,12 +1,12 @@
 {
     "ios": {
         "version": "1.0.0",
-        "build": 29
+        "build": 36
     },
     "android": {
         "version": "1.0.0",
-        "build": 29,
+        "build": 36,
         "versionCode": 12
     },
-    "www": 1012
+    "www": 1019
 }

+ 36 - 30
src/views/DistributionPage.vue

@@ -19,7 +19,7 @@
                         <ion-icon :icon="caretForwardCircleOutline"></ion-icon>
                     </div>
                 </div> -->
-                <!-- <div class="btn-invite" @click="drawQr"></div> -->
+                <!-- <div class="btn-invite" @click="onOpenInviteModal"></div> -->
             </div>
             <div class="stat">
                 <div class="bg">
@@ -47,7 +47,7 @@
                     </div>
                 </div>
             </div>
-            <div class="invite" @click="drawQr">
+            <div class="invite" @click="onOpenInviteModal">
                 <img src="@/assets/invite-bg.png" alt="" class="invite-bg" />
                 <span class="animate__pulse animate__animated animate__infinite">{{ $t('distribution.invite') }}</span>
             </div>
@@ -93,6 +93,7 @@ import { Filesystem, Directory, Encoding } from '@capacitor/filesystem'
 import { Media } from '@capacitor-community/media'
 import emptyImg from '@/assets/img_empty.png'
 import '@/styles/animate.css'
+import { AppsFlyer } from 'appsflyer-capacitor-plugin'
 
 export default {
     components: {
@@ -144,7 +145,7 @@ export default {
         this.showToolbar = this.$route.meta.showToolbar === true
         setTimeout(() => {
             if (this.$route.query.showShare === 'true' || this.$route.query.showShare == true) {
-                this.drawQr()
+                this.onOpenInviteModal()
             }
             this.$router.replace({ query: {} })
         }, 500)
@@ -161,25 +162,31 @@ export default {
                 this.empty = res.empty
             })
         },
-        drawQr() {
+        async getInviteUrl() {
+            if (Capacitor.isNativePlatform()) {
+                const { link } = await AppsFlyer.generateInviteLink({
+                    addParameters: { invitor: `${this.user.id}`, af_sub1: `${this.user.id}` }
+                })
+                return link
+            } else {
+                return `https://ifirstcash.onelink.me/cQAJ?af_js_web=true&af_ss_ver=2_3_0&pid=af_user_invite&invitor=${this.user.id}&af_sub1=${this.user.id}&af_ss_ui=true`
+            }
+        },
+        async onOpenInviteModal() {
             let qrImg = new Image()
             let bgImg = new Image()
-            let userId = this.user.id
-            function loadQR(text) {
+            const url = await this.getInviteUrl()
+            function loadQR() {
                 return new Promise((resolve, reject) => {
-                    qrcode.toDataURL(
-                        `https://ifirstcash.onelink.me/cQAJ/d0785cqz?invitor=${userId}`,
-                        { width: 335, height: 335, margin: 0 },
-                        function (err, url) {
-                            if (err) {
-                                reject(err)
-                            }
-                            qrImg.onload = () => {
-                                resolve()
-                            }
-                            qrImg.src = url
+                    qrcode.toDataURL(url, { width: 335, height: 335, margin: 0 }, function (err, url) {
+                        if (err) {
+                            reject(err)
+                        }
+                        qrImg.onload = () => {
+                            resolve()
                         }
-                    )
+                        qrImg.src = url
+                    })
                 })
             }
             function loadBg() {
@@ -191,18 +198,17 @@ export default {
                 })
             }
             this.$toast.loading('loading...')
-            Promise.all([loadQR(), loadBg()]).then(() => {
-                this.$toast.dismiss()
-                let canvas = document.createElement('canvas')
-                canvas.width = 1125
-                canvas.height = 1740
-                let ctx = canvas.getContext('2d')
-                ctx.drawImage(bgImg, 0, 0)
-                ctx.drawImage(qrImg, 395, 1095, 335, 335)
-                let dataUrl = canvas.toDataURL('image/png')
-                this.posterUrl = dataUrl
-                this.showShareModal = true
-            })
+            await Promise.all([loadQR(), loadBg()])
+            this.$toast.dismiss()
+            let canvas = document.createElement('canvas')
+            canvas.width = 1125
+            canvas.height = 1740
+            let ctx = canvas.getContext('2d')
+            ctx.drawImage(bgImg, 0, 0)
+            ctx.drawImage(qrImg, 395, 1095, 335, 335)
+            let dataUrl = canvas.toDataURL('image/png')
+            this.posterUrl = dataUrl
+            this.showShareModal = true
         },
         async save() {
             if (Capacitor.isNativePlatform()) {

+ 1 - 0
vite.config.js

@@ -11,6 +11,7 @@ export default defineConfig(({ command, mode }) => {
         base: process.env.VITE_BASE_URL,
         server: {
             host: '0.0.0.0',
+            port: 3000,
             fs: {
                 strict: false
             }