added pdf in withdraw and deposit and fix bug

This commit is contained in:
2026-06-09 21:06:29 +03:30
parent 8582ce4d1b
commit cf3dbbceb1
21 changed files with 454 additions and 85 deletions
@@ -3,7 +3,57 @@
<BaseCollapse title="اطلاعات محصول" active-key="0" :actives="activeKey">
<template #content>
<div
v-if="form.group_type === '' || form.group_type !== 'آبشده'"
v-if="isMeltedCategory"
class="md:flex flex-col gap-3 border-1 border-solid rounded-lg border-gray-200 p-3"
>
<div class="items-center">
<span class="ml-4">مرجع قیمت :</span>
<a-radio-group :value="meltedPriceOption" name="meltedPriceGroup" @update:value="$emit('update:meltedPriceOption', $event)">
<a-radio value="app">قیمت اپ (صفحه اصلی)</a-radio>
<a-radio value="fixed">ثابت</a-radio>
<a-radio value="reference">مرجع متفاوت</a-radio>
</a-radio-group>
</div>
<div v-if="meltedPriceOption === 'fixed'" class="md:flex items-center gap-3">
<span>قیمت ثابت :</span>
<BasicInput class="md:w-[20rem]" addon-before="ریال" type="price" v-model:value="form.price" />
</div>
<div v-if="meltedPriceOption === 'reference'" class="flex flex-col gap-2">
<div class="md:flex justify-between items-center">
<div class="ml-4">مرجع قیمت :</div>
<BasicSelect class="w-11rem method_style" allowClear :items="pricesList" valueName="name" keyName="id" v-model:value="form.reading_method" />
</div>
<div class="md:flex justify-between items-center">
<div class="ml-4">تعدیل نسبت به قیمت مرجع (٪) :</div>
<BasicInput
class="w-11rem"
type="number"
v-model:value="form.price_offset_percent"
placeholder="مثلاً 5 یا -3"
/>
</div>
<div class="text-xs text-gray-500">
مثبت = گران‌تر، منفی = ارزان‌تر نسبت به قیمت مرجع.
</div>
</div>
<div v-if="meltedPriceOption === 'app'" class="flex flex-col gap-2">
<div class="md:flex justify-between items-center">
<div class="ml-4">تعدیل نسبت به قیمت اپ (٪) :</div>
<BasicInput
class="w-11rem"
type="number"
v-model:value="form.price_offset_percent"
placeholder="مثلاً 5 یا -3"
/>
</div>
<div class="text-xs text-gray-500">
قیمت خرید/فروش از قیمت صفحه اصلی اپ محاسبه می‌شود. مثبت = گران‌تر، منفی = ارزان‌تر.
</div>
</div>
</div>
<div
v-if="!isMeltedCategory"
class="md:flex justify-between border-1 border-solid rounded-lg border-gray-200 p-2"
>
<div class="items-center">
@@ -46,7 +96,7 @@
</div>
<div
v-if="form.group_type === '' || form.group_type !== 'آبشده'"
v-if="!isMeltedCategory"
class="md:flex justify-between p-2 border-1 border-solid rounded-lg border-gray-200 mt-2"
>
<div>
@@ -59,36 +109,30 @@
<div v-if="weightOption === '1'" class="flex items-center">
<span class="ml-4 ">{{ weightFieldLabel }} :</span>
<BasicInput v-model:value="form.amount" type="number" />
<div class="mt-1 mr-4" v-if="form.amount && form.amount < 1 && 0 < form.amount && !isBourseCuProject">معادل {{ form.amount * 1000 }} سوت</div>
<div class="mt-1 mr-4" v-if="form.amount && form.amount < 1 && 0 < form.amount && tradeWeightUnit === 'گرم'">معادل {{ form.amount * 1000 }} سوت</div>
</div>
</div>
<a-form :model="form" ref="formRef" autocomplete="off">
<div class="grid md:grid-cols-2 gap-4">
<a-form-item label="عنوان" name="title" :rules="inputRules()"><BasicInput v-model:value="form.title" /></a-form-item>
<a-form-item v-if="getConfigApp('name') === 'boursecu'" label="دسته بندی" name="group_type" :rules="inputRules()">
<BasicSelect v-model:value="form.group_type" :items="boursemesCategoryItems" valueName="value" keyName="value" />
</a-form-item>
<a-form-item v-else-if="getConfigApp('name') === 'garoosi'" label="دسته بندی" name="group_type" :rules="inputRules()">
<BasicSelect v-model:value="form.group_type" :items="garoosiCategoryItems" valueName="value" keyName="value" />
</a-form-item>
<a-form-item v-else label="دسته بندی" name="group_type" :rules="inputRules()">
<BasicSelect v-model:value="form.group_type" :items="categoryItems" valueName="value" keyName="value" />
<a-form-item label="دسته بندی" name="group_type" :rules="inputRules()">
<BasicSelect v-model:value="form.group_type" :items="categoryItems" valueName="value" keyName="key" />
</a-form-item>
<a-form-item label="جنس فلز" name="metal_id" :rules="inputRules()">
<BasicSelect v-model:value="form.metal_id" :items="metalItems" valueName="value" keyName="key" />
</a-form-item>
<a-form-item label="نوع قیمت" name="direct_price" :rules="inputRules()">
<a-form-item v-if="!isMeltedCategory" label="نوع قیمت" name="direct_price" :rules="inputRules()">
<BasicSelect v-model:value="form.direct_price" :items="priceItems" valueName="value" keyName="key" />
</a-form-item>
<a-form-item label="واحد" name="unit" :rules="inputRules()">
<BasicSelect v-model:value="form.unit" :items="unitItems" valueName="value" keyName="value" />
</a-form-item>
<a-form-item v-if="form.group_type === '' || form.group_type !== 'آبشده'" label="هزینه نقدی موقع خرید" name="cash_fee_buy" :rules="inputRules()">
<BasicInput v-model:value="form.cash_fee_buy" type="number" />
<a-form-item label="هزینه نقدی موقع خرید" name="cash_fee_buy" :rules="inputRules()">
<BasicInput v-model:value="form.cash_fee_buy" addon-before="ریال" type="price" />
</a-form-item>
<a-form-item v-if="form.group_type === '' || form.group_type !== 'آبشده'" label="هزینه نقدی موقع فروش" name="cash_fee_sell" :rules="inputRules()">
<BasicInput v-model:value="form.cash_fee_sell" type="number" />
<a-form-item label="هزینه نقدی موقع فروش" name="cash_fee_sell" :rules="inputRules()">
<BasicInput v-model:value="form.cash_fee_sell" addon-before="ریال" type="price" />
</a-form-item>
<a-form-item label="زمان شروع فعال سازی" name="auto_open_at">
<TimePicker v-model:value="form.auto_open_at" :locale="customLocale" placeholder="انتخاب زمان" :defaultValue="dayjs('00:00:00', 'HH:mm:ss')" />
@@ -99,6 +143,9 @@
<a-form-item label="محدودیت مبلغ سفارش" name="order_limit_enabled">
<a-switch v-model:checked="form.order_limit_enabled" @change="onOrderLimitChange" />
</a-form-item>
<a-form-item label="نمایش در صفحه دارایی‌ها" name="show_in_assets">
<a-switch v-model:checked="form.show_in_assets" />
</a-form-item>
<template v-if="form.order_limit_enabled">
<div class="col-span-2 text-xs text-gray-500 -mt-2 mb-1">
حداقل یکی از «حداقل» یا «حداکثر» الزامی است؛ می‌توانید فقط یکی را پر کنید.
@@ -135,19 +182,20 @@ import { inputRules } from '@/utils/inputRules'
import Icon from '@core/components/BaseIcon/src/Icon.vue'
import BaseCollapse from '@/components/BaseCollapse.vue'
import IndexImageUploader from '@/components/ProductUploader/IndexImageUploader.vue'
import { getConfigApp } from '@/utils/config'
import { getConfiguration } from '@/api/configuration'
import { isMeltedTradeGroup } from '@/utils/productCategories'
import { resolveTradeWeightUnit, weightFieldLabelForUnit } from '@/utils/weightUnit'
import dayjs from 'dayjs'
import { computed } from 'vue'
import { computed, onMounted, ref, watch } from 'vue'
const props = defineProps<{
form: any
formRef: any
methodOption: string
weightOption: string
meltedPriceOption: string
activeKey: string[]
pricesList: Array<{ id: string; name: string }>
boursemesCategoryItems: any[]
garoosiCategoryItems: any[]
categoryItems: any[]
metalItems: any[]
priceItems: any[]
@@ -157,13 +205,47 @@ const props = defineProps<{
editId?: number
}>()
const isBourseCuProject = computed(() => getConfigApp('name') === 'boursecu')
const weightFieldLabel = computed(() =>
isBourseCuProject.value && (props.form.unit === 'کیلوگرم' || !props.form.unit)
? 'وزن به کیلوگرم'
: 'وزن به گرم'
const tradeWeightUnit = ref('گرم')
const isMeltedCategory = computed(() => isMeltedTradeGroup(props.form.group_type))
watch(
() => props.meltedPriceOption,
(option) => {
if (option === 'app' || option === 'fixed') {
props.form.reading_method = null
}
if (option === 'app') {
props.form.direct_price = 0
}
if (option === 'fixed') {
props.form.direct_price = 1
props.form.price_offset_percent = 0
}
if (option === 'reference') {
props.form.direct_price = 0
}
}
)
onMounted(async () => {
try {
const rows = await getConfiguration()
const unitRow = Array.isArray(rows) ? rows.find((row) => row.key === 'unit') : null
tradeWeightUnit.value = resolveTradeWeightUnit(unitRow?.value)
} catch {
tradeWeightUnit.value = 'گرم'
}
})
const weightFieldLabel = computed(() => {
const productUnit = props.form.unit?.trim()
if (productUnit === 'کیلوگرم' || productUnit === 'گرم') {
return weightFieldLabelForUnit(productUnit)
}
return weightFieldLabelForUnit(tradeWeightUnit.value)
})
function onOrderLimitChange(checked: boolean) {
if (!checked) {
props.form.min_order_cash = undefined
@@ -176,6 +258,7 @@ defineEmits<{
(e: 'minusPrice'): void
(e: 'update:methodOption', value: string): void
(e: 'update:weightOption', value: string): void
(e: 'update:meltedPriceOption', value: string): void
(e: 'update:activeKey', value: string[]): void
(e: 'update:productIndexImage', value: any[]): void
(e: 'uploadedIndexFile', id: number, response?: Record<string, any>): void
+37 -37
View File
@@ -23,17 +23,17 @@
:weightOption="weightOption"
:activeKey="activeKey_"
:pricesList="pricesList"
:boursemesCategoryItems="BoursemesCategoryItems"
:garoosiCategoryItems="GaroosiCategoryItems"
:categoryItems="categoryItems"
:categoryItems="categorySelectItems"
:metalItems="metalItems"
:priceItems="priceItems"
:unitItems="unitItems"
:customLocale="customLocale"
:productIndexImage="ProductIndexImage"
:editId="editId"
:meltedPriceOption="meltedPriceOption"
@update:methodOption="methodOption = $event"
@update:weightOption="weightOption = $event"
@update:meltedPriceOption="meltedPriceOption = $event"
@update:activeKey="activeKey_ = $event"
@update:productIndexImage="ProductIndexImage = $event"
@addPrice="addPrice"
@@ -73,7 +73,7 @@ import {
unwrapApiRecord
} from '@/utils/file'
import { normalizeProductOrderLimitForm, validateProductOrderLimitForm } from '@/utils/productOrderLimit'
import { getConfigApp } from '@/utils/config'
import { buildCategorySelectItems, isMeltedTradeGroup, resolveMeltedPriceSource } from '@/utils/productCategories'
dayjs.extend(customParseFormat)
@@ -83,6 +83,7 @@ const refreshTable = () => table.value?.fetch()
const methodOption = ref('1')
const weightOption = ref('1')
const meltedPriceOption = ref('app')
const activeKey_ = ref(['0'])
const ProductIndexImage = ref<Array<FileList>>([])
const addUserVisible = ref(false)
@@ -104,42 +105,18 @@ const customLocale = ref({
}
})
const unitItems = computed<Array<Item>>(() => {
if (getConfigApp('name') === 'boursecu') {
return [{ value: 'کیلوگرم' }, { value: 'عدد' }, { value: 'گرم' }]
}
const unitItems = computed<Array<Item>>(() => [
{ value: 'گرم' },
{ value: 'کیلوگرم' },
{ value: 'عدد' }
])
return [{ value: 'عدد' }, { value: 'گرم' }]
})
const GaroosiCategoryItems: Array<Item> = [
{ value: 'طلا' },
{ value: 'مکعب' },
{ value: 'گوی' },
{ value: 'سکه' },
{ value: 'سکه پارسیان' },
{ value: 'مس' },
{ value: 'نقره' }
]
const BoursemesCategoryItems: Array<Item> = [
{ value: 'آبشده' },
{ value: 'کاتد مس' },
{ value: 'مفتول مس' }
]
const categoryItems: Array<Item> = [
{ value: 'آبشده' },
{ value: 'مکعب' },
{ value: 'گوی' },
{ value: 'سکه' },
{ value: 'سکه پارسیان' },
{ value: 'مس' },
{ value: 'نقره' }
]
const metalItems: Array<Item> = [
{ key: 1, value: 'طلا' },
{ key: 2, value: 'نقره' },
{ key: 3, value: 'مس' }
{ key: 3, value: 'مس' },
]
const categorySelectItems = computed(() => buildCategorySelectItems(metalItems))
const priceItems: Array<Item> = [
{ key: 0, value: 'متغیر' },
{ key: 1, value: 'ثابت' }
@@ -241,6 +218,10 @@ async function edit(record: Product) {
}
methodOption.value = productData.reading_method ? '2' : '1'
meltedPriceOption.value = resolveMeltedPriceSource(productData)
if (isMeltedTradeGroup(productData.group_type)) {
methodOption.value = '1'
}
weightOption.value = productData.amount && productData.amount !== 1 ? '1' : '2'
const start = productData.auto_open_at
@@ -277,6 +258,7 @@ function resetData() {
ProductIndexImage.value = []
methodOption.value = '1'
weightOption.value = '1'
meltedPriceOption.value = 'app'
form.value = {
unit: '',
group_type: '',
@@ -291,6 +273,7 @@ function resetData() {
file_id: undefined,
file: undefined,
order_limit_enabled: false,
show_in_assets: true,
min_order_cash: undefined,
max_order_cash: undefined,
auto_open_at: dayjs('00:00:00', 'HH:mm:ss'),
@@ -314,8 +297,25 @@ async function ok() {
loading.value = false
return
}
if (methodOption.value === '1') {
delete payload.reading_method
if (isMeltedTradeGroup(payload.group_type)) {
payload.amount = 1
payload.direct_price = meltedPriceOption.value === 'fixed' ? 1 : 0
payload.cash_fee_buy = payload.cash_fee_buy ?? 0
payload.cash_fee_sell = payload.cash_fee_sell ?? 0
if (meltedPriceOption.value === 'app') {
payload.reading_method = null
delete payload.price
payload.price_offset_percent = Number(payload.price_offset_percent ?? 0)
} else if (meltedPriceOption.value === 'fixed') {
payload.reading_method = null
payload.price_offset_percent = 0
} else {
delete payload.price
payload.price_offset_percent = Number(payload.price_offset_percent ?? 0)
}
} else if (methodOption.value === '1') {
payload.reading_method = null
payload.price_offset_percent = 0
} else {
delete payload.price