change prices &...
This commit is contained in:
Vendored
+2
@@ -25,6 +25,7 @@ declare module 'vue' {
|
|||||||
ATag: typeof import('ant-design-vue/es')['Tag']
|
ATag: typeof import('ant-design-vue/es')['Tag']
|
||||||
ATextarea: typeof import('ant-design-vue/es')['Textarea']
|
ATextarea: typeof import('ant-design-vue/es')['Textarea']
|
||||||
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
||||||
|
AUpload: typeof import('ant-design-vue/es')['Upload']
|
||||||
BaseDatePicker: typeof import('./src/components/BasicPacks/BaseDatePicker/src/BaseDatePicker.vue')['default']
|
BaseDatePicker: typeof import('./src/components/BasicPacks/BaseDatePicker/src/BaseDatePicker.vue')['default']
|
||||||
Basic: typeof import('./src/components/BasicPacks/BaseDatePicker/src/datePick/demo/basic.vue')['default']
|
Basic: typeof import('./src/components/BasicPacks/BaseDatePicker/src/datePick/demo/basic.vue')['default']
|
||||||
BasicActionSheet: typeof import('./src/components/BasicPacks/BasicActionSheet.vue')['default']
|
BasicActionSheet: typeof import('./src/components/BasicPacks/BasicActionSheet.vue')['default']
|
||||||
@@ -54,6 +55,7 @@ declare module 'vue' {
|
|||||||
ListAnim: typeof import('./src/components/ListAnim.vue')['default']
|
ListAnim: typeof import('./src/components/ListAnim.vue')['default']
|
||||||
Mode: typeof import('./src/components/BasicPacks/BaseDatePicker/src/datePick/demo/mode.vue')['default']
|
Mode: typeof import('./src/components/BasicPacks/BaseDatePicker/src/datePick/demo/mode.vue')['default']
|
||||||
PresettedRanges: typeof import('./src/components/BasicPacks/BaseDatePicker/src/datePick/demo/presetted-ranges.vue')['default']
|
PresettedRanges: typeof import('./src/components/BasicPacks/BaseDatePicker/src/datePick/demo/presetted-ranges.vue')['default']
|
||||||
|
ProfileAvatarUpload: typeof import('./src/components/ProfileAvatarUpload.vue')['default']
|
||||||
RangePicker: typeof import('./src/components/BasicPacks/BaseDatePicker/src/datePick/demo/range-picker.vue')['default']
|
RangePicker: typeof import('./src/components/BasicPacks/BaseDatePicker/src/datePick/demo/range-picker.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import useAxios from '@/utils/useAxios'
|
||||||
|
|
||||||
|
export interface AvatarUploadResponse {
|
||||||
|
id: number
|
||||||
|
src?: string
|
||||||
|
full_src?: string
|
||||||
|
title?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/** POST multipart — expects backend route POST /customer/avatar */
|
||||||
|
export const uploadAvatar = async (file: File) => {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', file)
|
||||||
|
return useAxios.postForm<AvatarUploadResponse>('/customer/avatar', formData)
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex flex-col items-center gap-2">
|
||||||
|
<div class="relative">
|
||||||
|
<div
|
||||||
|
class="w-24 h-24 rounded-full overflow-hidden border-2 border-gray-200 bg-gray-100 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-if="previewUrl"
|
||||||
|
:src="previewUrl"
|
||||||
|
alt="عکس پروفایل"
|
||||||
|
class="w-full h-full object-cover"
|
||||||
|
/>
|
||||||
|
<BasicIcon v-else icon="vuesax-linear:user" size="40" color="#9CA3AF" />
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
v-if="previewUrl && !uploading"
|
||||||
|
type="button"
|
||||||
|
class="absolute bottom-0 left-0 z-10 p-1 rounded-full bg-white shadow"
|
||||||
|
aria-label="حذف عکس"
|
||||||
|
@click.stop="onRemove"
|
||||||
|
>
|
||||||
|
<BasicIcon icon="vuesax-linear:trash" class="text-red-600" size="18" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a-upload
|
||||||
|
name="file"
|
||||||
|
:show-upload-list="false"
|
||||||
|
accept="image/jpeg,image/png,image/webp,image/gif"
|
||||||
|
:disabled="uploading"
|
||||||
|
:before-upload="beforeUpload"
|
||||||
|
:custom-request="customRequest"
|
||||||
|
>
|
||||||
|
<BasicButton size="small" type="default" :disabled="uploading">
|
||||||
|
<a-spin v-if="uploading" size="small" class="ml-1" />
|
||||||
|
{{ previewUrl ? 'تغییر عکس' : 'انتخاب عکس پروفایل' }}
|
||||||
|
</BasicButton>
|
||||||
|
</a-upload>
|
||||||
|
<p class="text-xs text-gray-500 text-center">فرمت jpg، png یا webp — حداکثر ۲ مگابایت</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue'
|
||||||
|
import { message, Upload } from 'ant-design-vue'
|
||||||
|
import type { UploadProps } from 'ant-design-vue'
|
||||||
|
|
||||||
|
type UploadRequestOption = Parameters<NonNullable<UploadProps['customRequest']>>[0]
|
||||||
|
import BasicButton from '@/components/BasicPacks/BasicButton.vue'
|
||||||
|
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
|
||||||
|
import { uploadAvatar } from '@/api/avatar'
|
||||||
|
import { getFileUrl } from '@/utils/file'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
imageUrl?: string | null
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'uploaded', payload: { id: number; url: string }): void
|
||||||
|
(e: 'removed'): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const previewUrl = ref<string | null>(null)
|
||||||
|
const uploading = ref(false)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.imageUrl,
|
||||||
|
(url) => {
|
||||||
|
previewUrl.value = url || null
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
function beforeUpload(file: File) {
|
||||||
|
if (!file.type.startsWith('image/')) {
|
||||||
|
message.error('فقط فایل تصویری مجاز است')
|
||||||
|
return Upload.LIST_IGNORE
|
||||||
|
}
|
||||||
|
if (file.size / 1024 / 1024 > 2) {
|
||||||
|
message.error('حجم تصویر نباید بیشتر از ۲ مگابایت باشد')
|
||||||
|
return Upload.LIST_IGNORE
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
async function customRequest(options: UploadRequestOption) {
|
||||||
|
const file = options.file as File
|
||||||
|
uploading.value = true
|
||||||
|
const localPreview = URL.createObjectURL(file)
|
||||||
|
previewUrl.value = localPreview
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await uploadAvatar(file)
|
||||||
|
const url = res.full_src || getFileUrl(res) || localPreview
|
||||||
|
previewUrl.value = url
|
||||||
|
if (res.id != null) {
|
||||||
|
emit('uploaded', { id: res.id, url })
|
||||||
|
message.success('عکس پروفایل آپلود شد')
|
||||||
|
options.onSuccess?.(res)
|
||||||
|
} else {
|
||||||
|
throw new Error('invalid response')
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
previewUrl.value = props.imageUrl || null
|
||||||
|
message.error('آپلود عکس انجام نشد. (احتمالاً API سرور هنوز آماده نیست)')
|
||||||
|
options.onError?.(new Error('upload failed'))
|
||||||
|
} finally {
|
||||||
|
uploading.value = false
|
||||||
|
if (localPreview.startsWith('blob:')) {
|
||||||
|
URL.revokeObjectURL(localPreview)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRemove() {
|
||||||
|
previewUrl.value = null
|
||||||
|
emit('removed')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -15,6 +15,7 @@ export interface Series {
|
|||||||
export interface Price {
|
export interface Price {
|
||||||
sell: number
|
sell: number
|
||||||
buy: number
|
buy: number
|
||||||
|
price: number
|
||||||
price_last: number
|
price_last: number
|
||||||
goldir:number
|
goldir:number
|
||||||
}
|
}
|
||||||
+5
-1
@@ -19,7 +19,11 @@ export interface User {
|
|||||||
name: string;
|
name: string;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
mobile: string;
|
mobile: string;
|
||||||
avatar_id?: any;
|
avatar_id?: number | null;
|
||||||
|
avatar_url?: string | null;
|
||||||
|
full_src?: string | null;
|
||||||
|
avatar?: { id?: number; src?: string; full_src?: string; url?: string };
|
||||||
|
file?: { id?: number; src?: string; full_src?: string; url?: string };
|
||||||
last_seen_at: string;
|
last_seen_at: string;
|
||||||
default_address_id?: any;
|
default_address_id?: any;
|
||||||
sts?: any;
|
sts?: any;
|
||||||
|
|||||||
+2
-2
@@ -10,8 +10,8 @@ const projectName = getConfigApp('name')
|
|||||||
|
|
||||||
export const baseURL: string = projectBase
|
export const baseURL: string = projectBase
|
||||||
// export const baseURL: string = 'https://api-gholaktala.z23.ir/'
|
// export const baseURL: string = 'https://api-gholaktala.z23.ir/'
|
||||||
// const baseUploadURL: string = '/site/file'
|
/** Customer profile image upload (backend: POST /customer/avatar) */
|
||||||
// const uploadURL: string = baseURL + baseUploadURL
|
export const avatarUploadURL: string = `${projectBase.replace(/\/$/, '')}/customer/avatar`
|
||||||
// const baseURLStorage: string = baseURL + '/v1'
|
// const baseURLStorage: string = baseURL + '/v1'
|
||||||
const prefixCls: string = 'noname'
|
const prefixCls: string = 'noname'
|
||||||
// const version: string = pkg.version
|
// const version: string = pkg.version
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
import { baseURL } from '@/themeConfig'
|
import { baseURL } from '@/themeConfig'
|
||||||
|
import type { User } from '@/models/login'
|
||||||
|
|
||||||
export interface ProductFile {
|
export interface ProductFile {
|
||||||
id?: number
|
id?: number
|
||||||
url?: string | null
|
url?: string | null
|
||||||
src?: string
|
src?: string
|
||||||
|
full_src?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFileUrl(file?: ProductFile | null): string | null {
|
export function getFileUrl(file?: ProductFile | null): string | null {
|
||||||
if (!file) return null
|
if (!file) return null
|
||||||
|
if (file.full_src) return file.full_src
|
||||||
if (file.url) return file.url
|
if (file.url) return file.url
|
||||||
if (!file.src) return null
|
if (!file.src) return null
|
||||||
if (/^https?:\/\//i.test(file.src)) return file.src
|
if (/^https?:\/\//i.test(file.src)) return file.src
|
||||||
@@ -15,3 +18,12 @@ export function getFileUrl(file?: ProductFile | null): string | null {
|
|||||||
const path = file.src.replace(/^\//, '')
|
const path = file.src.replace(/^\//, '')
|
||||||
return `${base}/${path}`
|
return `${base}/${path}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Resolve profile avatar URL from GET /customer/me payload */
|
||||||
|
export function getUserAvatarUrl(user?: User | null): string | null {
|
||||||
|
if (!user) return null
|
||||||
|
if (typeof user.avatar_url === 'string' && user.avatar_url) return user.avatar_url
|
||||||
|
if (typeof user.full_src === 'string' && user.full_src) return user.full_src
|
||||||
|
const nested = user.avatar || user.file
|
||||||
|
return getFileUrl(nested as ProductFile | undefined)
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="config.config.name === 'garoosi'" class="wrap-fix bottom-0 px-10 pb-3rem flex gap-2 bg-white">
|
<div v-if="config.config.name === 'garoosi'" class="wrap-fix bottom-0 px-10 pb-3rem flex gap-2 bg-white">
|
||||||
<a class="w-full" href="tel:09306612518">
|
<a class="w-full" href="tel:09031265925">
|
||||||
<BasicButton class="w-full" type="primary">تماس با پشتیبانی</BasicButton>
|
<BasicButton class="w-full" type="primary">تماس با پشتیبانی</BasicButton>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://ble.ir/garoosigallery">
|
<a href="https://ble.ir/garoosigallery">
|
||||||
|
|||||||
@@ -308,8 +308,17 @@ const finalPrice = computed(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const payablePrice = computed(() => finalPrice.value)
|
const payablePrice = computed(() =>
|
||||||
const equivalentPrice = computed(() => usePriceWithoutType(((isBuy ? price.value?.buy ?? 0 : price.value?.sell ?? 0) * (parseFloat(((form.value?.goldValue ?? 0) * 0.01).toFixed(4))) ).toFixed(0)) )
|
isBuy.value ? finalPrice.value + feeInRial.value : finalPrice.value - feeInRial.value
|
||||||
|
)
|
||||||
|
const feeInGrams = computed(() =>
|
||||||
|
parseFloat(((form.value?.goldValue ?? 0) * 0.01).toFixed(4))
|
||||||
|
)
|
||||||
|
const unitPrice = computed(() =>
|
||||||
|
(props?.ProductItem?.price_profit ?? 0) + (props?.ProductItem?.price ?? 0)
|
||||||
|
)
|
||||||
|
const feeInRial = computed(() => unitPrice.value * feeInGrams.value)
|
||||||
|
const equivalentPrice = computed(() => usePriceWithoutType(feeInRial.value.toFixed(0)))
|
||||||
|
|
||||||
const disableTransaction = computed(() =>
|
const disableTransaction = computed(() =>
|
||||||
loading.value ||
|
loading.value ||
|
||||||
@@ -506,6 +515,28 @@ const limitedPrice = computed(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
function syncFormWithLatestPrice() {
|
||||||
|
if (!price.value) return
|
||||||
|
|
||||||
|
const goldValue = form.value.goldValue
|
||||||
|
if (goldValue !== undefined && goldValue !== null && goldValue !== '' && !isNaN(Number(goldValue))) {
|
||||||
|
calculateCash(Number(goldValue))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const goldCash = form.value.goldCash
|
||||||
|
if (goldCash !== undefined && goldCash !== null && goldCash !== '' && !isNaN(Number(goldCash))) {
|
||||||
|
calculateGold(Number(goldCash))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [basePriceValue.value, isBuy.value],
|
||||||
|
() => {
|
||||||
|
syncFormWithLatestPrice()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
function calculateCash(val: number) {
|
function calculateCash(val: number) {
|
||||||
priceErrorVisible.value = false
|
priceErrorVisible.value = false
|
||||||
if (price.value) {
|
if (price.value) {
|
||||||
@@ -597,10 +628,10 @@ const formatter = (value: number) => {
|
|||||||
const price = computed((): Price => <Price>lastPrice.value ?? 0)
|
const price = computed((): Price => <Price>lastPrice.value ?? 0)
|
||||||
|
|
||||||
const goldPriceValue = computed(() => {
|
const goldPriceValue = computed(() => {
|
||||||
if (!price.value) return 0
|
if (!lastPrice.value?.price) return 0
|
||||||
return isBuy.value
|
return isBuy.value
|
||||||
? (price.value.buy ?? 0)
|
? (lastPrice.value.buy ?? 0)
|
||||||
: (price.value.sell ?? 0)
|
: (lastPrice.value.sell ?? 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
async function initPrice() {
|
async function initPrice() {
|
||||||
|
|||||||
@@ -89,7 +89,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="config.config.name === 'garoosi'" class="wrap-fix bottom-0 px-10 py-6 flex gap-2 bg-white">
|
<div v-if="config.config.name === 'garoosi'" class="wrap-fix bottom-0 px-10 py-6 flex gap-2 bg-white">
|
||||||
<a class="w-full" href="tel:09306612518">
|
<a class="w-full" href="tel:09031265925">
|
||||||
<BasicButton class="w-full" type="primary">تماس با پشتیبانی</BasicButton>
|
<BasicButton class="w-full" type="primary">تماس با پشتیبانی</BasicButton>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://ble.ir/garoosigallery">
|
<a href="https://ble.ir/garoosigallery">
|
||||||
|
|||||||
@@ -167,7 +167,7 @@
|
|||||||
<div class="flex justify-between mt-3">
|
<div class="flex justify-between mt-3">
|
||||||
<div>کارمزد:</div>
|
<div>کارمزد:</div>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<div class="font-bold text-xl">{{ parseFloat(((form.goldValue ?? 0) * (Number(feeAmount))).toFixed(4)) }}</div>
|
<div class="font-bold text-xl">{{ feeInGrams }}</div>
|
||||||
<div class="text-xs mr-1">گرم</div>
|
<div class="text-xs mr-1">گرم</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -274,10 +274,18 @@ const sellPagination = ref<TableEngineInput>({
|
|||||||
}], limit: 6, page: 0
|
}], limit: 6, page: 0
|
||||||
})
|
})
|
||||||
|
|
||||||
const finalPrice = computed(() => (form.value?.goldValue * (isBuy.value ? price.value?.buy ?? 0 : price.value?.sell ?? 0)))
|
const unitPrice = computed(() =>
|
||||||
// const payablePrice = computed(() => finalPrice.value + finalPrice.value * 0.007)
|
isBuy.value ? price.value?.buy ?? 0 : price.value?.sell ?? 0
|
||||||
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 feeInGrams = computed(() =>
|
||||||
|
parseFloat(((form.value?.goldValue ?? 0) * Number(feeAmount.value)).toFixed(4))
|
||||||
|
)
|
||||||
|
const finalPrice = computed(() => (form.value?.goldValue ?? 0) * unitPrice.value)
|
||||||
|
const feeInRial = computed(() => unitPrice.value * feeInGrams.value)
|
||||||
|
const equivalentPrice = computed(() => usePriceWithoutType(feeInRial.value.toFixed(0)))
|
||||||
|
const payablePrice = computed(() =>
|
||||||
|
isBuy.value ? finalPrice.value + feeInRial.value : finalPrice.value - feeInRial.value
|
||||||
|
)
|
||||||
|
|
||||||
const disableTransaction = computed(() =>
|
const disableTransaction = computed(() =>
|
||||||
loading.value ||
|
loading.value ||
|
||||||
@@ -472,6 +480,28 @@ const limitedPrice = computed(() => {
|
|||||||
return walletStore?.limitedPrice[0]
|
return walletStore?.limitedPrice[0]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function syncFormWithLatestPrice() {
|
||||||
|
if (!price.value) return
|
||||||
|
|
||||||
|
const goldValue = form.value.goldValue
|
||||||
|
if (goldValue !== undefined && goldValue !== null && goldValue !== '' && !isNaN(Number(goldValue))) {
|
||||||
|
calculateCash(Number(goldValue))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const goldCash = form.value.goldCash
|
||||||
|
if (goldCash !== undefined && goldCash !== null && goldCash !== '' && !isNaN(Number(goldCash))) {
|
||||||
|
calculateGold(Number(goldCash))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [lastPrice.value?.buy, lastPrice.value?.sell, isBuy.value],
|
||||||
|
() => {
|
||||||
|
syncFormWithLatestPrice()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
function calculateCash(val: number) {
|
function calculateCash(val: number) {
|
||||||
priceErrorVisible.value = false
|
priceErrorVisible.value = false
|
||||||
// console.log(val)
|
// console.log(val)
|
||||||
@@ -556,7 +586,8 @@ const formatter = (value: number) => {
|
|||||||
const price = computed((): Price => <Price>lastPrice.value ?? 0)
|
const price = computed((): Price => <Price>lastPrice.value ?? 0)
|
||||||
|
|
||||||
const goldPriceValue = computed(() => {
|
const goldPriceValue = computed(() => {
|
||||||
if (!price.value) return 0
|
// if (!price.value) return 0
|
||||||
|
if (!lastPrice.value?.price) return 0
|
||||||
return isBuy.value
|
return isBuy.value
|
||||||
? (price.value.buy ?? 0)
|
? (price.value.buy ?? 0)
|
||||||
: (price.value.sell ?? 0)
|
: (price.value.sell ?? 0)
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ const chartOptions = computed(() => {
|
|||||||
tickAmount: 8,
|
tickAmount: 8,
|
||||||
show: false,
|
show: false,
|
||||||
labels: {
|
labels: {
|
||||||
formatter: (val: number) => toPersianNumber(usePrice(val)),
|
formatter: (val: number) => toPersianNumber(usePrice(val, true, 'ه.ریال')),
|
||||||
style: { fontSize: '13px', fontFamily }
|
style: { fontSize: '13px', fontFamily }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -87,7 +87,7 @@ const chartOptions = computed(() => {
|
|||||||
})}`
|
})}`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
formatter: (val: number) => toPersianNumber(usePrice(val)),
|
formatter: (val: number) => toPersianNumber(usePrice(val, true, 'ه.ریال')),
|
||||||
style: { fontFamily }
|
style: { fontFamily }
|
||||||
},
|
},
|
||||||
colors: [config.config.color],
|
colors: [config.config.color],
|
||||||
|
|||||||
@@ -652,6 +652,24 @@ onMounted(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
async function initPrice() {
|
async function initPrice() {
|
||||||
|
try {
|
||||||
|
// chartLoading.value = true
|
||||||
|
await getLastPrices()
|
||||||
|
// await setIntervalGetPrice()
|
||||||
|
loading.value = true
|
||||||
|
price.value = lastPrice.value
|
||||||
|
/*props.ProductItem.price = lastPrice.value?.buy * props.ProductItem?.amount
|
||||||
|
props.ProductItem.sellPrice = lastPrice.value?.sell * props.ProductItem?.amount*/
|
||||||
|
props.ProductItem.price = lastPrice?.value?.price? (lastPrice?.value?.price + props.ProductItem?.cash_fee_buy) * props.ProductItem?.amount: 0
|
||||||
|
props.ProductItem.sellPrice = lastPrice?.value?.price? (lastPrice?.value?.price - props.ProductItem?.percent_fee_sell) * props.ProductItem?.amount:0
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
// chartLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*async function initPrice() {
|
||||||
try {
|
try {
|
||||||
// chartLoading.value = true
|
// chartLoading.value = true
|
||||||
await getLastPrices()
|
await getLastPrices()
|
||||||
@@ -666,7 +684,7 @@ async function initPrice() {
|
|||||||
loading.value = false
|
loading.value = false
|
||||||
// chartLoading.value = false
|
// chartLoading.value = false
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// onMounted(() => {
|
// onMounted(() => {
|
||||||
// initPrice()
|
// initPrice()
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="config.config.name === 'garoosi'" class="wrap-fix bottom-0 px-10 pb-3rem flex gap-2 bg-white">
|
<div v-if="config.config.name === 'garoosi'" class="wrap-fix bottom-0 px-10 pb-3rem flex gap-2 bg-white">
|
||||||
<a class="w-full" href="tel:09306612518">
|
<a class="w-full" href="tel:09031265925">
|
||||||
<BasicButton class="w-full" type="primary">تماس با پشتیبانی</BasicButton>
|
<BasicButton class="w-full" type="primary">تماس با پشتیبانی</BasicButton>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://ble.ir/garoosigallery">
|
<a href="https://ble.ir/garoosigallery">
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<!-- <img :src="permission1" alt="" class="w-full">-->
|
<!-- <img :src="permission1" alt="" class="w-full">-->
|
||||||
<div class="mt-5 text-xs"></div>
|
<div class="mt-5 text-xs"></div>
|
||||||
<div v-if="config.config.name === 'garoosi'" class="wrap-fix bottom-0 px-10 pb-3rem flex gap-2 bg-white">
|
<div v-if="config.config.name === 'garoosi'" class="wrap-fix bottom-0 px-10 pb-3rem flex gap-2 bg-white">
|
||||||
<a class="w-full" href="tel:09306612518">
|
<a class="w-full" href="tel:09031265925">
|
||||||
<BasicButton class="w-full" type="primary">تماس با پشتیبانی</BasicButton>
|
<BasicButton class="w-full" type="primary">تماس با پشتیبانی</BasicButton>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://ble.ir/garoosigallery">
|
<a href="https://ble.ir/garoosigallery">
|
||||||
|
|||||||
@@ -14,6 +14,17 @@
|
|||||||
<div
|
<div
|
||||||
class="border-gray-200 border-1 rounded-xl p-5 trans flex flex-col items-center mx-5 z-1000 relative bg-white shadow-lg"
|
class="border-gray-200 border-1 rounded-xl p-5 trans flex flex-col items-center mx-5 z-1000 relative bg-white shadow-lg"
|
||||||
>
|
>
|
||||||
|
<!-- <div
|
||||||
|
class="w-20 h-20 rounded-full overflow-hidden border-2 border-gray-200 bg-gray-100 flex items-center justify-center mb-3"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-if="profileAvatarUrl"
|
||||||
|
:src="profileAvatarUrl"
|
||||||
|
alt="عکس پروفایل"
|
||||||
|
class="w-full h-full object-cover"
|
||||||
|
/>
|
||||||
|
<BasicIcon v-else icon="vuesax-linear:user" size="36" color="#9CA3AF" />
|
||||||
|
</div>-->
|
||||||
<div class="text-primary font-bold w-full text-center flex justify-between">
|
<div class="text-primary font-bold w-full text-center flex justify-between">
|
||||||
نام و نام خانوادگی:
|
نام و نام خانوادگی:
|
||||||
<div class="mr-2">{{ userStore.userInfo?.name }}</div>
|
<div class="mr-2">{{ userStore.userInfo?.name }}</div>
|
||||||
@@ -189,6 +200,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="h60vh overflow-y-auto pb20">
|
<div class="h60vh overflow-y-auto pb20">
|
||||||
|
<!-- <ProfileAvatarUpload
|
||||||
|
:image-url="editAvatarUrl"
|
||||||
|
class="mb-4"
|
||||||
|
@uploaded="onAvatarUploaded"
|
||||||
|
@removed="onAvatarRemoved"
|
||||||
|
/>-->
|
||||||
<a-form ref="formRef" :model="userFormState" class="!mt-5" name="basic" @finish="ok">
|
<a-form ref="formRef" :model="userFormState" class="!mt-5" name="basic" @finish="ok">
|
||||||
<a-form-item :rules="[isValidPersian()]" label="نام" name="fname">
|
<a-form-item :rules="[isValidPersian()]" label="نام" name="fname">
|
||||||
<BasicInput v-model:value="userFormState.fname" />
|
<BasicInput v-model:value="userFormState.fname" />
|
||||||
@@ -266,7 +283,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, reactive, ref, computed } from 'vue'
|
import { onMounted, ref, computed, watch } from 'vue'
|
||||||
import img from '@/assets/img/user_ly1.svg'
|
import img from '@/assets/img/user_ly1.svg'
|
||||||
import gr_bottom from './assets/img/gr_bottom_white.svg'
|
import gr_bottom from './assets/img/gr_bottom_white.svg'
|
||||||
import { loading } from '@/utils'
|
import { loading } from '@/utils'
|
||||||
@@ -289,6 +306,8 @@ import { message } from 'ant-design-vue'
|
|||||||
import { updateMe, updatePass } from '@/api/me'
|
import { updateMe, updatePass } from '@/api/me'
|
||||||
import { useUserStore } from '@/store/userStore'
|
import { useUserStore } from '@/store/userStore'
|
||||||
import BaseDatePicker from '@/components/BasicPacks/BaseDatePicker'
|
import BaseDatePicker from '@/components/BasicPacks/BaseDatePicker'
|
||||||
|
import ProfileAvatarUpload from '@/components/ProfileAvatarUpload.vue'
|
||||||
|
import { getUserAvatarUrl } from '@/utils/file'
|
||||||
import { useConfigStore } from '@/store/configStore'
|
import { useConfigStore } from '@/store/configStore'
|
||||||
import { getConfigApp, getReferralShareText, getReferralShareTitle } from '../../../utils/config'
|
import { getConfigApp, getReferralShareText, getReferralShareTitle } from '../../../utils/config'
|
||||||
|
|
||||||
@@ -311,11 +330,39 @@ const nameProject = useConfigStore().config.name_fa
|
|||||||
// const editPassVisible = ref<boolean>(false)
|
// const editPassVisible = ref<boolean>(false)
|
||||||
const editPassVisible = ref<boolean>(false)
|
const editPassVisible = ref<boolean>(false)
|
||||||
const editPasswordVisible = ref<boolean>(false)
|
const editPasswordVisible = ref<boolean>(false)
|
||||||
|
const localAvatarUrl = ref<string | null>(null)
|
||||||
|
|
||||||
|
const profileAvatarUrl = computed(() => localAvatarUrl.value || getUserAvatarUrl(userStore.userInfo))
|
||||||
|
|
||||||
|
const editAvatarUrl = computed(() => localAvatarUrl.value || getUserAvatarUrl(userFormState.value))
|
||||||
|
|
||||||
function setForm() {
|
function setForm() {
|
||||||
userFormState.value = userStore.userInfo
|
userFormState.value = { ...userStore.userInfo } as User
|
||||||
|
localAvatarUrl.value = getUserAvatarUrl(userStore.userInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onAvatarUploaded({ id, url }: { id: number; url: string }) {
|
||||||
|
userFormState.value.avatar_id = id
|
||||||
|
localAvatarUrl.value = url
|
||||||
|
if (userStore.userInfo) {
|
||||||
|
userStore.userInfo.avatar_id = id
|
||||||
|
userStore.userInfo.avatar_url = url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAvatarRemoved() {
|
||||||
|
userFormState.value.avatar_id = null
|
||||||
|
localAvatarUrl.value = null
|
||||||
|
if (userStore.userInfo) {
|
||||||
|
userStore.userInfo.avatar_id = null
|
||||||
|
userStore.userInfo.avatar_url = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(editPassVisible, (open) => {
|
||||||
|
if (open) setForm()
|
||||||
|
})
|
||||||
|
|
||||||
function copyCode() {
|
function copyCode() {
|
||||||
// nextTick(() => {
|
// nextTick(() => {
|
||||||
const val = userStore.userInfo?.referral_id
|
const val = userStore.userInfo?.referral_id
|
||||||
@@ -386,9 +433,9 @@ function ok() {
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
await updateMe(userFormState.value)
|
await updateMe(userFormState.value)
|
||||||
await userStore.getMyInfo()
|
await userStore.getMyInfo()
|
||||||
|
localAvatarUrl.value = getUserAvatarUrl(userStore.userInfo)
|
||||||
editPassVisible.value = false
|
editPassVisible.value = false
|
||||||
message.success('اطلاعات شما با موفقیت به روز رسانی شد')
|
message.success('اطلاعات شما با موفقیت به روز رسانی شد')
|
||||||
location.reload()
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in New Issue
Block a user