This commit is contained in:
2025-12-21 17:22:27 +03:30
parent 80fe9168b6
commit 7fc6918ded
11 changed files with 160 additions and 70 deletions
+8 -5
View File
@@ -62,6 +62,9 @@ export function setEnableAuthenticate() {
function goToLogin(to: RouteLocationNormalized, next: NavigationGuardNext) {
if (to.name === 'buyProduct') {
return next() // Allow access to buyProduct without login
}
if (to.name !== 'login') {
return next({ name: 'login' }) // Redirect to login
} else {
@@ -135,9 +138,9 @@ router.beforeEach(async (to, from, next) => {
return next()
}
} else {
// If no token, handle redirect to login or allow access to login or 404
if (['login', '404'].includes(to.name as string)) {
return next() // Allow access to login or 404
// If no token, handle redirect to login or allow access to login, 404, or buyProduct
if (['login', '404', 'buyProduct'].includes(to.name as string)) {
return next() // Allow access to login, 404, or buyProduct
}
goToLogin(to, next) // Redirect to login if no token
}
@@ -153,8 +156,8 @@ router.beforeEach(async (to, from, next) => {
return next() // Proceed to the intended route
} else {
// If no token, ensure proper redirection to login or 404
if (['login', '404'].includes(to.name as string)) {
return next() // Allow access to login or 404
if (['login', '404', 'buyProduct'].includes(to.name as string)) {
return next() // Allow access to login, 404, or buyProduct
}
return next({ name: 'login' })
}
+2 -1
View File
@@ -3,6 +3,7 @@ export interface Gold {
goldValue?: number | null,
percentWallet?: number,
method?:string,
goldVazn?: number | null
goldVazn?: number | null,
gateway?: boolean
}
+1
View File
@@ -20,4 +20,5 @@ export interface Order {
"product_id"?:number
"method"?:string
"number"?:number
"gateway"?:boolean
}
+1 -1
View File
@@ -17,7 +17,7 @@ const router = createRouter({
{
path: `/`,
name: 'main',
redirect: {name: 'login'},
redirect: {name: 'buyProduct'},
component: () => import('../views/base/index.vue'),
children: [
{
+16 -12
View File
@@ -135,6 +135,7 @@ let methodP = 'cash'
let amountP = 0
let isBuyP = true
let NumP = 0
let gatewayP = false
const checkNumber = async (_rule: Rule, value: number) => {
@@ -145,18 +146,20 @@ const checkNumber = async (_rule: Rule, value: number) => {
return Promise.reject('استفاده از اعداد اعشاری مجاز نمی باشد')
}
if (isBuyP) {
if (!walletCash?.walletInfo?.cash && methodP == 'cash') {
return Promise.reject('موجودی کیف پول ناکافی است')
// Skip wallet balance check if gateway is enabled
if (!gatewayP) {
if (!walletCash?.walletInfo?.cash && methodP == 'cash') {
return Promise.reject('موجودی کیف پول ناکافی است')
}
if (!walletCash?.walletInfo?.gold && methodP == 'gold') {
return Promise.reject('موجودی کیف طلا ناکافی است')
}
if (priceP * value > walletCash?.walletInfo?.cash && methodP == 'cash')
return Promise.reject('موجودی کیف پول ناکافی است')
if (amountP * value > walletCash?.walletInfo?.gold && methodP == 'gold')
return Promise.reject('موجودی کیف طلا ناکافی است')
}
if (!walletCash?.walletInfo?.gold && methodP == 'gold') {
return Promise.reject('موجودی کیف طلا ناکافی است')
}
if (priceP * value > walletCash?.walletInfo?.cash && methodP == 'cash')
return Promise.reject('موجودی کیف پول ناکافی است')
if (amountP * value > walletCash?.walletInfo?.gold && methodP == 'gold')
return Promise.reject('موجودی کیف طلا ناکافی است')
else
return Promise.resolve()
return Promise.resolve()
} else {
if (value > NumP)
return Promise.reject('موجودی محصول ناکافی است')
@@ -165,11 +168,12 @@ const checkNumber = async (_rule: Rule, value: number) => {
}
}
export const justNumber2 = (price: number, method?: string, amount?: number, isBuy?: boolean) => {
export const justNumber2 = (price: number, method?: string, amount?: number, isBuy?: boolean, gateway?: boolean) => {
priceP = price
methodP = method
amountP = amount
isBuyP = isBuy
gatewayP = gateway ?? false
return {
required: true,
validator: checkNumber,
+4 -2
View File
@@ -65,8 +65,10 @@ _axios.interceptors.response.use(
///removeToken()
console.log('error')
removeToken()
// router.push({ name: 'login' })
await router.push({name: 'login'})
// Don't redirect to login if user is on buyProduct page
if (router.currentRoute.value.name !== 'buyProduct') {
await router.push({name: 'login'})
}
} else if (error.response && error.response.status == 403) {
message.error('شما دسترسی لازم برای انجام این عملیات را ندارید')
} else if (error.response && error.response.status == 422) {
+7
View File
@@ -43,6 +43,13 @@
<div>دریافت طلای فیزیکی</div>
</div>
</BasicButton>
<BasicButton icon-size="16" class="!font-bold w-15rem"
@click="$router.push({name: 'buyProduct'}); popVisible = false">
<div class="flex gap-2 items-center">
<BasicIcon icon="vuesax-linear:products" size="16" class="absolute right-2" />
<div>محصولات</div>
</div>
</BasicButton>
<BasicButton icon-size="16" class="!font-bold w-15rem"
@click="openReceivesList(); popVisible = false">
<div class="flex gap-2 items-center">
@@ -44,7 +44,7 @@
حداقل مبلغ اولیه برای ثبت سفارش {{ usePriceWithoutType(limitedPrice.value as number ?? 0) }} ریال می باشد.
</div>
<!-- </a-spin>-->
<a-form ref="refInput" :model="form" class="!mt-5" name="basic" @finish="okConfirm()">
<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">
<bg_main />
<div class="z-100 relative">
@@ -60,7 +60,7 @@
</a-form-item>
<a-form-item v-if="isBuy" name="goldValue"
:rules="[justNumber2(props?.ProductItem?.price , form.method , props?.ProductItem?.amount, true)]">
:rules="[justNumber2(props?.ProductItem?.price , form.method , props?.ProductItem?.amount, true, form.gateway)]">
<BasicInput v-model:value="form.goldValue" addon-before="تعداد" addon-bg-color="#521620"
addon-text-color="white"
place-holder="تعداد"
@@ -104,6 +104,16 @@
</Transition>
</div>
</div>
<a-form-item-rest v-if="isBuy && form.method === 'cash'">
<div class="mt-4 w-full px-6 rounded-xl py-1 border-1 bg-white">
<div class="flex justify-between items-center">
<div>استفاده از درگاه:</div>
<div class="flex gap-2 items-center">
<a-switch v-model:checked="form.gateway" size="small" />
</div>
</div>
</div>
</a-form-item-rest>
<GoldLoading v-model:show="infoVisible" title="" />
<a-form-item>
<BasicButton
@@ -112,6 +122,7 @@
class=" w-full py-2 mt-5"
html-type="submit"
type="primary"
@click="() => console.log('Button clicked, disabled:', disableTransaction, 'walletStore:', !!walletStore)"
>
<div>
<a-spin v-if="loading" size="small" />
@@ -221,25 +232,24 @@
</div>
</div>
<BasicButton class="mb-20 mt-5 w-full" type="primary" @click="ok(); confirmAction= false">ثبت نهایی</BasicButton>
<BasicButton class="mb-20 mt-5 w-full" type="primary" @click="() => { ok(); confirmAction = false }">ثبت نهایی</BasicButton>
</BasicActionSheet>
</template>
<script lang="ts" setup>
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { computed, onMounted, ref, watch } from 'vue'
import img1 from '@/assets/img/home_ly2.svg'
import {useFormat, usePrice, usePriceWithoutType, useTowDecimal} from '@/utils/usePrice'
import {useFormat, usePrice, usePriceWithoutType} from '@/utils/usePrice'
import BasicInput from '@/components/BasicPacks/BasicInput.vue'
import type { Gold } from '@/models/gold'
import { loading, loadingMore, toFixedDownThreeChar } from '@/utils'
import { loading, loadingMore } from '@/utils'
import BasicButton from '@/components/BasicPacks/BasicButton.vue'
import router from '@/router'
import { useWalletStore } from '@/store/walletStore'
import { createOrder } from '@/api/order'
import { FormInstance, message } from 'ant-design-vue'
import type { Price } from '@/models/home'
// import {getLastPrice} from '@/api/home'
import Icon from '@/components/BasicPacks/BasicIcon.vue'
import { useUserStore } from '@/store/userStore'
import BasicActionSheet from '@/components/BasicPacks/BasicActionSheet.vue'
@@ -250,15 +260,14 @@ import GoldLoading from '@/components/GoldLoading.vue'
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import type { Transaction } from '@/models/transaction'
import type { TableEngineInput, TableOutput } from '@/models/table'
import { useInfiniteScroll } from '@vueuse/core'
import { getTransactionTable } from '@/api/transaction'
import { getLastPrices, lastPrice, setIntervalGetAllPrice, stopPriceInterval } from '@/utils/price'
import { getLastPrices, lastPrice } from '@/utils/price'
import { Product } from '@/models/products'
import BasicSelect from '@/components/BasicPacks/BasicSelect.vue'
import { SelectItem } from '@/models/SelectItem'
import Bg_main from '@/components/bg_main.vue'
import { useFundUserStore } from '@/store/fundStore'
// import Bg_main from "@/components/bg_main.vue";
const typeDeal: SelectItem[] = [
{
value: 'نقدی',
@@ -324,15 +333,30 @@ const finalPrice = computed(() => (form.value?.goldValue * (isBuy.value ? props.
// const payablePrice = computed(() => finalPrice.value + finalPrice.value * 0.007)
const payablePrice = computed(() => finalPrice.value)
const disableTransaction = computed(() =>
loading.value ||
form.value?.goldValue === undefined ||
form.value?.goldValue === '' ||
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) ||
price.value?.buy === undefined)
const disableTransaction = computed(() => {
// If gateway is enabled, skip wallet balance checks
if (isBuy.value && form.value?.gateway) {
return (
loading.value ||
form.value?.goldValue === undefined ||
form.value?.goldValue === '' ||
form.value?.goldCash === '' ||
form.value?.goldCash === undefined ||
price.value?.buy === undefined
)
}
// Normal validation when gateway is disabled
return (
loading.value ||
form.value?.goldValue === undefined ||
form.value?.goldValue === '' ||
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) ||
price.value?.buy === undefined
)
})
function refreshTable() {
sellItems.value = []
@@ -442,8 +466,10 @@ const form = ref<Gold>({
goldValue: undefined,
percentWallet: undefined,
method: 'cash',
goldVazn:undefined
goldVazn:undefined,
gateway: false
})
const allowedAsciiCodeFloat = [46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57]
// const allowedAsciiCodeInt = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57]
watch(form.value, () => {
@@ -454,8 +480,26 @@ watch(form.value, () => {
calculateCash(form.value.goldValue)
}
}
})
// Re-validate when gateway changes
watch(() => form.value.gateway, () => {
if (isBuy.value && form.value.goldValue) {
// Clear validation errors and re-validate
refInput.value?.clearValidate('goldValue')
setTimeout(() => {
refInput.value?.validateFields(['goldValue']).catch(() => {
// Ignore validation errors, just trigger re-validation
})
}, 100)
}
})
// Reset gateway when method changes to non-cash
watch(() => form.value.method, (newMethod) => {
if (newMethod !== 'cash' && form.value.gateway) {
form.value.gateway = false
}
})
onMounted(() => {
@@ -508,7 +552,6 @@ const limitedPrice = computed(() => {
function calculateCash(val: number) {
priceErrorVisible.value = false
// console.log(val)
if (price.value) {
form.value.goldVazn = parseFloat((val * (( props?.ProductItem?.price) + (props?.ProductItem?.cash_fee_buy)))/lastPrice.value?.buy).toFixed(1)
@@ -520,7 +563,6 @@ console.log(val,props?.ProductItem?.price,props?.ProductItem?.cash_fee_buy,lastP
else {
form.value.goldCash = 0
form.value.goldVazn = 0
}
}
else {
@@ -581,7 +623,6 @@ function useStyle() {
else return ' right: 98%; transform: translate(100%, 0);'
}
function setIsBuy(val: boolean) {
isBuy.value = val
form.value.goldValue = undefined
@@ -602,13 +643,7 @@ const formatter = (value: number) => {
return `${value}%`
}
const price = computed((): Price => <Price>lastPrice.value ?? 0)
onMounted(async () => {
// await initPrice()
// await setIntervalGetPrice()
// console.log('okkkkkkkkgold')
})
async function initPrice() {
try {
@@ -627,36 +662,68 @@ async function initPrice() {
}
}
// onMounted(() => {
// initPrice()
// })
function okConfirm() {
confirmAction.value = true
refInput.value?.validateFields()
async function okConfirm() {
try {
console.log('okConfirm called, form values:', form.value)
console.log('disableTransaction:', disableTransaction.value)
await refInput.value?.validateFields()
console.log('Validation passed, showing confirmation action sheet')
// If validation passes, show confirmation action sheet
confirmAction.value = true
console.log('confirmAction set to:', confirmAction.value)
} catch (error) {
// Validation failed, don't show action sheet
console.error('Validation failed:', error)
message.error('لطفا تمام فیلدها را به درستی پر کنید')
}
}
async function ok() {
console.log('ok() function called')
try {
loading.value = true
infoVisible.value = true
await createOrder({
const data = await createOrder({
direction: isBuy.value ? 1 : 2,
price: isBuy.value ? price.value?.buy : price.value?.sell,
amount: form.value.goldValue ?? 0,
gateway: form.value.gateway,
product_id: props.ProductItem.id,
method: form.value.method,
number: form.value.goldValue ?? 0
})
// console.log('Order response:', data) // Debug log
// Check if response has returnUrl (for gateway payment)
let returnUrl = null
if (Array.isArray(data)) {
const itemWithReturnUrl = data.find(item => item?.returnUrl)
returnUrl = itemWithReturnUrl?.returnUrl
} else if (data?.returnUrl) {
returnUrl = data.returnUrl
}
console.log('Return URL:', returnUrl) // Debug log
// If returnUrl exists, redirect to gateway and stop execution
if (returnUrl) {
window.location.href = returnUrl
return // Stop execution here
}
// If no gateway, continue with normal flow
await walletStore.getMyWallet()
await router.push({ name: 'transactions' })
form.value = {
goldValue: undefined,
goldCash: undefined,
percentWallet: undefined,
method: 'cash'
method: 'cash',
gateway: false
}
// refreshTable()
await fundStore.getMyFund()
message.success('سفارش شما با موفقیت انجام شد')
await fundStore.getMyFund()
} catch (e) {
// console.log(e)
// await initPrice()
@@ -706,7 +773,6 @@ async function ok() {
}
}
.animate.right {
right: 0;
}
+13 -8
View File
@@ -5,9 +5,7 @@
/>
</div>
<a-spin :spinning="loading">
<div class=" !h-full overflow-y-scroll">
<div class="w-full flex justify-center top-0 py-5" style="align-self: center">
<ARadioGroup @change="changeTab" v-model:value="activekey" button-style="solid">
<ARadioButton class="cats" value="همه">همه</ARadioButton>
@@ -44,15 +42,11 @@ import { getProducts } from '@/api/products'
import {
getLastPrices,
lastPrice,
setIntervalGetAllPrice,
// setIntervalGetLastPrice,
stopPriceInterval
} from '@/utils/price'
import { loading } from '@/utils'
import { Price } from '@/models/home'
import type { Product } from '@/models/products'
import BasicButton from '@/components/BasicPacks/BasicButton.vue'
import BaseDatePicker from '@/components/BasicPacks/BaseDatePicker/src/BaseDatePicker.vue'
import BasicActionSheet from '@/components/BasicPacks/BasicActionSheet.vue'
import indexGold from '@/views/base/gold/index.vue'
import DealProduct from '@/views/base/products/components/DealProduct.vue'
@@ -98,8 +92,14 @@ onMounted(async () => {
// await setIntervalGetLastPrice()
// console.log('run product')
} catch (e) {
} catch (e: any) {
console.log(e)
// If 401 error, set empty items to show page without products
if (e?.response?.status === 401) {
items.value = []
firstItems.value = []
typeItems.value = []
}
} finally {
loading.value = false
if (router.currentRoute.value.query.cat=="coin"){
@@ -146,8 +146,13 @@ async function initPrice() {
// await setIntervalGetPrice()
loading.value = true
price.value = lastPrice.value
} catch (e) {
} catch (e: any) {
console.log(e)
// If 401 error, just skip price initialization
if (e?.response?.status === 401) {
// Price will not be available, but page can still be shown
price.value = undefined
}
} finally {
loading.value = false
// chartLoading.value = false
-1
View File
@@ -59,7 +59,6 @@
متوجه شدم
</div>
</template>
</DialogVantOneButton>
<!-- <van-dialog/>-->