added some feature for plugin
This commit is contained in:
@@ -8,6 +8,7 @@ import MoneyInput from '@/components/MoneyInput.vue'
|
|||||||
import { useAuthStore } from '@/stores/auth'
|
import { useAuthStore } from '@/stores/auth'
|
||||||
import { SUPERADMIN_SYSTEM_SETTING_KEYS } from '@/config/superAdminSettingKeys'
|
import { SUPERADMIN_SYSTEM_SETTING_KEYS } from '@/config/superAdminSettingKeys'
|
||||||
import { rewriteLegacyUploadUrl } from '@/utils/rewriteLegacyUploadUrl'
|
import { rewriteLegacyUploadUrl } from '@/utils/rewriteLegacyUploadUrl'
|
||||||
|
import { formatNumber, rialToToman } from '@/utils/money'
|
||||||
import {
|
import {
|
||||||
resolveSettingDescription,
|
resolveSettingDescription,
|
||||||
resolveSettingTitle,
|
resolveSettingTitle,
|
||||||
@@ -250,13 +251,19 @@ async function save(item: CatalogItem) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const prices = item.prices.map((price) => ({
|
const prices = item.prices.map((price) => {
|
||||||
durationDays: price.durationDays,
|
const finalPriceRials = Math.max(0, Math.trunc(Number(price.finalPriceRials) || 0))
|
||||||
enabled: price.enabled,
|
const originalPriceRials =
|
||||||
originalPriceRials:
|
price.enabled && price.hasDiscount
|
||||||
price.enabled && price.hasDiscount ? price.originalPriceRials : price.finalPriceRials,
|
? Math.max(0, Math.trunc(Number(price.originalPriceRials) || 0))
|
||||||
finalPriceRials: price.finalPriceRials,
|
: finalPriceRials
|
||||||
}))
|
return {
|
||||||
|
durationDays: price.durationDays,
|
||||||
|
enabled: Boolean(price.enabled),
|
||||||
|
originalPriceRials,
|
||||||
|
finalPriceRials,
|
||||||
|
}
|
||||||
|
})
|
||||||
savingId.value = item.settingKey
|
savingId.value = item.settingKey
|
||||||
try {
|
try {
|
||||||
const id = await ensureCatalogId(item)
|
const id = await ensureCatalogId(item)
|
||||||
@@ -268,6 +275,7 @@ async function save(item: CatalogItem) {
|
|||||||
prices,
|
prices,
|
||||||
})
|
})
|
||||||
message.success('ذخیره شد')
|
message.success('ذخیره شد')
|
||||||
|
closeDetail()
|
||||||
await load()
|
await load()
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
const msg = e?.response?.data?.message
|
const msg = e?.response?.data?.message
|
||||||
@@ -339,6 +347,17 @@ function slotUploader(item: CatalogItem) {
|
|||||||
}) => uploadSlot(item, options)
|
}) => uploadSlot(item, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function priceSummary(item: CatalogItem): string[] {
|
||||||
|
return item.prices
|
||||||
|
.filter((row) => row.enabled)
|
||||||
|
.map((row) => {
|
||||||
|
const toman = rialToToman(row.finalPriceRials)
|
||||||
|
const label = durationLabel[row.durationDays]
|
||||||
|
if (toman <= 0) return `${label} رایگان`
|
||||||
|
return `${label} ${formatNumber(toman)} تومان`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(load)
|
onMounted(load)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -398,6 +417,10 @@ onMounted(load)
|
|||||||
>
|
>
|
||||||
<strong>{{ item.titleFa || 'بدون عنوان' }}</strong>
|
<strong>{{ item.titleFa || 'بدون عنوان' }}</strong>
|
||||||
<span class="catalog-key" dir="ltr">{{ item.settingKey }}</span>
|
<span class="catalog-key" dir="ltr">{{ item.settingKey }}</span>
|
||||||
|
<span v-if="priceSummary(item).length" class="catalog-prices">
|
||||||
|
{{ priceSummary(item).join(' · ') }}
|
||||||
|
</span>
|
||||||
|
<span v-else class="catalog-prices muted">قیمتی روشن نیست</span>
|
||||||
</button>
|
</button>
|
||||||
<div v-if="!filteredItems.length" class="empty-hint">
|
<div v-if="!filteredItems.length" class="empty-hint">
|
||||||
{{ items.length ? 'نتیجهای برای این جستجو نیست' : 'کلید دسترسیای در قالب نیست' }}
|
{{ items.length ? 'نتیجهای برای این جستجو نیست' : 'کلید دسترسیای در قالب نیست' }}
|
||||||
@@ -408,12 +431,13 @@ onMounted(load)
|
|||||||
<a-modal
|
<a-modal
|
||||||
v-model:open="showDetail"
|
v-model:open="showDetail"
|
||||||
:title="selectedItem?.titleFa || 'جزئیات افزونه'"
|
:title="selectedItem?.titleFa || 'جزئیات افزونه'"
|
||||||
width="40rem"
|
width="64rem"
|
||||||
wrap-class-name="sa-modal-wrap"
|
wrap-class-name="sa-modal-wrap catalog-detail-modal"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
@cancel="closeDetail"
|
@cancel="closeDetail"
|
||||||
>
|
>
|
||||||
<div v-if="selectedItem" class="catalog-detail">
|
<div v-if="selectedItem" class="catalog-detail">
|
||||||
|
<div class="catalog-detail-grid">
|
||||||
<a-form layout="vertical" class="catalog-form">
|
<a-form layout="vertical" class="catalog-form">
|
||||||
<a-form-item label="عنوان" required>
|
<a-form-item label="عنوان" required>
|
||||||
<a-input v-model:value="selectedItem.titleFa" :disabled="!canWrite" placeholder="مثلاً ماژول جدید" />
|
<a-input v-model:value="selectedItem.titleFa" :disabled="!canWrite" placeholder="مثلاً ماژول جدید" />
|
||||||
@@ -422,7 +446,7 @@ onMounted(load)
|
|||||||
<a-input :value="selectedItem.settingKey" disabled dir="ltr" />
|
<a-input :value="selectedItem.settingKey" disabled dir="ltr" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="توضیح">
|
<a-form-item label="توضیح">
|
||||||
<a-textarea v-model:value="selectedItem.description" :rows="4" :maxlength="4000" :disabled="!canWrite" />
|
<a-textarea v-model:value="selectedItem.description" :rows="2" :maxlength="4000" :disabled="!canWrite" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="عکسها">
|
<a-form-item label="عکسها">
|
||||||
<p class="img-hint">حداکثر سه عکس. در ادمین ماژول عکس اول روی کارت است.</p>
|
<p class="img-hint">حداکثر سه عکس. در ادمین ماژول عکس اول روی کارت است.</p>
|
||||||
@@ -493,7 +517,7 @@ onMounted(load)
|
|||||||
<span>اصلی</span>
|
<span>اصلی</span>
|
||||||
<MoneyInput
|
<MoneyInput
|
||||||
v-model:value="price.originalPriceRials"
|
v-model:value="price.originalPriceRials"
|
||||||
size="middle"
|
size="small"
|
||||||
addon-after="تومان"
|
addon-after="تومان"
|
||||||
:disabled="!canWrite || !price.enabled"
|
:disabled="!canWrite || !price.enabled"
|
||||||
/>
|
/>
|
||||||
@@ -502,7 +526,7 @@ onMounted(load)
|
|||||||
<span>{{ price.hasDiscount ? 'نهایی' : 'قیمت' }}</span>
|
<span>{{ price.hasDiscount ? 'نهایی' : 'قیمت' }}</span>
|
||||||
<MoneyInput
|
<MoneyInput
|
||||||
v-model:value="price.finalPriceRials"
|
v-model:value="price.finalPriceRials"
|
||||||
size="middle"
|
size="small"
|
||||||
addon-after="تومان"
|
addon-after="تومان"
|
||||||
:disabled="!canWrite || !price.enabled"
|
:disabled="!canWrite || !price.enabled"
|
||||||
/>
|
/>
|
||||||
@@ -511,6 +535,7 @@ onMounted(load)
|
|||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
</div>
|
||||||
<a-button
|
<a-button
|
||||||
v-if="canWrite"
|
v-if="canWrite"
|
||||||
type="primary"
|
type="primary"
|
||||||
@@ -633,9 +658,31 @@ onMounted(load)
|
|||||||
direction: ltr;
|
direction: ltr;
|
||||||
unicode-bidi: isolate;
|
unicode-bidi: isolate;
|
||||||
}
|
}
|
||||||
|
.catalog-prices {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: #17324d;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.45;
|
||||||
|
}
|
||||||
|
.catalog-prices.muted {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
.catalog-detail {
|
.catalog-detail {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
.catalog-detail-grid {
|
||||||
|
display: grid;
|
||||||
|
gap: 12px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
@media (min-width: 900px) {
|
||||||
|
.catalog-detail-grid {
|
||||||
|
grid-template-columns: minmax(16rem, 0.9fr) minmax(20rem, 1.2fr);
|
||||||
|
align-items: start;
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
.catalog-detail > .ant-btn {
|
.catalog-detail > .ant-btn {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
}
|
}
|
||||||
@@ -679,6 +726,11 @@ onMounted(load)
|
|||||||
display: grid;
|
display: grid;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.price-list {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
.price-item {
|
.price-item {
|
||||||
border: 1px solid #e8eef5;
|
border: 1px solid #e8eef5;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
@@ -738,8 +790,9 @@ onMounted(load)
|
|||||||
}
|
}
|
||||||
.img-slots {
|
.img-slots {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, 4.75rem);
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
|
justify-content: start;
|
||||||
}
|
}
|
||||||
.img-slot {
|
.img-slot {
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -768,9 +821,8 @@ onMounted(load)
|
|||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
.img-slots :deep(.ant-upload.ant-upload-select-picture-card) {
|
.img-slots :deep(.ant-upload.ant-upload-select-picture-card) {
|
||||||
width: 100%;
|
width: 4.75rem;
|
||||||
height: auto;
|
height: 4.75rem;
|
||||||
aspect-ratio: 1;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user