dingdanquanliucheng/frontend/web-admin/src/mockApi.js
taiyi cdaff4999d refactor: 订单中心+详情+物流轨迹全面优化
- 订单中心:移除管理员录入表单,全宽列表,增加来源/交付方式列,修正详情链接
- 订单详情:增加产品明细表、审批记录、物流信息;按钮绑定真实后端接口
- 物流轨迹:支持订单号搜索,显示关联订单信息,支持URL参数自动查询
- mockApi:新增 fetchOrderDetailAdmin、changeOrderStatus、fetchOrderList stats

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-05 13:03:26 +08:00

1405 lines
43 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 管理员端 API 请求模块(已对接真实后端)
* 职责:封装所有管理员端的 HTTP 请求,包括认证、用户管理、角色管理、
* 菜单管理、客户管理、产品管理、供应商管理、订单管理、审批管理、
* 审计日志、配置管理、报表统计、AI 识别、提醒中心等接口
*/
import { apiBaseUrl } from "./config";
/** API 请求基础地址 */
const API_BASE_URL = apiBaseUrl;
/** localStorage 中存储管理员 token 的键名 */
const ADMIN_TOKEN_KEY = "admin_token";
/**
* 将查询参数对象拼接为 URL 查询字符串
* @param {Object} [params={}] - 查询参数键值对
* @returns {string} URL 查询字符串(不含前导 ?
*/
function buildQuery(params = {}) {
const search = new URLSearchParams();
Object.entries(params).forEach(([key, value]) => {
if (value === undefined || value === null || value === "") {
return;
}
search.set(key, String(value));
});
return search.toString();
}
/**
* 发送 HTTP 请求到后端 API
* 自动附加 Authorization 头和 Content-Type统一处理响应和错误
* @param {string} path - API 路径(不含基础地址)
* @param {Object} [options={}] - fetch 请求选项
* @param {string} [options.method] - HTTP 方法,默认 GET
* @param {Object} [options.headers] - 额外请求头
* @param {string} [options.body] - 请求体JSON 字符串)
* @returns {Promise<any>} 后端返回的 data 字段内容
* @throws {Error} 当响应状态码非 2xx 或业务码非 0 时抛出
*/
async function request(path, options = {}) {
const token = localStorage.getItem(ADMIN_TOKEN_KEY) || "";
const response = await fetch(`${API_BASE_URL}${path}`, {
headers: {
"Content-Type": "application/json",
...(token ? { Authorization: `Bearer ${token}` } : {}),
...(options.headers || {}),
},
...options,
});
const result = await response.json().catch(() => ({}));
if (!response.ok || result.code !== 0) {
throw new Error(result.message || `请求失败: ${response.status}`);
}
return result.data;
}
// ========== 认证相关 ==========
/**
* 管理员登录
* @param {Object} form - 登录表单
* @param {string} form.username - 用户名
* @param {string} form.password - 密码
* @returns {Promise<{user: Object, token: string}>} 用户信息和 token
*/
export async function loginAdminUser(form) {
const data = await request("/api/auth/login", {
method: "POST",
body: JSON.stringify({
username: form.username,
password: form.password,
role_type: "admin",
}),
});
localStorage.setItem(ADMIN_TOKEN_KEY, data.token || "");
return {
user: {
userId: data.user_id,
username: data.username,
realName: data.real_name,
roleName: data.role_name,
roleCode: data.role_code,
},
token: data.token,
};
}
/**
* 清除管理员 token退出登录时调用
*/
export function clearAdminToken() {
localStorage.removeItem(ADMIN_TOKEN_KEY);
}
// ========== 状态映射工具函数 ==========
/**
* 将订单状态码映射为中文文本
* @param {string} status - 订单状态码(如 draft、pending_approve 等)
* @returns {string} 中文状态名称
*/
function mapOrderStatus(status) {
const statusMap = {
draft: "草稿",
pending_approve: "待审批",
approved: "已审批",
rejected: "已驳回",
cancel_pending: "待取消审批",
cancel_fulfillment_pending: "履约取消审批中",
canceled: "已取消",
pending_factory: "待工厂处理",
pending_driver: "待司机接单",
accepted: "已接单",
picked_up: "已揽货",
delivered: "已送达",
production: "生产中",
shipped: "已发货",
completed: "已完成",
settled: "已结算",
};
return statusMap[status] || status || "-";
}
/**
* 将审批类型码映射为中文文本
* @param {string} type - 审批类型码order / cancel_order
* @returns {string} 中文类型名称
*/
function mapApproveType(type) {
const typeMap = {
order: "订单审批",
cancel_order: "取消审批",
};
return typeMap[type] || type || "-";
}
/**
* 将审批结果码映射为中文文本
* @param {string} result - 审批结果码pass / reject
* @returns {string} 中文结果名称
*/
function mapApproveResult(result) {
const resultMap = {
pass: "通过",
reject: "驳回",
};
return resultMap[result] || result || "-";
}
/**
* 将后端订单数据映射为审批列表行对象
* @param {Object} item - 后端返回的订单原始数据
* @returns {Object} 前端展示用的审批行数据
*/
function buildApprovalRow(item) {
return {
orderId: item.order_id,
orderNo: item.order_no,
customerName: item.customer_name,
customerMobile: item.customer_mobile,
orderStatus: item.order_status,
statusText: mapOrderStatus(item.order_status),
orderSource: item.order_source || "-",
amount: Number(item.sale_price_total || 0).toFixed(2),
createdAt: item.created_at || "-",
};
}
// ========== 系统配置管理 ==========
/**
* 获取单个系统配置项
* @param {string} configKey - 配置键名
* @returns {Promise<Object>} 配置项详情configKey、configValue、configName 等)
*/
export async function fetchConfigItem(configKey) {
const data = await request(`/api/configs/${configKey}`);
return {
configKey: data.config_key,
configValue: data.config_value,
configName: data.config_name,
remark: data.remark || "",
status: Number(data.status ?? 1),
};
}
/**
* 更新系统配置项
* @param {string} configKey - 配置键名
* @param {Object} payload - 更新内容
* @returns {Promise<any>}
*/
export async function updateConfigItem(configKey, payload) {
return request(`/api/configs/${configKey}`, {
method: "PUT",
body: JSON.stringify(payload),
});
}
// ========== 系统用户管理 ==========
/**
* 获取系统用户列表
* @param {Object} [filters={}] - 筛选条件
* @param {string} [filters.username] - 用户名模糊搜索
* @param {string} [filters.real_name] - 真实姓名模糊搜索
* @param {string} [filters.mobile] - 手机号模糊搜索
* @param {number} [filters.role_id] - 角色 ID
* @param {number} [filters.status] - 状态1 启用 / 0 停用)
* @returns {Promise<{rows: Array}>} 用户列表
*/
export async function fetchSystemUsers(filters = {}) {
const query = buildQuery({
username: filters.username?.trim() || undefined,
real_name: filters.real_name?.trim() || undefined,
mobile: filters.mobile?.trim() || undefined,
role_id: filters.role_id || undefined,
status: filters.status || undefined,
page_no: 1,
page_size: 50,
});
const data = await request(`/api/system/users?${query}`);
return {
rows: (data.list || []).map((item) => ({
userId: item.user_id,
username: item.username,
realName: item.real_name,
mobile: item.mobile || "-",
roleId: item.role_id,
roleName: item.role_name || "-",
roleCode: item.role_code || "-",
status: Number(item.status || 1) === 1 ? "启用" : "停用",
createdAt: item.created_at || "-",
updatedAt: item.updated_at || "-",
})),
};
}
/**
* 获取用户下拉选项(用于业务员选择等场景)
* @returns {Promise<Array<{value: number, label: string}>>}
*/
export async function fetchUserOptions() {
const data = await request("/api/system/users?page_size=200");
return (data.list || []).map(u => ({
value: u.user_id,
label: u.real_name || u.username,
}));
}
/**
* 创建系统用户
* @param {Object} payload - 用户信息username、password、role_id 等)
* @returns {Promise<any>}
*/
export async function createSystemUser(payload) {
return request("/api/system/users", {
method: "POST",
body: JSON.stringify(payload),
});
}
/**
* 更新系统用户信息
* @param {number} userId - 用户 ID
* @param {Object} payload - 更新内容
* @returns {Promise<any>}
*/
export async function updateSystemUser(userId, payload) {
return request(`/api/system/users/${userId}`, {
method: "PUT",
body: JSON.stringify(payload),
});
}
/**
* 重置系统用户密码
* @param {number} userId - 用户 ID
* @param {Object} payload - 包含新密码的对象
* @returns {Promise<any>}
*/
export async function resetSystemUserPassword(userId, payload) {
return request(`/api/system/users/${userId}/reset-password`, {
method: "POST",
body: JSON.stringify(payload),
});
}
/**
* 切换用户启用/停用状态
* @param {number} userId - 用户 ID
* @param {number} status - 目标状态1 启用 / 0 停用)
* @returns {Promise<any>}
*/
export async function changeUserStatus(userId, status) {
return request(`/api/system/users/${userId}/status`, {
method: "POST",
body: JSON.stringify({ status }),
});
}
// ========== 系统角色管理 ==========
/**
* 获取系统角色列表
* @param {Object} [filters={}] - 筛选条件
* @param {string} [filters.role_name] - 角色名称模糊搜索
* @param {string} [filters.role_code] - 角色编码模糊搜索
* @param {number} [filters.status] - 状态1 启用 / 0 停用)
* @returns {Promise<{rows: Array}>} 角色列表
*/
export async function fetchSystemRoles(filters = {}) {
const query = buildQuery({
role_name: filters.role_name?.trim() || undefined,
role_code: filters.role_code?.trim() || undefined,
status: filters.status || undefined,
page_no: 1,
page_size: 50,
});
const data = await request(`/api/system/roles?${query}`);
return {
rows: (data.list || []).map((item) => ({
roleId: item.role_id,
roleName: item.role_name,
roleCode: item.role_code,
status: Number(item.status || 1) === 1 ? "启用" : "停用",
remark: item.remark || "-",
createdAt: item.created_at || "-",
})),
};
}
/**
* 创建系统角色
* @param {Object} payload - 角色信息role_name、role_code 等)
* @returns {Promise<any>}
*/
export async function createSystemRole(payload) {
return request("/api/system/roles", {
method: "POST",
body: JSON.stringify(payload),
});
}
/**
* 更新系统角色信息
* @param {number} roleId - 角色 ID
* @param {Object} payload - 更新内容
* @returns {Promise<any>}
*/
export async function updateSystemRole(roleId, payload) {
return request(`/api/system/roles/${roleId}`, {
method: "PUT",
body: JSON.stringify(payload),
});
}
// ========== 角色菜单权限管理 ==========
/**
* 获取指定角色已分配的菜单权限
* @param {number} roleId - 角色 ID
* @returns {Promise<any>} 菜单权限数据
*/
export async function fetchRoleMenuAssignment(roleId) {
return request(`/api/system/roles/${roleId}/menus`);
}
/**
* 分配菜单权限给指定角色
* @param {number} roleId - 角色 ID
* @param {Object} payload - 菜单 ID 列表等权限数据
* @returns {Promise<any>}
*/
export async function assignRoleMenus(roleId, payload) {
return request(`/api/system/roles/${roleId}/menus`, {
method: "PUT",
body: JSON.stringify(payload),
});
}
// ========== 系统菜单管理 ==========
/**
* 将后端树形菜单数据递归展平为带层级的列表
* @param {Array} [list=[]] - 后端返回的菜单树形数组
* @param {number} [level=0] - 当前层级深度
* @returns {Array} 展平后的菜单列表,每项包含 level 表示层级
*/
function flattenSystemMenus(list = [], level = 0) {
return list.flatMap((item) => [
{
menuId: item.menu_id,
parentId: item.parent_id,
menuName: item.menu_name,
menuPath: item.menu_path || "-",
menuType: item.menu_type || "-",
permissionCode: item.permission_code || "-",
icon: item.icon || "-",
sortNo: item.sort_no ?? 0,
status: Number(item.status || 1) === 1 ? "启用" : "停用",
level,
},
...flattenSystemMenus(item.children || [], level + 1),
]);
}
/**
* 获取系统菜单列表
* @param {Object} [filters={}] - 筛选条件
* @param {number} [filters.status] - 状态1 启用 / 0 停用)
* @param {string} [filters.menu_type] - 菜单类型
* @returns {Promise<{rows: Array}>} 展平后的菜单列表
*/
export async function fetchSystemMenus(filters = {}) {
const query = buildQuery({
status: filters.status || undefined,
menu_type: filters.menu_type || undefined,
});
const data = await request(`/api/system/menus?${query}`);
return {
rows: flattenSystemMenus(data || []),
};
}
/**
* 创建系统菜单
* @param {Object} payload - 菜单信息menu_name、parent_id、menu_path 等)
* @returns {Promise<any>}
*/
export async function createSystemMenu(payload) {
return request("/api/system/menus", {
method: "POST",
body: JSON.stringify(payload),
});
}
/**
* 更新系统菜单
* @param {number} menuId - 菜单 ID
* @param {Object} payload - 更新内容
* @returns {Promise<any>}
*/
export async function updateSystemMenu(menuId, payload) {
return request(`/api/system/menus/${menuId}`, {
method: "PUT",
body: JSON.stringify(payload),
});
}
// ========== 审计日志 ==========
/**
* 获取操作审计日志列表
* @param {Object} [filters={}] - 筛选条件
* @param {string} [filters.biz_type] - 业务类型
* @param {string} [filters.biz_id] - 业务 ID
* @param {string} [filters.operator_name] - 操作人姓名
* @param {string} [filters.operate_type] - 操作类型
* @param {string} [filters.start_time] - 开始时间
* @param {string} [filters.end_time] - 结束时间
* @returns {Promise<{rows: Array}>} 审计日志列表
*/
export async function fetchAuditLogs(filters = {}) {
const query = buildQuery({
biz_type: filters.biz_type || undefined,
biz_id: filters.biz_id || undefined,
operator_name: filters.operator_name || undefined,
operate_type: filters.operate_type || undefined,
start_time: filters.start_time || undefined,
end_time: filters.end_time || undefined,
page_no: 1,
page_size: 50,
});
const data = await request(`/api/audit-logs?${query}`);
return {
rows: (data.list || []).map((item) => ({
logId: item.log_id,
operatorName: item.operator_name || "系统",
operateType: item.operate_type,
bizType: item.biz_type,
bizId: item.biz_id,
result: item.result,
operateTime: item.operate_time || "-",
remark: item.remark || "-",
})),
};
}
// ========== 客户管理 ==========
/**
* 将结算类型码映射为中文文本
* @param {string} value - 结算类型码monthly / cash / delivered
* @returns {string} 中文结算类型
*/
function mapSettlementType(value) {
const map = {
monthly: "月结",
cash: "现结",
delivered: "送达结算",
};
return map[value] || value || "-";
}
/**
* 将客户类型码映射为中文文本
* @param {string} value - 客户类型码channel / retail / project
* @returns {string} 中文客户类型
*/
function mapCustomerType(value) {
const map = {
channel: "渠道客户",
retail: "零售客户",
project: "项目客户",
};
return map[value] || value || "-";
}
/**
* 将后端客户数据映射为前端展示行对象
* @param {Object} item - 后端返回的客户原始数据
* @returns {Object} 前端展示用的客户行数据
*/
function buildCustomerRow(item) {
return {
customerId: item.customer_id,
name: item.customer_name,
mobile: item.mobile,
address: item.address || "-",
settlement: mapSettlementType(item.settlement_type),
settlementType: item.settlement_type || "",
settlementDays: item.settlement_days ?? 0,
customerType: mapCustomerType(item.customer_type),
customerTypeValue: item.customer_type || "",
salesman: item.salesman_name || (item.salesman_id ? `业务员${item.salesman_id}` : "-"),
salesmanId: item.salesman_id ?? null,
arrears: Number(item.arrears_amount || 0).toFixed(2),
status: Number(item.status || 1) === 1 ? "启用" : "停用",
remark: item.remark || "-",
creditLimit: Number(item.credit_limit || 0).toFixed(2),
};
}
/**
* 获取客户列表
* @param {Object} [filters={}] - 筛选条件
* @param {string} [filters.customer_name] - 客户名称模糊搜索
* @param {string} [filters.mobile] - 手机号模糊搜索
* @param {string} [filters.customer_type] - 客户类型
* @param {string} [filters.settlement_type] - 结算方式
* @param {number} [filters.salesman_id] - 业务员 ID
* @returns {Promise<{rows: Array}>} 客户列表
*/
export async function fetchCustomerList(filters = {}) {
const query = buildQuery({
customer_name: filters.customer_name?.trim() || undefined,
mobile: filters.mobile?.trim() || undefined,
customer_type: filters.customer_type || undefined,
settlement_type: filters.settlement_type || undefined,
salesman_id: filters.salesman_id || undefined,
page_no: 1,
page_size: 50,
});
const data = await request(`/api/customers?${query}`);
return {
rows: (data.list || []).map(buildCustomerRow),
};
}
/**
* 获取客户详情
* @param {number} customerId - 客户 ID
* @returns {Promise<Object>} 客户详情数据
*/
export async function fetchCustomerDetail(customerId) {
return request(`/api/customers/${customerId}`);
}
/**
* 创建客户
* @param {Object} payload - 客户信息
* @returns {Promise<any>}
*/
export async function createCustomer(payload) {
return request("/api/customers", {
method: "POST",
body: JSON.stringify(payload),
});
}
/**
* 更新客户信息
* @param {number} customerId - 客户 ID
* @param {Object} payload - 更新内容
* @returns {Promise<any>}
*/
export async function updateCustomer(customerId, payload) {
return request(`/api/customers/${customerId}`, {
method: "PUT",
body: JSON.stringify(payload),
});
}
/**
* 批量导入客户数据
* @param {Object} payload - 导入数据(包含文件信息等)
* @returns {Promise<any>}
*/
export async function importCustomers(payload) {
return request("/api/customers/import", {
method: "POST",
body: JSON.stringify(payload),
});
}
/**
* 上传客户导入文件
* @param {Object} payload - 文件上传数据
* @returns {Promise<any>}
*/
export async function uploadImportCustomerFile(payload) {
return request("/api/files/upload", {
method: "POST",
body: JSON.stringify(payload),
});
}
// ========== 产品分类管理 ==========
/**
* 获取产品分类列表
* @param {Object} [filters={}] - 筛选条件
* @param {string} [filters.category_name] - 分类名称模糊搜索
* @param {number} [filters.status] - 状态1 启用 / 0 停用)
* @returns {Promise<{rows: Array}>} 产品分类列表
*/
export async function fetchProductCategoryList(filters = {}) {
const query = buildQuery({
category_name: filters.category_name?.trim() || undefined,
status: filters.status || undefined,
page_no: 1,
page_size: 50,
});
const data = await request(`/api/product-categories?${query}`);
return {
rows: (data.list || []).map((item) => ({
categoryId: item.category_id,
categoryName: item.category_name,
categoryCode: item.category_code,
sortNo: item.sort_no ?? 0,
status: Number(item.status || 1) === 1 ? "启用" : "停用",
remark: item.remark || "-",
})),
};
}
/**
* 创建产品分类
* @param {Object} payload - 分类信息category_name、category_code 等)
* @returns {Promise<any>}
*/
export async function createProductCategory(payload) {
return request("/api/product-categories", {
method: "POST",
body: JSON.stringify(payload),
});
}
/**
* 更新产品分类
* @param {number} categoryId - 分类 ID
* @param {Object} payload - 更新内容
* @returns {Promise<any>}
*/
export async function updateProductCategory(categoryId, payload) {
return request(`/api/product-categories/${categoryId}`, {
method: "PUT",
body: JSON.stringify(payload),
});
}
// ========== 产品管理 ==========
/**
* 更新产品规格信息
* @param {number} productId - 产品 ID
* @param {Object} payload - 规格更新内容
* @returns {Promise<any>}
*/
async function updateProductSpecification(productId, payload) {
return request(`/api/products/specifications/${productId}`, {
method: "PUT",
body: JSON.stringify(payload),
});
}
export { updateProductSpecification };
/**
* 给已有产品追加规格
* @param {number} productId - 产品组中任一规格的 ID
* @param {Object} payload - 新增规格数据
* @returns {Promise<any>}
*/
export async function addProductSpec(productId, payload) {
return request(`/api/products/${productId}/specifications`, {
method: "POST",
body: JSON.stringify(payload),
});
}
/**
* 获取产品列表(含规格信息)
* @param {Object} [filters={}] - 筛选条件
* @param {string} [filters.product_name] - 产品名称模糊搜索
* @param {string} [filters.specification] - 规格模糊搜索
* @param {number} [filters.category_id] - 分类 ID
* @param {number} [filters.status] - 状态1 启用 / 0 停用)
* @returns {Promise<{rows: Array}>} 产品列表(每项包含 specifications 数组)
*/
export async function fetchProductList(filters = {}) {
const query = buildQuery({
product_name: filters.product_name?.trim() || undefined,
specification: filters.specification?.trim() || undefined,
category_id: filters.category_id || undefined,
status: filters.status || undefined,
page_no: 1,
page_size: 50,
});
const data = await request(`/api/products?${query}`);
return {
rows: (data.list || []).map((item) => ({
productName: item.product_name,
categoryName: item.category_name || "-",
categoryId: item.category_id,
status: Number(item.status || 1) === 1 ? "启用" : "停用",
remark: item.remark || "-",
specifications: (item.specifications || []).map((spec) => ({
productId: spec.product_id,
specification: spec.specification || "-",
unit: spec.unit || "-",
costPrice: Number(spec.cost_price || 0).toFixed(2),
salePrice: Number(spec.sale_price || 0).toFixed(2),
isDefault: Boolean(spec.is_default),
status: Number(spec.status || 1) === 1 ? "启用" : "停用",
remark: spec.remark || "-",
})),
})),
};
}
/**
* 创建产品
* @param {Object} payload - 产品信息product_name、category_id 等)
* @returns {Promise<any>}
*/
export async function createProduct(payload) {
return request("/api/products", {
method: "POST",
body: JSON.stringify(payload),
});
}
/**
* 根据产品名称获取产品详情(含所有规格)
* @param {string} productName - 产品名称
* @returns {Promise<Object|null>} 产品详情对象,未找到时返回 null
*/
export async function fetchProductDetail(productName) {
const data = await request(`/api/products?product_name=${encodeURIComponent(productName)}`);
const first = (data.list || []).find((item) => item.product_name === productName) || data.list?.[0];
if (!first) {
return null;
}
return {
product_name: first.product_name,
category_name: first.category_name || "-",
category_id: first.category_id,
status: first.status,
remark: first.remark,
specifications: (first.specifications || []).map((spec) => ({
product_id: spec.product_id,
specification: spec.specification || "-",
unit: spec.unit || "-",
cost_price: Number(spec.cost_price || 0).toFixed(2),
sale_price: Number(spec.sale_price || 0).toFixed(2),
status: Number(spec.status || 1) === 1 ? "启用" : "停用",
remark: spec.remark || "-",
is_default: Boolean(spec.is_default),
})),
};
}
/**
* 设置指定产品规格为默认规格
* @param {number} productId - 产品规格 ID
* @returns {Promise<any>}
*/
export async function setDefaultProductSpec(productId) {
return request(`/api/products/specifications/${productId}/default`, {
method: "PUT",
});
}
// ========== 供应商管理 ==========
/**
* 获取供应商列表
* @param {Object} [filters={}] - 筛选条件
* @param {string} [filters.supplier_name] - 供应商名称模糊搜索
* @param {string} [filters.supplier_type] - 供应商类型
* @param {number} [filters.status] - 状态1 启用 / 0 停用)
* @returns {Promise<{rows: Array}>} 供应商列表
*/
export async function fetchSupplierList(filters = {}) {
const query = buildQuery({
supplier_name: filters.supplier_name?.trim() || undefined,
supplier_type: filters.supplier_type || undefined,
status: filters.status || undefined,
page_no: 1,
page_size: 50,
});
const data = await request(`/api/suppliers?${query}`);
return {
rows: (data.list || []).map((item) => ({
supplierId: item.supplier_id,
supplierName: item.supplier_name,
supplierType: item.supplier_type || "-",
contactName: item.contact_name || "-",
contactMobile: item.contact_mobile || "-",
address: item.address || "-",
templateType: item.template_type || "-",
status: Number(item.status || 1) === 1 ? "启用" : "停用",
remark: item.remark || "-",
})),
};
}
/**
* 获取供应商详情
* @param {number} supplierId - 供应商 ID
* @returns {Promise<Object>} 供应商详情数据
*/
export async function fetchSupplierDetail(supplierId) {
return request(`/api/suppliers/${supplierId}`);
}
/**
* 创建供应商
* @param {Object} payload - 供应商信息
* @returns {Promise<any>}
*/
export async function createSupplier(payload) {
return request("/api/suppliers", {
method: "POST",
body: JSON.stringify(payload),
});
}
/**
* 更新供应商信息
* @param {number} supplierId - 供应商 ID
* @param {Object} payload - 更新内容
* @returns {Promise<any>}
*/
export async function updateSupplier(supplierId, payload) {
return request(`/api/suppliers/${supplierId}`, {
method: "PUT",
body: JSON.stringify(payload),
});
}
// ========== 订单管理 ==========
/**
* 获取订单列表
* @param {Object} [filters={}] - 筛选条件(直接透传给后端)
* @returns {Promise<{total: number, pageNo: number, pageSize: number, rows: Array}>} 分页订单列表
*/
export async function fetchOrderList(filters = {}) {
const query = buildQuery(filters);
const data = await request(`/api/orders${query ? `?${query}` : ""}`);
const rows = (data.list || []).map((item) => ({
orderId: item.order_id,
orderNo: item.order_no,
customerName: item.customer_name,
customerMobile: item.customer_mobile,
orderStatus: item.order_status,
statusText: mapOrderStatus(item.order_status),
orderSource: item.order_source || "-",
deliveryType: item.delivery_type || "-",
salePriceTotal: Number(item.sale_price_total || 0).toFixed(2),
profitTotal: item.profit_total != null ? Number(item.profit_total).toFixed(2) : null,
commissionAmount: item.commission_amount != null ? Number(item.commission_amount).toFixed(2) : null,
createdAt: item.created_at || "-",
}));
const stats = { draft: 0, pending: 0, cancelPending: 0, factory: 0 };
rows.forEach((r) => {
if (r.orderStatus === "draft") stats.draft++;
else if (r.orderStatus === "pending_approve") stats.pending++;
else if (r.orderStatus === "cancel_pending" || r.orderStatus === "cancel_fulfillment_pending") stats.cancelPending++;
else if (r.orderStatus === "pending_factory" || r.orderStatus === "pending_driver") stats.factory++;
});
return { total: data.total, pageNo: data.page_no, pageSize: data.page_size, rows, stats };
}
/**
* 创建新订单
* @param {Object} payload - 订单数据(客户信息、商品明细等)
* @returns {Promise<any>} 后端返回的订单数据
*/
export async function createOrder(payload) {
const data = await request("/api/orders", {
method: "POST",
body: JSON.stringify(payload),
});
return data;
}
/**
* 提交订单进入审批流程
* @param {number} orderId - 订单 ID
* @returns {Promise<any>}
*/
export async function submitOrderToReview(orderId) {
const data = await request(`/api/orders/${orderId}/submit`, { method: "POST" });
return data;
}
/**
* 取消订单
* @param {number} orderId - 订单 ID
* @param {Object} payload - 取消原因等信息
* @returns {Promise<any>}
*/
export async function cancelOrderById(orderId, payload) {
const data = await request(`/api/orders/${orderId}/cancel`, {
method: "POST",
body: JSON.stringify(payload),
});
return data;
}
/**
* 获取订单详情(管理员版,含产品明细、审批记录、物流信息)
* @param {number} orderId - 订单 ID
* @returns {Promise<Object>} 完整订单数据
*/
export async function fetchOrderDetailAdmin(orderId) {
return request(`/api/orders/${orderId}`);
}
/**
* 变更订单状态
* @param {number} orderId - 订单 ID
* @param {Object} payload - { status: string, remark?: string }
* @returns {Promise<any>}
*/
export async function changeOrderStatus(orderId, payload) {
return request(`/api/orders/${orderId}/status`, {
method: "POST",
body: JSON.stringify(payload),
});
}
/**
* 获取工厂待处理订单(已审批 + 待工厂处理状态的订单)
* @returns {Promise<{rows: Array}>} 工厂待处理订单列表
*/
export async function fetchFactoryPendingOrders() {
const approvedQuery = buildQuery({
order_status: "approved",
page_no: 1,
page_size: 50,
});
const pendingFactoryQuery = buildQuery({
order_status: "pending_factory",
page_no: 1,
page_size: 50,
});
const [approvedData, pendingFactoryData] = await Promise.all([
request(`/api/orders?${approvedQuery}`),
request(`/api/orders?${pendingFactoryQuery}`),
]);
return {
rows: [...(approvedData.list || []), ...(pendingFactoryData.list || [])].map(buildApprovalRow),
};
}
/**
* 生成供应商发单文本
* @param {number} orderId - 订单 ID
* @param {number} supplierId - 供应商 ID
* @returns {Promise<any>} 生成的发单文本
*/
export async function generateSupplierText(orderId, supplierId) {
return request(`/api/orders/${orderId}/supplier-text`, {
method: "POST",
body: JSON.stringify({ supplier_id: supplierId }),
});
}
/**
* 确认供应商发单文本
* @param {number} orderId - 订单 ID
* @param {Object} payload - 确认数据(文本内容等)
* @returns {Promise<any>}
*/
export async function confirmSupplierText(orderId, payload) {
return request(`/api/orders/${orderId}/supplier-text/confirm`, {
method: "POST",
body: JSON.stringify(payload),
});
}
// ========== 物流任务管理 ==========
/**
* 获取物流任务列表
* @param {Object} [filters={}] - 筛选条件
* @param {number} [filters.order_id] - 关联订单 ID
* @param {string} [filters.task_no] - 任务编号
* @param {string} [filters.status] - 任务状态
* @returns {Promise<{rows: Array}>} 物流任务列表
*/
export async function fetchLogisticsTasks(filters = {}) {
const query = buildQuery({
order_id: filters.order_id || undefined,
task_no: filters.task_no?.trim() || undefined,
status: filters.status || undefined,
});
const data = await request(`/api/logistics/tasks?${query}`);
return { rows: data.list || [] };
}
/**
* 创建物流任务
* @param {Object} payload - 物流任务数据
* @returns {Promise<any>}
*/
export async function createLogisticsTask(payload) {
return request("/api/logistics/tasks", {
method: "POST",
body: JSON.stringify(payload),
});
}
// ========== 审批管理 ==========
/**
* 按状态查询审批订单列表(内部辅助函数)
* @param {string} status - 订单状态筛选值
* @param {Object} [filters={}] - 附加筛选条件
* @returns {Promise<Array>} 符合条件的审批行数据数组
*/
async function listApprovalOrdersByStatus(status, filters = {}) {
const query = buildQuery({
order_status: status,
order_no: filters.order_no?.trim() || undefined,
customer_name: filters.customer_name?.trim() || undefined,
page_no: 1,
page_size: 50,
});
const data = await request(`/api/orders?${query}`);
return (data.list || []).map(buildApprovalRow);
}
/**
* 获取审批工作台数据(汇总卡片 + 最近待审批列表)
* @returns {Promise<{summaryCards: Array, recentRows: Array}>}
*/
export async function fetchApprovalDashboard() {
const [pendingApproveRows, cancelApproveRows] = await Promise.all([
listApprovalOrdersByStatus("pending_approve"),
listApprovalOrdersByStatus("cancel_pending"),
]);
return {
summaryCards: [
{ label: "待订单审批", value: pendingApproveRows.length },
{ label: "待取消审批", value: cancelApproveRows.length },
{ label: "审批总待办", value: pendingApproveRows.length + cancelApproveRows.length },
],
recentRows: [...pendingApproveRows, ...cancelApproveRows]
.sort((first, second) => String(second.createdAt).localeCompare(String(first.createdAt)))
.slice(0, 8),
};
}
/**
* 获取审批列表(支持按审批状态筛选)
* @param {Object} [filters={}] - 筛选条件
* @param {string} [filters.approve_status] - 审批状态pending_approve / cancel_pending为空则查询全部
* @returns {Promise<{rows: Array}>} 按时间倒序排列的审批列表
*/
export async function fetchApprovalList(filters = {}) {
const targetStatus = filters.approve_status || "";
let rows = [];
if (targetStatus === "pending_approve" || targetStatus === "cancel_pending") {
rows = await listApprovalOrdersByStatus(targetStatus, filters);
} else {
const [pendingApproveRows, cancelApproveRows] = await Promise.all([
listApprovalOrdersByStatus("pending_approve", filters),
listApprovalOrdersByStatus("cancel_pending", filters),
]);
rows = [...pendingApproveRows, ...cancelApproveRows];
}
rows.sort((first, second) => String(second.createdAt).localeCompare(String(first.createdAt)));
return { rows };
}
/**
* 获取审批详情(订单信息 + 商品明细 + 审批日志 + 计算明细)
* @param {number} orderId - 订单 ID
* @returns {Promise<{orderInfo: Object, items: Array, approveLogs: Array, calculationDetail: Object|null}>}
*/
export async function fetchApprovalDetail(orderId) {
const data = await request(`/api/orders/${orderId}`);
return {
orderInfo: {
orderId: data.order_id,
orderNo: data.order_no,
customerName: data.customer_name,
customerMobile: data.customer_mobile,
customerAddress: data.customer_address || "-",
orderStatus: data.order_status,
statusText: mapOrderStatus(data.order_status),
orderSource: data.order_source || "-",
deliveryType: data.delivery_type || "-",
factoryName: data.factory_name || "-",
salePriceTotal: Number(data.sale_price_total || 0).toFixed(2),
costPriceTotal: Number(data.cost_price_total || 0).toFixed(2),
profitTotal: Number(data.profit_total || 0).toFixed(2),
profitRate: Number(data.profit_rate || 0).toFixed(2),
profitAlertThreshold: Number(data.profit_alert_threshold || 0),
remark: data.remark || "-",
},
items: (data.items || []).map((item) => ({
id: item.item_id,
productName: item.product_name,
specification: item.specification || "-",
unit: item.unit || "-",
quantity: Number(item.quantity || 0).toFixed(2),
salePrice: Number(item.sale_price || 0).toFixed(2),
costPrice: Number(item.cost_price || 0).toFixed(2),
})),
approveLogs: (data.approve_logs || []).map((item) => ({
id: item.log_id,
approveTime: item.approve_time || "-",
approveType: mapApproveType(item.approve_type),
approveResult: mapApproveResult(item.approve_result),
afterStatus: mapOrderStatus(item.after_status),
approveOpinion: item.approve_opinion || "-",
})),
calculationDetail: data.calculation_detail || null,
};
}
/**
* 审批订单(通过或驳回)
* @param {number} orderId - 订单 ID
* @param {Object} payload - 审批数据approve_result、approve_opinion 等)
* @returns {Promise<any>}
*/
export async function approveOrder(orderId, payload) {
return request(`/api/orders/${orderId}/approve`, {
method: "POST",
body: JSON.stringify(payload),
});
}
/**
* 取消订单审批(通过或驳回取消申请)
* @param {number} orderId - 订单 ID
* @param {Object} payload - 审批数据
* @returns {Promise<any>}
*/
export async function cancelApproveOrder(orderId, payload) {
return request(`/api/orders/${orderId}/cancel-approve`, {
method: "POST",
body: JSON.stringify(payload),
});
}
// ========== 报表统计 ==========
/**
* 获取业绩报表数据
* @param {Object} [filters={}] - 筛选条件
* @param {string} [filters.stat_type] - 统计类型month / day 等)
* @param {string} [filters.start_date] - 开始日期
* @param {string} [filters.end_date] - 结束日期
* @param {number} [filters.category_id] - 产品分类 ID
* @returns {Promise<any>} 报表数据
*/
export async function fetchPerformanceReport(filters = {}) {
const query = buildQuery({
stat_type: filters.stat_type || "month",
start_date: filters.start_date || undefined,
end_date: filters.end_date || undefined,
category_id: filters.category_id || undefined,
});
return await request(`/api/reports/performance?${query}`);
}
/**
* 导出业绩报表
* @param {Object} [filters={}] - 筛选条件(同 fetchPerformanceReport
* @param {string} [filters.export_format] - 导出格式csv 等)
* @returns {Promise<any>} 导出数据/下载链接
*/
export async function exportPerformanceReport(filters = {}) {
return request(
`/api/reports/performance/export?${buildQuery({
stat_type: filters.stat_type || "month",
start_date: filters.start_date || undefined,
end_date: filters.end_date || undefined,
category_id: filters.category_id || undefined,
export_format: filters.export_format || "csv",
})}`
);
}
// ========== AI 图像识别 ==========
/**
* 提交图片进行 AI 识别(订单内容提取)
* @param {Object} payload - 识别请求数据(图片 URL 或 Base64 等)
* @returns {Promise<any>} AI 识别结果
*/
export async function recognizeAiImage(payload) {
return request('/api/ai/recognize', {
method: 'POST',
body: JSON.stringify(payload),
});
}
/**
* 纠正 AI 识别结果
* @param {number} logId - 识别日志 ID
* @param {Object} payload - 纠正后的数据
* @returns {Promise<any>}
*/
export async function correctAiRecognizeResult(logId, payload) {
return request(`/api/ai/recognize/${logId}/correct`, {
method: 'POST',
body: JSON.stringify(payload),
});
}
// ========== 提醒中心 ==========
/**
* 将后端提醒数据映射为前端展示行对象
* @param {Object} item - 后端返回的提醒原始数据
* @returns {Object} 前端展示用的提醒行数据
*/
function buildReminderRow(item) {
return {
reminder_id: item.reminder_id,
title: item.title,
content: item.content,
type: item.type,
biz_type: item.biz_type,
biz_id: item.biz_id,
status: item.status || "pending",
created_at: item.created_at || item.sent_at || "-",
sent_at: item.sent_at || "-",
};
}
/**
* 获取提醒中心仪表盘数据(提醒列表 + 统计摘要)
* @returns {Promise<{list: Array, summary: Object, checkedAt: string}>}
*/
export async function fetchReminderDashboard() {
const data = await request("/api/reminders/dashboard");
const list = (data.list || []).map(buildReminderRow);
return { list, summary: data.summary || {}, checkedAt: data.checked_at || "" };
}
/**
* 标记单条提醒为已读
* @param {number} reminderId - 提醒 ID
* @returns {Promise<any>}
*/
export async function markReminderRead(reminderId) {
return request(`/api/reminders/${reminderId}/read`, {
method: "POST",
});
}
/**
* 执行全部提醒检查(物流超时、欠款、不活跃客户等)
* @returns {Promise<any>}
*/
export async function runAllReminderChecks() {
return request("/api/reminders/check-all", { method: "POST" });
}
/**
* 执行物流超时提醒检查
* @returns {Promise<any>}
*/
export async function runLogisticsTimeoutCheck() {
return request("/api/reminders/logistics-timeout/check", { method: "POST" });
}
/**
* 执行欠款提醒检查
* @returns {Promise<any>}
*/
export async function runArrearsCheck() {
return request("/api/reminders/arrears/check", { method: "POST" });
}
/**
* 执行不活跃客户提醒检查
* @returns {Promise<any>}
*/
export async function runInactiveCustomerCheck() {
return request("/api/reminders/inactive-customers/check", { method: "POST" });
}
// ========== 删除操作 ==========
export async function deleteProductCategory(categoryId) {
return request(`/api/product-categories/${categoryId}`, { method: "DELETE" });
}
export async function permanentDeleteProductCategory(categoryId) {
return request(`/api/product-categories/${categoryId}/permanent`, { method: "DELETE" });
}
export async function deleteProduct(productId) {
return request(`/api/products/${productId}`, { method: "DELETE" });
}
export async function permanentDeleteProduct(productId) {
return request(`/api/products/${productId}/permanent`, { method: "DELETE" });
}
export async function deleteSupplier(supplierId) {
return request(`/api/suppliers/${supplierId}`, { method: "DELETE" });
}
export async function permanentDeleteSupplier(supplierId) {
return request(`/api/suppliers/${supplierId}/permanent`, { method: "DELETE" });
}
export async function deleteCustomer(customerId) {
return request(`/api/customers/${customerId}`, { method: "DELETE" });
}
export async function permanentDeleteCustomer(customerId) {
return request(`/api/customers/${customerId}/permanent`, { method: "DELETE" });
}
export async function deleteUser(userId) {
return request(`/api/system/users/${userId}`, { method: "DELETE" });
}
export async function permanentDeleteUser(userId) {
return request(`/api/system/users/${userId}/permanent`, { method: "DELETE" });
}
export async function deleteRole(roleId) {
return request(`/api/system/roles/${roleId}`, { method: "DELETE" });
}
export async function permanentDeleteRole(roleId) {
return request(`/api/system/roles/${roleId}/permanent`, { method: "DELETE" });
}
// ========== 批量删除 ==========
export async function batchDeleteProductCategory(ids, permanent = false) {
return request("/api/product-categories/batch-delete", { method: "POST", body: JSON.stringify({ ids, permanent }) });
}
export async function batchDeleteProduct(ids, permanent = false) {
return request("/api/products/batch-delete", { method: "POST", body: JSON.stringify({ ids, permanent }) });
}
export async function batchDeleteCustomer(ids, permanent = false) {
return request("/api/customers/batch-delete", { method: "POST", body: JSON.stringify({ ids, permanent }) });
}
export async function batchDeleteSupplier(ids, permanent = false) {
return request("/api/suppliers/batch-delete", { method: "POST", body: JSON.stringify({ ids, permanent }) });
}
export async function batchDeleteUser(ids, permanent = false) {
return request("/api/system/users/batch-delete", { method: "POST", body: JSON.stringify({ ids, permanent }) });
}
export async function batchDeleteRole(ids, permanent = false) {
return request("/api/system/roles/batch-delete", { method: "POST", body: JSON.stringify({ ids, permanent }) });
}