feat: 主要优化产品相关工作 #39

Merged
zksu merged 1 commits from zksu/WEB:main into main 2026-01-09 02:49:29 +00:00
27 changed files with 167 additions and 228 deletions

View File

@ -170,6 +170,11 @@ export default defineConfig({
path: '/product/sync',
component: './Product/Sync',
},
{
name: '产品CSV 工具',
path: '/product/csvtool',
component: './Product/CsvTool',
}
],
},
{

View File

@ -7,7 +7,7 @@ WORKDIR /app
# 复制 package.json 和 package-lock.json
COPY package*.json ./
# 安装依赖(使用 --legacy-peer-deps 解决依赖冲突)
# 安装依赖(使用 --legacy-peer-deps 解决依赖冲突)
RUN npm install --legacy-peer-deps
# 复制源代码

View File

@ -36,7 +36,7 @@ export const showSyncResult = (
} = result;
// 构建结果消息
let resultMessage = `同步完成!共处理 ${processed}${entityType}(总数 ${total} 个):`;
let resultMessage = `同步完成!共处理 ${processed}${entityType}(总数 ${total} 个):`;
if (created > 0) resultMessage += ` 新建 ${created}`;
if (updated > 0) resultMessage += ` 更新 ${updated}`;
if (synced > 0) resultMessage += ` 同步成功 ${synced}`;
@ -50,7 +50,7 @@ export const showSyncResult = (
<div>
<div>{resultMessage}</div>
<div style={{ marginTop: 8, fontSize: 12, color: '#faad14' }}>
:
{errors
.slice(0, 3)
.map((err: any) => `${err.identifier}: ${err.error}`)

View File

@ -8,7 +8,7 @@ interface Site {
[key: string]: any;
}
// 自定义 Hook管理站点数据
// 自定义 Hook:管理站点数据
const useSites = () => {
// 添加站点数据状态
const [sites, setSites] = useState<Site[]>([]);

View File

@ -60,7 +60,7 @@ const HistoryOrders: React.FC<HistoryOrdersProps> = ({ customer, siteId }) => {
const items = order.line_items || order.items || [];
if (Array.isArray(items)) {
items.forEach((item: any) => {
// 检查商品名称或SKU是否包含yoone(不区分大小写)
// 检查商品名称或SKU是否包含yoone(不区分大小写)
const itemName = (item.name || '').toLowerCase();
const sku = (item.sku || '').toLowerCase();

View File

@ -502,7 +502,7 @@ const SyncCustomersModal: React.FC<{
};
}
// 添加日期范围过滤(使用 after 和 before 参数)
// 添加日期范围过滤(使用 after 和 before 参数)
if (values.dateRange && values.dateRange[0] && values.dateRange[1]) {
params.where = {
...params.where,
@ -536,7 +536,7 @@ const SyncCustomersModal: React.FC<{
errors = [],
} = result;
let resultMessage = `同步完成!共处理 ${total} 个客户`;
let resultMessage = `同步完成!共处理 ${total} 个客户:`;
if (created > 0) resultMessage += ` 新建 ${created}`;
if (updated > 0) resultMessage += ` 更新 ${updated}`;
if (synced > 0) resultMessage += ` 同步成功 ${synced}`;
@ -549,7 +549,7 @@ const SyncCustomersModal: React.FC<{
<div>
<div>{resultMessage}</div>
<div style={{ marginTop: 8, fontSize: 12, color: '#faad14' }}>
:
{errors
.slice(0, 3)
.map((err: any) => err.email || err.error)
@ -653,12 +653,12 @@ const SyncCustomersModal: React.FC<{
placeholder="选择排序方式"
options={[
{ label: '默认排序', value: '' },
{ label: '注册时间(升序)', value: 'date_created:asc' },
{ label: '注册时间(降序)', value: 'date_created:desc' },
{ label: '邮箱(升序)', value: 'email:asc' },
{ label: '邮箱(降序)', value: 'email:desc' },
{ label: '姓名(升序)', value: 'first_name:asc' },
{ label: '姓名(降序)', value: 'first_name:desc' },
{ label: '注册时间(升序)', value: 'date_created:asc' },
{ label: '注册时间(降序)', value: 'date_created:desc' },
{ label: '邮箱(升序)', value: 'email:asc' },
{ label: '邮箱(降序)', value: 'email:desc' },
{ label: '姓名(升序)', value: 'first_name:asc' },
{ label: '姓名(降序)', value: 'first_name:desc' },
]}
fieldProps={{
allowClear: true,

View File

@ -38,7 +38,7 @@ const DictPage: React.FC = () => {
const [isEditDictModalVisible, setIsEditDictModalVisible] = useState(false);
const [editDictData, setEditDictData] = useState<any>(null);
// 字典项模态框状态(由 DictItemModal 组件管理)
// 字典项模态框状态(由 DictItemModal 组件管理)
const [isDictItemModalVisible, setIsDictItemModalVisible] = useState(false);
const [isEditDictItem, setIsEditDictItem] = useState(false);
const [editingDictItemData, setEditingDictItemData] = useState<any>(null);
@ -137,7 +137,7 @@ const DictPage: React.FC = () => {
link.remove();
window.URL.revokeObjectURL(url);
} catch (error: any) {
message.error('下载字典模板失败' + (error.message || '未知错误'));
message.error('下载字典模板失败:' + (error.message || '未知错误'));
}
};
@ -173,7 +173,7 @@ const DictPage: React.FC = () => {
}
};
// 处理字典项模态框提交(添加或编辑)
// 处理字典项模态框提交(添加或编辑)
const handleDictItemModalOk = async (values: any) => {
try {
if (isEditDictItem && editingDictItemData) {
@ -205,7 +205,7 @@ const DictPage: React.FC = () => {
}, 100);
} catch (error: any) {
message.error(
`${isEditDictItem ? '更新' : '添加'}失败${
`${isEditDictItem ? '更新' : '添加'}失败:${
error.message || '未知错误'
}`,
);
@ -275,7 +275,7 @@ const DictPage: React.FC = () => {
message.success(`成功导出 ${response.length} 条数据`);
} catch (error: any) {
message.error('导出字典项失败' + (error.message || '未知错误'));
message.error('导出字典项失败:' + (error.message || '未知错误'));
}
};
@ -477,7 +477,7 @@ const DictPage: React.FC = () => {
};
}
// 兼容旧的响应格式(直接返回数组)
// 兼容旧的响应格式(直接返回数组)
return {
data: res || [],
success: true,
@ -524,7 +524,7 @@ const DictPage: React.FC = () => {
</Content>
</Layout>
{/* 字典项 Modal(添加或编辑) */}
{/* 字典项 Modal(添加或编辑) */}
<DictItemModal
visible={isDictItemModalVisible}
isEdit={isEditDictItem}

View File

@ -11,19 +11,19 @@ interface DictItemActionsProps {
selectedDict?: any;
// ProTable 的 actionRef用于刷新列表
actionRef?: React.MutableRefObject<ActionType | undefined>;
// 是否显示导出按钮(某些页面可能不需要导出功能)
// 是否显示导出按钮(某些页面可能不需要导出功能)
showExport?: boolean;
// 导入字典项的回调函数(如果不提供,则使用默认的导入逻辑)
// 导入字典项的回调函数(如果不提供,则使用默认的导入逻辑)
onImport?: (file: File, dictId: number) => Promise<any>;
// 导出字典项的回调函数
onExport?: () => Promise<void>;
// 添加字典项的回调函数
onAdd?: () => void;
// 刷新字典列表的回调函数(导入成功后可能需要刷新左侧字典列表)
// 刷新字典列表的回调函数(导入成功后可能需要刷新左侧字典列表)
onRefreshDicts?: () => void;
}
// 字典项操作组合组件(包含添加、导入、导出按钮)
// 字典项操作组合组件(包含添加、导入、导出按钮)
const DictItemActions: React.FC<DictItemActionsProps> = ({
selectedDict,
actionRef,

View File

@ -34,7 +34,7 @@ const DictItemExportButton: React.FC<DictItemExportButtonProps> = ({
message.warning('未提供导出函数');
}
} catch (error: any) {
message.error('导出字典项失败' + (error.message || '未知错误'));
message.error('导出字典项失败:' + (error.message || '未知错误'));
}
};

View File

@ -12,7 +12,7 @@ interface DictItemImportButtonProps {
actionRef?: React.MutableRefObject<ActionType | undefined>;
// 是否禁用按钮
disabled?: boolean;
// 自定义导入函数,返回 Promise(如果不提供,则使用默认的导入逻辑)
// 自定义导入函数,返回 Promise(如果不提供,则使用默认的导入逻辑)
onImport?: (file: File, dictId: number) => Promise<any>;
// 导入成功后刷新字典列表的回调函数
onRefreshDicts?: () => void;
@ -73,7 +73,7 @@ const DictItemImportButton: React.FC<DictItemImportButtonProps> = ({
// 显示导入结果详情
const showImportResult = (result: any) => {
// 从 result.data 中获取实际数据(因为后端返回格式为 { success: true, data: {...} }
// 从 result.data 中获取实际数据(因为后端返回格式为 { success: true, data: {...} })
const data = result.data || result;
const { total, processed, updated, created, errors } = data;

View File

@ -24,7 +24,7 @@ const AttributePage: React.FC = () => {
// 右侧字典项 ProTable 的引用
const actionRef = useRef<ActionType>();
// 字典项模态框状态(由 DictItemModal 组件管理)
// 字典项模态框状态(由 DictItemModal 组件管理)
const [isDictItemModalVisible, setIsDictItemModalVisible] = useState(false);
const [isEditDictItem, setIsEditDictItem] = useState(false);
const [editingDictItemData, setEditingDictItemData] = useState<any>(null);
@ -99,7 +99,7 @@ const AttributePage: React.FC = () => {
message.success(`成功导出 ${data.length} 条数据`);
} catch (error: any) {
message.error('导出字典项失败' + (error.message || '未知错误'));
message.error('导出字典项失败:' + (error.message || '未知错误'));
}
};
@ -389,7 +389,7 @@ const AttributePage: React.FC = () => {
</Content>
</Layout>
{/* 字典项 Modal(添加或编辑) */}
{/* 字典项 Modal(添加或编辑) */}
<DictItemModal
visible={isDictItemModalVisible}
isEdit={isEditDictItem}

View File

@ -0,0 +1,7 @@
export default function CsvTool() {
return (
<div>
<h1>CSV </h1>
</div>
);
}

View File

@ -77,7 +77,7 @@ const CreateForm: React.FC<{
const strengthName: string = String(strengthValues?.[0] || '');
const flavorName: string = String(flavorValues?.[0] || '');
const humidityName: string = String(humidityValues?.[0] || '');
console.log(formValues)
// 调用模板渲染API来生成SKU
const {
data: rendered,
@ -86,10 +86,25 @@ const CreateForm: React.FC<{
} = await templatecontrollerRendertemplate(
{ name: 'product.sku' },
{
brand: brandName || '',
strength: strengthName || '',
flavor: flavorName || '',
humidity: humidityName ? capitalize(humidityName) : '',
category: formValues.category,
attributes: [
{
dict: {name: "brand"},
shortName: brandName || '',
},
{
dict: {name: "flavor"},
shortName: flavorName || '',
},
{
dict: {name: "strength"},
shortName: strengthName || '',
},
{
dict: {name: "humidity"},
shortName: humidityName ? capitalize(humidityName) : '',
},
]
},
);
if (!success) {

View File

@ -217,7 +217,7 @@ const List: React.FC = () => {
sorter: true,
},
{
title: '商品SKU',
title: '关联商品',
dataIndex: 'siteSkus',
render: (_, record) => (
<>
@ -244,13 +244,7 @@ const List: React.FC = () => {
},
},
{
title: '商品类型',
dataIndex: 'category',
render: (_, record: any) => {
return record.category?.title || record.category?.name || '-';
},
},
{
title: '价格',
dataIndex: 'price',
@ -262,6 +256,13 @@ const List: React.FC = () => {
dataIndex: 'promotionPrice',
hideInSearch: true,
sorter: true,
},
{
title: '商品类型',
dataIndex: 'category',
render: (_, record: any) => {
return record.category?.title || record.category?.name || '-';
},
},
{
title: '属性',
@ -442,6 +443,7 @@ const List: React.FC = () => {
onError?.(error);
}
}}
>
<Button></Button>
</Upload>,
@ -541,6 +543,11 @@ const List: React.FC = () => {
rowSelection={{
onChange: (_, selectedRows) => setSelectedRows(selectedRows),
}}
pagination={{
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: ['10', '20', '50', '100', '1000', '2000'],
}}
/>
<BatchEditModal
visible={batchEditModalVisible}

View File

@ -211,7 +211,7 @@ const PermutationPage: React.FC = () => {
return;
}
// 生成CSV表头包含所有属性列和SKU列
// 生成CSV表头(包含所有属性列和SKU列)
const headers = [
...attributes.map((attr) => attr.title || attr.name),
'SKU',
@ -239,7 +239,7 @@ const PermutationPage: React.FC = () => {
// 将表头和数据行合并
const csvContent = [headers, ...rows]
.map((row) =>
// 处理CSV中的特殊字符(逗号、双引号、换行符)
// 处理CSV中的特殊字符(逗号、双引号、换行符)
row
.map((cell) => {
const cellStr = String(cell || '');
@ -268,7 +268,7 @@ const PermutationPage: React.FC = () => {
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
// 生成文件名(包含当前分类名称和日期)
// 生成文件名(包含当前分类名称和日期)
const category = categories.find((c) => c.id === categoryId);
const categoryName = category?.name || '产品';
const date = new Date().toISOString().slice(0, 10);

View File

@ -17,7 +17,7 @@ interface Site {
isDisabled?: boolean;
}
// 定义本地产品接口(与后端 Product 实体匹配)
// 定义本地产品接口(与后端 Product 实体匹配)
interface SiteProduct {
id: number;
sku: string;
@ -115,7 +115,7 @@ const SiteProductCell: React.FC<SiteProductCellProps> = ({
setLoading(true);
try {
// 首先查找该产品在该站点的实际SKU
// 注意siteSkus 现在是字符串数组,无法直接匹配站点
// 注意:siteSkus 现在是字符串数组,无法直接匹配站点
// 这里使用模板生成的 SKU 作为默认值
let siteProductSku = '';
// 如果需要更精确的站点 SKU 匹配,需要后端提供额外的接口
@ -363,7 +363,7 @@ const SiteProductCell: React.FC<SiteProductCellProps> = ({
// 如果没有找到站点产品,显示同步按钮
if (!siteProduct) {
// 首先查找该产品在该站点的实际SKU
// 注意siteSkus 现在是字符串数组,无法直接匹配站点
// 注意:siteSkus 现在是字符串数组,无法直接匹配站点
// 这里使用模板生成的 SKU 作为默认值
let siteProductSku = '';
// 如果需要更精确的站点 SKU 匹配,需要后端提供额外的接口

View File

@ -29,7 +29,7 @@ interface Site {
isDisabled?: boolean;
}
// 定义本地产品接口(与后端 Product 实体匹配)
// 定义本地产品接口(与后端 Product 实体匹配)
interface SiteProduct {
id: number;
sku: string;
@ -438,7 +438,7 @@ const ProductSyncPage: React.FC = () => {
>
<div style={{ marginBottom: 16 }}>
<p>
:
<strong>{sites.find((s) => s.id === selectedSiteId)?.name}</strong>
</p>
{selectedRows.length > 0 ? (
@ -452,17 +452,17 @@ const ProductSyncPage: React.FC = () => {
{syncing && (
<div style={{ marginBottom: 16 }}>
<div style={{ marginBottom: 8 }}></div>
<div style={{ marginBottom: 8 }}>:</div>
<Progress percent={syncProgress} status="active" />
<div style={{ marginTop: 8, fontSize: 12, color: '#666' }}>
{syncResults.success} | {syncResults.failed}
:{syncResults.success} | :{syncResults.failed}
</div>
</div>
)}
{syncResults.errors.length > 0 && (
<div style={{ marginBottom: 16, maxHeight: 200, overflow: 'auto' }}>
<div style={{ marginBottom: 8, color: '#ff4d4f' }}></div>
<div style={{ marginBottom: 8, color: '#ff4d4f' }}>:</div>
{syncResults.errors.slice(0, 10).map((error, index) => (
<div
key={index}

View File

@ -411,7 +411,7 @@ const SiteList: React.FC = () => {
name="areas"
label="区域"
mode="multiple"
placeholder="请选择区域(留空表示不修改)"
placeholder="请选择区域(留空表示不修改)"
showSearch
filterOption={(input, option) =>
(option?.label ?? '').toLowerCase().includes(input.toLowerCase())
@ -422,7 +422,7 @@ const SiteList: React.FC = () => {
name="stockPointIds"
label="关联仓库"
mode="multiple"
placeholder="请选择关联仓库(留空表示不修改)"
placeholder="请选择关联仓库(留空表示不修改)"
request={async () => {
// 从后端接口获取仓库数据
const res = await stockcontrollerGetallstockpoints();

View File

@ -116,7 +116,6 @@ const ProductsPage: React.FC = () => {
// ID
title: 'ID',
dataIndex: 'id',
hideInSearch: true,
width: 120,
copyable: true,
render: (_, record) => {
@ -156,7 +155,7 @@ const ProductsPage: React.FC = () => {
},
{
// 库存
title: '库存',
title: '库存数量',
dataIndex: 'stock_quantity',
hideInSearch: true,
},
@ -423,7 +422,7 @@ const ProductsPage: React.FC = () => {
params: {
page,
per_page: pageSize,
...where,
where,
...(orderObj
? {
sortField: Object.keys(orderObj)[0],

View File

@ -121,7 +121,7 @@ const WebhooksPage: React.FC = () => {
message.error(isEditMode ? '更新失败' : '创建失败');
}
} catch (error: any) {
message.error('表单验证失败' + error.message);
message.error('表单验证失败:' + error.message);
}
};
@ -305,12 +305,12 @@ const WebhooksPage: React.FC = () => {
{ type: 'url', message: '请输入有效的URL' },
]}
>
<Input placeholder="请输入回调URLhttps://example.com/webhook" />
<Input placeholder="请输入回调URL:https://example.com/webhook" />
</Form.Item>
<Form.Item
name="secret"
label="密钥(可选)"
label="密钥(可选)"
rules={[{ max: 255, message: '密钥不能超过255个字符' }]}
>
<Input placeholder="请输入密钥用于验证webhook请求" />

View File

@ -69,12 +69,12 @@ export const ErpProductBindModal: React.FC<ErpProductBindModalProps> = ({
onFinish={handleBind}
>
<div style={{ marginBottom: 16 }}>
<strong></strong>
<strong>:</strong>
<div>SKU: {siteProduct.sku}</div>
<div>: {siteProduct.name}</div>
{siteProduct.erpProduct && (
<div style={{ color: '#ff4d4f' }}>
ERP产品{siteProduct.erpProduct.sku} -{' '}
ERP产品:{siteProduct.erpProduct.sku} -{' '}
{siteProduct.erpProduct.name}
</div>
)}
@ -164,7 +164,7 @@ export const ErpProductBindModal: React.FC<ErpProductBindModalProps> = ({
border: '1px solid #b7eb8f',
}}
>
<strong></strong>
<strong>:</strong>
<div>SKU: {selectedProduct.sku}</div>
<div>: {selectedProduct.name}</div>
{selectedProduct.nameCn && (

View File

@ -1,14 +1,13 @@
// @ts-ignore
/* eslint-disable */
// API 更新时间
// API 唯一标识
// API 更新时间:
// API 唯一标识:
import * as area from './area';
import * as category from './category';
import * as customer from './customer';
import * as dict from './dict';
import * as locales from './locales';
import * as logistics from './logistics';
import * as media from './media';
import * as order from './order';
import * as product from './product';
import * as site from './site';
@ -26,7 +25,6 @@ export default {
dict,
locales,
logistics,
media,
order,
product,
siteApi,

View File

@ -1,92 +0,0 @@
// @ts-ignore
/* eslint-disable */
import { request } from 'umi';
/** 此处后端没有提供注释 DELETE /media/${param0} */
export async function mediacontrollerDelete(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.mediacontrollerDeleteParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<any>(`/media/${param0}`, {
method: 'DELETE',
params: {
...queryParams,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /media/list */
export async function mediacontrollerList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.mediacontrollerListParams,
options?: { [key: string]: any },
) {
return request<any>('/media/list', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /media/update/${param0} */
export async function mediacontrollerUpdate(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.mediacontrollerUpdateParams,
body: Record<string, any>,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<any>(`/media/update/${param0}`, {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
params: { ...queryParams },
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /media/upload */
export async function mediacontrollerUpload(
body: {},
files?: File[],
options?: { [key: string]: any },
) {
const formData = new FormData();
if (files) {
files.forEach((f) => formData.append('files', f || ''));
}
Object.keys(body).forEach((ele) => {
const item = (body as any)[ele];
if (item !== undefined && item !== null) {
if (typeof item === 'object' && !(item instanceof File)) {
if (item instanceof Array) {
item.forEach((f) => formData.append(ele, f || ''));
} else {
formData.append(
ele,
new Blob([JSON.stringify(item)], { type: 'application/json' }),
);
}
} else {
formData.append(ele, item);
}
}
});
return request<any>('/media/upload', {
method: 'POST',
data: formData,
requestType: 'form',
...(options || {}),
});
}

View File

@ -282,6 +282,20 @@ export async function siteapicontrollerBatchfulfillorders(
);
}
/** 此处后端没有提供注释 GET /site-api/${param0}/orders/count */
export async function siteapicontrollerCountorders(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.siteapicontrollerCountordersParams,
options?: { [key: string]: any },
) {
const { siteId: param0, ...queryParams } = params;
return request<Record<string, any>>(`/site-api/${param0}/orders/count`, {
method: 'GET',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /site-api/${param0}/orders/export */
export async function siteapicontrollerExportorders(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
@ -776,23 +790,18 @@ export async function siteapicontrollerCancelfulfillment(
);
}
/** 此处后端没有提供注释 POST /site-api/${param1}/orders/${param0}/fulfill */
export async function siteapicontrollerFulfillorder(
/** 此处后端没有提供注释 GET /site-api/${param1}/orders/${param0}/fulfillments */
export async function siteapicontrollerGetorderfulfillments(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.siteapicontrollerFulfillorderParams,
body: API.FulfillmentDTO,
params: API.siteapicontrollerGetorderfulfillmentsParams,
options?: { [key: string]: any },
) {
const { id: param0, siteId: param1, ...queryParams } = params;
const { orderId: param0, siteId: param1, ...queryParams } = params;
return request<Record<string, any>>(
`/site-api/${param1}/orders/${param0}/fulfill`,
`/site-api/${param1}/orders/${param0}/fulfillments`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
method: 'GET',
params: { ...queryParams },
data: body,
...(options || {}),
},
);
@ -859,23 +868,6 @@ export async function siteapicontrollerCreateordernote(
);
}
/** 此处后端没有提供注释 GET /site-api/${param1}/orders/${param0}/trackings */
export async function siteapicontrollerGetordertrackings(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.siteapicontrollerGetordertrackingsParams,
options?: { [key: string]: any },
) {
const { orderId: param0, siteId: param1, ...queryParams } = params;
return request<Record<string, any>>(
`/site-api/${param1}/orders/${param0}/trackings`,
{
method: 'GET',
params: { ...queryParams },
...(options || {}),
},
);
}
/** 此处后端没有提供注释 GET /site-api/${param1}/products/${param0} */
export async function siteapicontrollerGetproduct(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)

View File

@ -62,7 +62,7 @@ declare namespace API {
};
type BatchErrorItemDTO = {
/** 错误项标识如ID、邮箱等 */
/** 错误项标识(如ID、邮箱等) */
identifier?: string;
/** 错误信息 */
error?: string;
@ -591,22 +591,6 @@ declare namespace API {
weight?: Cubid;
};
type mediacontrollerDeleteParams = {
force?: boolean;
siteId?: number;
id: number;
};
type mediacontrollerListParams = {
pageSize?: number;
page?: number;
siteId?: number;
};
type mediacontrollerUpdateParams = {
id: number;
};
type Money = {
currency?: string;
value?: string;
@ -1433,7 +1417,7 @@ declare namespace API {
keyword?: string;
/** 是否禁用 */
isDisabled?: boolean;
/** 站点ID列表(逗号分隔) */
/** 站点ID列表(逗号分隔) */
ids?: string;
};
@ -1635,6 +1619,10 @@ declare namespace API {
siteId: number;
};
type siteapicontrollerCountordersParams = {
siteId: number;
};
type siteapicontrollerCreatecustomerParams = {
siteId: number;
};
@ -1813,11 +1801,6 @@ declare namespace API {
siteId: number;
};
type siteapicontrollerFulfillorderParams = {
id: string;
siteId: number;
};
type siteapicontrollerGetcustomerordersParams = {
/** 页码 */
page?: number;
@ -1882,6 +1865,11 @@ declare namespace API {
siteId: number;
};
type siteapicontrollerGetorderfulfillmentsParams = {
orderId: string;
siteId: number;
};
type siteapicontrollerGetordernotesParams = {
id: string;
siteId: number;
@ -1910,11 +1898,6 @@ declare namespace API {
siteId: number;
};
type siteapicontrollerGetordertrackingsParams = {
orderId: string;
siteId: number;
};
type siteapicontrollerGetproductParams = {
id: string;
siteId: number;
@ -2095,7 +2078,7 @@ declare namespace API {
keyword?: string;
/** 是否禁用 */
isDisabled?: boolean;
/** 站点ID列表(逗号分隔) */
/** 站点ID列表(逗号分隔) */
ids?: string;
};
@ -2406,7 +2389,7 @@ declare namespace API {
type SyncCustomersDTO = {
/** 站点ID */
siteId?: number;
/** 查询参数支持where和orderBy */
/** 查询参数(支持where和orderBy) */
params?: UnifiedSearchParamsDTO;
};
@ -2787,7 +2770,7 @@ declare namespace API {
variation?: boolean;
/** 属性选项 */
options?: string[];
/** 变体属性值(单个值) */
/** 变体属性值(单个值) */
option?: string;
};
@ -3222,6 +3205,11 @@ declare namespace API {
id?: number;
};
type webhookcontrollerHandleshoppywebhookParams = {
signature?: string;
siteId?: string;
};
type webhookcontrollerHandlewoowebhookParams = {
siteId?: string;
};

View File

@ -10,6 +10,26 @@ export async function webhookcontrollerTest(options?: { [key: string]: any }) {
});
}
/** 此处后端没有提供注释 POST /webhook/shoppy */
export async function webhookcontrollerHandleshoppywebhook(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.webhookcontrollerHandleshoppywebhookParams,
body: Record<string, any>,
options?: { [key: string]: any },
) {
return request<any>('/webhook/shoppy', {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
params: {
...params,
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /webhook/woocommerce */
export async function webhookcontrollerHandlewoowebhook(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)

View File

@ -22,7 +22,7 @@ export interface BatchOperationResult {
}
/**
*
* ()
* @param result
* @param operationType
*/
@ -30,12 +30,12 @@ export function showBatchOperationResult(
result: BatchOperationResult,
operationType: string = '操作',
): string {
// 从 result.data 中获取实际数据(因为后端返回格式为 { success: true, data: {...} }
// 从 result.data 中获取实际数据(因为后端返回格式为 { success: true, data: {...} })
const data = (result as any).data || result;
const { total, processed, created, updated, deleted, errors } = data;
// 构建结果消息
let messageContent = `${operationType}结果${total} 条,成功 ${processed}`;
let messageContent = `${operationType}结果:${total} 条,成功 ${processed}`;
if (created) {
messageContent += `,创建 ${created}`;
@ -54,7 +54,7 @@ export function showBatchOperationResult(
const errorDetails = errors
.map((err: BatchErrorItem) => `${err.identifier}: ${err.error}`)
.join('\n');
message.warning(messageContent + '\n\n错误详情\n' + errorDetails);
message.warning(messageContent + '\n\n错误详情:\n' + errorDetails);
} else {
message.success(messageContent);
}