fix some bugs
This commit is contained in:
+3
-1
@@ -41,7 +41,7 @@
|
|||||||
class="text-center text-xs"
|
class="text-center text-xs"
|
||||||
:class="isBoursecuProject() ? 'text-white' : ''"
|
:class="isBoursecuProject() ? 'text-white' : ''"
|
||||||
>
|
>
|
||||||
نسخه: {{ pkg.version }}
|
نسخه: {{ displayVersion }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="absolute bottom-10">
|
<div class="absolute bottom-10">
|
||||||
@@ -91,6 +91,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import pkg from '../package.json'
|
import pkg from '../package.json'
|
||||||
|
import { getDisplayAppVersion } from '@/config/config-cache'
|
||||||
import {useRegisterSW} from 'virtual:pwa-register/vue'
|
import {useRegisterSW} from 'virtual:pwa-register/vue'
|
||||||
import {computed, defineAsyncComponent, h, onMounted, ref, watch} from 'vue'
|
import {computed, defineAsyncComponent, h, onMounted, ref, watch} from 'vue'
|
||||||
import img_topGradiant from '@/views/login/assets/img/gr_top_white.svg'
|
import img_topGradiant from '@/views/login/assets/img/gr_top_white.svg'
|
||||||
@@ -126,6 +127,7 @@ const showDesktopFloatingCredit = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
useRegisterSW()
|
useRegisterSW()
|
||||||
|
const displayVersion = getDisplayAppVersion(pkg.version)
|
||||||
const config = useConfigStore()
|
const config = useConfigStore()
|
||||||
const splashIndicator = computed(() => h(LoadingOutlined, {
|
const splashIndicator = computed(() => h(LoadingOutlined, {
|
||||||
style: {
|
style: {
|
||||||
|
|||||||
@@ -91,6 +91,10 @@ export function getStoredAppVersion() {
|
|||||||
return localStorage.getItem(VERSION_STORAGE_KEY)
|
return localStorage.getItem(VERSION_STORAGE_KEY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getDisplayAppVersion(fallbackVersion: string) {
|
||||||
|
return getStoredAppVersion() || fallbackVersion
|
||||||
|
}
|
||||||
|
|
||||||
export function writeStoredAppVersion(version: string) {
|
export function writeStoredAppVersion(version: string) {
|
||||||
localStorage.setItem(VERSION_STORAGE_KEY, String(version).trim())
|
localStorage.setItem(VERSION_STORAGE_KEY, String(version).trim())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type {Order} from "@/models/order";
|
import type {Order} from "@/models/order";
|
||||||
|
import type { Product } from '@/models/products'
|
||||||
import type { Wallet } from '@/models/wallet'
|
import type { Wallet } from '@/models/wallet'
|
||||||
|
|
||||||
export interface Transaction {
|
export interface Transaction {
|
||||||
@@ -32,6 +33,7 @@ export interface Transaction {
|
|||||||
balance_gold?: number
|
balance_gold?: number
|
||||||
percentWallet?: number
|
percentWallet?: number
|
||||||
wallet?: Wallet
|
wallet?: Wallet
|
||||||
|
product?: Product
|
||||||
otp?: string
|
otp?: string
|
||||||
extra_note?: string
|
extra_note?: string
|
||||||
tracked_number: number
|
tracked_number: number
|
||||||
|
|||||||
@@ -603,14 +603,54 @@ export function getTradePriceUnitLabel() {
|
|||||||
return useSettingsStore().metalTypeLabel
|
return useSettingsStore().metalTypeLabel
|
||||||
}
|
}
|
||||||
|
|
||||||
/** برچسب قیمت حین معامله — معامله مقداری: نام و واحد همان محصول */
|
export type TransactionTradeProductSource = {
|
||||||
|
product?: (ProductUnitSource & { title?: string | null }) | null
|
||||||
|
wallet?: { product?: (ProductUnitSource & { title?: string | null }) | null } | null
|
||||||
|
title?: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
/** محصول معاملهشده — نه لزوماً همان کیف پول (مثلاً خرید مفتول با کیف کاتد) */
|
||||||
|
export function resolveTransactionTradeProduct(
|
||||||
|
item?: TransactionTradeProductSource | null,
|
||||||
|
): (ProductUnitSource & { title?: string | null }) | null {
|
||||||
|
if (!item) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const fromTransaction = item.product
|
||||||
|
if ((fromTransaction?.title ?? '').trim()) {
|
||||||
|
return fromTransaction ?? null
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = (item.title ?? '').trim()
|
||||||
|
const match = title.match(/^(?:خرید|فروش)\s+(.+)$/u)
|
||||||
|
if (match?.[1]?.trim()) {
|
||||||
|
return {
|
||||||
|
...(item.wallet?.product ?? {}),
|
||||||
|
title: match[1].trim(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return item.wallet?.product ?? null
|
||||||
|
}
|
||||||
|
|
||||||
|
/** برچسب قیمت حین معامله — نام و واحد همان محصول معاملهشده */
|
||||||
export function getTransactionTradePriceLabel(product?: (ProductUnitSource & { title?: string | null }) | null) {
|
export function getTransactionTradePriceLabel(product?: (ProductUnitSource & { title?: string | null }) | null) {
|
||||||
if (product && usesQuantityTrade(product)) {
|
if (!product) {
|
||||||
|
return `قیمت هر ${getWeightUnit()} ${getTradePriceUnitLabel()}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = (product.title ?? '').trim()
|
||||||
|
|
||||||
|
if (usesQuantityTrade(product)) {
|
||||||
const unit = getProductQuantityUnit(product)
|
const unit = getProductQuantityUnit(product)
|
||||||
const title = (product.title ?? '').trim()
|
|
||||||
return title ? `قیمت هر ${unit} ${title}` : `قیمت هر ${unit}`
|
return title ? `قیمت هر ${unit} ${title}` : `قیمت هر ${unit}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (title) {
|
||||||
|
return `قیمت هر ${getWeightUnit()} ${title}`
|
||||||
|
}
|
||||||
|
|
||||||
return `قیمت هر ${getWeightUnit()} ${getTradePriceUnitLabel()}`
|
return `قیمت هر ${getWeightUnit()} ${getTradePriceUnitLabel()}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+72
-33
@@ -108,11 +108,7 @@ _axios.interceptors.response.use(
|
|||||||
},
|
},
|
||||||
async function (error) {
|
async function (error) {
|
||||||
const response = error.response
|
const response = error.response
|
||||||
const config = error.config
|
const config = error.config as MyAxiosRequestConfig | undefined
|
||||||
|
|
||||||
if (response?.data?.message && response.status !== 401) {
|
|
||||||
checkStatus(response.data.message, response.status, config)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response?.status === 401) {
|
if (response?.status === 401) {
|
||||||
const hadAuth = Boolean(config?.headers?.Authorization)
|
const hadAuth = Boolean(config?.headers?.Authorization)
|
||||||
@@ -124,42 +120,85 @@ _axios.interceptors.response.use(
|
|||||||
scheduleSessionVerify()
|
scheduleSessionVerify()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (response?.status === 403) {
|
return Promise.reject(error)
|
||||||
message.error('شما دسترسی لازم برای انجام این عملیات را ندارید')
|
|
||||||
} else if (error.response && error.response.status == 422) {
|
|
||||||
// message.error(error.response.data?.message)
|
|
||||||
} else if (error.response) {
|
|
||||||
message.error('خطا در بارگذاری اطلاعات')
|
|
||||||
}
|
}
|
||||||
// Any status codes that falls outside the range of 2xx cause this function to trigger
|
|
||||||
// Do something with response error
|
|
||||||
|
|
||||||
//const { response, code, message, config } = error || {}
|
if (!shouldShowApiError(config)) {
|
||||||
//const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none'
|
return Promise.reject(error)
|
||||||
//const msg: string = response?.data?.error?.message ?? ''
|
}
|
||||||
//checkStatus(error?.response?.status, msg)
|
|
||||||
|
const apiMessage = extractApiErrorMessage(response?.data)
|
||||||
|
|
||||||
|
if (response?.status === 403) {
|
||||||
|
showApiError(apiMessage || 'شما دسترسی لازم برای انجام این عملیات را ندارید', config)
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response?.status === 422) {
|
||||||
|
if (apiMessage) {
|
||||||
|
showApiError(apiMessage, config)
|
||||||
|
}
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response) {
|
||||||
|
showApiError(apiMessage || DEFAULT_LOAD_ERROR, config)
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
showApiError(DEFAULT_LOAD_ERROR, config)
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
})
|
})
|
||||||
|
|
||||||
function checkStatus(msg: string, code: number, config: any) {
|
const DEFAULT_LOAD_ERROR = 'خطا در بارگذاری اطلاعات'
|
||||||
//const { code, data, message } = data
|
|
||||||
const errorMessage = get(config, 'meta.errorMessage', 'message')
|
function extractApiErrorMessage(data: unknown): string {
|
||||||
/*if (config.meta) {
|
if (!data || typeof data !== 'object') {
|
||||||
if (config.meta.message) {
|
return ''
|
||||||
errorMessage = config.meta.message
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
console.log('this is config', config)
|
|
||||||
if (errorMessage == 'none') return
|
|
||||||
switch (errorMessage) {
|
|
||||||
case 'message':
|
|
||||||
message.error(msg)
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
message.error(msg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const record = data as Record<string, unknown>
|
||||||
|
const rawMessage = record.message
|
||||||
|
|
||||||
|
if (typeof rawMessage === 'string' && rawMessage.trim()) {
|
||||||
|
return rawMessage.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof rawMessage === 'number') {
|
||||||
|
return String(rawMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
const rawError = record.error
|
||||||
|
if (typeof rawError === 'string' && rawError.trim()) {
|
||||||
|
return rawError.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
const errors = record.errors
|
||||||
|
if (errors && typeof errors === 'object') {
|
||||||
|
for (const value of Object.values(errors as Record<string, unknown>)) {
|
||||||
|
if (Array.isArray(value) && typeof value[0] === 'string' && value[0].trim()) {
|
||||||
|
return value[0].trim()
|
||||||
|
}
|
||||||
|
if (typeof value === 'string' && value.trim()) {
|
||||||
|
return value.trim()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function shouldShowApiError(config: MyAxiosRequestConfig | undefined): boolean {
|
||||||
|
return get(config, 'meta.errorMessage', 'message') !== 'none'
|
||||||
|
}
|
||||||
|
|
||||||
|
function showApiError(msg: string, config: MyAxiosRequestConfig | undefined) {
|
||||||
|
if (!shouldShowApiError(config)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
message.error(msg)
|
||||||
|
}
|
||||||
|
|
||||||
const myAxios = {
|
const myAxios = {
|
||||||
//AxiosResponse<T>
|
//AxiosResponse<T>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="item.order" :class="variant === 'desktop' ? 'dtxn-detail__row' : 'flex justify-between mb-3'">
|
<div v-if="item.order" :class="variant === 'desktop' ? 'dtxn-detail__row' : 'flex justify-between mb-3'">
|
||||||
<div :class="variant === 'desktop' ? 'dtxn-detail__label' : 'text-primary'">
|
<div :class="variant === 'desktop' ? 'dtxn-detail__label' : 'text-primary'">
|
||||||
{{ getTransactionTradePriceLabel(item.wallet?.product) }} حین معامله:
|
{{ getTransactionTradePriceLabel(tradeProduct) }} حین معامله:
|
||||||
</div>
|
</div>
|
||||||
<div :class="['flex text-xs items-center number-ltr', variant === 'desktop' ? 'dtxn-detail__value' : '']">
|
<div :class="['flex text-xs items-center number-ltr', variant === 'desktop' ? 'dtxn-detail__value' : '']">
|
||||||
<div class="text-base ml-1">{{ usePriceWithoutType(item.order?.price ?? 0) }}</div>
|
<div class="text-base ml-1">{{ usePriceWithoutType(item.order?.price ?? 0) }}</div>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div :class="variant === 'desktop' ? 'dtxn-detail__row' : 'flex justify-between mb-3'">
|
<div :class="variant === 'desktop' ? 'dtxn-detail__row' : 'flex justify-between mb-3'">
|
||||||
<div :class="variant === 'desktop' ? 'dtxn-detail__label' : 'text-primary'">
|
<div :class="variant === 'desktop' ? 'dtxn-detail__label' : 'text-primary'">
|
||||||
مقدار {{ item.wallet?.product ? item.wallet.product.title : getMeltedGoldTradeLabel() }} مبادله شده:
|
مقدار {{ tradeProductLabel }} مبادله شده:
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
:class="[
|
:class="[
|
||||||
@@ -38,10 +38,10 @@
|
|||||||
{{ item.unit }}
|
{{ item.unit }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="shouldShowTransactionTotalWeightLine(item.wallet?.product)"
|
v-if="shouldShowTransactionTotalWeightLine(tradeProduct)"
|
||||||
class="text-gray-500"
|
class="text-gray-500"
|
||||||
>
|
>
|
||||||
{{ getProductTotalWeightLabel(Math.abs(item.gold ?? 0), item.wallet?.product) }}
|
{{ getProductTotalWeightLabel(Math.abs(item.gold ?? 0), tradeProduct) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -107,6 +107,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
import { formatGoldAmount, usePriceWithoutType } from '@/utils/usePrice'
|
import { formatGoldAmount, usePriceWithoutType } from '@/utils/usePrice'
|
||||||
import type { Transaction } from '@/models/transaction'
|
import type { Transaction } from '@/models/transaction'
|
||||||
import {
|
import {
|
||||||
@@ -118,15 +119,21 @@ import {
|
|||||||
getProductUnitWeightLabel,
|
getProductUnitWeightLabel,
|
||||||
getTransactionTradePriceLabel,
|
getTransactionTradePriceLabel,
|
||||||
getWeightUnit,
|
getWeightUnit,
|
||||||
|
resolveTransactionTradeProduct,
|
||||||
shouldShowTransactionTotalWeightLine,
|
shouldShowTransactionTotalWeightLine,
|
||||||
} from '@/utils/productDealMethod'
|
} from '@/utils/productDealMethod'
|
||||||
import { toJalaliNotime, toTime } from '@/utils/useDateTime'
|
import { toJalaliNotime, toTime } from '@/utils/useDateTime'
|
||||||
|
|
||||||
withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
item: Transaction
|
item: Transaction
|
||||||
variant?: 'mobile' | 'desktop'
|
variant?: 'mobile' | 'desktop'
|
||||||
}>(),
|
}>(),
|
||||||
{ variant: 'mobile' },
|
{ variant: 'mobile' },
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const tradeProduct = computed(() => resolveTransactionTradeProduct(props.item))
|
||||||
|
const tradeProductLabel = computed(
|
||||||
|
() => (tradeProduct.value?.title ?? '').trim() || getMeltedGoldTradeLabel(),
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import pkg from '../../../../../package.json'
|
import pkg from '../../../../../package.json'
|
||||||
|
import { getDisplayAppVersion } from '@/config/config-cache'
|
||||||
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
|
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
|
||||||
import { useConfigStore } from '@/store/configStore'
|
import { useConfigStore } from '@/store/configStore'
|
||||||
import {
|
import {
|
||||||
@@ -54,7 +55,7 @@ const config = useConfigStore()
|
|||||||
const isBoursecu = isBoursecuProject()
|
const isBoursecu = isBoursecuProject()
|
||||||
const isSoroushgold = isSoroushgoldProject()
|
const isSoroushgold = isSoroushgoldProject()
|
||||||
const hasCustomLayout = hasCustomLoginLogoLayout() || isSoroushgold
|
const hasCustomLayout = hasCustomLoginLogoLayout() || isSoroushgold
|
||||||
const version = pkg.version
|
const version = getDisplayAppVersion(pkg.version)
|
||||||
|
|
||||||
const logo = computed(() => getProjectDesktopLoginBrandLogo(config.config?.avatar))
|
const logo = computed(() => getProjectDesktopLoginBrandLogo(config.config?.avatar))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user