- 订单中心:移除管理员录入表单,全宽列表,增加来源/交付方式列,修正详情链接 - 订单详情:增加产品明细表、审批记录、物流信息;按钮绑定真实后端接口 - 物流轨迹:支持订单号搜索,显示关联订单信息,支持URL参数自动查询 - mockApi:新增 fetchOrderDetailAdmin、changeOrderStatus、fetchOrderList stats Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1405 lines
43 KiB
JavaScript
1405 lines
43 KiB
JavaScript
/**
|
||
* 管理员端 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 }) });
|
||
}
|