fix bugs
This commit is contained in:
+16
-2
@@ -326,7 +326,15 @@
|
||||
}
|
||||
|
||||
function getVersionUrls() {
|
||||
return ['https://nerkh.gold/get_version', 'https://tablo.talasevin.ir/get_version', 'https://abshode-service.montgit.ir/server/get_version']
|
||||
var protocol = getProtocol()
|
||||
|
||||
return [
|
||||
'https://nerkh.gold/get_version',
|
||||
'https://tablo.talasevin.ir/get_version',
|
||||
'https://abshode-service.montgit.ir/server/get_version',
|
||||
protocol + '//212.23.201.173:8381/get_version',
|
||||
protocol + '//91.212.174.137:4040/server/get_version'
|
||||
]
|
||||
}
|
||||
|
||||
function getConfigUrls() {
|
||||
@@ -453,6 +461,9 @@
|
||||
localStorage.setItem(VERSION_SUCCESS_URL_KEY, url)
|
||||
return version
|
||||
} catch (error) {
|
||||
if (localStorage.getItem(VERSION_SUCCESS_URL_KEY) === url) {
|
||||
localStorage.removeItem(VERSION_SUCCESS_URL_KEY)
|
||||
}
|
||||
console.warn('Version failed:', url, error)
|
||||
return undefined
|
||||
} finally {
|
||||
@@ -496,6 +507,9 @@
|
||||
url: url
|
||||
}
|
||||
} catch (error) {
|
||||
if (localStorage.getItem(CONFIG_SUCCESS_URL_KEY) === url) {
|
||||
localStorage.removeItem(CONFIG_SUCCESS_URL_KEY)
|
||||
}
|
||||
console.warn('Config failed:', url, 'round:', round, error)
|
||||
}
|
||||
}
|
||||
@@ -626,7 +640,7 @@
|
||||
renderRecovering('در حال دریافت تنظیمات جدید برنامه...')
|
||||
|
||||
var version = await loadRemoteVersion(5)
|
||||
var freshConfigResult = await fetchFreshConfig(2)
|
||||
var freshConfigResult = await fetchFreshConfig(5)
|
||||
|
||||
clearReadableCookies()
|
||||
// clearLocalStorageExceptToken()
|
||||
|
||||
+1
-10
@@ -2,7 +2,6 @@ import { computed, watch } from 'vue'
|
||||
import router from '@/router'
|
||||
import { authenticateWithFingerprint, getToken, isIphone, removeToken } from '@/utils'
|
||||
import { useUserStore } from '@/store/userStore'
|
||||
import { useWalletStore } from '@/store/walletStore'
|
||||
import type { NavigationGuardNext, RouteLocationNormalized } from 'vue-router'
|
||||
import { useAuthStore } from '@/store/useAuthStore'
|
||||
import {
|
||||
@@ -16,7 +15,6 @@ import {
|
||||
|
||||
export function setupRouterGuards() {
|
||||
const userStore = useUserStore()
|
||||
const walletStore = useWalletStore()
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const isApple: boolean = isIphone()
|
||||
@@ -29,16 +27,9 @@ export function setupRouterGuards() {
|
||||
return
|
||||
}
|
||||
|
||||
const tasks: Promise<unknown>[] = [
|
||||
walletStore.getLimitedPrice(),
|
||||
walletStore.getLimitedBuyGold(),
|
||||
]
|
||||
|
||||
if (!userStore.userInfo) {
|
||||
tasks.push(userStore.getMyInfo())
|
||||
await userStore.getMyInfo()
|
||||
}
|
||||
|
||||
await Promise.all(tasks)
|
||||
}
|
||||
|
||||
function goToLogin(to: RouteLocationNormalized, next: NavigationGuardNext) {
|
||||
|
||||
+21
-11
@@ -2,6 +2,7 @@ import type { AppConfig } from '@/config/types'
|
||||
import { readCachedAppConfig, writeCachedAppConfig } from '@/config/config-cache'
|
||||
|
||||
const CONFIG_SUCCESS_URL_KEY = 'CONFIG_Success_URL'
|
||||
export const CONFIG_RETRY_ROUNDS = 5
|
||||
|
||||
function getProtocol() {
|
||||
return window.location.protocol === 'https:' ? 'https:' : 'http:'
|
||||
@@ -29,6 +30,12 @@ export function sortConfigUrls(urls: string[]) {
|
||||
})
|
||||
}
|
||||
|
||||
function clearStaleConfigSuccessUrl(url: string) {
|
||||
if (localStorage.getItem(CONFIG_SUCCESS_URL_KEY) === url) {
|
||||
localStorage.removeItem(CONFIG_SUCCESS_URL_KEY)
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchConfig(url: string, timeout = 3000): Promise<AppConfig> {
|
||||
const controller = new AbortController()
|
||||
const timeoutId = window.setTimeout(() => controller.abort(), timeout)
|
||||
@@ -59,22 +66,25 @@ async function fetchConfig(url: string, timeout = 3000): Promise<AppConfig> {
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchFreshAppConfig(): Promise<AppConfig> {
|
||||
export async function fetchFreshAppConfig(rounds = CONFIG_RETRY_ROUNDS): Promise<AppConfig> {
|
||||
const urls = sortConfigUrls(getConfigUrls())
|
||||
|
||||
for (let index = 0; index < urls.length; index++) {
|
||||
const url = urls[index]
|
||||
for (let round = 1; round <= rounds; round++) {
|
||||
for (let index = 0; index < urls.length; index++) {
|
||||
const url = urls[index]
|
||||
|
||||
try {
|
||||
const timeout = index === urls.length - 1 ? 5000 : 2500
|
||||
const config = await fetchConfig(url, timeout)
|
||||
try {
|
||||
const timeout = index === urls.length - 1 ? 7000 : 4000
|
||||
const config = await fetchConfig(url, timeout)
|
||||
|
||||
localStorage.setItem(CONFIG_SUCCESS_URL_KEY, url)
|
||||
writeCachedAppConfig(config)
|
||||
localStorage.setItem(CONFIG_SUCCESS_URL_KEY, url)
|
||||
writeCachedAppConfig(config)
|
||||
|
||||
return config
|
||||
} catch (error) {
|
||||
console.warn(`Config failed from ${url}`, error)
|
||||
return config
|
||||
} catch (error) {
|
||||
clearStaleConfigSuccessUrl(url)
|
||||
console.warn(`Config failed from ${url}. Round: ${round}`, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,16 +9,24 @@ type VersionResponse =
|
||||
}
|
||||
|
||||
const VERSION_SUCCESS_URL_KEY = 'VERSION_Success_URL'
|
||||
const VERSION_RETRY_ROUNDS = 5
|
||||
export const VERSION_RETRY_ROUNDS = 5
|
||||
|
||||
let versionFetchPromise: Promise<string | null> | null = null
|
||||
let cachedVersionResult: string | null | undefined
|
||||
|
||||
function getProtocol() {
|
||||
return window.location.protocol === 'https:' ? 'https:' : 'http:'
|
||||
}
|
||||
|
||||
function getVersionUrls() {
|
||||
const protocol = getProtocol()
|
||||
|
||||
return [
|
||||
'https://nerkh.gold/get_version',
|
||||
'https://tablo.talasevin.ir/get_version',
|
||||
'https://abshode-service.montgit.ir/server/get_version'
|
||||
'https://abshode-service.montgit.ir/server/get_version',
|
||||
`${protocol}//212.23.201.173:8381/get_version`,
|
||||
`${protocol}//91.212.174.137:4040/server/get_version`
|
||||
]
|
||||
}
|
||||
|
||||
@@ -33,6 +41,12 @@ function sortVersionUrls(urls: string[]) {
|
||||
return [lastSuccessUrl, ...others]
|
||||
}
|
||||
|
||||
function clearStaleVersionSuccessUrl(url: string) {
|
||||
if (localStorage.getItem(VERSION_SUCCESS_URL_KEY) === url) {
|
||||
localStorage.removeItem(VERSION_SUCCESS_URL_KEY)
|
||||
}
|
||||
}
|
||||
|
||||
function readUserVersion(user: unknown) {
|
||||
if (!user || typeof user !== 'object' || Array.isArray(user)) {
|
||||
return ''
|
||||
@@ -82,7 +96,6 @@ async function fetchVersion(url: string, timeout = 3500): Promise<string | null>
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
// Non-2xx/timeout should be treated as "request failed" and we may try the next URL.
|
||||
throw new Error(`Version request failed with status ${response.status}`)
|
||||
}
|
||||
|
||||
@@ -94,10 +107,8 @@ async function fetchVersion(url: string, timeout = 3500): Promise<string | null>
|
||||
|
||||
const version = normalizeVersionResponse(data)
|
||||
|
||||
// IMPORTANT: if the request returned 200/ok, we stop here even if we couldn't extract a version.
|
||||
// This prevents unnecessary looping when the endpoint is "reachable" but returns an empty payload.
|
||||
if (!version) {
|
||||
return null
|
||||
throw new Error('Version response is empty')
|
||||
}
|
||||
|
||||
localStorage.setItem(VERSION_SUCCESS_URL_KEY, url)
|
||||
@@ -118,10 +129,11 @@ async function fetchVersionWithRetry(rounds = VERSION_RETRY_ROUNDS): Promise<str
|
||||
|
||||
try {
|
||||
const version = await fetchVersion(url, timeout)
|
||||
// fetchVersion only throws on real request failures (non-ok / timeout).
|
||||
// If it returns null, we got HTTP 200 but empty version => stop immediately.
|
||||
return version
|
||||
if (version) {
|
||||
return version
|
||||
}
|
||||
} catch (error) {
|
||||
clearStaleVersionSuccessUrl(url)
|
||||
console.warn(`Version failed from ${url}. Round: ${round}`, error)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ export interface Order {
|
||||
sts_str?: string
|
||||
payment_sts?: number
|
||||
payment_amount?: number
|
||||
target_cash?: number
|
||||
service_charge_price?: number
|
||||
total_fee?: number
|
||||
total_price?: number
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import { type ComputedRef, ref } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
import {defineStore} from "pinia";
|
||||
import {getMe} from "@/api/me";
|
||||
import type {User} from "@/models/login";
|
||||
import type {Wallet} from "@/models/wallet";
|
||||
import {getWallet} from "@/api/wallet";
|
||||
import type {Const} from "@/models/const";
|
||||
import {getConstByKey} from "@/api/const";
|
||||
export const useWalletStore = defineStore('wallet', () => {
|
||||
const walletInfo = ref<Wallet | undefined>(undefined)
|
||||
const limitedPrice = ref<Const[]>()
|
||||
const limitedBuyGold = ref<Const[]>()
|
||||
|
||||
async function getMyWallet() {
|
||||
try {
|
||||
@@ -19,40 +13,6 @@ export const useWalletStore = defineStore('wallet', () => {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
async function getLimitedPrice(){
|
||||
try {
|
||||
limitedPrice.value = await getConstByKey('limited_price')
|
||||
return limitedPrice.value
|
||||
}catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
|
||||
async function getLimitedBuyGold(){
|
||||
try {
|
||||
limitedBuyGold.value = await getConstByKey('first_customer_wallet_value')
|
||||
return limitedBuyGold.value
|
||||
}catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
|
||||
/* const permissions: ComputedRef<string[]> = computed(() => {
|
||||
const permissions: string[] = get(userInfo.value, 'permission', [])
|
||||
const excludes: string[] = get(userInfo.value, 'exclude', [])
|
||||
return permissions.filter((item) => !excludes.includes(item))
|
||||
})*/
|
||||
|
||||
/*
|
||||
function canAccess(permissionKey: string) {
|
||||
if (isAdmin.value) return true
|
||||
return permissions.value.includes(permissionKey)
|
||||
}
|
||||
*/
|
||||
/*
|
||||
const isAdmin = computed(() => {
|
||||
return userInfo.value?.is_admin
|
||||
})*/
|
||||
|
||||
return { walletInfo, getMyWallet, getLimitedPrice, getLimitedBuyGold, limitedPrice, limitedBuyGold/* permissions, canAccess, isAdmin*/ }
|
||||
return { walletInfo, getMyWallet }
|
||||
})
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
import { ref } from 'vue'
|
||||
import { getSettings } from '@/api/configuration'
|
||||
|
||||
export const serviceFeePercentage = ref<number>(0.01)
|
||||
|
||||
/** true = مبالغ رند: فروش → ریال دقیق (کارمزد از طلا)؛ خرید → وزن دقیق (کارمزد از ریال) */
|
||||
export const feeDeductFromGold = ref(false)
|
||||
|
||||
export async function loadServiceFeeFromSettings() {
|
||||
try {
|
||||
const settings = await getSettings()
|
||||
if (settings && Array.isArray(settings)) {
|
||||
const feeSetting = settings.find(
|
||||
(s) => s?.key === 'fee_service_charge_percentage' && s?.is_active === true
|
||||
)
|
||||
if (feeSetting?.value !== undefined && feeSetting?.value !== null) {
|
||||
serviceFeePercentage.value = Number(feeSetting.value)
|
||||
}
|
||||
|
||||
const feeModeSetting = settings.find(
|
||||
(s) => s?.key === 'fee_deduct_from_gold' && s?.is_active === true
|
||||
)
|
||||
if (feeModeSetting?.value !== undefined && feeModeSetting?.value !== null) {
|
||||
const raw = String(feeModeSetting.value).trim().toLowerCase()
|
||||
feeDeductFromGold.value = raw === 'true' || raw === '1'
|
||||
} else {
|
||||
feeDeductFromGold.value = false
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
|
||||
export function calcFeeInGrams(goldValue?: number | null) {
|
||||
return parseFloat(((goldValue ?? 0) * Number(serviceFeePercentage.value)).toFixed(4))
|
||||
}
|
||||
|
||||
/** گرم معادل برای دریافت دقیق مبلغ ریالی در فروش */
|
||||
export function calcGoldAmountFromTargetRial(rialAmount: number, unitPriceRial: number) {
|
||||
if (!rialAmount || !unitPriceRial) return 0
|
||||
return parseFloat((rialAmount / unitPriceRial).toFixed(6))
|
||||
}
|
||||
|
||||
/** مبلغ نهایی قابل پرداخت (خرید) یا دریافت (فروش) به ریال */
|
||||
export function calcPayablePriceRial(
|
||||
finalPriceRial: number,
|
||||
feeInRial: number,
|
||||
isBuy: boolean,
|
||||
targetRialCash?: number | null
|
||||
) {
|
||||
if (feeDeductFromGold.value) {
|
||||
if (isBuy) return finalPriceRial + feeInRial
|
||||
if (targetRialCash != null && Number(targetRialCash) > 0) return Number(targetRialCash)
|
||||
return finalPriceRial
|
||||
}
|
||||
return isBuy ? finalPriceRial : Math.max(0, finalPriceRial - feeInRial)
|
||||
}
|
||||
|
||||
/** وزن ارسالی به سرور — فروش رند: از مبلغ ریالی هدف */
|
||||
export function calcOrderGoldAmount(
|
||||
goldValue?: number | null,
|
||||
goldCash?: number | null,
|
||||
unitPriceRial?: number,
|
||||
isBuy?: boolean
|
||||
) {
|
||||
const gold = Number(goldValue ?? 0)
|
||||
if (isBuy || !feeDeductFromGold.value) {
|
||||
return parseFloat(gold.toFixed(6))
|
||||
}
|
||||
const targetCash = calcSellTargetCash(goldCash, goldValue, unitPriceRial)
|
||||
const unit = Number(unitPriceRial ?? 0)
|
||||
if (targetCash != null && unit > 0) {
|
||||
return calcGoldAmountFromTargetRial(targetCash, unit)
|
||||
}
|
||||
return parseFloat(gold.toFixed(6))
|
||||
}
|
||||
|
||||
/** مبلغ ریالی دقیق دریافتی در فروش (فقط وقتی کاربر با ریال وارد کرده) */
|
||||
export function calcSellTargetCash(
|
||||
goldCash?: number | null,
|
||||
goldValue?: number | null,
|
||||
unitPriceRial?: number
|
||||
) {
|
||||
const cash = Number(goldCash ?? 0)
|
||||
if (!feeDeductFromGold.value || cash <= 0) return undefined
|
||||
const gold = Number(goldValue ?? 0)
|
||||
const unit = Number(unitPriceRial ?? 0)
|
||||
if (gold > 0 && unit > 0) {
|
||||
const derived = Math.round(gold * unit)
|
||||
if (Math.abs(derived - Math.round(cash)) <= 1) return undefined
|
||||
}
|
||||
return Math.round(cash)
|
||||
}
|
||||
|
||||
/** کل طلای کسرشونده از کیف در فروش (شامل کارمزد وقتی fee_deduct_from_gold روشن است) */
|
||||
export function calcSellGoldDebit(goldValue?: number | null, feeInGrams?: number | null) {
|
||||
const gold = Number(goldValue ?? 0)
|
||||
const fee = Number(feeInGrams ?? 0)
|
||||
if (feeDeductFromGold.value) {
|
||||
return parseFloat((gold + fee).toFixed(4))
|
||||
}
|
||||
return gold
|
||||
}
|
||||
@@ -37,11 +37,6 @@
|
||||
<div v-else class="w-full h-[88px]">
|
||||
<GoldSkeleton class="w-full" />
|
||||
</div>
|
||||
<div v-if="limitedPrice !== undefined && userStore?.userInfo.trade_active !== 1"
|
||||
class="text-red text-xs flex gap-1 items-center justify-center my-2">
|
||||
<Icon icon="vuesax-linear:info-circle" size="16" />
|
||||
حداقل مبلغ اولیه برای ثبت سفارش {{ usePriceWithoutType(limitedPrice.value as number ?? 0) }} ریال می باشد.
|
||||
</div>
|
||||
</a-spin>
|
||||
<a-form :model="form" class="!mt-5" name="basic" @finish="okConfirm()">
|
||||
<div class="border-gray-200 border-1 rounded-xl p-5 h-58 relative">
|
||||
@@ -108,10 +103,11 @@
|
||||
<div v-else>{{ !isBuy ? 'فروش' : 'خرید' }}</div>
|
||||
</div>
|
||||
</BasicButton>
|
||||
<div v-if="!isBuy && form.goldValue > walletStore?.walletInfo?.gold"
|
||||
<div v-if="!isBuy && sellGoldDebit > (walletStore?.walletInfo?.gold ?? 0)"
|
||||
class="text-red-700 text-xs font-bold mt-2">
|
||||
مقدار گرم طلای وارد شده جهت فروش ({{ form.goldValue }}گرم) بیشتر از مقدار موجودی شما
|
||||
({{ walletStore?.walletInfo?.gold }}گرم) می باشد.
|
||||
<span v-if="feeDeductFromGold"> (با احتساب {{ feeInGrams }} گرم کارمزد، مجموعاً {{ sellGoldDebit }} گرم کسر میشود)</span>
|
||||
</div>
|
||||
<!-- <div>{{form?.goldValue? true: false}}</div>-->
|
||||
<div v-if="isBuy? ((form?.goldValue || form.goldValue === 0)? form?.goldCash < 500000: false) : false"
|
||||
@@ -125,7 +121,7 @@
|
||||
<div class="flex justify-between items-center">
|
||||
<div>کارمزد:</div>
|
||||
<div class="flex gap-2 items-center">
|
||||
<div class="">{{ parseFloat(((form.goldValue ?? 0) * 0.01).toFixed(4)) }}</div>
|
||||
<div class="">{{ feeInGrams }}</div>
|
||||
<!-- <div class="font-bold text-2xl">{{ 0 }}</div>-->
|
||||
<div>
|
||||
گرم
|
||||
@@ -165,11 +161,25 @@
|
||||
<div class="flex justify-between mt-3">
|
||||
<div>کارمزد:</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="font-bold text-xl">{{ parseFloat(((form.goldValue ?? 0) * 0.01).toFixed(4)) }}</div>
|
||||
<div class="font-bold text-xl">{{ feeInGrams }}</div>
|
||||
<div class="text-xs mr-1">گرم</div>
|
||||
</div>
|
||||
</div>
|
||||
<div >(معادل {{ equivalentPrice }} ریال)</div>
|
||||
<div v-if="isBuy && feeDeductFromGold" class="flex justify-between mt-3">
|
||||
<div>طلا دریافتی:</div>
|
||||
<div class="flex items-center">
|
||||
<div class="font-bold">{{ form.goldValue }}</div>
|
||||
<div class="text-xs mr-1">گرم (دقیق — کارمزد از ریال)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!isBuy && feeDeductFromGold" class="flex justify-between mt-3">
|
||||
<div>کسر از کیف طلا:</div>
|
||||
<div class="flex items-center">
|
||||
<div class="font-bold">{{ sellGoldDebit }}</div>
|
||||
<div class="text-xs mr-1">گرم</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-between mt-3">
|
||||
<div>{{ isBuy ? 'قیمت قابل پرداخت:' : 'مبلغ دریافتی:' }}</div>
|
||||
<div class="flex items-center">
|
||||
@@ -228,6 +238,15 @@ import { getTransactionTable } from '@/api/transaction'
|
||||
import { getLastPrices, lastPrice, setIntervalGetAllPrice, stopPriceInterval } from '@/utils/price'
|
||||
import type { Product } from '@/models/products'
|
||||
import { useFundUserStore } from '@/store/fundStore'
|
||||
import {
|
||||
calcFeeInGrams,
|
||||
calcOrderGoldAmount,
|
||||
calcPayablePriceRial,
|
||||
calcSellGoldDebit,
|
||||
calcSellTargetCash,
|
||||
feeDeductFromGold,
|
||||
loadServiceFeeFromSettings
|
||||
} from '@/utils/serviceFee'
|
||||
import Bg_main from '@/components/bg_main.vue'
|
||||
import Vue3Odometer from 'vue3-odometer'
|
||||
import 'odometer/themes/odometer-theme-default.css'
|
||||
@@ -270,10 +289,25 @@ const sellPagination = ref<TableEngineInput>({
|
||||
}], limit: 6, page: 0
|
||||
})
|
||||
|
||||
const finalPrice = computed(() => (form.value?.goldValue * (isBuy.value ? price.value?.buy ?? 0 : price.value?.sell ?? 0)))
|
||||
// const payablePrice = computed(() => finalPrice.value + finalPrice.value * 0.007)
|
||||
const payablePrice = computed(() => finalPrice.value)
|
||||
const equivalentPrice = computed(() => usePriceWithoutType(((isBuy ? price.value?.buy ?? 0 : price.value?.sell ?? 0) * (parseFloat(((form.value?.goldValue ?? 0) * 0.01).toFixed(4))) ).toFixed(0)) )
|
||||
const unitPrice = computed(() =>
|
||||
isBuy.value ? (price.value?.buy ?? 0) : (price.value?.sell ?? 0)
|
||||
)
|
||||
const orderGoldAmount = computed(() =>
|
||||
calcOrderGoldAmount(form.value?.goldValue, form.value?.goldCash, unitPrice.value, isBuy.value)
|
||||
)
|
||||
const feeInGrams = computed(() => calcFeeInGrams(orderGoldAmount.value))
|
||||
const finalPrice = computed(() => orderGoldAmount.value * unitPrice.value)
|
||||
const feeInRial = computed(() => unitPrice.value * feeInGrams.value)
|
||||
const equivalentPrice = computed(() => usePriceWithoutType(feeInRial.value.toFixed(0)))
|
||||
const payablePrice = computed(() =>
|
||||
calcPayablePriceRial(
|
||||
finalPrice.value,
|
||||
feeInRial.value,
|
||||
isBuy.value,
|
||||
!isBuy.value ? form.value?.goldCash : undefined
|
||||
)
|
||||
)
|
||||
const sellGoldDebit = computed(() => calcSellGoldDebit(orderGoldAmount.value, feeInGrams.value))
|
||||
|
||||
const disableTransaction = computed(() =>
|
||||
loading.value ||
|
||||
@@ -282,7 +316,8 @@ const disableTransaction = computed(() =>
|
||||
form.value?.goldCash === '' ||
|
||||
form.value?.goldCash === undefined ||
|
||||
(isBuy.value ? (form.value?.goldCash ?? 0) < 500000 : (form.value?.goldValue ?? 0) < 0.001) ||
|
||||
(!isBuy.value && form.value.goldValue > walletStore?.walletInfo?.gold) ||
|
||||
(!isBuy.value && sellGoldDebit.value > (walletStore?.walletInfo?.gold ?? 0)) ||
|
||||
(isBuy.value && payablePrice.value > (walletStore?.walletInfo?.cash ?? 0)) ||
|
||||
price.value?.buy === undefined)
|
||||
|
||||
function refreshTable() {
|
||||
@@ -385,6 +420,7 @@ onMounted(async () => {
|
||||
break
|
||||
}
|
||||
await initPrice()
|
||||
await loadServiceFeeFromSettings()
|
||||
/* await initSellTable()
|
||||
await initBuyTable()*/
|
||||
})
|
||||
@@ -505,11 +541,6 @@ const unitCashCalculator = computed(() => {
|
||||
return (walletStore?.walletInfo?.cash ?? 0) / 100
|
||||
})
|
||||
|
||||
const limitedPrice = computed(() => {
|
||||
if (walletStore.limitedPrice)
|
||||
return walletStore?.limitedPrice[0]
|
||||
})
|
||||
|
||||
function calculateCash(val: number) {
|
||||
priceErrorVisible.value = false
|
||||
// console.log(val)
|
||||
@@ -542,9 +573,13 @@ function calculateGold(val: number) {
|
||||
}
|
||||
} else {
|
||||
if (val) {
|
||||
form.value.goldValue = toFixedDownThreeChar(parseFloat((val / price?.value?.sell)))
|
||||
if (parseInt(finalPrice.value) > 0) priceErrorVisible.value = true
|
||||
if (parseInt(finalPrice.value) === 0) priceErrorVisible.value = false
|
||||
if (feeDeductFromGold.value) {
|
||||
form.value.goldValue = parseFloat((val / (price?.value?.sell ?? 1)).toFixed(6))
|
||||
} else {
|
||||
form.value.goldValue = toFixedDownThreeChar(parseFloat(String(val / price?.value?.sell)))
|
||||
}
|
||||
if (parseInt(String(finalPrice.value)) > 0) priceErrorVisible.value = true
|
||||
if (parseInt(String(finalPrice.value)) === 0) priceErrorVisible.value = false
|
||||
} else if (val.toString() === '') {
|
||||
// console.log('sasasasasasa')
|
||||
form.value.goldValue = undefined
|
||||
@@ -625,8 +660,9 @@ async function ok() {
|
||||
infoVisible.value = true
|
||||
await createOrder({
|
||||
direction: isBuy.value ? 1 : 2,
|
||||
price: isBuy.value ? price.value?.buy : price.value?.sell,
|
||||
amount: form.value.goldValue ?? 0
|
||||
price: Math.round(unitPrice.value),
|
||||
amount: orderGoldAmount.value,
|
||||
target_cash: calcSellTargetCash(form.value.goldCash, form.value.goldValue, unitPrice.value),
|
||||
})
|
||||
await walletStore.getMyWallet()
|
||||
await router.push({ name: 'transactions' })
|
||||
|
||||
@@ -1,36 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, inject } from 'vue'
|
||||
import { useUserStore } from '@/store/userStore'
|
||||
import { usePriceWithoutType } from '@/utils/usePrice'
|
||||
import { inject } from 'vue'
|
||||
import { isBoursecuProject } from '@/utils/config'
|
||||
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
|
||||
import { HOME_PAGE_CONTEXT_KEY } from '../../composables/useHomePage'
|
||||
|
||||
const ctx = inject(HOME_PAGE_CONTEXT_KEY)!
|
||||
const userStore = useUserStore()
|
||||
const isBoursecu = isBoursecuProject()
|
||||
|
||||
const showLimitedPrice = computed(
|
||||
() =>
|
||||
ctx.limitedPrice.value !== undefined &&
|
||||
userStore.userInfo?.trade_active !== 1,
|
||||
)
|
||||
|
||||
const limitedPriceText = computed(() =>
|
||||
usePriceWithoutType(Number(ctx.limitedPrice.value?.value ?? 0)),
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="showLimitedPrice || ctx.showClosedMessage.value" class="dhome-alerts">
|
||||
<div v-if="showLimitedPrice" class="dhome-alert dhome-alert--warning">
|
||||
<BasicIcon icon="vuesax-linear:info-circle" size="14" />
|
||||
<span>
|
||||
حداقل مبلغ اولیه برای ثبت سفارش {{ limitedPriceText }} ریال میباشد.
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="!isBoursecu && ctx.showClosedMessage.value" class="dhome-alerts">
|
||||
<div
|
||||
v-if="!isBoursecu && ctx.showClosedMessage.value"
|
||||
class="dhome-alert dhome-alert--info"
|
||||
v-html="ctx.closedMessage.value"
|
||||
/>
|
||||
|
||||
@@ -10,15 +10,6 @@
|
||||
v-if="!loading"
|
||||
class="bg-white w-full md:w-auto h-fit px-5 m-[-1px]"
|
||||
>
|
||||
<div
|
||||
v-if="limitedPrice !== undefined && userStore?.userInfo.trade_active !== 1"
|
||||
class="text-red text-xs flex gap-1 items-center justify-center mb-2"
|
||||
>
|
||||
<Icon icon="vuesax-linear:info-circle" size="16" />
|
||||
حداقل مبلغ اولیه برای ثبت سفارش
|
||||
{{ usePriceWithoutType(parseInt(limitedPrice.value) ?? 0) }} ریال می باشد.
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="px-5 py-5 shadow-lg rounded-2xl text-white relative overflow-hidden shadow-lg"
|
||||
style=" background: linear-gradient(145deg, #a72b77 0%, #711d4d 40%, #a72b77 100%); "
|
||||
@@ -776,10 +767,6 @@ const updateData = (timeline) => {
|
||||
fetchPrices()
|
||||
}
|
||||
|
||||
const limitedPrice = computed(() => {
|
||||
if (walletStore.limitedPrice) return walletStore?.limitedPrice[0]
|
||||
})
|
||||
|
||||
const test_series = [
|
||||
{
|
||||
name: 'candle',
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
export type HomeLayoutId = 'default' | 'boursecu'
|
||||
|
||||
export type HomeSectionId =
|
||||
| 'limitedPriceAlert'
|
||||
| 'garoosiAssets'
|
||||
| 'mainActions'
|
||||
| 'boursecuQuickActions'
|
||||
|
||||
@@ -42,11 +42,6 @@
|
||||
<div v-else class="w-full h-[88px]">
|
||||
<GoldSkeleton class="w-full" />
|
||||
</div>
|
||||
<div v-if="limitedPrice !== undefined && userStore?.userInfo.trade_active !== 1"
|
||||
class="text-red text-xs flex gap-1 items-center justify-center my-2">
|
||||
<Icon icon="vuesax-linear:info-circle" size="16" />
|
||||
حداقل مبلغ اولیه برای ثبت سفارش {{ usePriceWithoutType(limitedPrice.value as number ?? 0) }} ریال می باشد.
|
||||
</div>
|
||||
<!-- </a-spin>-->
|
||||
<a-form ref="refInput" :model="form" class="!mt-5" name="basic" @finish="okConfirm()">
|
||||
<div class="border-gray-200 border-1 rounded-xl p-5 relative">
|
||||
@@ -505,11 +500,6 @@ const unitCashCalculator = computed(() => {
|
||||
return (walletStore?.walletInfo?.cash ?? 0) / 100
|
||||
})
|
||||
|
||||
const limitedPrice = computed(() => {
|
||||
if (walletStore.limitedPrice)
|
||||
return walletStore?.limitedPrice[0]
|
||||
})
|
||||
|
||||
function calculateCash(val: number) {
|
||||
priceErrorVisible.value = false
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<div class="w-full flex justify-between" v-for="item in props.item.transaction">
|
||||
<div class="flex items-center gap-1">
|
||||
<div class="w-7 h-7 flex justify-center rounded-lg bg-gray-100 ">
|
||||
<img width="30" class="p-1" :src="item.product.group_type=='گوی'?goyImg:mokaabImg">
|
||||
<ProductImage :product="item.product" img-class="p-1 max-h-full max-w-full object-contain" />
|
||||
</div>
|
||||
<div class="text-xs">{{ item?.title }}</div>
|
||||
</div>
|
||||
@@ -38,8 +38,7 @@
|
||||
<script setup lang="ts">
|
||||
import type {Physicalreceive} from "@/models/physicalreceive";
|
||||
import {toJalali} from "../../../../utils/useDateTime";
|
||||
import goyImg from "@/assets/img/goyImg.svg"
|
||||
import mokaabImg from "@/assets/img/mokaabImg.svg"
|
||||
import ProductImage from "@/components/ProductImage.vue";
|
||||
|
||||
interface Prop {
|
||||
item: Physicalreceive
|
||||
|
||||
@@ -38,11 +38,6 @@
|
||||
<div v-else class="w-full h-[88px]">
|
||||
<GoldSkeleton class="w-full" />
|
||||
</div>
|
||||
<div v-if="limitedPrice !== undefined && userStore?.userInfo.trade_active !== 1"
|
||||
class="text-red text-xs flex gap-1 items-center justify-center my-2">
|
||||
<Icon icon="vuesax-linear:info-circle" size="16" />
|
||||
حداقل مبلغ اولیه برای ثبت سفارش {{ usePriceWithoutType(limitedPrice.value as number ?? 0) }} ریال می باشد.
|
||||
</div>
|
||||
<!-- </a-spin>-->
|
||||
<a-form ref="refInput" :model="form" class="!mt-5" name="basic" @finish="okConfirm()" @finishFailed="(errorInfo) => { console.log('Form submit failed:', errorInfo); console.log('Error fields details:', JSON.stringify(errorInfo.errorFields, null, 2)); if (errorInfo.errorFields && errorInfo.errorFields.length > 0) { const firstError = errorInfo.errorFields[0]; console.log('First error field:', firstError.name, 'errors:', firstError.errors); message.error(firstError.errors?.[0] || 'لطفا تمام فیلدها را به درستی پر کنید') } }">
|
||||
<div class="border-gray-200 border-1 rounded-xl p-5 relative">
|
||||
@@ -552,11 +547,6 @@ const unitCashCalculator = computed(() => {
|
||||
return (walletStore?.walletInfo?.cash ?? 0) / 100
|
||||
})
|
||||
|
||||
const limitedPrice = computed(() => {
|
||||
if (walletStore.limitedPrice)
|
||||
return walletStore?.limitedPrice[0]
|
||||
})
|
||||
|
||||
function calculateCash(val: number) {
|
||||
priceErrorVisible.value = false
|
||||
console.log("val",val,props?.ProductItem)
|
||||
|
||||
Reference in New Issue
Block a user