Insert image for product

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-17 13:45:52 +03:30
co-authored by Cursor
parent f994a61567
commit 1c2647d093
11 changed files with 457 additions and 97 deletions
+162 -74
View File
@@ -22,7 +22,7 @@
:title="`${editId ? 'ویرایش' : 'افزودن'} محصول`"
@ok="ok"
:loading="loading"
@close="addUserVisible = false"
@close="closeProductModal"
>
<Collapse class="grid grid-cols-1 gap-2" v-model:activeKey="activeKey_">
<BaseCollapse title="اطلاعات محصول" active-key="0" :actives="activeKey_">
@@ -228,18 +228,12 @@
</BaseCollapse>
<BaseCollapse title="تصاویر محصول" active-key="1" :actives="activeKey_">
<template #content>
<div class="flex gap-2">
<IndexImageUploader
v-model:file-list="ProductIndexImage"
@ok="uploadedIndexFile"
@delete="deleteIndexFile"
/>
<ProductImageUploader
v-model:file-list="ImageFileList"
@ok="uploadedFile"
@delete="deleteFile"
/>
</div>
<IndexImageUploader
:key="editId ?? 'new-product'"
v-model:file-list="ProductIndexImage"
@ok="uploadedIndexFile"
@delete="deleteIndexFile"
/>
</template>
</BaseCollapse>
</Collapse>
@@ -431,7 +425,17 @@ import {confirmDeleteItem} from "@/utils/confirmModal";
import {cloneDeep} from "lodash";
import type {Item} from "@/model/Item";
import type {Customer} from "@/model/customer";
import {createProduct, deleteCustomer, updateCustomer} from "@/api/product";
import {createProduct, deleteCustomer, getCustomerById, updateCustomer} from "@/api/product";
import {fetchProductImageUrl} from "@/api/file";
import {
applyFileToUploadList,
normalizeFileResource,
normalizeUploadFileResponse,
pickImageFromRecord,
pickRawFileFromRecord,
resolveProductImageSrc,
unwrapApiRecord
} from "@/utils/file";
import type {Charge} from "@/model/wallet";
import customers from "@/router/routes/products";
import {chargeWallet} from "@/api/wallet";
@@ -446,7 +450,6 @@ import type {Order} from "@/model/order";
import Icon from "@core/components/BaseIcon/src/Icon.vue";
import type {MethodePrices, Product} from "@/model/product";
import IndexImageUploader from "@/components/ProductUploader/IndexImageUploader.vue";
import ProductImageUploader from "@/components/ProductUploader/ProductImageUploader.vue";
//tabs
const activeKey = ref("اطلاعات جامع");
@@ -474,19 +477,6 @@ const methodOption = ref<string>("1");
const weightOption = ref<string>("1");
const activeKey_ = ref(["0"]);
const ImageFileList = ref<Array<FileList>>([]);
function uploadedFile(id: number) {
// console.log(id)
let arr: number[] | undefined = form.value.image_ids;
arr?.push(id);
form.value.image_ids = arr;
}
function deleteFile() {
form.value.image_ids = ImageFileList?.value.map((x: FileList) => x.uid);
}
import BaseCollapse from "@/pages/menuPages/products/base/components/BaseCollapse.vue";
import {methodePrices} from "@/api/price";
import {getAllPrices} from "@/api/dashboard";
@@ -494,17 +484,67 @@ import dayjs from "dayjs";
const ProductIndexImage = ref<Array<FileList>>([]);
function uploadedIndexFile(id: number) {
// console.log(id)
form.value.original_image_id = id;
function uploadedIndexFile(id: number, response?: Record<string, any>) {
const fileRecord = unwrapApiRecord(response)
const fileResource =
normalizeUploadFileResponse(response) ||
normalizeUploadFileResponse({ id, src: response?.src })
if (!fileRecord && !fileResource) {
form.value.file_id = id
return
}
form.value.file_id = fileRecord?.id ?? fileResource?.id ?? id
if (fileRecord) form.value.file = fileRecord
ProductIndexImage.value = applyFileToUploadList(form.value.file_id, fileResource) as Array<FileList>
}
function deleteIndexFile() {
form.value.original_image_id = null;
form.value.original_image = null;
form.value.file_id = undefined;
form.value.file = undefined;
ProductIndexImage.value = [];
}
async function setProductIndexImage(record: Record<string, any>, productId?: number) {
ProductIndexImage.value = [];
const rawFile = pickRawFileFromRecord(record);
const fileId = record.file_id ?? record.original_image_id ?? rawFile?.id;
if (!fileId && !rawFile) return;
if (fileId) form.value.file_id = Number(fileId);
if (rawFile) form.value.file = rawFile;
const image =
pickImageFromRecord(record) ||
(rawFile ? normalizeFileResource(rawFile) : null);
let uploadList = applyFileToUploadList(form.value.file_id ?? fileId ?? rawFile?.id, image);
if (!uploadList.length) {
let imageSrc = resolveProductImageSrc(record);
if (!imageSrc && productId) {
imageSrc = await fetchProductImageUrl(productId);
}
if (imageSrc) {
uploadList = [
{
uid: String(fileId ?? rawFile?.id),
name: rawFile?.original_name || rawFile?.title || image?.name || "image",
status: "done",
url: imageSrc,
thumbUrl: imageSrc
}
];
}
}
await nextTick();
ProductIndexImage.value = uploadList as Array<FileList>;
}
let updateKey = ref<number>(0);
@@ -647,16 +687,40 @@ let editId: number | undefined = undefined;
async function edit(record: Customer) {
addUserVisible.value = true;
editId = record.id;
console.log(record);
const customForm = cloneDeep(record);
const start = dayjs(customForm.auto_open_at, "HH:mm:ss");
const close = dayjs(customForm.auto_close_at, "HH:mm:ss");
delete customForm.auto_open_at;
delete customForm.auto_close_at;
form.value.auto_open_at = start;
form.value.auto_close_at = close;
console.log(form.value);
form.value = cloneDeep(customForm);
let productData = cloneDeep(record) as Record<string, any>;
if (!pickRawFileFromRecord(productData) && productData.file_id) {
try {
const detail = unwrapApiRecord(await getCustomerById(record.id));
if (detail) productData = { ...productData, ...detail };
} catch {
/* use table row data */
}
}
methodOption.value = productData.reading_method ? "2" : "1";
weightOption.value = productData.amount && productData.amount !== 1 ? "1" : "2";
const start = productData.auto_open_at
? dayjs(productData.auto_open_at, "HH:mm:ss")
: dayjs("00:00:00", "HH:mm:ss");
const close = productData.auto_close_at
? dayjs(productData.auto_close_at, "HH:mm:ss")
: dayjs("00:00:00", "HH:mm:ss");
form.value = {
...productData,
direct_price: productData.direct_price ?? 0,
auto_open_at: start.isValid() ? start : dayjs("00:00:00", "HH:mm:ss"),
auto_close_at: close.isValid() ? close : dayjs("00:00:00", "HH:mm:ss")
};
await setProductIndexImage(productData, record.id);
}
function closeProductModal() {
addUserVisible.value = false;
editId = undefined;
}
//add
@@ -715,6 +779,9 @@ async function chargeGoldWallet() {
//reset data
const resetData = () => {
formRef.value?.resetFields();
ProductIndexImage.value = [];
methodOption.value = "1";
weightOption.value = "1";
form.value = {
unit: "",
group_type: "",
@@ -723,7 +790,12 @@ const resetData = () => {
cash_fee_buy: 0,
percent_fee_sell: 0,
cash_fee_sell: 0,
metal_id: 1
metal_id: 1,
direct_price: 0,
file_id: undefined,
file: undefined,
auto_open_at: dayjs("00:00:00", "HH:mm:ss"),
auto_close_at: dayjs("00:00:00", "HH:mm:ss")
};
};
@@ -746,37 +818,53 @@ const userInfo = ref<Customer>();
//submit user
async function ok() {
formRef.value?.validateFields().then(async () => {
// console.log('salam', form.value)
// return
loading.value = true;
try {
if (methodOption.value === "1") delete form.value.reading_method;
else delete form.value.price;
if (weightOption.value === "2")
form.value.amount = 1;
form.value.auto_open_at = dayjs(form.value.auto_open_at).format("HH:mm:ss");
form.value.auto_close_at = dayjs(form.value.auto_close_at).format("HH:mm:ss");
await methodePrices(form.value);
if (editId) {
await updateCustomer(editId, form.value);
} else {
await createProduct(form.value);
}
addUserVisible.value = false;
refreshTable();
resetData();
message.success("عملیات با موفقیت انجام شد");
// await getResponsible()
// await getQC()
// await getManager()
} catch (e) {
console.error(e);
// message.error('خطا در بارگذاری اطلاعات')
} finally {
loading.value = false;
try {
await formRef.value?.validateFields();
} catch {
return;
}
loading.value = true;
try {
const payload = cloneDeep(form.value);
if (methodOption.value === "1") delete payload.reading_method;
else delete payload.price;
if (weightOption.value === "2") payload.amount = 1;
payload.auto_open_at = payload.auto_open_at
? dayjs(payload.auto_open_at).format("HH:mm:ss")
: "00:00:00";
payload.auto_close_at = payload.auto_close_at
? dayjs(payload.auto_close_at).format("HH:mm:ss")
: "00:00:00";
delete payload.original_image;
delete payload.original_image_id;
delete payload.image_ids;
if (payload.file_id && payload.file) {
payload.file_id = payload.file.id ?? payload.file_id
} else if (!payload.file_id) {
delete payload.file
}
});
if (editId) {
await updateCustomer(editId, payload);
} else {
await createProduct(payload);
}
addUserVisible.value = false;
editId = undefined;
refreshTable();
resetData();
message.success("عملیات با موفقیت انجام شد");
} catch (e) {
console.error(e);
message.error("خطا در ثبت اطلاعات");
} finally {
loading.value = false;
}
}
const result = {