Fix admin product image handling and clarify support phone settings.

This commit is contained in:
2026-09-16 20:04:12 +03:30
parent 2de2f697f1
commit ab5ce96529
6 changed files with 71 additions and 17 deletions
+43 -11
View File
@@ -14,7 +14,7 @@ import { useToast } from '@/composables/useToast'
import { formatCurrency, formatNumber } from '@/utils/format'
import type { Catalog, Product } from '@/types'
import AdminCurrencyInput from '@/components/ui/AdminCurrencyInput.vue'
import { fileToCatalogImage } from '@/utils/catalogImage'
import { fileToCatalogImage, toCssBackgroundUrl } from '@/utils/catalogImage'
const productList = ref<Product[]>([])
const catalogs = ref<Catalog[]>([])
@@ -219,6 +219,36 @@ function removeProductImage(index: number) {
form.extraImageUrls.splice(index, 1)
}
function buildProductMedia() {
const colorEntries: Array<{ name: string; imageUrl?: string }> = []
const imageUrls: string[] = []
const seen = new Set<string>()
const pushImage = (url?: string) => {
const trimmed = url?.trim()
if (!trimmed || seen.has(trimmed)) return
seen.add(trimmed)
imageUrls.push(trimmed)
}
form.colorRows.forEach((row, index) => {
const imageUrl = row.imageUrl.trim() || undefined
const name =
row.name.trim() ||
(index === 0 ? form.color.trim() : '') ||
(imageUrl ? `رنگ ${index + 1}` : '')
if (!name && !imageUrl) return
if (name) {
colorEntries.push({ name, imageUrl })
}
pushImage(imageUrl)
})
form.extraImageUrls.forEach((url) => pushImage(url))
return { colorEntries, imageUrls }
}
function closeModal() {
modalMode.value = null
editingId.value = null
@@ -237,12 +267,7 @@ async function submitProduct() {
return
}
const colorEntries = form.colorRows
.map((row) => ({
name: row.name.trim(),
imageUrl: row.imageUrl.trim() || undefined,
}))
.filter((row) => row.name)
const { colorEntries, imageUrls } = buildProductMedia()
const catalogPayload = {
usageCategory: form.usageCategory,
season: form.season,
@@ -252,7 +277,7 @@ async function submitProduct() {
rollMeters: form.rollMeters,
isNew: form.isNew,
colorsJson: colorEntries,
imageUrlsJson: form.extraImageUrls,
imageUrlsJson: imageUrls,
}
const productCode = form.productCode.trim() || `${cat.code}-NEW`
saving.value = true
@@ -294,6 +319,9 @@ async function submitProduct() {
}
closeModal()
} catch (err) {
if (err instanceof ApiError && err.status === 0) {
formError.value = err.message
}
toast.error(err instanceof ApiError ? err.message : 'ذخیره محصول انجام نشد.')
} finally {
saving.value = false
@@ -384,7 +412,7 @@ function clearFilters() {
<span
class="product-thumb"
:class="{ 'product-thumb--empty': !product.imageUrls?.[0] }"
:style="product.imageUrls?.[0] ? { backgroundImage: `url(${product.imageUrls[0]})` } : undefined"
:style="product.imageUrls?.[0] ? { backgroundImage: toCssBackgroundUrl(product.imageUrls[0]) } : undefined"
/>
</td>
<td>{{ product.productCode }}</td>
@@ -538,7 +566,10 @@ function clearFilters() {
<div class="admin-form__field">
<label>رنگ‌ها و تصویر هر رنگ</label>
<p class="color-variants__hint">برای هر رنگ یک نام و یک عکس جدا بگذارید؛ در فروشگاه با انتخاب همان رنگ، همان عکس نمایش داده می‌شود.</p>
<p class="color-variants__hint">
برای هر رنگ نام و عکس بگذارید. اگر فقط عکس دارید، نام رنگ اصلی (بالا) یا «رنگ ۱» استفاده می‌شود.
تصویر با زدن «ذخیره تغییرات» روی سرور ثبت می‌شود.
</p>
<div class="color-variants">
<div v-for="(row, index) in form.colorRows" :key="index" class="color-variant">
<AdminImagePicker
@@ -565,13 +596,14 @@ function clearFilters() {
<div class="admin-form__field">
<label>تصاویر عمومی محصول (اختیاری)</label>
<p class="color-variants__hint">پس از انتخاب فایل، حتماً دکمه ذخیره را بزنید.</p>
<div class="product-images">
<div
v-for="(src, index) in form.extraImageUrls"
:key="`${index}-${src.slice(0, 24)}`"
class="product-images__item"
>
<span class="product-images__thumb" :style="{ backgroundImage: `url(${src})` }" />
<span class="product-images__thumb" :style="{ backgroundImage: toCssBackgroundUrl(src) }" />
<button type="button" class="product-images__remove" @click="removeProductImage(index)">
حذف
</button>
+3 -1
View File
@@ -241,7 +241,9 @@ async function sendBroadcast() {
<div class="admin-form__field">
<label for="support-phone">تلفن پشتیبانی</label>
<input id="support-phone" v-model="settings.supportPhone" type="text" class="admin-input" dir="ltr" />
<p class="settings-page__hint">این شماره در صفحه ورود اپ (پشتیبانی و تماس با ما) نمایش داده می‌شود.</p>
<p class="settings-page__hint">
این شماره در صفحه ورود اپ و بخش پشتیبانی سایدبار دسکتاپ نمایش داده می‌شود.
</p>
</div>
<div class="admin-form__field">