296 lines
8.5 KiB
TypeScript
296 lines
8.5 KiB
TypeScript
import { defineStore } from "pinia";
|
|
import type { PreviewData, SubmitResult, UploadFileAsset, UploadItem } from "../api/appraisal";
|
|
|
|
type ProductState = {
|
|
categoryId: number;
|
|
categoryName: string;
|
|
brandId: number;
|
|
brandName: string;
|
|
};
|
|
|
|
type ExtraState = {
|
|
purchaseChannel: string;
|
|
purchasePrice: string;
|
|
purchaseDate: string;
|
|
usageStatus: string;
|
|
conditionDesc: string;
|
|
accessories: string[];
|
|
remark: string;
|
|
};
|
|
|
|
type ReturnAddressState = {
|
|
id: number;
|
|
consignee: string;
|
|
mobile: string;
|
|
province: string;
|
|
city: string;
|
|
district: string;
|
|
detailAddress: string;
|
|
fullAddress: string;
|
|
isDefault: boolean;
|
|
};
|
|
|
|
const storageKey = "anxinyan_appraisal_flow";
|
|
const legacyDemoExtra: ExtraState = {
|
|
purchaseChannel: "专柜",
|
|
purchasePrice: "8500",
|
|
purchaseDate: "",
|
|
usageStatus: "light_use",
|
|
conditionDesc: "轻微使用痕迹",
|
|
accessories: ["防尘袋", "包装盒"],
|
|
remark: "",
|
|
};
|
|
|
|
function initialProduct(): ProductState {
|
|
return {
|
|
categoryId: 0,
|
|
categoryName: "",
|
|
brandId: 0,
|
|
brandName: "",
|
|
};
|
|
}
|
|
|
|
function initialExtra(): ExtraState {
|
|
return {
|
|
purchaseChannel: "",
|
|
purchasePrice: "",
|
|
purchaseDate: "",
|
|
usageStatus: "",
|
|
conditionDesc: "",
|
|
accessories: [],
|
|
remark: "",
|
|
};
|
|
}
|
|
|
|
function isLegacyDemoExtra(extra: Partial<ExtraState> | undefined) {
|
|
if (!extra) return false;
|
|
const accessories = Array.isArray(extra.accessories) ? extra.accessories : [];
|
|
return (
|
|
extra.purchaseChannel === legacyDemoExtra.purchaseChannel &&
|
|
extra.purchasePrice === legacyDemoExtra.purchasePrice &&
|
|
(extra.purchaseDate || "") === legacyDemoExtra.purchaseDate &&
|
|
extra.usageStatus === legacyDemoExtra.usageStatus &&
|
|
extra.conditionDesc === legacyDemoExtra.conditionDesc &&
|
|
(extra.remark || "") === legacyDemoExtra.remark &&
|
|
accessories.length === legacyDemoExtra.accessories.length &&
|
|
accessories.every((item, index) => item === legacyDemoExtra.accessories[index])
|
|
);
|
|
}
|
|
|
|
function initialReturnAddress(): ReturnAddressState {
|
|
return {
|
|
id: 0,
|
|
consignee: "",
|
|
mobile: "",
|
|
province: "",
|
|
city: "",
|
|
district: "",
|
|
detailAddress: "",
|
|
fullAddress: "",
|
|
isDefault: false,
|
|
};
|
|
}
|
|
|
|
export const useAppraisalStore = defineStore("appraisal", {
|
|
state: () => ({
|
|
draftId: 0,
|
|
serviceProvider: "anxinyan",
|
|
serviceMode: "physical",
|
|
pricePackageId: 0,
|
|
pricePackageName: "",
|
|
pricePackageCode: "",
|
|
pricePackagePrice: 0,
|
|
currentStep: 1,
|
|
product: initialProduct(),
|
|
extra: initialExtra(),
|
|
returnAddress: initialReturnAddress(),
|
|
uploadTemplateId: 0,
|
|
requiredItems: [] as UploadItem[],
|
|
optionalItems: [] as UploadItem[],
|
|
preview: null as PreviewData | null,
|
|
submitResult: null as SubmitResult | null,
|
|
}),
|
|
actions: {
|
|
hydrate() {
|
|
const raw = uni.getStorageSync(storageKey);
|
|
if (!raw) return;
|
|
try {
|
|
const parsed = JSON.parse(raw);
|
|
Object.assign(this, parsed);
|
|
if (isLegacyDemoExtra(this.extra)) {
|
|
this.extra = initialExtra();
|
|
this.persist();
|
|
}
|
|
} catch (error) {
|
|
console.warn("hydrate appraisal store failed", error);
|
|
}
|
|
},
|
|
persist() {
|
|
uni.setStorageSync(
|
|
storageKey,
|
|
JSON.stringify({
|
|
draftId: this.draftId,
|
|
serviceProvider: this.serviceProvider,
|
|
serviceMode: this.serviceMode,
|
|
pricePackageId: this.pricePackageId,
|
|
pricePackageName: this.pricePackageName,
|
|
pricePackageCode: this.pricePackageCode,
|
|
pricePackagePrice: this.pricePackagePrice,
|
|
currentStep: this.currentStep,
|
|
product: this.product,
|
|
extra: this.extra,
|
|
returnAddress: this.returnAddress,
|
|
uploadTemplateId: this.uploadTemplateId,
|
|
requiredItems: this.requiredItems,
|
|
optionalItems: this.optionalItems,
|
|
preview: this.preview,
|
|
submitResult: this.submitResult,
|
|
}),
|
|
);
|
|
},
|
|
setServiceProvider(serviceProvider: string) {
|
|
this.serviceProvider = serviceProvider;
|
|
this.persist();
|
|
},
|
|
setPricePackage(payload: {
|
|
id: number;
|
|
packageName: string;
|
|
packageCode: string;
|
|
price: number;
|
|
}) {
|
|
this.pricePackageId = payload.id;
|
|
this.pricePackageName = payload.packageName;
|
|
this.pricePackageCode = payload.packageCode;
|
|
this.pricePackagePrice = payload.price;
|
|
this.persist();
|
|
},
|
|
setDraft(id: number) {
|
|
this.draftId = id;
|
|
this.persist();
|
|
},
|
|
setCurrentStep(step: number) {
|
|
this.currentStep = step;
|
|
this.persist();
|
|
},
|
|
setProduct(payload: Partial<ProductState>) {
|
|
this.product = {
|
|
...this.product,
|
|
...payload,
|
|
};
|
|
this.persist();
|
|
},
|
|
setExtra(payload: Partial<ExtraState>) {
|
|
this.extra = {
|
|
...this.extra,
|
|
...payload,
|
|
};
|
|
this.persist();
|
|
},
|
|
resetExtra() {
|
|
this.extra = initialExtra();
|
|
this.persist();
|
|
},
|
|
clearLegacyExtraDefaults() {
|
|
if (!isLegacyDemoExtra(this.extra)) {
|
|
return false;
|
|
}
|
|
this.extra = initialExtra();
|
|
this.persist();
|
|
return true;
|
|
},
|
|
setReturnAddress(payload: Partial<ReturnAddressState>) {
|
|
this.returnAddress = {
|
|
...this.returnAddress,
|
|
...payload,
|
|
};
|
|
this.persist();
|
|
},
|
|
clearReturnAddress() {
|
|
this.returnAddress = initialReturnAddress();
|
|
this.persist();
|
|
},
|
|
setUploadTemplate(templateId: number, requiredItems: UploadItem[], optionalItems: UploadItem[]) {
|
|
const requiredMap = new Map(this.requiredItems.map((item) => [item.item_code, item.files || []]));
|
|
const optionalMap = new Map(this.optionalItems.map((item) => [item.item_code, item.files || []]));
|
|
this.uploadTemplateId = templateId;
|
|
this.requiredItems = requiredItems.map((item) => ({
|
|
...item,
|
|
files: item.files || requiredMap.get(item.item_code) || [],
|
|
}));
|
|
this.optionalItems = optionalItems.map((item) => ({
|
|
...item,
|
|
files: item.files || optionalMap.get(item.item_code) || [],
|
|
}));
|
|
this.persist();
|
|
},
|
|
hydrateUploadItems(items: UploadItem[]) {
|
|
const required = items.filter((item) => item.is_required);
|
|
const optional = items.filter((item) => !item.is_required);
|
|
this.requiredItems = required.map((item) => ({
|
|
...item,
|
|
files: item.files || [],
|
|
}));
|
|
this.optionalItems = optional.map((item) => ({
|
|
...item,
|
|
files: item.files || [],
|
|
}));
|
|
this.persist();
|
|
},
|
|
upsertUploadFile(itemCode: string, file: UploadFileAsset, isRequired: boolean) {
|
|
const target = isRequired ? this.requiredItems : this.optionalItems;
|
|
const index = target.findIndex((item) => item.item_code === itemCode);
|
|
if (index >= 0) {
|
|
const currentFiles = target[index].files || [];
|
|
const nextFiles = [...currentFiles, file];
|
|
target[index] = {
|
|
...target[index],
|
|
files: nextFiles,
|
|
quality_status: nextFiles.length ? "uploaded" : "pending",
|
|
quality_message: "",
|
|
};
|
|
this.persist();
|
|
}
|
|
},
|
|
removeUploadFile(itemCode: string, fileId: string, isRequired: boolean) {
|
|
const target = isRequired ? this.requiredItems : this.optionalItems;
|
|
const index = target.findIndex((item) => item.item_code === itemCode);
|
|
if (index >= 0) {
|
|
const nextFiles = (target[index].files || []).filter((item) => item.file_id !== fileId);
|
|
target[index] = {
|
|
...target[index],
|
|
files: nextFiles,
|
|
quality_status: nextFiles.length ? "uploaded" : (target[index].is_required ? "pending" : "optional"),
|
|
};
|
|
this.persist();
|
|
}
|
|
},
|
|
setPreview(preview: PreviewData | null) {
|
|
this.preview = preview;
|
|
this.persist();
|
|
},
|
|
setSubmitResult(result: SubmitResult | null) {
|
|
this.submitResult = result;
|
|
this.persist();
|
|
},
|
|
resetForNewFlow() {
|
|
this.serviceProvider = "anxinyan";
|
|
this.serviceMode = "physical";
|
|
this.pricePackageId = 0;
|
|
this.pricePackageName = "";
|
|
this.pricePackageCode = "";
|
|
this.pricePackagePrice = 0;
|
|
this.draftId = 0;
|
|
this.currentStep = 1;
|
|
this.product = initialProduct();
|
|
this.extra = initialExtra();
|
|
this.returnAddress = initialReturnAddress();
|
|
this.uploadTemplateId = 0;
|
|
this.requiredItems = [];
|
|
this.optionalItems = [];
|
|
this.preview = null;
|
|
this.submitResult = null;
|
|
this.persist();
|
|
},
|
|
},
|
|
});
|