first
This commit is contained in:
820
user-app/src/api/app.ts
Normal file
820
user-app/src/api/app.ts
Normal file
@@ -0,0 +1,820 @@
|
||||
import { parseUploadResponse, request } from "../utils/request";
|
||||
import { buildAuthHeaders } from "../utils/auth";
|
||||
import { resolveApiBaseUrl } from "../utils/env";
|
||||
|
||||
export interface PageVisualsData {
|
||||
order_background_image_url?: string;
|
||||
report_background_image_url?: string;
|
||||
}
|
||||
|
||||
export interface HomeData {
|
||||
banners: Array<{
|
||||
title: string;
|
||||
subtitle: string;
|
||||
description: string;
|
||||
background_image_url?: string;
|
||||
}>;
|
||||
page_visuals: PageVisualsData;
|
||||
service_entries: Array<{
|
||||
service_provider: string;
|
||||
title: string;
|
||||
tag: string;
|
||||
description: string;
|
||||
meta: string;
|
||||
}>;
|
||||
category_entries: Array<{
|
||||
category_id: number;
|
||||
category_name: string;
|
||||
category_code: string;
|
||||
image_url?: string;
|
||||
}>;
|
||||
trust_points: Array<{
|
||||
title: string;
|
||||
desc: string;
|
||||
}>;
|
||||
quick_entries: Array<{
|
||||
code: string;
|
||||
title: string;
|
||||
desc: string;
|
||||
}>;
|
||||
trust_metrics: Array<{
|
||||
value: string;
|
||||
label: string;
|
||||
}>;
|
||||
faqs: string[];
|
||||
}
|
||||
|
||||
export interface HelpCategoryItem {
|
||||
code: "all" | "service" | "report" | "shipping" | "support";
|
||||
title: string;
|
||||
desc: string;
|
||||
count: number;
|
||||
}
|
||||
|
||||
export interface HelpArticleSummary {
|
||||
id: number;
|
||||
title: string;
|
||||
category: "service" | "report" | "shipping" | "support";
|
||||
category_text: string;
|
||||
summary: string;
|
||||
keywords: string[];
|
||||
updated_at: string;
|
||||
is_recommended: boolean;
|
||||
}
|
||||
|
||||
export interface HelpCenterData {
|
||||
categories: HelpCategoryItem[];
|
||||
articles: HelpArticleSummary[];
|
||||
}
|
||||
|
||||
export interface TicketTypeOption {
|
||||
code: string;
|
||||
title: string;
|
||||
hint: string;
|
||||
quick_desc: string;
|
||||
}
|
||||
|
||||
export interface TicketStatusOption {
|
||||
code: string;
|
||||
title: string;
|
||||
desc: string;
|
||||
}
|
||||
|
||||
export interface MessagePageCopy {
|
||||
title: string;
|
||||
desc: string;
|
||||
}
|
||||
|
||||
export interface HelpArticleDetailData {
|
||||
article: HelpArticleSummary & {
|
||||
content_blocks: string[];
|
||||
};
|
||||
related_articles: HelpArticleSummary[];
|
||||
}
|
||||
|
||||
export interface SettingsData {
|
||||
profile_info: {
|
||||
user_id: number;
|
||||
nickname: string;
|
||||
mobile: string;
|
||||
avatar: string;
|
||||
status: string;
|
||||
status_text: string;
|
||||
password_set: boolean;
|
||||
};
|
||||
preferences: {
|
||||
notify_order: boolean;
|
||||
notify_report: boolean;
|
||||
notify_supplement: boolean;
|
||||
notify_ticket: boolean;
|
||||
marketing_notify: boolean;
|
||||
privacy_mode: boolean;
|
||||
};
|
||||
legal_entries: Array<{
|
||||
code: string;
|
||||
title: string;
|
||||
desc: string;
|
||||
target_url: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface MineOverviewData {
|
||||
profile_info: SettingsData["profile_info"];
|
||||
asset_summary: {
|
||||
total_valuation: number;
|
||||
item_count: number;
|
||||
report_count: number;
|
||||
authentic_rate: number;
|
||||
unread_count: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface OrderListItem {
|
||||
order_id: number;
|
||||
order_no: string;
|
||||
appraisal_no: string;
|
||||
order_status: string;
|
||||
product_name: string;
|
||||
product_cover: string;
|
||||
service_provider: string;
|
||||
display_status: string;
|
||||
status_desc: string;
|
||||
estimated_finish_time: string;
|
||||
primary_action: string;
|
||||
}
|
||||
|
||||
export interface OrderDetailData {
|
||||
order_info: {
|
||||
order_id: number;
|
||||
order_no: string;
|
||||
appraisal_no: string;
|
||||
service_provider: string;
|
||||
order_status: string;
|
||||
display_status: string;
|
||||
status_desc: string;
|
||||
estimated_finish_time: string;
|
||||
can_edit_return_address: boolean;
|
||||
};
|
||||
product_info: {
|
||||
product_name: string;
|
||||
category_name: string;
|
||||
brand_name: string;
|
||||
color: string;
|
||||
size_spec: string;
|
||||
serial_no: string;
|
||||
};
|
||||
extra_info: {
|
||||
purchase_channel: string;
|
||||
purchase_price: number;
|
||||
purchase_date: string;
|
||||
usage_status: string;
|
||||
usage_status_text: string;
|
||||
condition_desc: string;
|
||||
has_accessories: boolean;
|
||||
accessories: string[];
|
||||
remark: string;
|
||||
};
|
||||
materials: Array<{
|
||||
upload_item_id: number;
|
||||
item_code: string;
|
||||
item_name: string;
|
||||
is_required: boolean;
|
||||
source_type: string;
|
||||
source_type_text: string;
|
||||
status: string;
|
||||
status_text: string;
|
||||
file_count: number;
|
||||
files: Array<{
|
||||
file_id: string;
|
||||
file_url: string;
|
||||
thumbnail_url: string;
|
||||
quality_status: string;
|
||||
quality_message: string;
|
||||
}>;
|
||||
}>;
|
||||
return_address: null | {
|
||||
user_address_id: number;
|
||||
consignee: string;
|
||||
mobile: string;
|
||||
province: string;
|
||||
city: string;
|
||||
district: string;
|
||||
detail_address: string;
|
||||
full_address: string;
|
||||
};
|
||||
return_logistics: null | {
|
||||
express_company: string;
|
||||
tracking_no: string;
|
||||
tracking_status: string;
|
||||
tracking_status_text: string;
|
||||
latest_desc: string;
|
||||
latest_time: string;
|
||||
nodes: Array<{
|
||||
node_time: string;
|
||||
node_desc: string;
|
||||
node_location: string;
|
||||
}>;
|
||||
};
|
||||
timeline: Array<{
|
||||
node_code: string;
|
||||
node_text: string;
|
||||
node_desc: string;
|
||||
occurred_at: string;
|
||||
}>;
|
||||
supplement_task: null | {
|
||||
task_id: number;
|
||||
reason: string;
|
||||
deadline: string;
|
||||
items: Array<{
|
||||
item_code: string;
|
||||
item_name: string;
|
||||
guide_text: string;
|
||||
}>;
|
||||
};
|
||||
available_actions: {
|
||||
primary_action: string;
|
||||
secondary_action: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ShippingDetailData {
|
||||
order_info: {
|
||||
order_id: number;
|
||||
order_no: string;
|
||||
appraisal_no: string;
|
||||
service_provider: string;
|
||||
display_status: string;
|
||||
estimated_finish_time: string;
|
||||
product_name: string;
|
||||
};
|
||||
shipping_address: {
|
||||
warehouse_id?: number;
|
||||
warehouse_name?: string;
|
||||
warehouse_code?: string;
|
||||
receiver_name: string;
|
||||
receiver_mobile: string;
|
||||
province: string;
|
||||
city: string;
|
||||
district: string;
|
||||
detail_address: string;
|
||||
service_time: string;
|
||||
notice: string;
|
||||
};
|
||||
shipping_options: {
|
||||
current_warehouse_id: number;
|
||||
can_select_warehouse: boolean;
|
||||
list: Array<{
|
||||
id: number;
|
||||
warehouse_name: string;
|
||||
warehouse_code: string;
|
||||
warehouse_type: string;
|
||||
warehouse_type_text: string;
|
||||
service_provider: string;
|
||||
service_provider_text: string;
|
||||
receiver_name: string;
|
||||
receiver_mobile: string;
|
||||
province: string;
|
||||
city: string;
|
||||
district: string;
|
||||
detail_address: string;
|
||||
full_address: string;
|
||||
service_time: string;
|
||||
notice: string;
|
||||
supported_category_ids: number[];
|
||||
supported_category_names: string[];
|
||||
status: string;
|
||||
status_text: string;
|
||||
is_default: boolean;
|
||||
is_recommended?: boolean;
|
||||
recommended_reason?: string;
|
||||
sort_order: number;
|
||||
remark: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}>;
|
||||
};
|
||||
shipping_notice: {
|
||||
tips: string[];
|
||||
express_recommendations: string[];
|
||||
};
|
||||
logistics_info: {
|
||||
express_company: string;
|
||||
tracking_no: string;
|
||||
tracking_status: string;
|
||||
tracking_status_text: string;
|
||||
latest_desc: string;
|
||||
latest_time: string;
|
||||
is_submitted: boolean;
|
||||
};
|
||||
logistics_nodes: Array<{
|
||||
node_time: string;
|
||||
node_desc: string;
|
||||
node_location: string;
|
||||
}>;
|
||||
can_submit_tracking: boolean;
|
||||
}
|
||||
|
||||
export interface UserAddressItem {
|
||||
id: number;
|
||||
consignee: string;
|
||||
mobile: string;
|
||||
province: string;
|
||||
city: string;
|
||||
district: string;
|
||||
detail_address: string;
|
||||
full_address: string;
|
||||
is_default: boolean;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface ReportListItem {
|
||||
report_id: number | null;
|
||||
order_id: number;
|
||||
report_no: string;
|
||||
product_name: string;
|
||||
product_cover: string;
|
||||
service_provider: string;
|
||||
status: string;
|
||||
result_text: string;
|
||||
institution_name: string;
|
||||
publish_time: string;
|
||||
}
|
||||
|
||||
export interface ReportDetailData {
|
||||
evidence_attachments: EvidenceAttachmentAsset[];
|
||||
report_header: {
|
||||
report_id: number;
|
||||
report_no: string;
|
||||
report_type: string;
|
||||
report_title: string;
|
||||
report_status: string;
|
||||
service_provider: string;
|
||||
institution_name: string;
|
||||
publish_time: string;
|
||||
};
|
||||
result_info: Record<string, any>;
|
||||
product_info: Record<string, any>;
|
||||
appraisal_info: Record<string, any>;
|
||||
valuation_info: Record<string, any>;
|
||||
risk_notice_text: string;
|
||||
verify_info: {
|
||||
report_no: string;
|
||||
verify_status: string;
|
||||
verify_url: string;
|
||||
verify_qrcode_url: string;
|
||||
};
|
||||
file_info: {
|
||||
pdf_url: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface VerifyData {
|
||||
verify_status: string;
|
||||
verify_message: string;
|
||||
evidence_attachments: EvidenceAttachmentAsset[];
|
||||
report_summary: {
|
||||
report_no: string;
|
||||
report_title?: string;
|
||||
institution_name: string;
|
||||
publish_time: string;
|
||||
};
|
||||
product_summary: Record<string, any>;
|
||||
result_summary: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface MaterialTagData {
|
||||
tag_status: "unbound" | "pending_report" | "published" | "not_found";
|
||||
status_text: string;
|
||||
message: string;
|
||||
qr_token: string;
|
||||
qr_url: string;
|
||||
scan_count: number;
|
||||
verify_count: number;
|
||||
report_summary: null | {
|
||||
report_id?: number;
|
||||
report_no: string;
|
||||
report_title: string;
|
||||
institution_name: string;
|
||||
publish_time: string;
|
||||
};
|
||||
product_summary: Record<string, any>;
|
||||
result_summary: Record<string, any>;
|
||||
verify_passed: boolean;
|
||||
}
|
||||
|
||||
export interface MaterialTagVerifyResult {
|
||||
verify_passed: boolean;
|
||||
verify_message: string;
|
||||
verify_count: number;
|
||||
}
|
||||
|
||||
export interface MessageSummaryData {
|
||||
total_count: number;
|
||||
unread_count: number;
|
||||
category_counts: {
|
||||
all: number;
|
||||
order: number;
|
||||
report: number;
|
||||
supplement: number;
|
||||
ticket: number;
|
||||
};
|
||||
latest_title: string;
|
||||
latest_time: string;
|
||||
}
|
||||
|
||||
export interface UserMessageItem {
|
||||
id: number;
|
||||
title: string;
|
||||
content: string;
|
||||
biz_type: string;
|
||||
biz_type_text: string;
|
||||
category: "all" | "order" | "report" | "supplement" | "ticket";
|
||||
category_text: string;
|
||||
biz_id: number;
|
||||
is_read: boolean;
|
||||
created_at: string;
|
||||
target_url: string;
|
||||
target_label: string;
|
||||
}
|
||||
|
||||
export interface UserMessageListData {
|
||||
list: UserMessageItem[];
|
||||
summary: {
|
||||
total_count: number;
|
||||
unread_count: number;
|
||||
category_counts: {
|
||||
all: number;
|
||||
order: number;
|
||||
report: number;
|
||||
supplement: number;
|
||||
ticket: number;
|
||||
};
|
||||
current_count: number;
|
||||
current_category: "all" | "order" | "report" | "supplement" | "ticket";
|
||||
unread_only: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SupplementFileItem {
|
||||
id: number;
|
||||
file_id: string;
|
||||
file_url: string;
|
||||
thumbnail_url: string;
|
||||
}
|
||||
|
||||
export interface SupplementDetailData {
|
||||
order_id: number;
|
||||
order_no: string;
|
||||
appraisal_no: string;
|
||||
reason: string;
|
||||
deadline: string;
|
||||
items: Array<{
|
||||
upload_item_id: number;
|
||||
item_code: string;
|
||||
item_name: string;
|
||||
guide_text: string;
|
||||
is_required: boolean;
|
||||
status: string;
|
||||
files: SupplementFileItem[];
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface TicketOverviewCard {
|
||||
title: string;
|
||||
value: number;
|
||||
desc: string;
|
||||
}
|
||||
|
||||
export interface TicketAttachmentAsset {
|
||||
file_id: string;
|
||||
file_url: string;
|
||||
thumbnail_url: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export interface EvidenceAttachmentAsset {
|
||||
file_id: string;
|
||||
file_url: string;
|
||||
thumbnail_url: string;
|
||||
name?: string;
|
||||
file_type: string;
|
||||
mime_type: string;
|
||||
}
|
||||
|
||||
export interface UserTicketListItem {
|
||||
id: number;
|
||||
ticket_no: string;
|
||||
ticket_type: string;
|
||||
ticket_type_text: string;
|
||||
status: string;
|
||||
status_text: string;
|
||||
priority: string;
|
||||
priority_text: string;
|
||||
title: string;
|
||||
order_id: number;
|
||||
latest_message: string;
|
||||
updated_at: string;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface UserTicketDetailData {
|
||||
ticket_info: {
|
||||
id: number;
|
||||
ticket_no: string;
|
||||
ticket_type: string;
|
||||
ticket_type_text: string;
|
||||
status: string;
|
||||
status_text: string;
|
||||
priority: string;
|
||||
priority_text: string;
|
||||
title: string;
|
||||
content: string;
|
||||
order_id: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
};
|
||||
order_info: null | {
|
||||
order_id: number;
|
||||
order_no: string;
|
||||
display_status: string;
|
||||
};
|
||||
messages: Array<{
|
||||
sender_type: string;
|
||||
sender_type_text: string;
|
||||
content: string;
|
||||
attachments: TicketAttachmentAsset[];
|
||||
created_at: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export const appApi = {
|
||||
getHomeData() {
|
||||
return request<HomeData>("/api/app/home/index");
|
||||
},
|
||||
getPageVisuals() {
|
||||
return request<PageVisualsData>("/api/app/content/page-visuals");
|
||||
},
|
||||
getHelpCenter(params?: Record<string, string | number | undefined>) {
|
||||
return request<HelpCenterData>("/api/app/help-center", {
|
||||
params,
|
||||
});
|
||||
},
|
||||
getHelpArticleDetail(id: number) {
|
||||
return request<HelpArticleDetailData>("/api/app/help-article/detail", {
|
||||
params: { id },
|
||||
});
|
||||
},
|
||||
getSettings() {
|
||||
return request<SettingsData>("/api/app/settings");
|
||||
},
|
||||
getMineOverview() {
|
||||
return request<MineOverviewData>("/api/app/mine/overview");
|
||||
},
|
||||
saveSettings(payload: {
|
||||
nickname: string;
|
||||
preferences: SettingsData["preferences"];
|
||||
}) {
|
||||
return request<SettingsData>("/api/app/settings/save", {
|
||||
method: "POST",
|
||||
data: payload,
|
||||
});
|
||||
},
|
||||
getOrders() {
|
||||
return request<{ list: OrderListItem[] }>("/api/app/orders");
|
||||
},
|
||||
getOrderDetail(id: number) {
|
||||
return request<OrderDetailData>("/api/app/order/detail", {
|
||||
params: { id },
|
||||
});
|
||||
},
|
||||
getOrderShippingDetail(orderId: number) {
|
||||
return request<ShippingDetailData>("/api/app/order/shipping", {
|
||||
params: { order_id: orderId },
|
||||
});
|
||||
},
|
||||
saveOrderShipping(payload: {
|
||||
order_id: number;
|
||||
express_company: string;
|
||||
tracking_no: string;
|
||||
warehouse_id?: number;
|
||||
}) {
|
||||
return request<{
|
||||
order_id: number;
|
||||
express_company: string;
|
||||
tracking_no: string;
|
||||
}>("/api/app/order/shipping/save", {
|
||||
method: "POST",
|
||||
data: payload,
|
||||
});
|
||||
},
|
||||
saveOrderReturnAddress(payload: {
|
||||
order_id: number;
|
||||
address_id: number;
|
||||
}) {
|
||||
return request<{
|
||||
order_id: number;
|
||||
return_address: OrderDetailData["return_address"];
|
||||
}>("/api/app/order/return-address/save", {
|
||||
method: "POST",
|
||||
data: payload,
|
||||
});
|
||||
},
|
||||
getAddresses() {
|
||||
return request<{ list: UserAddressItem[] }>("/api/app/addresses");
|
||||
},
|
||||
getAddressDetail(id: number) {
|
||||
return request<UserAddressItem>("/api/app/address/detail", {
|
||||
params: { id },
|
||||
});
|
||||
},
|
||||
saveAddress(payload: {
|
||||
id?: number;
|
||||
consignee: string;
|
||||
mobile: string;
|
||||
province: string;
|
||||
city: string;
|
||||
district: string;
|
||||
detail_address: string;
|
||||
is_default: boolean;
|
||||
}) {
|
||||
return request<{ id: number; address: UserAddressItem }>("/api/app/address/save", {
|
||||
method: "POST",
|
||||
data: payload,
|
||||
});
|
||||
},
|
||||
setDefaultAddress(id: number) {
|
||||
return request<{ id: number }>("/api/app/address/default", {
|
||||
method: "POST",
|
||||
data: { id },
|
||||
});
|
||||
},
|
||||
deleteAddress(id: number) {
|
||||
return request<{ id: number }>("/api/app/address/delete", {
|
||||
method: "POST",
|
||||
data: { id },
|
||||
});
|
||||
},
|
||||
getReports() {
|
||||
return request<{ list: ReportListItem[] }>("/api/app/reports");
|
||||
},
|
||||
getReportDetail(params: { id?: number; report_no?: string }) {
|
||||
return request<ReportDetailData>("/api/app/report/detail", {
|
||||
params,
|
||||
});
|
||||
},
|
||||
verifyReport(reportNo: string) {
|
||||
return request<VerifyData>("/api/app/verify", {
|
||||
params: { report_no: reportNo },
|
||||
});
|
||||
},
|
||||
getMaterialTag(token: string) {
|
||||
return request<MaterialTagData>("/api/app/material-tag", {
|
||||
params: { token },
|
||||
});
|
||||
},
|
||||
verifyMaterialTag(payload: {
|
||||
token: string;
|
||||
report_no: string;
|
||||
verify_code: string;
|
||||
}) {
|
||||
return request<MaterialTagVerifyResult>("/api/app/material-tag/verify", {
|
||||
method: "POST",
|
||||
data: payload,
|
||||
});
|
||||
},
|
||||
getMessageSummary() {
|
||||
return request<MessageSummaryData>("/api/app/messages/summary");
|
||||
},
|
||||
getMessageMeta() {
|
||||
return request<{ message_page_copy: MessagePageCopy }>("/api/app/messages/meta");
|
||||
},
|
||||
getMessages(params?: Record<string, string | number | undefined>) {
|
||||
return request<UserMessageListData>("/api/app/messages", {
|
||||
params,
|
||||
});
|
||||
},
|
||||
readMessage(id: number) {
|
||||
return request<{ id: number; is_read: boolean }>("/api/app/message/read", {
|
||||
method: "POST",
|
||||
data: { id },
|
||||
});
|
||||
},
|
||||
readAllMessages() {
|
||||
return request<{ affected: number }>("/api/app/messages/read-all", {
|
||||
method: "POST",
|
||||
});
|
||||
},
|
||||
getSupplementDetail(orderId: number) {
|
||||
return request<SupplementDetailData>("/api/app/order/supplement", {
|
||||
params: { order_id: orderId },
|
||||
});
|
||||
},
|
||||
uploadSupplementFile(payload: {
|
||||
uploadItemId: number;
|
||||
filePath: string;
|
||||
}) {
|
||||
const baseUrl = resolveApiBaseUrl().replace(/\/$/, "");
|
||||
return new Promise<SupplementFileItem>((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
url: `${baseUrl}/api/app/order/supplement/file/upload`,
|
||||
filePath: payload.filePath,
|
||||
name: "file",
|
||||
header: buildAuthHeaders(),
|
||||
formData: {
|
||||
upload_item_id: payload.uploadItemId,
|
||||
},
|
||||
success: (response) => {
|
||||
try {
|
||||
resolve(parseUploadResponse<SupplementFileItem>(response, "补资料上传失败"));
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
},
|
||||
fail: (error) => reject(error),
|
||||
});
|
||||
});
|
||||
},
|
||||
deleteSupplementFile(fileId: string) {
|
||||
return request<{ file_id: string }>("/api/app/order/supplement/file/delete", {
|
||||
method: "POST",
|
||||
data: {
|
||||
file_id: fileId,
|
||||
},
|
||||
});
|
||||
},
|
||||
submitSupplement(orderId: number) {
|
||||
return request<{ order_id: number; next_status: string }>("/api/app/order/supplement/submit", {
|
||||
method: "POST",
|
||||
data: {
|
||||
order_id: orderId,
|
||||
},
|
||||
});
|
||||
},
|
||||
getTicketOverview() {
|
||||
return request<{ cards: TicketOverviewCard[]; ticket_types: TicketTypeOption[] }>("/api/app/tickets/overview");
|
||||
},
|
||||
getTicketMeta() {
|
||||
return request<{ ticket_types: TicketTypeOption[]; ticket_statuses: TicketStatusOption[] }>("/api/app/ticket/meta");
|
||||
},
|
||||
getTickets(params?: Record<string, string | number | undefined>) {
|
||||
return request<{ list: UserTicketListItem[] }>("/api/app/tickets", {
|
||||
params,
|
||||
});
|
||||
},
|
||||
getTicketDetail(id: number) {
|
||||
return request<UserTicketDetailData>("/api/app/ticket/detail", {
|
||||
params: { id },
|
||||
});
|
||||
},
|
||||
createTicket(payload: {
|
||||
ticket_type: string;
|
||||
title: string;
|
||||
content: string;
|
||||
order_id?: number;
|
||||
report_id?: number;
|
||||
attachments?: TicketAttachmentAsset[];
|
||||
}) {
|
||||
return request<{ ticket_id: number; ticket_no: string }>("/api/app/ticket/create", {
|
||||
method: "POST",
|
||||
data: payload,
|
||||
});
|
||||
},
|
||||
replyTicket(ticketId: number, content: string, attachments: TicketAttachmentAsset[] = []) {
|
||||
return request<{ ticket_id: number }>("/api/app/ticket/reply", {
|
||||
method: "POST",
|
||||
data: {
|
||||
ticket_id: ticketId,
|
||||
content,
|
||||
attachments,
|
||||
},
|
||||
});
|
||||
},
|
||||
uploadTicketFile(filePath: string) {
|
||||
const baseUrl = resolveApiBaseUrl().replace(/\/$/, "");
|
||||
return new Promise<TicketAttachmentAsset>((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
url: `${baseUrl}/api/app/ticket/file/upload`,
|
||||
filePath,
|
||||
name: "file",
|
||||
header: buildAuthHeaders(),
|
||||
success: (response) => {
|
||||
try {
|
||||
resolve(parseUploadResponse<TicketAttachmentAsset>(response, "附件上传失败"));
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
},
|
||||
fail: (error) => reject(error),
|
||||
});
|
||||
});
|
||||
},
|
||||
deleteTicketFile(fileUrl: string) {
|
||||
return request<{ file_url: string }>("/api/app/ticket/file/delete", {
|
||||
method: "POST",
|
||||
data: {
|
||||
file_url: fileUrl,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
175
user-app/src/api/appraisal.ts
Normal file
175
user-app/src/api/appraisal.ts
Normal file
@@ -0,0 +1,175 @@
|
||||
import { parseUploadResponse, request } from "../utils/request";
|
||||
import { buildAuthHeaders } from "../utils/auth";
|
||||
import { resolveApiBaseUrl } from "../utils/env";
|
||||
import { resolveOrderSourceChannel } from "../utils/order-source";
|
||||
|
||||
export interface CatalogOption {
|
||||
brand_id?: number;
|
||||
brand_name?: string;
|
||||
}
|
||||
|
||||
export interface CategoryOption {
|
||||
category_id: number;
|
||||
category_name: string;
|
||||
category_code: string;
|
||||
}
|
||||
|
||||
export interface UploadItem {
|
||||
item_code: string;
|
||||
item_name: string;
|
||||
guide_text: string;
|
||||
sample_image_url: string;
|
||||
is_required: boolean;
|
||||
quality_status: string;
|
||||
quality_message: string;
|
||||
files?: UploadFileAsset[];
|
||||
}
|
||||
|
||||
export interface UploadFileAsset {
|
||||
file_id: string;
|
||||
file_url: string;
|
||||
thumbnail_url: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export interface DraftDetail {
|
||||
draft_id: number;
|
||||
service_provider: string;
|
||||
service_mode: string;
|
||||
current_step: number;
|
||||
product_info: Record<string, any>;
|
||||
extra_info: Record<string, any>;
|
||||
upload_info?: {
|
||||
items: UploadItem[];
|
||||
};
|
||||
}
|
||||
|
||||
export interface PreviewData {
|
||||
service_summary: {
|
||||
service_provider: string;
|
||||
service_provider_text: string;
|
||||
};
|
||||
product_summary: {
|
||||
product_name: string;
|
||||
category_name: string;
|
||||
brand_name: string;
|
||||
price: number;
|
||||
};
|
||||
upload_summary: {
|
||||
uploaded_count: number;
|
||||
};
|
||||
fee_detail: {
|
||||
service_fee: number;
|
||||
discount_fee: number;
|
||||
pay_amount: number;
|
||||
};
|
||||
agreements: Array<{
|
||||
code: string;
|
||||
title: string;
|
||||
desc: string;
|
||||
target_url: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface SubmitResult {
|
||||
order_id: number;
|
||||
order_no: string;
|
||||
appraisal_no: string;
|
||||
pay_amount: number;
|
||||
next_status: string;
|
||||
}
|
||||
|
||||
export const appraisalApi = {
|
||||
createDraft(serviceProvider: string) {
|
||||
return request<{ draft_id: number; service_provider: string; service_mode: string }>(
|
||||
"/api/app/appraisal/draft/create",
|
||||
{
|
||||
method: "POST",
|
||||
data: {
|
||||
service_provider: serviceProvider,
|
||||
service_mode: "physical",
|
||||
},
|
||||
},
|
||||
);
|
||||
},
|
||||
getDraft(draftId: number) {
|
||||
return request<DraftDetail>("/api/app/appraisal/draft", {
|
||||
params: { draft_id: draftId },
|
||||
});
|
||||
},
|
||||
saveDraft(payload: Record<string, unknown>) {
|
||||
return request<{ draft_id: number; current_step: number }>("/api/app/appraisal/draft/save", {
|
||||
method: "POST",
|
||||
data: payload,
|
||||
});
|
||||
},
|
||||
getBrands(categoryId: number) {
|
||||
return request<{ list: CatalogOption[] }>("/api/app/catalog/brands", {
|
||||
params: { category_id: categoryId },
|
||||
});
|
||||
},
|
||||
getCategories() {
|
||||
return request<{ list: CategoryOption[] }>("/api/app/catalog/categories");
|
||||
},
|
||||
getUploadTemplate(categoryId: number, serviceProvider: string) {
|
||||
return request<{ template_id: number; required_items: UploadItem[]; optional_items: UploadItem[] }>(
|
||||
"/api/app/appraisal/upload-template",
|
||||
{
|
||||
params: { category_id: categoryId, service_provider: serviceProvider },
|
||||
},
|
||||
);
|
||||
},
|
||||
preview(draftId: number) {
|
||||
return request<PreviewData>("/api/app/appraisal/preview", {
|
||||
method: "POST",
|
||||
data: { draft_id: draftId },
|
||||
});
|
||||
},
|
||||
submit(draftId: number, returnAddressId?: number) {
|
||||
return request<SubmitResult>("/api/app/appraisal/submit", {
|
||||
method: "POST",
|
||||
data: {
|
||||
draft_id: draftId,
|
||||
return_address_id: returnAddressId,
|
||||
source_channel: resolveOrderSourceChannel(),
|
||||
},
|
||||
});
|
||||
},
|
||||
uploadFile(payload: {
|
||||
draftId: number;
|
||||
itemCode: string;
|
||||
itemName: string;
|
||||
filePath: string;
|
||||
}) {
|
||||
const baseUrl = resolveApiBaseUrl().replace(/\/$/, "");
|
||||
return new Promise<UploadFileAsset>((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
url: `${baseUrl}/api/app/appraisal/file/upload`,
|
||||
filePath: payload.filePath,
|
||||
name: "file",
|
||||
header: buildAuthHeaders(),
|
||||
formData: {
|
||||
draft_id: payload.draftId,
|
||||
item_code: payload.itemCode,
|
||||
item_name: payload.itemName,
|
||||
},
|
||||
success: (response) => {
|
||||
try {
|
||||
resolve(parseUploadResponse<UploadFileAsset>(response, "图片上传失败"));
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
},
|
||||
fail: (error) => reject(error),
|
||||
});
|
||||
});
|
||||
},
|
||||
deleteFile(fileUrl: string) {
|
||||
return request<{ file_url: string }>("/api/app/appraisal/file/delete", {
|
||||
method: "POST",
|
||||
data: {
|
||||
file_url: fileUrl,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
62
user-app/src/api/auth.ts
Normal file
62
user-app/src/api/auth.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { request } from "../utils/request";
|
||||
|
||||
export interface AuthUserInfo {
|
||||
id: number;
|
||||
nickname: string;
|
||||
mobile: string;
|
||||
avatar: string;
|
||||
status: string;
|
||||
password_set: boolean;
|
||||
}
|
||||
|
||||
export interface SendLoginCodeResult {
|
||||
mobile: string;
|
||||
scene: string;
|
||||
expire_seconds: number;
|
||||
retry_after_seconds: number;
|
||||
debug_code?: string;
|
||||
}
|
||||
|
||||
export interface LoginResult {
|
||||
token: string;
|
||||
user_info: AuthUserInfo;
|
||||
}
|
||||
|
||||
export const authApi = {
|
||||
sendLoginCode(mobile: string) {
|
||||
return request<SendLoginCodeResult>("/api/app/auth/send-code", {
|
||||
method: "POST",
|
||||
data: { mobile },
|
||||
});
|
||||
},
|
||||
loginByCode(mobile: string, code: string) {
|
||||
return request<LoginResult>("/api/app/auth/login/code", {
|
||||
method: "POST",
|
||||
data: { mobile, code },
|
||||
});
|
||||
},
|
||||
loginByPassword(mobile: string, password: string) {
|
||||
return request<LoginResult>("/api/app/auth/login/password", {
|
||||
method: "POST",
|
||||
data: { mobile, password },
|
||||
});
|
||||
},
|
||||
getMe() {
|
||||
return request<{ user_info: AuthUserInfo }>("/api/app/auth/me");
|
||||
},
|
||||
savePassword(payload: {
|
||||
current_password?: string;
|
||||
new_password: string;
|
||||
confirm_password: string;
|
||||
}) {
|
||||
return request<{ user_id: number; password_set: boolean; had_password: boolean }>("/api/app/auth/password/save", {
|
||||
method: "POST",
|
||||
data: payload,
|
||||
});
|
||||
},
|
||||
logout() {
|
||||
return request<Record<string, never>>("/api/app/auth/logout", {
|
||||
method: "POST",
|
||||
});
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user