zksu
/
WEB
forked from yoone/WEB
1
0
Fork 0
This commit is contained in:
cll 2025-05-22 15:09:09 +08:00
parent 27801fd448
commit a500b88b31
54 changed files with 11394 additions and 0 deletions

3
.eslintrc.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = {
extends: require.resolve('@umijs/max/eslint'),
};

16
.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
/node_modules
/.env.local
/.umirc.local.ts
/config/config.local.ts
/src/.umi
/src/.umi-production
/src/.umi-test
/.umi
/.umi-production
/.umi-test
/dist
/.mfsu
.swc
/package-lock.json
/package.json
/yarn.lock

2
.npmrc Normal file
View File

@ -0,0 +1,2 @@
registry=https://registry.npmmirror.com/

4
.openapi2tsrc.ts Normal file
View File

@ -0,0 +1,4 @@
export default {
schemaPath: 'http://127.0.0.1:7001/swagger-ui/index.json',
serversPath: './src/servers',
};

3
.prettierignore Normal file
View File

@ -0,0 +1,3 @@
node_modules
.umi
.umi-production

8
.prettierrc Normal file
View File

@ -0,0 +1,8 @@
{
"printWidth": 80,
"singleQuote": true,
"trailingComma": "all",
"proseWrap": "never",
"overrides": [{ "files": ".prettierrc", "options": { "parser": "json" } }],
"plugins": ["prettier-plugin-organize-imports", "prettier-plugin-packagejson"]
}

3
.stylelintrc.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = {
extends: require.resolve('@umijs/max/stylelint'),
};

172
.umirc.ts Normal file
View File

@ -0,0 +1,172 @@
import { defineConfig } from '@umijs/max';
const isDev = process.env.NODE_ENV === 'development';
const UMI_APP_API_URL = isDev
? 'http://localhost:7001'
: 'https://api.yoone.ca';
export default defineConfig({
antd: {},
access: {},
model: {},
initialState: {},
request: {},
layout: {
title: 'YOONE',
},
define: {
UMI_APP_API_URL,
},
routes: [
{ path: '/', redirect: '/home' },
{ name: '追踪', path: '/track', component: './Track', layout: false },
{ name: '登录', path: '/login', component: './Login', layout: false },
{ name: '首页', path: '/home', component: './Home' },
{
name: '组织架构',
path: '/organiza',
access: 'canSeeSuper',
routes: [
{
name: '用户管理',
path: '/organiza/user',
component: './Organiza/User',
},
],
},
{
name: '商品管理',
path: '/product',
routes: [
{
name: '商品分类',
path: '/product/category',
component: './Product/Category',
},
{
name: '强度',
path: '/product/strength',
component: './Product/Strength',
},
{
name: '口味',
path: '/product/flavors',
component: './Product/Flavors',
},
{
name: '产品列表',
path: '/product/list',
component: './Product/List',
},
{
name: 'WP商品列表',
path: '/product/wp_list',
component: './Product/WpList',
},
],
},
{
name: '库存管理',
path: '/stock',
routes: [
{
name: '库存列表',
path: '/stock/list',
component: './Stock/List',
},
{
name: '仓库点',
path: '/stock/warehouse',
component: './Stock/Warehouse',
},
{
name: '入库管理',
path: '/stock/purchaseOrder',
component: './Stock/PurchaseOrder',
},
{
name: '调拨管理',
path: '/stock/transfer',
component: './Stock/Transfer',
},
{
name: '库存记录',
path: '/stock/record',
component: './Stock/Record',
},
],
},
{
name: '订单管理',
path: '/order',
access: 'canSeeAdmin',
routes: [
{
name: '订单列表',
path: '/order/list',
component: './Order/List',
},
],
},
// {
// name: '物流管理',
// path: '/logistics',
// routes: [
// {
// name: '服务商',
// path: '/logistics/services',
// component: './Logistics/Services',
// },
// {
// name: '地址管理',
// path: '/logistics/address',
// component: './Logistics/Address',
// },
// {
// name: '物流列表',
// path: '/logistics/list',
// component: './Logistics/List',
// },
// ],
// },
{
name: '数据统计',
path: '/statistics',
routes: [
{
name: '销售统计',
path: '/statistics/sales',
component: './Statistics/Sales',
access: 'canSeeSuper',
},
{
name: '订单统计',
path: '/statistics/order',
component: './Statistics/Order',
access: 'canSeeSuper',
},
{
name: '客户统计',
path: '/statistics/customer',
component: './Statistics/Customer',
access: 'canSeeSuper',
},
{
name: '库存预测',
path: '/statistics/inventoryForecast',
component: './Statistics/InventoryForecast',
},
{
name: '补货',
path: '/statistics/restocking',
component: './Statistics/Restocking',
},
],
},
// {
// path: '*',
// component: './404',
// },
],
npmClient: 'pnpm',
});

20
mock/userAPI.ts Normal file
View File

@ -0,0 +1,20 @@
const users = [
{ id: 0, name: 'Umi', nickName: 'U', gender: 'MALE' },
{ id: 1, name: 'Fish', nickName: 'B', gender: 'FEMALE' },
];
export default {
'GET /api/v1/queryUserList': (req: any, res: any) => {
res.json({
success: true,
data: { list: users },
errorCode: 0,
});
},
'PUT /api/v1/user/': (req: any, res: any) => {
res.json({
success: true,
errorCode: 0,
});
},
};

9
src/access.ts Normal file
View File

@ -0,0 +1,9 @@
export default (initialState: any) => {
const canSeeSuper = initialState?.user?.isSuper;
const canSeeAdmin =
initialState?.user?.isSuper || initialState?.user?.isAdmin;
return {
canSeeSuper,
canSeeAdmin,
};
};

128
src/app.tsx Normal file
View File

@ -0,0 +1,128 @@
// 运行时配置
import { LogoutOutlined, UserOutlined } from '@ant-design/icons';
import {
ProLayoutProps,
ProSchemaValueEnumObj,
ProTable,
} from '@ant-design/pro-components';
import { RequestConfig, history, useModel } from '@umijs/max';
import { App, Avatar, ConfigProvider, Dropdown, MenuProps } from 'antd';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import { usercontrollerGetuser } from './servers/api/user';
// 设置 dayjs 全局语言为中文
dayjs.locale('zh-cn');
// 全局初始化数据配置,用于 Layout 用户信息和权限初始化
// 更多信息见文档https://umijs.org/docs/api/runtime-config#getinitialstate
export async function getInitialState(): Promise<{
user?: Record<string, any>;
categoryList?: ProSchemaValueEnumObj;
sites?: API.SiteConfig[];
}> {
if (!localStorage.getItem('token') || history.location.pathname === '/login')
return {};
const { data: user } = await usercontrollerGetuser();
return { user };
}
export const layout = (): ProLayoutProps => {
const { initialState } = useModel('@@initialState');
const items: MenuProps['items'] = [
{
key: '1',
label: '我的账号',
disabled: true,
},
{
type: 'divider',
},
{
key: '3',
label: '退出登录',
icon: <LogoutOutlined />,
onClick: async () => {
//TODO 清理服务器登陆状态
localStorage.removeItem('token');
history.push('/login');
},
},
];
return {
menu: {
locale: false,
},
layout: 'mix',
actionsRender: () => (
<Dropdown key="avatar" menu={{ items }}>
<div style={{ cursor: 'pointer' }}>
<Avatar size="large" icon={<UserOutlined />} />
<span style={{ marginLeft: 8 }}>{initialState?.name}</span>
</div>
</Dropdown>
),
};
};
export const request: RequestConfig = {
baseURL: UMI_APP_API_URL,
requestInterceptors: [
(url: string, options: any) => {
const token = localStorage.getItem('token');
return {
url,
options: {
...options,
headers: {
...options.headers,
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
},
};
},
],
errorConfig: {
errorHandler: (error: any) => {
if (error?.response?.status === 401) {
localStorage.removeItem('token');
history.push('/login');
}
},
},
};
export const onRouteChange = ({ location }: { location: Location }) => {
const token = localStorage.getItem('token');
// 白名单,不需要登录的页面
const whiteList = ['/login', '/track'];
if (!token && !whiteList.includes(location.pathname)) {
// 没有 token 且不在白名单内,跳转到登录页
history.push('/login');
}
};
export function rootContainer(container: React.ReactNode) {
// 全局过滤空字段逻辑
(ProTable as any).defaultProps = {
...(ProTable as any).defaultProps,
beforeSearchSubmit: (params: any) => {
return Object.fromEntries(
Object.entries(params).filter(
([_, value]) => value !== undefined && value !== null && value !== '',
),
);
},
};
return (
<ConfigProvider>
<App>{container}</App>
</ConfigProvider>
);
}

0
src/assets/.gitkeep Normal file
View File

View File

@ -0,0 +1,84 @@
import { Input, Select } from 'antd';
import React, { useEffect } from 'react';
const { Option } = Select;
// 定义国家代码和扩展码的映射关系
const phoneExtensions: { [key: string]: string } = {
CA: '1',
CN: '86',
US: '1',
};
interface InternationalPhoneInputProps {
value?: { country?: string; phone?: string; extension?: string };
onChange?: (value: {
country: string;
phone: string;
extension?: string;
}) => void;
}
const InternationalPhoneInput: React.FC<InternationalPhoneInputProps> = ({
value = {},
onChange,
}) => {
const {
country = 'CA',
phone = '',
extension = phoneExtensions['CA'],
} = value || {};
useEffect(() => {
triggerChange({ extension });
}, []);
const triggerChange = (
changedValue: Partial<{
country: string;
phone: string;
extension?: string;
}>,
) => {
if (onChange) {
onChange({
country,
phone,
...value,
...changedValue,
});
}
};
const onCountryChange = (newCountry: string) => {
triggerChange({
country: newCountry,
extension: phoneExtensions[newCountry],
});
};
const onPhoneChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
triggerChange({ phone: e.target.value });
};
return (
<Input
addonBefore={
<Select
value={country}
onChange={onCountryChange}
style={{ width: 100 }}
>
<Option value="CA">🇨🇦 +1</Option>
<Option value="CN">🇨🇳 +86</Option>
<Option value="US">🇺🇸 +1</Option>
{/* 添加更多国家代码 */}
</Select>
}
value={phone}
onChange={onPhoneChange}
placeholder="请输入联系电话"
/>
);
};
export default InternationalPhoneInput;

93
src/constants/index.ts Normal file
View File

@ -0,0 +1,93 @@
import { ProSchemaValueEnumObj } from '@ant-design/pro-components';
export const DEFAULT_NAME = 'YOONE';
export const PRODUCT_STATUS_ENUM: ProSchemaValueEnumObj = {
publish: {
text: '已发布',
status: 'success',
},
draft: {
text: '草稿',
status: 'default',
},
pending: {
text: '待审核',
status: 'warning',
},
private: {
text: '私有',
status: 'warning',
},
trash: {
text: '已删除',
status: 'error',
},
'auto-draft': {
text: '字段草稿',
status: 'default',
},
future: {
text: '定时发布',
status: 'success',
},
inherit: {
text: '继承状态',
status: 'default',
},
};
export const Purchase_Order_STATUS_ENUM: ProSchemaValueEnumObj = {
draft: {
text: '草稿',
status: 'default',
},
submitted: {
text: '已发货',
status: 'warning',
},
received: {
text: '已到达',
status: 'success',
disabled: true,
},
};
export const ORDER_STATUS_ENUM: ProSchemaValueEnumObj = {
pending: {
text: '待确认',
status: 'default',
},
processing: {
text: '待发货',
status: 'success',
},
completed: {
text: '已完成',
status: 'success',
},
cancelled: {
text: '已取消',
status: 'error',
},
refunded: {
text: '已退款',
status: 'warning',
},
failed: {
text: '失败',
status: 'error',
},
after_sale_pending: {
text: '售后处理中',
status: 'warning',
},
pending_reshipment: {
text: '待补发',
status: 'warning',
},
pending_refund: {
text: '待退款',
status: 'warning',
},
};

13
src/models/global.ts Normal file
View File

@ -0,0 +1,13 @@
// 全局共享数据示例
import { DEFAULT_NAME } from '@/constants';
import { useState } from 'react';
const useUser = () => {
const [name, setName] = useState<string>(DEFAULT_NAME);
return {
name,
setName,
};
};
export default useUser;

View File

@ -0,0 +1,3 @@
.container {
padding-top: 80px;
}

14
src/pages/Home/index.tsx Normal file
View File

@ -0,0 +1,14 @@
import { PageContainer } from '@ant-design/pro-components';
import { useModel } from '@umijs/max';
import styles from './index.less';
const HomePage: React.FC = () => {
const { name } = useModel('global');
return (
<PageContainer ghost>
<div className={styles.container}></div>
</PageContainer>
);
};
export default HomePage;

116
src/pages/Login/index.tsx Normal file
View File

@ -0,0 +1,116 @@
import { usercontrollerGetuser, usercontrollerLogin } from '@/servers/api/user';
import { LockOutlined, UserOutlined } from '@ant-design/icons';
import {
LoginFormPage,
ProConfigProvider,
ProFormText,
} from '@ant-design/pro-components';
import { history, useModel } from '@umijs/max';
import { App, theme } from 'antd';
const Page = () => {
const { setInitialState } = useModel('@@initialState');
const { token } = theme.useToken();
const { message } = App.useApp();
const onFinish = async (values: { username: string; password: string }) => {
try {
const { data, success } = await usercontrollerLogin(values);
if (success) {
message.success('登录成功');
localStorage.setItem('token', data?.token as string);
const { data: user } = await usercontrollerGetuser();
setInitialState({ user });
history.push('/');
}
} catch {
message.error('登录失败');
}
};
return (
<div
style={{
backgroundColor: 'white',
height: '100vh',
}}
>
<LoginFormPage
backgroundImageUrl="https://mdn.alipayobjects.com/huamei_gcee1x/afts/img/A*y0ZTS6WLwvgAAAAAAAAAAAAADml6AQ/fmt.webp"
backgroundVideoUrl="https://gw.alipayobjects.com/v/huamei_gcee1x/afts/video/jXRBRK_VAwoAAAAAAAAAAAAAK4eUAQBr"
title="Yoone"
containerStyle={{
backgroundColor: 'rgba(0, 0, 0,0.65)',
backdropFilter: 'blur(4px)',
}}
onFinish={onFinish}
>
<ProFormText
name="username"
fieldProps={{
size: 'large',
prefix: (
<UserOutlined
style={{
color: token.colorText,
}}
className={'prefixIcon'}
/>
),
}}
placeholder={'请输入用户名!'}
rules={[
{
required: true,
message: '请输入用户名!',
},
]}
/>
<ProFormText.Password
name="password"
fieldProps={{
size: 'large',
prefix: (
<LockOutlined
style={{
color: token.colorText,
}}
className={'prefixIcon'}
/>
),
}}
placeholder={'请输入密码!'}
rules={[
{
required: true,
message: '请输入密码!',
},
]}
/>
{/* <div
style={{
marginBlockEnd: 24,
}}
>
<ProFormCheckbox noStyle name="autoLogin">
</ProFormCheckbox>
<a
style={{
float: 'right',
}}
>
</a>
</div> */}
</LoginFormPage>
</div>
);
};
export default () => {
return (
<ProConfigProvider>
<Page />
</ProConfigProvider>
);
};

View File

@ -0,0 +1,405 @@
import InternationalPhoneInput from '@/components/InternationalPhoneInput';
import {
logisticscontrollerCreateshippingaddress,
logisticscontrollerDelshippingaddress,
logisticscontrollerGetshippingaddresslist,
logisticscontrollerUpdateshippingaddress,
} from '@/servers/api/logistics';
import { stockcontrollerGetallstockpoints } from '@/servers/api/stock';
import { EditOutlined, PlusOutlined } from '@ant-design/icons';
import {
ActionType,
DrawerForm,
PageContainer,
ProColumns,
ProForm,
ProFormItem,
ProFormSelect,
ProFormText,
ProTable,
} from '@ant-design/pro-components';
import { App, Button, Divider, Popconfirm } from 'antd';
import { useRef } from 'react';
const ListPage: React.FC = () => {
const actionRef = useRef<ActionType>();
const { message } = App.useApp();
const columns: ProColumns<API.ShippingAddress>[] = [
{
title: '仓库点',
dataIndex: 'stockPointId',
hideInSearch: true,
valueType: 'select',
request: async () => {
const { data = [] } = await stockcontrollerGetallstockpoints();
return data.map((item) => ({
label: item.name,
value: item.id,
}));
},
},
{
title: '地区',
dataIndex: ['address', 'region'],
hideInSearch: true,
},
{
title: '城市',
dataIndex: ['address', 'city'],
hideInSearch: true,
},
{
title: '邮编',
dataIndex: ['address', 'postal_code'],
hideInSearch: true,
},
{
title: '详细地址',
dataIndex: ['address', 'address_line_1'],
hideInSearch: true,
},
{
title: '联系电话',
render: (_, record) =>
`+${record.phone_number_extension} ${record.phone_number}`,
hideInSearch: true,
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => (
<>
<UpdateForm tableRef={actionRef} value={record} />
<Divider type="vertical" />
<Popconfirm
title="删除"
description="确认删除?"
onConfirm={async () => {
try {
const { success, message: errMsg } =
await logisticscontrollerDelshippingaddress({
id: record.id as number,
});
if (!success) {
throw new Error(errMsg);
}
actionRef.current?.reload();
} catch (error: any) {
message.error(error.message);
}
}}
>
<Button type="primary" danger>
</Button>
</Popconfirm>
</>
),
},
];
return (
<PageContainer ghost>
<ProTable
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
toolBarRender={() => [<CreateForm tableRef={actionRef} />]}
request={async () => {
const { data, success } =
await logisticscontrollerGetshippingaddresslist();
if (success) {
return {
data: data,
};
}
return {
data: [],
};
}}
columns={columns}
/>
</PageContainer>
);
};
const region = {
AB: 'Alberta',
BC: 'British',
MB: 'Manitoba',
NB: 'New',
NL: 'Newfoundland',
NS: 'Nova',
ON: 'Ontario',
PE: 'Prince',
QC: 'Quebec',
SK: 'Saskatchewan',
NT: 'Northwest',
NU: 'Nunavut',
YT: 'Yukon',
};
const CreateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
}> = ({ tableRef }) => {
const { message } = App.useApp();
return (
<DrawerForm
title="新建"
trigger={
<Button type="primary">
<PlusOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
const { contact, ...params } = values;
try {
const { success, message: errMsg } =
await logisticscontrollerCreateshippingaddress({
...params,
phone_number: contact?.phone,
phone_number_extension: contact?.extension,
phone_number_country: contact?.country,
} as API.ShippingAddress);
if (!success) {
throw new Error(errMsg);
}
tableRef.current?.reload();
message.success('提交成功');
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProFormText
name="name"
label="名称"
width="lg"
placeholder="请输入名称"
required
rules={[{ required: true, message: '请输入名称' }]}
/>
<ProFormSelect
name="stockPointId"
width="lg"
label="仓库点"
placeholder="请选择仓库点"
required
rules={[{ required: true, message: '请选择仓库点' }]}
request={async () => {
const { data = [] } = await stockcontrollerGetallstockpoints();
return data.map((item) => ({
label: item.name,
value: item.id,
}));
}}
/>
<ProForm.Group title="地址">
<ProFormText
name={['address', 'country']}
label="国家"
initialValue={'CA'}
hidden
/>
<ProFormSelect
name={['address', 'region']}
label="地区"
placeholder={'请选择地区'}
showSearch
required
valueEnum={region}
rules={[{ required: true, message: '请选择地区' }]}
/>
<ProFormText
name={['address', 'city']}
label="城市"
placeholder="请输入城市"
required
rules={[{ required: true, message: '请输入城市' }]}
/>
<ProFormText
name={['address', 'postal_code']}
label="邮编"
placeholder="请输入邮编"
required
rules={[{ required: true, message: '请输入邮编' }]}
/>
<ProFormText
name={['address', 'address_line_1']}
label="详细地址"
placeholder="请输入详细地址"
width="lg"
required
rules={[{ required: true, message: '请输入详细地址' }]}
/>
</ProForm.Group>
<ProFormItem
name="contact"
label="联系电话"
required
rules={[
{
required: true,
async validator(_, value) {
if (!value?.phone) {
return Promise.reject('请输入联系电话');
}
return Promise.resolve();
},
},
]}
>
<InternationalPhoneInput />
</ProFormItem>
</DrawerForm>
);
};
const UpdateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
value: API.ShippingAddress;
}> = ({ tableRef, value }) => {
const { message } = App.useApp();
const {
id,
phone_number,
phone_number_country,
phone_number_extension,
...initialValue
} = value;
return (
<DrawerForm
title="编辑"
trigger={
<Button type="primary">
<EditOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
const { contact, ...params } = values;
try {
const { success, message: errMsg } =
await logisticscontrollerUpdateshippingaddress(
{ id: id as number },
{
...params,
phone_number: contact?.phone,
phone_number_extension: contact?.extension,
phone_number_country: contact?.country,
} as API.ShippingAddress,
);
if (!success) {
throw new Error(errMsg);
}
tableRef.current?.reload();
message.success('提交成功');
return true;
} catch (error: any) {
message.error(error.message);
}
}}
initialValues={{
...initialValue,
contact: {
phone: phone_number,
extension: phone_number_extension,
country: phone_number_country,
},
}}
>
<ProFormText
name="name"
label="名称"
width="lg"
placeholder="请输入名称"
required
rules={[{ required: true, message: '请输入名称' }]}
/>
<ProFormSelect
name="stockPointId"
width="lg"
label="仓库点"
placeholder="请选择仓库点"
required
rules={[{ required: true, message: '请选择仓库点' }]}
request={async () => {
const { data = [] } = await stockcontrollerGetallstockpoints();
return data.map((item) => ({
label: item.name,
value: item.id,
}));
}}
/>
<ProForm.Group title="地址">
<ProFormText
name={['address', 'country']}
label="国家"
initialValue={'CA'}
hidden
/>
<ProFormSelect
name={['address', 'region']}
label="地区"
placeholder={'请选择地区'}
showSearch
required
valueEnum={region}
rules={[{ required: true, message: '请选择地区' }]}
/>
<ProFormText
name={['address', 'city']}
label="城市"
placeholder="请输入城市"
required
rules={[{ required: true, message: '请输入城市' }]}
/>
<ProFormText
name={['address', 'postal_code']}
label="邮编"
placeholder="请输入邮编"
required
rules={[{ required: true, message: '请输入邮编' }]}
/>
<ProFormText
name={['address', 'address_line_1']}
label="详细地址"
placeholder="请输入详细地址"
width="lg"
required
rules={[{ required: true, message: '请输入详细地址' }]}
/>
</ProForm.Group>
<ProFormItem
name="contact"
label="联系电话"
required
rules={[
{
required: true,
async validator(_, value) {
if (!value?.phone) {
return Promise.reject('请输入联系电话');
}
return Promise.resolve();
},
},
]}
>
<InternationalPhoneInput />
</ProFormItem>
</DrawerForm>
);
};
export default ListPage;

View File

@ -0,0 +1,146 @@
import { logisticscontrollerGetlist } from '@/servers/api/logistics';
import { stockcontrollerGetallstockpoints } from '@/servers/api/stock';
import { formatShipmentState } from '@/utils/format';
import { printPDF } from '@/utils/util';
import { CopyOutlined } from '@ant-design/icons';
import {
ActionType,
PageContainer,
ProColumns,
ProTable,
} from '@ant-design/pro-components';
import { App, Button } from 'antd';
import { useRef, useState } from 'react';
const ListPage: React.FC = () => {
const actionRef = useRef<ActionType>();
const { message } = App.useApp();
const [selectedRows, setSelectedRows] = useState([]);
const columns: ProColumns<API.Service>[] = [
{
title: '服务商',
dataIndex: 'tracking_provider',
hideInSearch: true,
},
{
title: '仓库',
dataIndex: 'stockPointId',
hideInTable: true,
valueType: 'select',
request: async () => {
const { data = [] } = await stockcontrollerGetallstockpoints();
return data.map((item) => ({
label: item.name,
value: item.id,
}));
},
},
{
title: '快递单号',
dataIndex: 'primary_tracking_number',
render(_, record) {
return (
<>
{record.primary_tracking_number}
<CopyOutlined
onClick={async () => {
try {
await navigator.clipboard.writeText(record.tracking_url);
message.success('复制成功!');
} catch (err) {
message.error('复制失败!');
}
}}
/>
</>
);
},
},
{
title: '状态',
dataIndex: 'state',
hideInSearch: true,
render(_, record) {
return formatShipmentState(record.state);
},
},
{
title: '创建时间',
dataIndex: 'createdAt',
hideInSearch: true,
valueType: 'dateTime',
},
{
title: '操作',
dataIndex: 'operation',
hideInSearch: true,
render(_, record) {
if (!record?.labels?.length) return null;
return (
<Button
type="primary"
onClick={() => {
// printPDF([record.labels[record.labels.length - 1].url])
window.open(
record.labels[record.labels.length - 1].url,
'_blank',
);
}}
>
</Button>
);
},
},
];
const handleBatchPrint = async () => {
if (selectedRows.length === 0) {
message.warning('请选择要打印的项');
return;
}
await printPDF(
selectedRows.map((row) => row.labels[row.labels.length - 1].url),
);
setSelectedRows([]);
};
return (
<PageContainer ghost>
<ProTable
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
request={async (values) => {
console.log(values);
const { data, success } = await logisticscontrollerGetlist({
params: values,
});
if (success) {
return {
total: data?.total || 0,
data: data?.items || [],
};
}
return {
data: [],
};
}}
// rowSelection={{
// selectedRowKeys: selectedRows.map((row) => row.id),
// onChange: (_, selectedRows) => setSelectedRows(selectedRows),
// }}
columns={columns}
tableAlertOptionRender={() => {
return (
<Button onClick={handleBatchPrint} type="primary">
</Button>
);
}}
/>
</PageContainer>
);
};
export default ListPage;

View File

@ -0,0 +1,110 @@
import {
logisticscontrollerGetservicelist,
logisticscontrollerSyncservices,
logisticscontrollerToggleactive,
} from '@/servers/api/logistics';
import {
ActionType,
PageContainer,
ProColumns,
ProFormSwitch,
ProTable,
} from '@ant-design/pro-components';
import { App, Button } from 'antd';
import { useRef } from 'react';
const ListPage: React.FC = () => {
const actionRef = useRef<ActionType>();
const { message } = App.useApp();
const columns: ProColumns<API.Service>[] = [
{
title: '服务商 ID',
dataIndex: 'id',
hideInSearch: true,
},
{
title: '运营商名称',
dataIndex: 'carrier_name',
},
{
title: '服务商名称',
dataIndex: 'service_name',
hideInSearch: true,
},
{
title: '启用',
dataIndex: 'isActive',
valueType: 'switch',
render(_, record) {
return (
<ProFormSwitch
fieldProps={{
checked: record.isActive,
onChange: async (value) => {
try {
const { success } = await logisticscontrollerToggleactive({
id: record.id,
isActive: value,
});
if (!success) {
throw new Error('启动失败');
}
actionRef.current?.reload();
} catch (e: any) {
message.error(e?.message || '启动失败');
}
},
}}
/>
);
},
},
];
return (
<PageContainer ghost>
<ProTable
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
toolBarRender={() => [
<Button
key="syncSite"
type="primary"
onClick={async () => {
try {
const { success } = await logisticscontrollerSyncservices();
if (!success) {
throw new Error('同步失败');
}
actionRef.current?.reload();
} catch (e: any) {
message.error(e?.message || '同步失败');
}
}}
>
</Button>,
]}
request={async (values) => {
console.log(values);
const { data, success } = await logisticscontrollerGetservicelist(
values,
);
if (success) {
return {
total: data?.total || 0,
data: data?.items || [],
};
}
return {
data: [],
};
}}
columns={columns}
/>
</PageContainer>
);
};
export default ListPage;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,125 @@
import {
usercontrollerAdduser,
usercontrollerListusers,
} from '@/servers/api/user';
import { PlusOutlined } from '@ant-design/icons';
import {
ActionType,
DrawerForm,
PageContainer,
ProColumns,
ProForm,
ProFormText,
ProTable,
} from '@ant-design/pro-components';
import { App, Button } from 'antd';
import { useRef } from 'react';
const ListPage: React.FC = () => {
const actionRef = useRef<ActionType>();
const columns: ProColumns[] = [
{
title: '用户名',
dataIndex: 'username',
},
{
title: '激活',
dataIndex: 'isActive',
valueEnum: {
true: {
text: '是',
},
false: {
text: '否',
},
},
},
{
title: '超管',
dataIndex: 'isSuper',
valueEnum: {
true: {
text: '是',
},
false: {
text: '否',
},
},
},
];
return (
<PageContainer ghost>
<ProTable
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
request={async (params) => {
const { data, success } = await usercontrollerListusers(params);
return {
total: data?.total || 0,
data: data?.items || [],
success,
};
}}
columns={columns}
toolBarRender={() => [<CreateForm tableRef={actionRef} />]}
/>
</PageContainer>
);
};
const CreateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
}> = ({ tableRef }) => {
const { message } = App.useApp();
return (
<DrawerForm
title="新建"
trigger={
<Button type="primary">
<PlusOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
try {
const { success, message: errMsg } = await usercontrollerAdduser(
values,
);
if (!success) {
throw new Error(errMsg);
}
tableRef.current?.reload();
message.success('提交成功');
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProForm.Group>
<ProFormText
name="username"
label="用户名"
width="lg"
placeholder="请输入用户名"
rules={[{ required: true, message: '请输入用户名' }]}
/>
<ProFormText
name="password"
label="密码"
width="lg"
placeholder="请输入密码"
rules={[{ required: true, message: '请输入密码' }]}
/>
</ProForm.Group>
</DrawerForm>
);
};
export default ListPage;

View File

@ -0,0 +1,210 @@
import {
productcontrollerCreatecategory,
productcontrollerDeletecategory,
productcontrollerGetcategories,
productcontrollerUpdatecategory,
} from '@/servers/api/product';
import { EditOutlined, PlusOutlined } from '@ant-design/icons';
import {
ActionType,
DrawerForm,
PageContainer,
ProColumns,
ProForm,
ProFormText,
ProTable,
} from '@ant-design/pro-components';
import { App, Button, Popconfirm } from 'antd';
import { useRef } from 'react';
const List: React.FC = () => {
const actionRef = useRef<ActionType>();
const { message } = App.useApp();
const columns: ProColumns<API.Category>[] = [
{
title: '名称',
dataIndex: 'name',
tip: '名称是唯一的 key',
formItemProps: {
rules: [
{
required: true,
message: '名称为必填项',
},
],
},
},
{
title: '标识',
dataIndex: 'unique_key',
hideInSearch: true,
},
{
title: '更新时间',
dataIndex: 'updatedAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '创建时间',
dataIndex: 'createdAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => (
<>
{/* <UpdateForm tableRef={actionRef} values={record} />
<Divider type="vertical" /> */}
<Popconfirm
title="删除"
description="确认删除?"
onConfirm={async () => {
try {
const { success, message: errMsg } =
await productcontrollerDeletecategory({ id: record.id });
if (!success) {
throw new Error(errMsg);
}
actionRef.current?.reload();
} catch (error: any) {
message.error(error.message);
}
}}
>
<Button type="primary" danger>
</Button>
</Popconfirm>
</>
),
},
];
return (
<PageContainer header={{ title: '分类列表' }}>
<ProTable<API.Category>
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
toolBarRender={() => [<CreateForm tableRef={actionRef} />]}
request={async (params) => {
const { data, success } = await productcontrollerGetcategories(
params,
);
return {
total: data?.total || 0,
data: data?.items || [],
success,
};
}}
columns={columns}
/>
</PageContainer>
);
};
const CreateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
}> = ({ tableRef }) => {
const { message } = App.useApp();
return (
<DrawerForm<API.CreateCategoryDTO>
title="新建"
trigger={
<Button type="primary">
<PlusOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
try {
const { success, message: errMsg } =
await productcontrollerCreatecategory(values);
if (!success) {
throw new Error(errMsg);
}
tableRef.current?.reload();
message.success('提交成功');
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProFormText
name="name"
width="md"
label="分类名称"
placeholder="请输入名称"
rules={[{ required: true, message: '请输入名称' }]}
/>
<ProFormText
name="unique_key"
width="md"
label="Key"
placeholder="请输入Key"
rules={[{ required: true, message: '请输入Key' }]}
/>
</DrawerForm>
);
};
const UpdateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
values: API.Category;
}> = ({ tableRef, values: initialValues }) => {
const { message } = App.useApp();
return (
<DrawerForm<API.UpdateCategoryDTO>
title="编辑"
initialValues={initialValues}
trigger={
<Button type="primary">
<EditOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
try {
const { success, message: errMsg } =
await productcontrollerUpdatecategory(
{ id: initialValues.id },
values,
);
if (!success) {
throw new Error(errMsg);
}
message.success('提交成功');
tableRef.current?.reload();
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProForm.Group>
<ProFormText
name="name"
width="md"
label="分类名称"
placeholder="请输入名称"
rules={[{ required: true, message: '请输入名称' }]}
/>
</ProForm.Group>
</DrawerForm>
);
};
export default List;

View File

@ -0,0 +1,208 @@
import {
productcontrollerCreateflavors,
productcontrollerDeleteflavors,
productcontrollerGetflavors,
productcontrollerUpdateflavors,
} from '@/servers/api/product';
import { EditOutlined, PlusOutlined } from '@ant-design/icons';
import {
ActionType,
DrawerForm,
PageContainer,
ProColumns,
ProForm,
ProFormText,
ProTable,
} from '@ant-design/pro-components';
import { App, Button, Popconfirm } from 'antd';
import { useRef } from 'react';
const List: React.FC = () => {
const actionRef = useRef<ActionType>();
const { message } = App.useApp();
const columns: ProColumns<API.Category>[] = [
{
title: '名称',
dataIndex: 'name',
tip: '名称是唯一的 key',
formItemProps: {
rules: [
{
required: true,
message: '名称为必填项',
},
],
},
},
{
title: '标识',
dataIndex: 'unique_key',
hideInSearch: true,
},
{
title: '更新时间',
dataIndex: 'updatedAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '创建时间',
dataIndex: 'createdAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => (
<>
{/* <UpdateForm tableRef={actionRef} values={record} />
<Divider type="vertical" /> */}
<Popconfirm
title="删除"
description="确认删除?"
onConfirm={async () => {
try {
const { success, message: errMsg } =
await productcontrollerDeleteflavors({ id: record.id });
if (!success) {
throw new Error(errMsg);
}
actionRef.current?.reload();
} catch (error: any) {
message.error(error.message);
}
}}
>
<Button type="primary" danger>
</Button>
</Popconfirm>
</>
),
},
];
return (
<PageContainer header={{ title: '口味列表' }}>
<ProTable<API.Category>
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
toolBarRender={() => [<CreateForm tableRef={actionRef} />]}
request={async (params) => {
const { data, success } = await productcontrollerGetflavors(params);
return {
total: data?.total || 0,
data: data?.items || [],
success,
};
}}
columns={columns}
/>
</PageContainer>
);
};
const CreateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
}> = ({ tableRef }) => {
const { message } = App.useApp();
return (
<DrawerForm<API.CreateCategoryDTO>
title="新建"
trigger={
<Button type="primary">
<PlusOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
try {
const { success, message: errMsg } =
await productcontrollerCreateflavors(values);
if (!success) {
throw new Error(errMsg);
}
tableRef.current?.reload();
message.success('提交成功');
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProFormText
name="name"
width="md"
label="口味名称"
placeholder="请输入名称"
rules={[{ required: true, message: '请输入名称' }]}
/>
<ProFormText
name="unique_key"
width="md"
label="Key"
placeholder="请输入Key"
rules={[{ required: true, message: '请输入Key' }]}
/>
</DrawerForm>
);
};
const UpdateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
values: API.Category;
}> = ({ tableRef, values: initialValues }) => {
const { message } = App.useApp();
return (
<DrawerForm<API.UpdateCategoryDTO>
title="编辑"
initialValues={initialValues}
trigger={
<Button type="primary">
<EditOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
try {
const { success, message: errMsg } =
await productcontrollerUpdateflavors(
{ id: initialValues.id },
values,
);
if (!success) {
throw new Error(errMsg);
}
message.success('提交成功');
tableRef.current?.reload();
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProForm.Group>
<ProFormText
name="name"
width="md"
label="口味名称"
placeholder="请输入名称"
rules={[{ required: true, message: '请输入名称' }]}
/>
</ProForm.Group>
</DrawerForm>
);
};
export default List;

View File

@ -0,0 +1,232 @@
import {
productcontrollerCreateproduct,
productcontrollerDeleteproduct,
productcontrollerGetcategorieall,
productcontrollerGetflavorsall,
productcontrollerGetproductlist,
productcontrollerGetstrengthall,
} from '@/servers/api/product';
import { PlusOutlined } from '@ant-design/icons';
import {
ActionType,
DrawerForm,
PageContainer,
ProColumns,
ProForm,
ProFormSelect,
ProFormText,
ProFormTextArea,
ProTable,
} from '@ant-design/pro-components';
import { App, Button, Popconfirm } from 'antd';
import React, { useRef } from 'react';
const List: React.FC = () => {
const actionRef = useRef<ActionType>();
const { message } = App.useApp();
const columns: ProColumns<API.Product>[] = [
{
title: '名称',
dataIndex: 'name',
},
{
title: '产品描述',
dataIndex: 'description',
hideInSearch: true,
},
{
title: '产品分类',
dataIndex: 'categoryName',
},
{
title: '强度',
dataIndex: 'strengthName',
},
{
title: '口味',
dataIndex: 'flavorsName',
},
{
title: '湿度',
dataIndex: 'humidity',
},
{
title: 'sku',
dataIndex: 'sku',
hideInSearch: true,
},
{
title: '更新时间',
dataIndex: 'updatedAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '创建时间',
dataIndex: 'createdAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => (
<>
<Popconfirm
title="删除"
description="确认删除?"
onConfirm={async () => {
try {
const { success, message: errMsg } =
await productcontrollerDeleteproduct({ id: record.id });
if (!success) {
throw new Error(errMsg);
}
actionRef.current?.reload();
} catch (error: any) {
message.error(error.message);
}
}}
>
<Button type="primary" danger>
</Button>
</Popconfirm>
</>
),
},
];
return (
<PageContainer header={{ title: '产品列表' }}>
<ProTable<API.Product>
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
toolBarRender={() => [<CreateForm tableRef={actionRef} />]}
request={async (params) => {
const { data, success } = await productcontrollerGetproductlist(
params,
);
return {
total: data?.total || 0,
data: data?.items || [],
success,
};
}}
columns={columns}
rowSelection={{
onChange: (_, selectedRows) => setSelectedRows(selectedRows),
}}
/>
</PageContainer>
);
};
const CreateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
}> = ({ tableRef }) => {
const { message } = App.useApp();
return (
<DrawerForm<API.CreateProductDTO>
title="新建"
trigger={
<Button type="primary">
<PlusOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
try {
const { success, message: errMsg } =
await productcontrollerCreateproduct(values);
if (!success) {
throw new Error(errMsg);
}
tableRef.current?.reload();
message.success('提交成功');
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProForm.Group>
<ProFormText
name="name"
label="名称"
width="lg"
placeholder="请输入名称"
rules={[{ required: true, message: '请输入名称' }]}
/>
<ProFormTextArea
name="description"
width="lg"
label="产品描述"
placeholder="请输入产品描述"
/>
<ProFormSelect
name="categoryId"
width="lg"
label="产品分类"
placeholder="请选择产品分类"
request={async () => {
const { data = [] } = await productcontrollerGetcategorieall();
return data.map((item) => ({
label: item.name,
value: item.id,
}));
}}
rules={[{ required: true, message: '请选择产品分类' }]}
/>
<ProFormSelect
name="strengthId"
width="lg"
label="强度"
placeholder="请选择强度"
request={async () => {
const { data = [] } = await productcontrollerGetstrengthall();
return data.map((item) => ({
label: item.name,
value: item.id,
}));
}}
rules={[{ required: true, message: '请选择强度' }]}
/>
<ProFormSelect
name="flavorsId"
width="lg"
label="口味"
placeholder="请选择口味"
request={async () => {
const { data = [] } = await productcontrollerGetflavorsall();
return data.map((item) => ({
label: item.name,
value: item.id,
}));
}}
rules={[{ required: true, message: '请选择口味' }]}
/>
<ProFormSelect
name="humidity"
width="lg"
label="干湿"
placeholder="请选择干湿"
valueEnum={{
dry: '干',
wet: '湿',
}}
rules={[{ required: true, message: '请选择干湿' }]}
/>
</ProForm.Group>
</DrawerForm>
);
};
export default List;

View File

@ -0,0 +1,206 @@
import {
productcontrollerCreatestrength,
productcontrollerDeletestrength,
productcontrollerGetstrength,
} from '@/servers/api/product';
import { PlusOutlined } from '@ant-design/icons';
import {
ActionType,
DrawerForm,
PageContainer,
ProColumns,
ProFormText,
ProTable,
} from '@ant-design/pro-components';
import { App, Button, Popconfirm } from 'antd';
import { useRef } from 'react';
const List: React.FC = () => {
const actionRef = useRef<ActionType>();
const { message } = App.useApp();
const columns: ProColumns<API.Category>[] = [
{
title: '名称',
dataIndex: 'name',
tip: '名称是唯一的 key',
formItemProps: {
rules: [
{
required: true,
message: '名称为必填项',
},
],
},
},
{
title: '标识',
dataIndex: 'unique_key',
hideInSearch: true,
},
{
title: '更新时间',
dataIndex: 'updatedAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '创建时间',
dataIndex: 'createdAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => (
<>
{/* <UpdateForm tableRef={actionRef} values={record} />
<Divider type="vertical" /> */}
<Popconfirm
title="删除"
description="确认删除?"
onConfirm={async () => {
try {
const { success, message: errMsg } =
await productcontrollerDeletestrength({ id: record.id });
if (!success) {
throw new Error(errMsg);
}
actionRef.current?.reload();
} catch (error: any) {
message.error(error.message);
}
}}
>
<Button type="primary" danger>
</Button>
</Popconfirm>
</>
),
},
];
return (
<PageContainer header={{ title: '强度列表' }}>
<ProTable<API.Category>
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
toolBarRender={() => [<CreateForm tableRef={actionRef} />]}
request={async (params) => {
const { data, success } = await productcontrollerGetstrength(params);
return {
total: data?.total || 0,
data: data?.items || [],
success,
};
}}
columns={columns}
/>
</PageContainer>
);
};
const CreateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
}> = ({ tableRef }) => {
const { message } = App.useApp();
return (
<DrawerForm<API.CreateCategoryDTO>
title="新建"
trigger={
<Button type="primary">
<PlusOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
try {
const { success, message: errMsg } =
await productcontrollerCreatestrength(values);
if (!success) {
throw new Error(errMsg);
}
tableRef.current?.reload();
message.success('提交成功');
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProFormText
name="name"
width="md"
label="强度名称"
placeholder="请输入名称"
rules={[{ required: true, message: '请输入名称' }]}
/>
<ProFormText
name="unique_key"
width="md"
label="Key"
placeholder="请输入Key"
rules={[{ required: true, message: '请输入Key' }]}
/>
</DrawerForm>
);
};
// const UpdateForm: React.FC<{
// tableRef: React.MutableRefObject<ActionType | undefined>;
// values: API.Category;
// }> = ({ tableRef, values: initialValues }) => {
// const { message } = App.useApp();
// return (
// <DrawerForm<API.UpdateCategoryDTO>
// title="编辑"
// initialValues={initialValues}
// trigger={
// <Button type="primary">
// <EditOutlined />
// 编辑
// </Button>
// }
// autoFocusFirstInput
// drawerProps={{
// destroyOnClose: true,
// }}
// onFinish={async (values) => {
// try {
// const { success, message: errMsg } =
// await productcontrollerUpdatestrength(
// { id: initialValues.id },
// values,
// );
// if (!success) {
// throw new Error(errMsg);
// }
// message.success('提交成功');
// tableRef.current?.reload();
// return true;
// } catch (error: any) {
// message.error(error.message);
// }
// }}
// >
// <ProForm.Group>
// <ProFormText
// name="name"
// width="md"
// label="强度名称"
// placeholder="请输入名称"
// rules={[{ required: true, message: '请输入名称' }]}
// />
// </ProForm.Group>
// </DrawerForm>
// );
// };
export default List;

View File

@ -0,0 +1,540 @@
import { PRODUCT_STATUS_ENUM } from '@/constants';
import {
productcontrollerProductbysku,
productcontrollerSearchproducts,
} from '@/servers/api/product';
import { sitecontrollerAll } from '@/servers/api/site';
import {
wpproductcontrollerGetwpproducts,
wpproductcontrollerSetconstitution,
wpproductcontrollerSyncproducts,
wpproductcontrollerUpdateproduct,
wpproductcontrollerUpdatevariation,
} from '@/servers/api/wpProduct';
import { EditOutlined } from '@ant-design/icons';
import {
ActionType,
DrawerForm,
PageContainer,
ProColumns,
ProForm,
ProFormDigit,
ProFormList,
ProFormSelect,
ProFormText,
ProTable,
} from '@ant-design/pro-components';
import { App, Button, Divider, Form } from 'antd';
import { useRef } from 'react';
const List: React.FC = () => {
const actionRef = useRef<ActionType>();
const columns: ProColumns<API.WpProductDTO>[] = [
{
title: '名称',
dataIndex: 'name',
},
{
title: '站点',
dataIndex: 'siteId',
valueType: 'select',
request: async () => {
const { data = [] } = await sitecontrollerAll();
return data.map((item) => ({
label: item.siteName,
value: item.id,
}));
},
},
{
title: 'sku',
dataIndex: 'sku',
hideInSearch: true,
},
{
title: '产品状态',
dataIndex: 'status',
valueType: 'select',
valueEnum: PRODUCT_STATUS_ENUM,
},
{
title: '常规价格',
dataIndex: 'regular_price',
hideInSearch: true,
},
{
title: '销售价格',
dataIndex: 'sale_price',
hideInSearch: true,
},
{
title: '更新时间',
dataIndex: 'updatedAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '创建时间',
dataIndex: 'createdAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => (
<>
<UpdateForm tableRef={actionRef} values={record} />
{record.type === 'simple' && record.sku ? (
<>
<Divider type="vertical" />
<SetComponent
tableRef={actionRef}
values={record}
isProduct={true}
/>
</>
) : (
<></>
)}
</>
),
},
];
const varColumns: ProColumns<API.VariationDTO>[] = [
{
title: '变体名',
dataIndex: 'name',
},
{
title: 'sku',
dataIndex: 'sku',
hideInSearch: true,
},
{
title: '常规价格',
dataIndex: 'regular_price',
hideInSearch: true,
},
{
title: '销售价格',
dataIndex: 'sale_price',
hideInSearch: true,
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => (
<>
<UpdateVaritation tableRef={actionRef} values={record} />
{record.sku ? (
<>
<Divider type="vertical" />
<SetComponent
tableRef={actionRef}
values={record}
isProduct={false}
/>
</>
) : (
<></>
)}
</>
),
},
];
return (
<PageContainer header={{ title: 'WP产品列表' }}>
<ProTable<API.WpProductDTO>
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
request={async (params) => {
const { data, success } = await wpproductcontrollerGetwpproducts(
params,
);
return {
total: data?.total || 0,
data: data?.items || [],
success,
};
}}
columns={columns}
toolBarRender={() => [<SyncForm tableRef={actionRef} />]}
expandable={{
rowExpandable: (record) => record.type === 'variable',
expandedRowRender: (record) => (
<ProTable<API.VariationDTO>
rowKey="id"
dataSource={record.variations}
pagination={false}
search={false}
options={false}
columns={varColumns}
/>
),
}}
/>
</PageContainer>
);
};
const SyncForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
}> = ({ tableRef }) => {
const { message } = App.useApp();
return (
<DrawerForm<API.wpproductcontrollerSyncproductsParams>
title="同步产品"
trigger={
<Button key="syncSite" type="primary">
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
try {
const { success, message: errMsg } =
await wpproductcontrollerSyncproducts(values);
if (!success) {
throw new Error(errMsg);
}
message.success('同步成功');
tableRef.current?.reload();
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProForm.Group>
<ProFormSelect
name="siteId"
width="lg"
label="站点"
placeholder="请选择站点"
request={async () => {
const { data = [] } = await sitecontrollerAll();
return data.map((item) => ({
label: item.siteName,
value: item.id,
}));
}}
/>
</ProForm.Group>
</DrawerForm>
);
};
const UpdateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
values: API.WpProductDTO;
}> = ({ tableRef, values: initialValues }) => {
const { message } = App.useApp();
return (
<DrawerForm<API.UpdateProductDTO>
title="编辑产品"
initialValues={initialValues}
trigger={
<Button type="primary">
<EditOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
const { siteId, ...params } = values;
try {
const { success, message: errMsg } =
await wpproductcontrollerUpdateproduct(
{
productId: initialValues.externalProductId,
siteId,
},
params,
);
if (!success) {
throw new Error(errMsg);
}
message.success('提交成功');
tableRef.current?.reload();
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProForm.Group>
<ProFormText label="名称" width="lg" name="name" />
<ProFormSelect
width="lg"
label="站点"
request={async () => {
const { data = [] } = await sitecontrollerAll();
return data.map((item) => ({
label: item.siteName,
value: item.id,
}));
}}
name="siteId"
disabled
/>
<ProFormText
name="sku"
width="lg"
label="sku"
tooltip="Example: TO-ZY-06MG-WG-S-0001"
placeholder="请输入SKU"
/>
{initialValues.type === 'simple' ? (
<>
<ProFormDigit
name="regular_price"
width="lg"
label="常规价格"
fieldProps={{
precision: 2,
}}
/>
<ProFormDigit
name="sale_price"
width="lg"
label="促销价格"
fieldProps={{
precision: 2,
}}
/>
</>
) : (
<></>
)}
</ProForm.Group>
</DrawerForm>
);
};
const UpdateVaritation: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
values: API.VariationDTO;
}> = ({ tableRef, values: initialValues }) => {
const { message } = App.useApp();
return (
<DrawerForm<API.UpdateProductDTO>
title="编辑变体"
initialValues={initialValues}
trigger={
<Button type="primary">
<EditOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
const { ...params } = values;
try {
const { success, message: errMsg } =
await wpproductcontrollerUpdatevariation(
{
siteId: initialValues.siteId,
productId: initialValues.externalProductId,
variationId: initialValues.externalVariationId,
},
params,
);
if (!success) {
throw new Error(errMsg);
}
message.success('提交成功');
tableRef.current?.reload();
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProForm.Group>
<ProFormText label="变体名称" width="lg" name="name" />
<ProFormText
name="sku"
width="lg"
label="sku"
tooltip="Example: TO-ZY-06MG-WG-S-0001"
placeholder="请输入SKU"
/>
<ProFormDigit
name="regular_price"
width="lg"
label="常规价格"
fieldProps={{
precision: 2,
}}
/>
<ProFormDigit
name="sale_price"
width="lg"
label="促销价格"
fieldProps={{
precision: 2,
}}
/>
</ProForm.Group>
</DrawerForm>
);
};
const SetComponent: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
values: API.VariationDTO | API.WpProductDTO;
isProduct: boolean;
}> = ({ tableRef, values: { id, constitution, name }, isProduct = false }) => {
const { message } = App.useApp();
const [form] = Form.useForm();
const fetchInitialValues = async () => {
const initData = await Promise.all(
constitution?.map?.(async (item) => {
const { data } = await productcontrollerProductbysku({
sku: item.sku as string,
});
return {
quantity: item.quantity,
sku: {
label: data?.name,
value: item.sku,
},
};
}) || [],
);
form.setFieldsValue({
constitution: initData,
});
};
return (
<DrawerForm<API.SetConstitutionDTO>
title={name}
form={form}
trigger={
<Button type="primary" danger={constitution?.length === 0}>
<EditOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async ({ constitution }) => {
try {
const { success, message: errMsg } =
await wpproductcontrollerSetconstitution(
{
id,
},
{
isProduct,
constitution,
},
);
if (!success) {
throw new Error(errMsg);
}
message.success('提交成功');
tableRef.current?.reload();
return true;
} catch (error: any) {
message.error(error.message);
}
}}
onOpenChange={(visiable) => {
if (visiable) fetchInitialValues();
}}
>
<ProForm.Group>
<ProFormList<{
sku: string;
quantity: number;
}>
name="constitution"
rules={[
{
required: true,
message: '至少需要一个商品',
validator: (_, value) =>
value && value.length > 0
? Promise.resolve()
: Promise.reject('至少需要一个商品'),
},
]}
creatorButtonProps={{ children: '新增' }}
>
{(fields, idx, { remove }) => (
<div key={idx}>
<ProFormSelect
request={async ({ keyWords }) => {
if (keyWords.length < 3) return [];
try {
const { data } = await productcontrollerSearchproducts({
name: keyWords,
});
const arr =
data?.map((item) => {
return {
label: item.name,
value: item.sku,
};
}) || [];
return arr;
} catch (error) {
console.log(error);
return [];
}
}}
name="sku"
label="产品"
width="lg"
placeholder="请选择产品"
tooltip="至少输入3个字符"
fieldProps={{
showSearch: true,
filterOption: false,
}}
transform={(value) => {
return value?.value || value;
}}
debounceTime={300} // 防抖,减少请求频率
rules={[{ required: true, message: '请选择产品' }]}
/>
<ProFormDigit
name="quantity"
label="数量"
placeholder="请输入数量"
rules={[{ required: true, message: '请输入数量' }]}
fieldProps={{
precision: 0,
}}
/>
<Button type="link" danger onClick={() => remove(fields.key)}>
</Button>
</div>
)}
</ProFormList>
</ProForm.Group>
</DrawerForm>
);
};
export default List;

View File

@ -0,0 +1,236 @@
import { statisticscontrollerGetcustomerorders } from '@/servers/api/statistics';
import {
PageContainer,
ProDescriptions,
ProForm,
ProFormDateMonthRangePicker,
} from '@ant-design/pro-components';
import { Space } from 'antd';
import { useState } from 'react';
const ListPage: React.FC = () => {
const [month, setMonth] = useState('');
return (
<PageContainer ghost>
<Space direction="vertical" size={30}>
<ProForm
layout="inline"
onFinish={async (values) => {
setMonth(values.month);
}}
>
<ProFormDateMonthRangePicker label="日期" name="month" />
</ProForm>
<ProDescriptions
params={{ month }}
request={async (params) => {
const { data, success } =
await statisticscontrollerGetcustomerorders(params);
return { data };
}}
>
<ProDescriptions.Item label="总用户数" dataIndex="users" />
<ProDescriptions.Item label="3MG订单数" dataIndex="order_with_3mg" />
<ProDescriptions.Item label="6MG订单数" dataIndex="order_with_6mg" />
<ProDescriptions.Item label="9MG订单数" dataIndex="order_with_9mg" />
<ProDescriptions.Item
label="12MG订单数"
dataIndex="order_with_12mg"
/>
<ProDescriptions.Item
label="15MG订单数"
dataIndex="order_with_15mg"
/>
<ProDescriptions.Item
label="ZYN3MG订单数"
dataIndex="zyn_3mg_orders"
/>
<ProDescriptions.Item
label="ZYN6MG订单数"
dataIndex="zyn_6mg_orders"
/>
<ProDescriptions.Item
label="ZOLT订单数"
dataIndex="zolt_15mg_orders"
/>
<ProDescriptions.Item
label="一购用户数"
dataIndex="users_one_purchase"
/>
<ProDescriptions.Item
label="二购用户数"
dataIndex="users_two_purchases"
/>
<ProDescriptions.Item
label="三购用户数"
dataIndex="users_three_purchases"
/>
<ProDescriptions.Item
label="YOONE一购用户数"
dataIndex="users_with_yoone_one_purchase"
/>
<ProDescriptions.Item
label="YOONE二购用户数"
dataIndex="users_with_yoone_two_purchases"
/>
<ProDescriptions.Item
label="YOONE三购用户数"
dataIndex="users_with_yoone_three_purchases"
/>
<ProDescriptions.Item
label="YOONE 3MG一购用户数"
dataIndex="users_with_yoone_3mg_one_purchase"
/>
<ProDescriptions.Item
label="YOONE 3MG二购用户数"
dataIndex="users_with_yoone_3mg_two_purchases"
/>
<ProDescriptions.Item
label="YOON 3MG三购用户数"
dataIndex="users_with_yoone_3mg_three_purchases"
/>
<ProDescriptions.Item
label="YOONE 6MG一购用户数"
dataIndex="users_with_yoone_6mg_one_purchase"
/>
<ProDescriptions.Item
label="YOONE 6MG二购用户数"
dataIndex="users_with_yoone_6mg_two_purchases"
/>
<ProDescriptions.Item
label="YOON 6MG三购用户数"
dataIndex="users_with_yoone_6mg_three_purchases"
/>
<ProDescriptions.Item
label="YOONE 9MG一购用户数"
dataIndex="users_with_yoone_9mg_one_purchase"
/>
<ProDescriptions.Item
label="YOONE 9MG二购用户数"
dataIndex="users_with_yoone_9mg_two_purchases"
/>
<ProDescriptions.Item
label="YOON 9MG三购用户数"
dataIndex="users_with_yoone_9mg_three_purchases"
/>
<ProDescriptions.Item
label="YOONE 12MG一购用户数"
dataIndex="users_with_yoone_12mg_one_purchase"
/>
<ProDescriptions.Item
label="YOONE 12MG二购用户数"
dataIndex="users_with_yoone_12mg_two_purchases"
/>
<ProDescriptions.Item
label="YOON 12MG三购用户数"
dataIndex="users_with_yoone_12mg_three_purchases"
/>
<ProDescriptions.Item
label="YOONE 15MG一购用户数"
dataIndex="users_with_yoone_15mg_one_purchase"
/>
<ProDescriptions.Item
label="YOONE 15MG二购用户数"
dataIndex="users_with_yoone_15mg_two_purchases"
/>
<ProDescriptions.Item
label="YOON 15MG三购用户数"
dataIndex="users_with_yoone_15mg_three_purchases"
/>
<ProDescriptions.Item
label="ZYN一购用户数"
dataIndex="users_with_zyn_one_purchase"
/>
<ProDescriptions.Item
label="ZYN二购用户数"
dataIndex="users_with_zyn_two_purchases"
/>
<ProDescriptions.Item
label="ZYN三购用户数"
dataIndex="users_with_zyn_three_purchases"
/>
<ProDescriptions.Item
label="ZYN 3MG一购用户数"
dataIndex="users_with_zyn_3mg_one_purchase"
/>
<ProDescriptions.Item
label="ZYN 3MG二购用户数"
dataIndex="users_with_zyn_3mg_two_purchases"
/>
<ProDescriptions.Item
label="ZYN 3MG三购用户数"
dataIndex="users_with_zyn_3mg_three_purchases"
/>
<ProDescriptions.Item
label="ZYN 6G一购用户数"
dataIndex="users_with_zyn_6mg_one_purchase"
/>
<ProDescriptions.Item
label="ZYN 6G二购用户数"
dataIndex="users_with_zyn_6mg_two_purchases"
/>
<ProDescriptions.Item
label="ZYN 6G三购用户数"
dataIndex="users_with_zyn_6mg_three_purchases"
/>
<ProDescriptions.Item
label="ZOLT一购用户数"
dataIndex="users_with_zolt_one_purchase"
/>
<ProDescriptions.Item
label="ZOLT二购用户数"
dataIndex="users_with_zolt_two_purchases"
/>
<ProDescriptions.Item
label="ZOLT三购用户数"
dataIndex="users_with_zolt_three_purchases"
/>
<ProDescriptions.Item
label="一购产品"
render={(_, record) => {
return (
<div>
{record?.first_hot_purchase?.map((v) => (
<div>
{v.name} :{v.user_count}
</div>
))}
</div>
);
}}
/>
<ProDescriptions.Item
label="二购产品"
render={(_, record) => {
return (
<div>
{record?.second_hot_purchase?.map((v) => (
<div>
{v.name} :{v.user_count}
</div>
))}
</div>
);
}}
/>
<ProDescriptions.Item
label="三购产品"
render={(_, record) => {
return (
<div>
{record?.third_hot_purchase?.map((v) => (
<div>
{v.name} :{v.user_count}
</div>
))}
</div>
);
}}
/>
</ProDescriptions>
</Space>
</PageContainer>
);
};
export default ListPage;

View File

@ -0,0 +1,201 @@
import { statisticscontrollerStockforecast } from '@/servers/api/statistics';
import { stockcontrollerGetallstockpoints } from '@/servers/api/stock';
import {
ActionType,
PageContainer,
ProColumns,
ProFormDatePicker,
ProFormDigit,
ProTable,
} from '@ant-design/pro-components';
import dayjs from 'dayjs';
import { useEffect, useRef, useState } from 'react';
const ListPage: React.FC = () => {
const actionRef = useRef<ActionType>();
const [points, setPoints] = useState<API.StockPoint[]>([]);
useEffect(() => {
stockcontrollerGetallstockpoints().then(({ data }) => {
setPoints(data as API.StockPoint[]);
});
}, []);
const [real, setReal] = useState({});
const columns: ProColumns[] = [
{
title: '产品名称',
dataIndex: 'productName',
},
{
title: 'SKU',
dataIndex: 'productSku',
hideInSearch: true,
},
...points
?.filter((point: API.StockPoint) => !point.ignore)
?.map((point: API.StockPoint) => ({
title: point.name,
dataIndex: `point_${point.name}`,
hideInSearch: true,
render(_: any, record: any) {
const quantity = record.stockDetails?.find(
(item: any) => item.id === point.id,
)?.quantity;
return quantity || 0;
},
})),
{
title: '途中库存',
dataIndex: 'transitStock',
hideInSearch: true,
},
{
title: '加拿大库存',
dataIndex: 'caTotalStock',
hideInSearch: true,
render(_, record) {
if (!record.caTotalStock || record.caTotalStock > 400) {
return record.caTotalStock;
}
return <span style={{ color: 'red' }}>{record.caTotalStock}</span>;
},
},
{
title: '总库存',
dataIndex: 'totalStock',
hideInSearch: true,
},
{
title: '30天',
dataIndex: 'totalSales_30',
hideInSearch: true,
},
{
title: '2*15天',
dataIndex: 'totalSales_15',
hideInSearch: true,
},
{
title: '补货数量',
dataIndex: 'restockQuantity',
hideInSearch: true,
},
{
title: '实补数量',
dataIndex: 'restockQuantityReal',
hideInSearch: true,
render(_, record) {
return (
<ProFormDigit
key={record.productSku}
initialValue={0}
fieldProps={{
onChange(value) {
setReal({
...real,
[record.productSku]: value,
});
},
}}
/>
);
},
},
{
title: 'B端实补数量',
dataIndex: 'restockQuantityReal',
hideInSearch: true,
render(_, record) {
return <ProFormDigit key={'b_' + record.productSku} />;
},
},
{
title: '加拿大剩余天数',
dataIndex: 'caAvailableDays',
hideInSearch: true,
render(_, record) {
if (!record.caAvailableDays || record.caAvailableDays > 40) {
return record.caAvailableDays;
}
return <span style={{ color: 'red' }}>{record.caAvailableDays}</span>;
},
},
{
title: '剩余天数',
dataIndex: 'availableDays',
hideInSearch: true,
render(_, record) {
if (!record.availableDays || record.availableDays > 70) {
return record.availableDays;
}
return <span style={{ color: 'red' }}>{record.availableDays}</span>;
},
},
{
title: '实补后剩余天数',
hideInSearch: true,
render(_, record) {
if (!record.availableDays) return '-';
const availableDays = Number(record.availableDays);
const quantity = real?.[record.productSku] || 0;
const day =
availableDays +
Math.floor(
quantity /
(Math.max(record.totalSales_30, record.totalSales_15) / 30),
);
return day;
},
},
{
title: '实补后日期',
hideInSearch: true,
render(_, record) {
if (!record.availableDays) return '-';
const availableDays = Number(record.availableDays);
const quantity = real?.[record.productSku] || 0;
const day =
availableDays +
Math.floor(
quantity /
(Math.max(record.totalSales_30, record.totalSales_15) / 30),
);
return (
<ProFormDatePicker
readonly
fieldProps={{ value: dayjs().add(day, 'd') }}
/>
);
},
},
];
return (
<PageContainer ghost>
<ProTable
// tableStyle={{ height: '80vh', overflow: 'auto' }}
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
request={async (param) => {
const { data, success } = await statisticscontrollerStockforecast(
param,
);
if (success) {
return {
total: data?.total || 0,
data: data?.items || [],
};
}
return {
data: [],
};
}}
columns={columns}
dateFormatter="number"
/>
</PageContainer>
);
};
export default ListPage;

View File

@ -0,0 +1,887 @@
import { ORDER_STATUS_ENUM } from '@/constants';
import { sitecontrollerAll } from '@/servers/api/site';
import {
statisticscontrollerGetorderbydate,
statisticscontrollerGetorderbyemail,
statisticscontrollerGetorderstatistics,
} from '@/servers/api/statistics';
import { formatSource } from '@/utils/format';
import {
ModalForm,
PageContainer,
ProForm,
ProFormDateRangePicker,
ProFormSelect,
ProTable,
} from '@ant-design/pro-components';
import { Button } from 'antd';
import dayjs from 'dayjs';
import ReactECharts from 'echarts-for-react';
import { useEffect, useMemo, useState } from 'react';
const highlightText = (text: string, keyword: string) => {
if (!keyword) return text;
const parts = text.split(new RegExp(`(${keyword})`, 'gi'));
return parts.map((part, index) =>
part.toLowerCase() === keyword.toLowerCase() ? (
<span key={index} style={{ color: 'red', fontWeight: 'bold' }}>
{part}
</span>
) : (
part
),
);
};
const ListPage: React.FC = () => {
const [xAxis, setXAxis] = useState([]);
const [series, setSeries] = useState<any[]>([]);
const [selectedDate, setSelectedDate] = useState(null);
const option = useMemo(
() => ({
tooltip: {
trigger: 'axis',
formatter: function (params) {
const items = params.map((item) => {
return `<span style="display: inline-block;width: 250px">${item.marker} ${item.seriesName}: ${item.value}</span>`;
});
// 每4个一行
const rows = [];
for (let i = 0; i < items.length; i += 4) {
rows.push(items.slice(i, i + 4).join(''));
}
return rows.join('<br/>');
},
},
legend: {
data: ['订单数', '总金额', '平均金额', '盒数'],
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
xAxis: {
type: 'category',
boundaryGap: false,
data: xAxis,
},
yAxis: [
{
type: 'value',
name: '订单数',
position: 'left',
},
{
type: 'value',
name: '总金额',
position: 'right',
offset: 60,
},
{
type: 'value',
name: '平均金额',
position: 'right',
},
{
type: 'value',
name: '盒数',
position: 'left',
offset: 60,
},
],
series,
}),
[xAxis, series],
);
return (
<PageContainer ghost>
<ProForm
layout="inline"
onFinish={async (values) => {
setXAxis([]);
setSeries([]);
setSelectedDate(null);
// setKeyword(values?.keyword || '');
const { date, ...params } = values;
const [startDate, endDate] = date;
const { data, success } =
await statisticscontrollerGetorderstatistics({
startDate,
endDate,
...params,
});
if (success) {
const res = data?.sort(() => -1);
setXAxis(res?.map((v) => dayjs(v.order_date).format('YYYY-MM-DD')));
setSeries([
{
name: '首购订单数',
type: 'line',
data: res?.map((v) => v.first_purchase_orders),
},
{
name: '首购金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.first_purchase_total),
},
{
name: '复购订单数',
type: 'line',
data: res?.map((v) => v.repeat_purchase_orders),
},
{
name: '复购金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.repeat_purchase_total),
},
{
name: 'TOGO CPC订单数',
type: 'line',
data: res?.map((v) => v.togo_cpc_orders),
},
{
name: 'TOGO 非CPC订单数',
type: 'line',
data: res?.map((v) => v.non_togo_cpc_orders),
},
{
name: 'CAN CPC订单数',
type: 'line',
data: res?.map((v) => v.can_cpc_orders),
},
{
name: 'CAN 非CPC订单数',
type: 'line',
data: res?.map((v) => v.non_can_cpc_orders),
},
{
name: 'CPC订单数',
type: 'line',
data: res?.map((v) => v.cpc_orders),
},
{
name: 'ZYN CPC订单数',
type: 'line',
data: res?.map((v) => v.zyn_orders),
},
{
name: 'YOONE CPC订单数',
type: 'line',
data: res?.map((v) => v.yoone_orders),
},
{
name: 'ZEX CPC订单数',
type: 'line',
data: res?.map((v) => v.zex_orders),
},
{
name: 'CPC金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.cpc_total),
},
{
name: 'ZYN CPC金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.zyn_total),
},
{
name: 'YOONE CPC金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.yoone_total),
},
{
name: 'ZEX CPC金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.zex_total),
},
{
name: '非CPC订单数',
type: 'line',
data: res?.map((v) => v.non_cpc_orders),
},
{
name: 'ZYN 非CPC订单数',
type: 'line',
data: res?.map((v) => v.non_zyn_orders),
},
{
name: 'YOONE 非CPC订单数',
type: 'line',
data: res?.map((v) => v.non_yoone_orders),
},
{
name: 'ZEX 非CPC订单数',
type: 'line',
data: res?.map((v) => v.non_zex_orders),
},
{
name: '非CPC金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.non_cpc_total),
},
{
name: 'ZYN 非CPC金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.non_zyn_total),
},
{
name: 'YOONE 非CPC金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.non_yoone_total),
},
{
name: 'ZEX 非CPC金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.non_zex_total),
},
{
name: 'ZYN 盒数金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.zyn_amount),
},
{
name: 'ZYN 盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.zyn_quantity),
},
{
name: 'ZYN CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.cpc_zyn_quantity),
},
{
name: 'ZYN 非CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.non_cpc_zyn_quantity),
},
{
name: 'YOONE 盒数金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.yoone_amount),
},
{
name: 'YOONE 盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.yoone_quantity),
},
{
name: 'YOONE CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.cpc_yoone_quantity),
},
{
name: 'YOONE 非CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.non_cpc_yoone_quantity),
},
{
name: 'YOONE套装金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.yoone_G_amount),
},
{
name: 'YOONE套装盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.yoone_G_quantity),
},
{
name: 'YOONE套装CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.cpc_yoone_G_quantity),
},
{
name: 'YOONE套装非CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.non_cpc_yoone_G_quantity),
},
{
name: 'YOONE单盒金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.yoone_S_amount),
},
{
name: 'YOONE单盒盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.yoone_S_quantity),
},
{
name: 'YOONE单盒CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.cpc_yoone_S_quantity),
},
{
name: 'YOONE单盒非CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.non_cpc_yoone_S_quantity),
},
{
name: 'YOONE 3MG 盒数金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.yoone_3_amount),
},
{
name: 'YOONE 3MG 盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.yoone_3_quantity),
},
{
name: 'YOONE 3MG CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.cpc_yoone_3_quantity),
},
{
name: 'YOONE 3MG 非CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.non_cpc_yoone_3_quantity),
},
{
name: 'YOONE 6MG 盒数金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.yoone_6_amount),
},
{
name: 'YOONE 6MG 盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.yoone_6_quantity),
},
{
name: 'YOONE 6MG CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.cpc_yoone_6_quantity),
},
{
name: 'YOONE 6MG 非CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.non_cpc_yoone_6_quantity),
},
{
name: 'YOONE 9MG 盒数金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.yoone_9_amount),
},
{
name: 'YOONE 9MG 盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.yoone_9_quantity),
},
{
name: 'YOONE 9MG CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.cpc_yoone_9_quantity),
},
{
name: 'YOONE 9MG 非CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.non_cpc_yoone_9_quantity),
},
{
name: 'YOONE 12MG 盒数金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.yoone_12_amount),
},
{
name: 'YOONE 12MG 盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.yoone_12_quantity),
},
{
name: 'YOONE 12MG CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.cpc_yoone_12_quantity),
},
{
name: 'YOONE 12MG 非CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.non_cpc_yoone_12_quantity),
},
{
name: 'YOONE 15MG 盒数金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.yoone_15_amount),
},
{
name: 'YOONE 15MG 盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.yoone_15_quantity),
},
{
name: 'YOONE 15MG CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.cpc_yoone_15_quantity),
},
{
name: 'YOONE 15MG 非CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.non_cpc_yoone_15_quantity),
},
{
name: 'ZEX 盒数金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.zex_amount),
},
{
name: 'ZEX 盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.zex_quantity),
},
{
name: 'ZEX CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.cpc_zex_quantity),
},
{
name: 'ZEX 非CPC盒数',
type: 'line',
yAxisIndex: 3,
data: res?.map((v) => v.non_cpc_zex_quantity),
},
{
name: '订单数',
type: 'line',
data: res?.map((v) => v.total_orders),
},
{
name: 'TOGO订单数',
type: 'line',
data: res?.map((v) => v.togo_total_orders),
},
{
name: 'CAN订单数',
type: 'line',
data: res?.map((v) => v.can_total_orders),
},
{
name: '总金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.total_amount),
},
{
name: 'TOGO总金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.togo_total_amount),
},
{
name: 'CAN总金额',
type: 'line',
yAxisIndex: 1,
data: res?.map((v) => v.can_total_amount),
},
{
name: '平均金额',
type: 'line',
yAxisIndex: 2,
data: res?.map((v) => v.avg_total_amount),
},
{
name: 'TOGO平均金额',
type: 'line',
yAxisIndex: 2,
data: res?.map((v) => v.avg_togo_total_amount),
},
{
name: 'CAN平均金额',
type: 'line',
yAxisIndex: 2,
data: res?.map((v) => v.avg_can_total_amount),
},
]);
}
}}
>
<ProFormDateRangePicker
label="日期"
rules={[{ required: true, message: '请选择日期' }]}
name="date"
/>
{/* <ProFormText label="关键词" name="keyword" /> */}
<ProFormSelect
label="站点"
name="siteId"
request={async () => {
const { data = [] } = await sitecontrollerAll();
return data.map((item) => ({
label: item.siteName,
value: item.id,
}));
}}
/>
{/* <ProFormSelect
label="类型"
name="purchaseType"
valueEnum={{
first_purchase: '首购',
repeat_purchase: '复购',
}}
/>
<ProFormSelect
label="来源"
name="orderType"
valueEnum={{
cpc: '广告',
non_cpc: '非广告',
}}
/>
<ProFormSelect
label="品牌"
name="brand"
valueEnum={{
zyn: 'ZYN',
zex: 'ZEX',
yoone: 'YOONE',
}}
/> */}
</ProForm>
{series?.length ? (
<ReactECharts
style={{ height: 450 }}
option={option}
onEvents={{
click: (params) => {
if (params.componentType === 'series') {
setSelectedDate(params.name);
}
},
}}
/>
) : (
<></>
)}
<DailyOrders selectedDate={selectedDate} />
</PageContainer>
);
};
const DailyOrders: React.FC<{
selectedDate;
}> = ({ selectedDate }) => {
const [orders, setOrders] = useState([]);
useEffect(() => {
if (!selectedDate) {
setOrders([]);
return;
}
statisticscontrollerGetorderbydate({
date: selectedDate,
}).then(({ data, success }) => {
if (success) {
setOrders(data);
}
});
}, [selectedDate]);
const handleTableChange = (pagination, filters, sorter) => {
// 获取排序字段和排序方式
const { field, order } = sorter || {};
if (field && order) {
const sortedData = [...orders].sort((a, b) => {
if (['total', 'order_count', 'total_spent'].includes(field)) {
const valA = Number(a[field]);
const valB = Number(b[field]);
if (isNaN(valA)) return 1;
if (isNaN(valB)) return -1;
if (order === 'ascend') {
return valA - valB;
}
return valB - valA;
}
if (order === 'ascend') {
return a[field] > b[field] ? 1 : -1;
}
return a[field] < b[field] ? 1 : -1;
});
setOrders(sortedData);
}
};
if (!selectedDate) return <></>;
return (
<ProTable
search={false}
columns={[
{
title: '订单号',
dataIndex: 'externalOrderId',
},
{
title: '客户邮箱',
dataIndex: 'customer_email',
},
{
title: '站点',
dataIndex: 'siteId',
valueType: 'select',
request: async () => {
const { data = [] } = await sitecontrollerAll();
return data.map((item) => ({
label: item.siteName,
value: item.id,
}));
},
},
{
title: '首单时间',
dataIndex: 'first_purchase_date',
valueType: 'dateTime',
sorter: true,
},
{
title: '支付时间',
dataIndex: 'date_paid',
valueType: 'dateTime',
sorter: true,
},
{
title: '订单金额',
dataIndex: 'total',
sorter: true,
},
{
title: '总订单数',
dataIndex: 'order_count',
sorter: true,
},
{
title: '总订单金额',
dataIndex: 'total_spent',
sorter: true,
},
{
title: '订单类型',
dataIndex: 'purchase_type',
sorter: true,
render: (_, record) => {
if (record.purchase_type === 'first_purchase') return '首单';
return '复购单';
},
filters: [
{ text: '首单', value: 'first_purchase' },
{ text: '复购单', value: 'repeat_purchase' },
],
onFilter: (value, record) => {
return record.purchase_type === value;
},
},
{
title: '状态',
dataIndex: 'orderStatus',
hideInSearch: true,
valueType: 'select',
valueEnum: ORDER_STATUS_ENUM,
sorter: true,
},
{
title: '来源',
hideInSearch: true,
sorter: true,
render: (_, record) =>
formatSource(record.source_type, record.utm_source),
filters: [
{ text: 'google广告', value: 'source' },
{ text: 'google搜索', value: 'organic' },
{ text: '直达', value: 'direct' },
{ text: '其他', value: 'other' },
],
onFilter: (value, record) => {
if (value === 'source') {
return (
record.source_type === 'utm' && record.utm_source === 'google'
);
}
if (value === 'organic') {
return (
record.source_type === 'organic' &&
record.utm_source === 'google'
);
}
if (value === 'direct') {
return record.source_type === 'typein';
}
if (value === '其他') {
return !['utm', 'organic', 'typein'].includes(record.source_type);
}
},
},
{
title: '订单内容',
dataIndex: 'orderItems',
render: (_, record) => {
return (
<div>
{record.orderItems?.map((item) => (
// <div>{highlightText(item.name, keyword)}</div>
<div>{item.name}</div>
))}
</div>
);
},
filters: [
{ text: 'ZYN', value: 'zyn' },
{ text: 'YOONE', value: 'yoone' },
{ text: 'ZEX', value: 'zex' },
],
onFilter: (value, record) => {
return record.orderItems?.some((v) =>
v?.name?.toLowerCase().includes(value),
);
},
},
{
title: '操作',
dataIndex: 'action',
valueType: 'option',
render: (_, record) => {
return <HistoryOrder email={record.customer_email} />;
},
},
]}
dataSource={orders}
onChange={handleTableChange}
/>
);
};
const HistoryOrder: React.FC<{
email: string;
}> = ({ email }) => {
return (
<ModalForm
title={`历史订单${email}`}
trigger={<Button type="primary"></Button>}
modalProps={{ destroyOnClose: true, footer: null }}
width="80vw"
>
<ProTable
search={false}
columns={[
{
title: '订单号',
dataIndex: 'externalOrderId',
},
{
title: '客户邮箱',
dataIndex: 'customer_email',
},
{
title: '站点',
dataIndex: 'siteId',
valueType: 'select',
request: async () => {
const { data = [] } = await sitecontrollerAll();
return data.map((item) => ({
label: item.siteName,
value: item.id,
}));
},
},
{
title: '支付时间',
dataIndex: 'date_paid',
valueType: 'dateTime',
},
{
title: '订单金额',
dataIndex: 'total',
},
{
title: '状态',
dataIndex: 'orderStatus',
hideInSearch: true,
valueType: 'select',
valueEnum: ORDER_STATUS_ENUM,
},
{
title: '来源',
hideInSearch: true,
render: (_, record) =>
formatSource(record.source_type, record.utm_source),
},
{
title: '订单内容',
dataIndex: 'orderItems',
render: (_, record) => {
return (
<div>
{record.orderItems?.map((item) => (
<div>
${item.total} : {item.name} * {item.quantity}
</div>
))}
</div>
);
},
},
]}
request={async () => {
const { data, success } = await statisticscontrollerGetorderbyemail({
email,
});
return {
data,
success,
};
}}
/>
</ModalForm>
);
};
export default ListPage;

View File

@ -0,0 +1,187 @@
import { statisticscontrollerRestocking } from '@/servers/api/statistics';
import {
ActionType,
PageContainer,
ProColumns,
ProFormDigit,
ProFormText,
ProTable,
} from '@ant-design/pro-components';
import dayjs from 'dayjs';
import { useMemo, useRef, useState } from 'react';
const ListPage: React.FC = () => {
const actionRef = useRef<ActionType>();
const [count, setCount] = useState(4);
const history = useMemo(
() =>
Array.from({ length: Math.min(!!count ? count : 5, 10) }).map((_, i) => {
if (dayjs().date() > 20) i++;
return dayjs().add(i, 'month').format('YYYY-MM');
}),
[count],
);
const [savety, setSavety] = useState({});
const columns: ProColumns[] = [
{
title: '产品名称',
dataIndex: 'productName',
},
{
title: '30天销量',
dataIndex: 'last30DaysSales',
hideInSearch: true,
},
{
title: '2*15天销量',
dataIndex: 'last15DaysSales',
hideInSearch: true,
render(_, record) {
return 2 * record.last15DaysSales;
},
},
{
title: '库存',
dataIndex: 'totalStock',
hideInSearch: true,
},
...history.map((v, i) => ({
title: v,
onCell: () => ({ style: { padding: 0 } }),
align: 'center' as any,
hideInSearch: true,
render(_, record) {
const base = record.lastMonthSales;
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
position: 'absolute',
justifyContent: 'center',
left: 0,
right: 0,
top: 0,
bottom: 0,
}}
>
<div style={{ position: 'absolute', zIndex: 99 }}>
<div>{base}</div>
<div>{base}</div>
<div>{base}</div>
</div>
<div
style={{
position: 'absolute',
zIndex: 1,
width:
Math.max(Math.min(record.totalStock / base - i, 1), 0) * 100 +
'%',
height: '100%',
alignItems: 'flex-start',
alignSelf: 'flex-start',
backgroundColor: 'red',
}}
></div>
</div>
);
},
})),
{
title: '安全补充系数',
hideInSearch: true,
render(_, record) {
return (
<ProFormDigit
key={record.productSku}
width={100}
fieldProps={{
defaultValue: 0,
onChange(value) {
setSavety({
...savety,
[record.productSku]: value,
});
},
}}
/>
);
},
},
{
title: '',
hideInSearch: true,
render(_, record) {
const base = record.lastMonthSales;
return (
<div>
<div>{count * base}</div>
<div>{2 * count * base}</div>
</div>
);
},
},
{
title: '合计',
hideInSearch: true,
render(_, record) {
const base = record.lastMonthSales;
return 3 * count * base + (savety[record.productSku] || 0);
},
},
{
title: '修正数',
hideInSearch: true,
render(_, record) {
const base = record.lastMonthSales;
return (
<ProFormDigit
key={'fix' + record.productSku + (savety[record.productSku] || 0)}
width={100}
fieldProps={{
defaultValue: 3 * count * base + (savety[record.productSku] || 0),
}}
/>
);
},
},
];
return (
<PageContainer ghost>
<ProTable
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
request={async (param) => {
const { data, success } = await statisticscontrollerRestocking(param);
if (success) {
return {
total: data?.total || 0,
data: data?.items || [],
};
}
return {
data: [],
};
}}
columns={columns}
dateFormatter="number"
toolBarRender={() => [
<ProFormText
key="count"
width="100px"
fieldProps={{
onChange: (e) => setCount(e.target.value),
value: count,
}}
/>,
]}
/>
</PageContainer>
);
};
export default ListPage;

View File

@ -0,0 +1,185 @@
import { ordercontrollerGetordersales } from '@/servers/api/order';
import { sitecontrollerAll } from '@/servers/api/site';
import {
ActionType,
PageContainer,
ProColumns,
ProFormSwitch,
ProTable,
} from '@ant-design/pro-components';
import dayjs from 'dayjs';
import { useRef, useState } from 'react';
const ListPage: React.FC = () => {
const actionRef = useRef<ActionType>();
const [total, setTotal] = useState(0);
const [isSource, setIsSource] = useState(false);
const [yooneTotal, setYooneTotal] = useState({});
const columns: ProColumns<API.OrderSaleDTO>[] = [
{
title: '时间段',
dataIndex: 'dateRange',
valueType: 'dateTimeRange',
hideInTable: true,
formItemProps: {
rules: [
{
required: true,
message: '请选择时间段',
},
],
},
},
{
title: '产品名称',
dataIndex: 'name',
},
{
title: '站点',
dataIndex: 'siteId',
valueType: 'select',
request: async () => {
const { data = [] } = await sitecontrollerAll();
return data.map((item) => ({
label: item.siteName,
value: item.id,
}));
},
hideInTable: true,
},
{
title: '分类',
dataIndex: 'categoryName',
hideInSearch: true,
hideInTable: isSource,
},
{
title: '数量',
dataIndex: 'totalQuantity',
hideInSearch: true,
},
{
title: '一单订单数',
dataIndex: 'firstOrderCount',
hideInSearch: true,
render(_, record) {
if (isSource) return record.firstOrderCount;
return `${record.firstOrderCount}(${record.firstOrderYOONEBoxCount})`;
},
},
{
title: '两单订单数',
dataIndex: 'secondOrderCount',
hideInSearch: true,
render(_, record) {
if (isSource) return record.secondOrderCount;
return `${record.secondOrderCount}(${record.secondOrderYOONEBoxCount})`;
},
},
{
title: '三单订单数',
dataIndex: 'thirdOrderCount',
hideInSearch: true,
render(_, record) {
if (isSource) return record.thirdOrderCount;
return `${record.thirdOrderCount}(${record.thirdOrderYOONEBoxCount})`;
},
},
{
title: '三单以上订单数',
dataIndex: 'moreThirdOrderCount',
hideInSearch: true,
render(_, record) {
if (isSource) return record.moreThirdOrderCount;
return `${record.moreThirdOrderCount}(${record.moreThirdOrderYOONEBoxCount})`;
},
},
{
title: '订单数',
dataIndex: 'totalOrders',
hideInSearch: true,
},
];
return (
<PageContainer ghost>
<ProTable
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
params={{ isSource }}
form={{
// ignoreRules: false,
initialValues: {
dateRange: [dayjs().startOf('month'), dayjs().endOf('month')],
},
}}
request={async ({ dateRange, ...param }) => {
const [startDate, endDate] = dateRange.values();
const { data, success } = await ordercontrollerGetordersales({
startDate,
endDate,
...param,
});
if (success) {
setTotal(data?.totalQuantity || 0);
setYooneTotal({
yoone3Quantity: data?.yoone3Quantity || 0,
yoone6Quantity: data?.yoone6Quantity || 0,
yoone9Quantity: data?.yoone9Quantity || 0,
yoone12Quantity: data?.yoone12Quantity || 0,
yoone15Quantity: data?.yoone15Quantity || 0,
});
return {
total: data?.total || 0,
data: data?.items || [],
};
}
setTotal(0);
setYooneTotal({});
return {
data: [],
};
}}
columns={columns}
dateFormatter="number"
footer={() => `总计: ${total}`}
toolBarRender={() => [
<ProFormSwitch
label="原产品"
fieldProps={{
value: isSource,
onChange: () => setIsSource(!isSource),
}}
/>,
]}
/>
<div
style={{
background: '#fff',
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
padding: '10px',
marginTop: '20px',
}}
>
<div>
YOONE:{' '}
{(yooneTotal.yoone3Quantity || 0) +
(yooneTotal.yoone6Quantity || 0) +
(yooneTotal.yoone9Quantity || 0) +
(yooneTotal.yoone12Quantity || 0) +
(yooneTotal.yoone15Quantity || 0)}
</div>
<div>YOONE 3MG: {yooneTotal.yoone3Quantity || 0}</div>
<div>YOONE 6MG: {yooneTotal.yoone6Quantity || 0}</div>
<div>YOONE 9MG: {yooneTotal.yoone9Quantity || 0}</div>
<div>YOONE 12MG: {yooneTotal.yoone12Quantity || 0}</div>
<div>YOONE 15MG: {yooneTotal.yoone15Quantity || 0}</div>
</div>
</PageContainer>
);
};
export default ListPage;

View File

@ -0,0 +1,85 @@
import {
stockcontrollerGetallstockpoints,
stockcontrollerGetstocks,
} from '@/servers/api/stock';
import {
ActionType,
PageContainer,
ProColumns,
ProTable,
} from '@ant-design/pro-components';
import { App } from 'antd';
import { useEffect, useRef, useState } from 'react';
const ListPage: React.FC = () => {
const { message } = App.useApp();
const actionRef = useRef<ActionType>();
const [points, setPoints] = useState<API.StockPoint[]>([]);
useEffect(() => {
stockcontrollerGetallstockpoints().then(({ data }) => {
setPoints(data as API.StockPoint[]);
});
}, []);
const columns: ProColumns<API.StockDTO>[] = [
{
title: '产品名称',
dataIndex: 'productName',
},
{
title: 'SKU',
dataIndex: 'productSku',
hideInSearch: true,
},
...points?.map((point: API.StockPoint) => ({
title: point.name,
dataIndex: `point_${point.name}`,
hideInSearch: true,
render(_: any, record: API.StockDTO) {
const quantity = record.stockPoint?.find(
(item) => item.id === point.id,
)?.quantity;
return quantity || 0;
},
})),
{
title: '运输中',
dataIndex: 'inTransitQuantity',
hideInSearch: true,
},
// {
// title: '更新时间',
// dataIndex: 'updatedAt',
// valueType: 'dateTime',
// hideInSearch: true,
// },
// {
// title: '创建时间',
// dataIndex: 'createdAt',
// valueType: 'dateTime',
// hideInSearch: true,
// },
];
return (
<PageContainer ghost>
<ProTable<API.StockDTO>
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
request={async (params) => {
const { data, success } = await stockcontrollerGetstocks(params);
return {
total: data?.total || 0,
data: data?.items || [],
success,
};
}}
columns={columns}
// toolBarRender={() => [<CreateForm tableRef={actionRef} />]}
/>
</PageContainer>
);
};
export default ListPage;

View File

@ -0,0 +1,682 @@
import { Purchase_Order_STATUS_ENUM } from '@/constants';
import { productcontrollerSearchproducts } from '@/servers/api/product';
import {
stockcontrollerCreatepurchaseorder,
stockcontrollerDelpurchaseorder,
stockcontrollerGetallstockpoints,
stockcontrollerGetpurchaseorders,
stockcontrollerReceivepurchaseorder,
stockcontrollerUpdatepurchaseorder,
} from '@/servers/api/stock';
import { EditOutlined, PlusOutlined } from '@ant-design/icons';
import {
ActionType,
DrawerForm,
PageContainer,
ProColumns,
ProForm,
ProFormDatePicker,
ProFormDependency,
ProFormDigit,
ProFormList,
ProFormSelect,
ProFormText,
ProFormTextArea,
ProTable,
} from '@ant-design/pro-components';
import { App, Button, Divider, Form, Popconfirm } from 'antd';
import { useRef } from 'react';
const PurchaseOrderPage: React.FC = () => {
const { message } = App.useApp();
const actionRef = useRef<ActionType>();
const columns: ProColumns<API.PurchaseOrderDTO>[] = [
{
title: '订单编号',
dataIndex: 'orderNumber',
},
{
title: '仓库',
dataIndex: 'stockPointName',
hideInSearch: true,
},
{
title: '状态',
dataIndex: 'status',
valueType: 'select',
valueEnum: Purchase_Order_STATUS_ENUM,
hideInSearch: true,
},
{
title: '预计到货时间',
dataIndex: 'expectedArrivalTime',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '数量',
hideInSearch: true,
render(_, record) {
return record.items.reduce((cur, next) => {
return cur + next.quantity;
}, 0);
},
},
{
title: '备注',
dataIndex: 'note',
hideInSearch: true,
},
{
title: '更新时间',
dataIndex: 'updatedAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '创建时间',
dataIndex: 'createdAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => (
<>
{record.status !== 'received' && (
<UpdateForm tableRef={actionRef} values={record} />
)}
{record.status === 'draft' ? (
<>
<Divider type="vertical" />
<Popconfirm
title="删除"
description="确认删除?"
onConfirm={async () => {
try {
const { success, message: errMsg } =
await stockcontrollerDelpurchaseorder({
id: record.id as number,
});
if (!success) {
throw new Error(errMsg);
}
actionRef.current?.reload();
} catch (error: any) {
message.error(error.message);
}
}}
>
<Button type="primary" danger>
</Button>
</Popconfirm>
</>
) : record.status === 'submitted' ? (
<>
<Divider type="vertical" />
<Popconfirm
title="入库"
description="确认已到达?"
onConfirm={async () => {
try {
const { success, message: errMsg } =
await stockcontrollerReceivepurchaseorder({
id: record.id as number,
});
if (!success) {
throw new Error(errMsg);
}
actionRef.current?.reload();
} catch (error: any) {
message.error(error.message);
}
}}
>
<Button type="primary"></Button>
</Popconfirm>
</>
) : (
<DetailForm tableRef={actionRef} values={record} />
)}
</>
),
},
];
return (
<PageContainer ghost>
<ProTable<API.PurchaseOrderDTO>
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
request={async (params) => {
const { data, success } = await stockcontrollerGetpurchaseorders(
params,
);
return {
total: data?.total || 0,
data: data?.items || [],
success,
};
}}
columns={columns}
toolBarRender={() => [<CreateForm tableRef={actionRef} />]}
/>
</PageContainer>
);
};
const CreateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
}> = ({ tableRef }) => {
const { message } = App.useApp();
const [form] = Form.useForm();
return (
<DrawerForm<API.CreatePurchaseOrderDTO>
title="新建"
trigger={
<Button type="primary">
<PlusOutlined />
</Button>
}
form={form}
autoFocusFirstInput
layout="vertical"
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
try {
const { success, message: errMsg } =
await stockcontrollerCreatepurchaseorder(values);
if (!success) {
throw new Error(errMsg);
}
tableRef.current?.reload();
message.success('提交成功');
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProFormSelect
request={async () => {
try {
const { data } = await stockcontrollerGetallstockpoints();
return (
data?.map((item) => {
return {
label: item.name,
value: item.id,
};
}) || []
);
} catch (error) {
return [];
}
}}
name="stockPointId"
label="仓库"
width="lg"
placeholder="请选择仓库"
rules={[{ required: true, message: '请选择仓库' }]}
/>
<ProFormSelect
name={'status'}
label="状态"
placeholder={'请选择状态'}
valueEnum={Purchase_Order_STATUS_ENUM}
width={'lg'}
rules={[{ required: true, message: '请选择状态' }]}
/>
<ProFormTextArea label="备注" name="note" width={'lg'} />
<ProFormDatePicker
name="expectedArrivalTime"
label="预计到货时间"
placeholder={'请选择预计到货时间'}
width={'lg'}
rules={[{ required: true, message: '请选择预计到货时间' }]}
/>
<ProFormDependency name={['items']}>
{({ items }) => {
return '数量:' + items?.reduce((acc, cur) => acc + cur.quantity, 0);
}}
</ProFormDependency>
<ProFormList<API.PurchaseOrderItem>
name="items"
label="产品"
rules={[
{
required: true,
message: '至少需要一个商品',
validator: (_, value) =>
value && value.length > 0
? Promise.resolve()
: Promise.reject('至少需要一个商品'),
},
]}
creatorButtonProps={{ children: '新增', size: 'large' }}
wrapperCol={{ span: 24 }}
>
{(fields, idx, { remove }) => (
<div key={idx}>
<ProFormSelect
request={async ({ keyWords }) => {
if (keyWords.length < 3) return [];
try {
const { data } = await productcontrollerSearchproducts({
name: keyWords,
});
return (
data?.map((item) => {
return {
label: item.name,
value: item.sku,
};
}) || []
);
} catch (error) {
return [];
}
}}
name="productSku"
label={'产品' + (idx + 1)}
width="lg"
placeholder="请选择产品"
tooltip="至少输入3个字符"
fieldProps={{
showSearch: true,
filterOption: false,
}}
transform={(value) => {
return value?.value || value;
}}
debounceTime={300} // 防抖,减少请求频率
rules={[{ required: true, message: '请选择产品' }]}
onChange={(_, option) => {
form.setFieldValue(
['items', fields.key, 'productName'],
option.title,
);
}}
/>
<ProFormText name={'productName'} label="产品名称" hidden={true} />
<ProFormDigit
name="quantity"
label="数量"
placeholder="请输入数量"
rules={[{ required: true, message: '请输入数量' }]}
fieldProps={{
precision: 0,
}}
/>
<ProFormDigit
name="price"
label="价格"
placeholder="请输入价格"
rules={[{ required: true, message: '请输入价格' }]}
fieldProps={{
precision: 2,
}}
/>
<Button type="link" danger onClick={() => remove(fields.key)}>
</Button>
</div>
)}
</ProFormList>
</DrawerForm>
);
};
const UpdateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
values: API.UpdatePurchaseOrderDTO & {
id: number;
};
}> = ({ tableRef, values }) => {
const { message } = App.useApp();
const [form] = Form.useForm();
const initialValues = {
...values,
items: values?.items?.map((item: API.PurchaseOrderItem) => ({
...item,
productSku: {
label: item.productName,
value: item.productSku,
},
})),
};
return (
<DrawerForm<API.UpdatePurchaseOrderDTO>
title="编辑"
form={form}
initialValues={initialValues}
trigger={
<Button type="primary">
<EditOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
try {
const { success, message: errMsg } =
await stockcontrollerUpdatepurchaseorder(
{ id: initialValues.id },
values,
);
if (!success) {
throw new Error(errMsg);
}
message.success('提交成功');
tableRef.current?.reload();
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProForm.Group>
<ProFormSelect
request={async () => {
try {
const { data } = await stockcontrollerGetallstockpoints();
return (
data?.map((item) => {
return {
label: item.name,
value: item.id,
};
}) || []
);
} catch (error) {
return [];
}
}}
name="stockPointId"
label="仓库"
width="lg"
placeholder="请选择仓库"
rules={[{ required: true, message: '请选择仓库' }]}
/>
<ProFormSelect
name={'status'}
label="状态"
placeholder={'请选择状态'}
valueEnum={Purchase_Order_STATUS_ENUM}
width={'lg'}
rules={[{ required: true, message: '请选择状态' }]}
/>
<ProFormDatePicker
name="expectedArrivalTime"
label="预计到货时间"
placeholder={'请选择预计到货时间'}
width={'lg'}
rules={[{ required: true, message: '请选择预计到货时间' }]}
/>
<ProFormTextArea label="备注" name="note" width={'lg'} />
<ProFormDependency name={['items']}>
{({ items }) => {
return (
'数量:' + items?.reduce((acc, cur) => acc + cur.quantity, 0)
);
}}
</ProFormDependency>
<ProFormList<API.PurchaseOrderItem>
name="items"
rules={[
{
required: true,
message: '至少需要一个商品',
validator: (_, value) =>
value && value.length > 0
? Promise.resolve()
: Promise.reject('至少需要一个商品'),
},
]}
creatorButtonProps={{ children: '新增', size: 'large' }}
wrapperCol={{ span: 24 }}
>
{(fields, idx, { remove }) => (
<div key={idx}>
<ProFormSelect
request={async ({ keyWords }) => {
if (keyWords.length < 3) return [];
try {
const { data } = await productcontrollerSearchproducts({
name: keyWords,
});
return (
data?.map((item) => {
return {
label: item.name,
value: item.sku,
};
}) || []
);
} catch (error) {
return [];
}
}}
name="productSku"
label="产品"
width="lg"
placeholder="请选择产品"
tooltip="至少输入3个字符"
fieldProps={{
showSearch: true,
filterOption: false,
}}
transform={(value) => {
return value?.value || value;
}}
debounceTime={300} // 防抖,减少请求频率
rules={[{ required: true, message: '请选择产品' }]}
onChange={(_, option) => {
form.setFieldValue(
['items', fields.key, 'productName'],
option?.title,
);
}}
/>
<ProFormText name="productName" label="产品名称" hidden={true} />
<ProFormDigit
name="quantity"
label="数量"
placeholder="请输入数量"
rules={[{ required: true, message: '请输入数量' }]}
fieldProps={{
precision: 0,
}}
/>
<ProFormDigit
name="price"
label="价格"
placeholder="请输入价格"
rules={[{ required: true, message: '请输入价格' }]}
fieldProps={{
precision: 2,
}}
/>
<Button type="link" danger onClick={() => remove(fields.key)}>
</Button>
</div>
)}
</ProFormList>
</ProForm.Group>
</DrawerForm>
);
};
const DetailForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
values: API.UpdatePurchaseOrderDTO & {
id: number;
};
}> = ({ tableRef, values }) => {
const { message } = App.useApp();
const [form] = Form.useForm();
const initialValues = {
...values,
items: values?.items?.map((item: API.PurchaseOrderItem) => ({
...item,
productSku: {
label: item.productName,
value: item.productSku,
},
})),
};
return (
<DrawerForm<API.UpdatePurchaseOrderDTO>
title="详情"
form={form}
initialValues={initialValues}
trigger={<Button type="primary"></Button>}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
readonly={true}
layout="vertical"
>
<ProFormSelect
request={async () => {
try {
const { data } = await stockcontrollerGetallstockpoints();
return (
data?.map((item) => {
return {
label: item.name,
value: item.id,
};
}) || []
);
} catch (error) {
return [];
}
}}
name="stockPointId"
label="仓库"
width="lg"
placeholder="请选择仓库"
rules={[{ required: true, message: '请选择仓库' }]}
/>
<ProFormText
name="orderNumber"
label="订单编号"
placeholder="请输入订单编号"
width={'lg'}
rules={[{ required: true, message: '请输入订单编号' }]}
/>
<ProFormSelect
name={'status'}
label="状态"
placeholder={'请选择状态'}
valueEnum={Purchase_Order_STATUS_ENUM}
width={'lg'}
rules={[{ required: true, message: '请选择状态' }]}
/>
<ProFormDatePicker
name="expectedArrivalTime"
label="预计到货时间"
placeholder={'请选择预计到货时间'}
width={'lg'}
rules={[{ required: true, message: '请选择预计到货时间' }]}
/>
<ProFormTextArea label="备注" name="note" width={'lg'} />
<ProFormList<API.PurchaseOrderItem>
name="items"
rules={[
{
required: true,
message: '至少需要一个商品',
validator: (_, value) =>
value && value.length > 0
? Promise.resolve()
: Promise.reject('至少需要一个商品'),
},
]}
creatorButtonProps={{ children: '新增', size: 'large' }}
wrapperCol={{ span: 24 }}
>
{(fields, idx, { remove }) => (
<div key={idx}>
<ProForm.Group>
<ProFormSelect
request={async ({ keyWords }) => {
if (keyWords.length < 3) return [];
try {
const { data } = await productcontrollerSearchproducts({
name: keyWords,
});
return (
data?.map((item) => {
return {
label: item.name,
value: item.sku,
};
}) || []
);
} catch (error) {
return [];
}
}}
name="productSku"
label="产品"
width="lg"
placeholder="请选择产品"
tooltip="至少输入3个字符"
fieldProps={{
showSearch: true,
filterOption: false,
}}
transform={(value) => {
return value?.value || value;
}}
debounceTime={300} // 防抖,减少请求频率
rules={[{ required: true, message: '请选择产品' }]}
onChange={(_, option) => {
form.setFieldValue(
['items', fields.key, 'productName'],
option?.title,
);
}}
/>
<ProFormText name="productName" label="产品名称" hidden={true} />
<ProFormDigit
name="quantity"
label="数量"
placeholder="请输入数量"
rules={[{ required: true, message: '请输入数量' }]}
fieldProps={{
precision: 0,
}}
/>
<ProFormDigit
name="price"
label="价格"
placeholder="请输入价格"
rules={[{ required: true, message: '请输入价格' }]}
fieldProps={{
precision: 2,
}}
/>
</ProForm.Group>
</div>
)}
</ProFormList>
</DrawerForm>
);
};
export default PurchaseOrderPage;

View File

@ -0,0 +1,81 @@
import { stockcontrollerGetstockrecords } from '@/servers/api/stock';
import {
ActionType,
PageContainer,
ProColumns,
ProTable,
} from '@ant-design/pro-components';
import { App } from 'antd';
import { useRef } from 'react';
const ListPage: React.FC = () => {
const { message } = App.useApp();
const actionRef = useRef<ActionType>();
const columns: ProColumns<API.StockRecordDTO>[] = [
{
title: '仓库',
dataIndex: 'stockPointName',
hideInSearch: true,
},
{
title: '产品名称',
dataIndex: 'productName',
},
{
title: 'SKU',
dataIndex: 'productSku',
hideInSearch: true,
},
{
title: '库存',
hideInSearch: true,
render: (_, record: API.StockRecordDTO) => (
<span>
{record?.operationType === 'in' ? '+' : '-'}
{record.quantityChange}
</span>
),
},
{
title: '操作人',
dataIndex: 'operatorName',
hideInSearch: true,
},
{
title: '备注',
dataIndex: 'note',
hideInSearch: true,
},
{
title: '创建时间',
dataIndex: 'createdAt',
valueType: 'dateTime',
hideInSearch: true,
},
];
return (
<PageContainer ghost>
<ProTable<API.StockRecordDTO>
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
request={async (params) => {
const { data, success } = await stockcontrollerGetstockrecords(
params,
);
return {
total: data?.total || 0,
data: data?.items || [],
success,
};
}}
columns={columns}
// toolBarRender={() => [<CreateForm tableRef={actionRef} />]}
/>
</PageContainer>
);
};
export default ListPage;

View File

@ -0,0 +1,688 @@
import { productcontrollerSearchproducts } from '@/servers/api/product';
import {
stockcontrollerCanceltransfer,
stockcontrollerCreatetransfer,
stockcontrollerGetallstockpoints,
stockcontrollerGettransfers,
stockcontrollerLosttransfer,
stockcontrollerReceivetransfer,
stockcontrollerUpdatetransfer,
} from '@/servers/api/stock';
import { EditOutlined, PlusOutlined } from '@ant-design/icons';
import {
ActionType,
DrawerForm,
PageContainer,
ProColumns,
ProForm,
ProFormDatePicker,
ProFormDependency,
ProFormDigit,
ProFormList,
ProFormSelect,
ProFormText,
ProFormTextArea,
ProTable,
} from '@ant-design/pro-components';
import { App, Button, Divider, Form, Popconfirm } from 'antd';
import { useRef } from 'react';
const TransferPage: React.FC = () => {
const { message } = App.useApp();
const actionRef = useRef<ActionType>();
const columns: ProColumns[] = [
{
title: '订单编号',
dataIndex: 'orderNumber',
},
{
title: '源仓库',
dataIndex: 'sourceStockPointName',
hideInSearch: true,
},
{
title: '目标仓库',
dataIndex: 'destStockPointName',
hideInSearch: true,
},
{
title: '状态',
dataIndex: 'status',
hideInSearch: true,
render(_, record) {
if (record.isLost) return '已丢失';
if (record.isCancel) return '已取消';
if (record.isArrived) return '已到达';
return '运输中';
},
},
{
title: '数量',
hideInSearch: true,
render(_, record) {
return record.items.reduce((cur, next) => {
return cur + next.quantity;
}, 0);
},
},
{
title: '备注',
dataIndex: 'note',
hideInSearch: true,
},
{
title: '到货时间',
dataIndex: 'arriveAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '发货时间',
dataIndex: 'sendAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => (
<>
{!record.isCancel && !record.isArrived && !record.isLost ? (
<>
<UpdateForm tableRef={actionRef} values={record} />
<Divider type="vertical" />
<Popconfirm
title="入库"
description="确认已到达?"
onConfirm={async () => {
try {
const { success, message: errMsg } =
await stockcontrollerReceivetransfer({
id: record.id as number,
});
if (!success) {
throw new Error(errMsg);
}
actionRef.current?.reload();
} catch (error: any) {
message.error(error.message);
}
}}
>
<Button type="primary"></Button>
</Popconfirm>
<Divider type="vertical" />
<Popconfirm
title="丢失"
description="确认该批货已丢失?"
onConfirm={async () => {
try {
const { success, message: errMsg } =
await stockcontrollerLosttransfer({
id: record.id as number,
});
if (!success) {
throw new Error(errMsg);
}
actionRef.current?.reload();
} catch (error: any) {
message.error(error.message);
}
}}
>
<Button type="primary"></Button>
</Popconfirm>
<Divider type="vertical" />
<Popconfirm
title="取消"
description="确认取消?"
onConfirm={async () => {
try {
const { success, message: errMsg } =
await stockcontrollerCanceltransfer({
id: record.id as number,
});
if (!success) {
throw new Error(errMsg);
}
actionRef.current?.reload();
} catch (error: any) {
message.error(error.message);
}
}}
>
<Button type="primary" danger>
</Button>
</Popconfirm>
</>
) : (
<DetailForm tableRef={actionRef} values={record} />
)}
</>
),
},
];
return (
<PageContainer ghost>
<ProTable
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
request={async (params) => {
const { data, success } = await stockcontrollerGettransfers(params);
return {
total: data?.total || 0,
data: data?.items || [],
success,
};
}}
columns={columns}
toolBarRender={() => [<CreateForm tableRef={actionRef} />]}
/>
</PageContainer>
);
};
const CreateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
}> = ({ tableRef }) => {
const { message } = App.useApp();
const [form] = Form.useForm();
return (
<DrawerForm
title="新建"
trigger={
<Button type="primary">
<PlusOutlined />
</Button>
}
form={form}
autoFocusFirstInput
layout="vertical"
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
try {
console.log(values);
const { success, message: errMsg } =
await stockcontrollerCreatetransfer(values);
if (!success) {
throw new Error(errMsg);
}
tableRef.current?.reload();
message.success('提交成功');
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProFormDatePicker
name="sendAt"
label="发货时间"
rules={[{ required: true, message: '请选择发货时间' }]}
/>
<ProFormSelect
request={async () => {
try {
const { data } = await stockcontrollerGetallstockpoints();
return (
data?.map((item) => {
return {
label: item.name,
value: item.id,
};
}) || []
);
} catch (error) {
return [];
}
}}
name="sourceStockPointId"
label="源仓库"
width="lg"
placeholder="请选择仓库"
rules={[{ required: true, message: '请选择源仓库' }]}
/>
<ProFormSelect
request={async () => {
try {
const { data } = await stockcontrollerGetallstockpoints();
return (
data?.map((item) => {
return {
label: item.name,
value: item.id,
};
}) || []
);
} catch (error) {
return [];
}
}}
name="destStockPointId"
label="目标仓库"
width="lg"
placeholder="请选择仓库"
rules={[{ required: true, message: '请选择源目标仓库' }]}
/>
<ProFormTextArea name="note" label="备注" />
<ProFormDependency name={['items']}>
{({ items }) => {
return '数量:' + items?.reduce((acc, cur) => acc + cur.quantity, 0);
}}
</ProFormDependency>
<ProFormList
name="items"
label="产品"
rules={[
{
required: true,
message: '至少需要一个商品',
validator: (_, value) =>
value && value.length > 0
? Promise.resolve()
: Promise.reject('至少需要一个商品'),
},
]}
creatorButtonProps={{ children: '新增', size: 'large' }}
wrapperCol={{ span: 24 }}
>
{(fields, idx, { remove }) => (
<div key={idx}>
<ProFormSelect
request={async ({ keyWords }) => {
if (keyWords.length < 3) return [];
try {
const { data } = await productcontrollerSearchproducts({
name: keyWords,
});
return (
data?.map((item) => {
return {
label: item.name,
value: item.sku,
};
}) || []
);
} catch (error) {
return [];
}
}}
name="productSku"
label={'产品' + (idx + 1)}
width="lg"
placeholder="请选择产品"
tooltip="至少输入3个字符"
fieldProps={{
showSearch: true,
}}
transform={(value) => {
return value?.value || value;
}}
debounceTime={300} // 防抖,减少请求频率
rules={[{ required: true, message: '请选择产品' }]}
onChange={(_, option) => {
form.setFieldValue(
['items', fields.key, 'productName'],
option.title,
);
}}
/>
<ProFormText name={'productName'} label="产品名称" hidden={true} />
<ProFormDigit
name="quantity"
label="数量"
placeholder="请输入数量"
rules={[{ required: true, message: '请输入数量' }]}
fieldProps={{
precision: 0,
}}
/>
</div>
)}
</ProFormList>
</DrawerForm>
);
};
const UpdateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
values: API.UpdatePurchaseOrderDTO & {
id: number;
};
}> = ({ tableRef, values }) => {
const { message } = App.useApp();
const [form] = Form.useForm();
const initialValues = {
...values,
items: values?.items?.map((item: API.PurchaseOrderItem) => ({
...item,
productSku: {
label: item.productName,
value: item.productSku,
},
})),
};
return (
<DrawerForm<API.UpdatePurchaseOrderDTO>
title="编辑"
form={form}
initialValues={initialValues}
trigger={
<Button type="primary">
<EditOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
try {
const { success, message: errMsg } =
await stockcontrollerUpdatetransfer(
{ id: initialValues.id },
values,
);
if (!success) {
throw new Error(errMsg);
}
message.success('提交成功');
tableRef.current?.reload();
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProFormSelect
readonly
request={async () => {
try {
const { data } = await stockcontrollerGetallstockpoints();
return (
data?.map((item) => {
return {
label: item.name,
value: item.id,
};
}) || []
);
} catch (error) {
return [];
}
}}
name="sourceStockPointId"
label="源仓库"
width="lg"
placeholder="请选择仓库"
rules={[{ required: true, message: '请选择源仓库' }]}
/>
<ProFormSelect
request={async () => {
try {
const { data } = await stockcontrollerGetallstockpoints();
return (
data?.map((item) => {
return {
label: item.name,
value: item.id,
};
}) || []
);
} catch (error) {
return [];
}
}}
name="destStockPointId"
label="目标仓库"
width="lg"
placeholder="请选择仓库"
rules={[{ required: true, message: '请选择源目标仓库' }]}
/>
<ProFormTextArea name="note" label="备注" />
<ProFormDependency name={['items']}>
{({ items }) => {
return '数量:' + items?.reduce((acc, cur) => acc + cur.quantity, 0);
}}
</ProFormDependency>
<ProFormList
name="items"
label="产品"
rules={[
{
required: true,
message: '至少需要一个商品',
validator: (_, value) =>
value && value.length > 0
? Promise.resolve()
: Promise.reject('至少需要一个商品'),
},
]}
creatorButtonProps={{ children: '新增', size: 'large' }}
wrapperCol={{ span: 24 }}
>
{(fields, idx, { remove }) => (
<div key={idx}>
<ProFormSelect
request={async ({ keyWords }) => {
if (keyWords.length < 3) return [];
try {
const { data } = await productcontrollerSearchproducts({
name: keyWords,
});
return (
data?.map((item) => {
return {
label: item.name,
value: item.sku,
};
}) || []
);
} catch (error) {
return [];
}
}}
name="productSku"
label={'产品' + (idx + 1)}
width="lg"
placeholder="请选择产品"
tooltip="至少输入3个字符"
fieldProps={{
showSearch: true,
}}
transform={(value) => {
return value?.value || value;
}}
debounceTime={300} // 防抖,减少请求频率
rules={[{ required: true, message: '请选择产品' }]}
onChange={(_, option) => {
form.setFieldValue(
['items', fields.key, 'productName'],
option.title,
);
}}
/>
<ProFormText name={'productName'} label="产品名称" hidden={true} />
<ProFormDigit
name="quantity"
label="数量"
placeholder="请输入数量"
rules={[{ required: true, message: '请输入数量' }]}
fieldProps={{
precision: 0,
}}
/>
</div>
)}
</ProFormList>
</DrawerForm>
);
};
const DetailForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
values: Record<string, any>;
}> = ({ tableRef, values }) => {
const { message } = App.useApp();
const [form] = Form.useForm();
const initialValues = {
...values,
items: values?.items?.map(
(item: { productName: string; productSku: string }) => ({
...item,
productSku: {
label: item.productName,
value: item.productSku,
},
}),
),
};
return (
<DrawerForm
title="详情"
form={form}
initialValues={initialValues}
trigger={<Button type="primary"></Button>}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
readonly={true}
layout="vertical"
>
<ProFormText
name="orderNumber"
label="订单编号"
placeholder="请输入订单编号"
width={'lg'}
rules={[{ required: true, message: '请输入订单编号' }]}
/>
<ProFormSelect
request={async () => {
try {
const { data } = await stockcontrollerGetallstockpoints();
return (
data?.map((item) => {
return {
label: item.name,
value: item.id,
};
}) || []
);
} catch (error) {
return [];
}
}}
name="sourceStockPointId"
label="源仓库"
width="lg"
placeholder="请选择仓库"
rules={[{ required: true, message: '请选择源仓库' }]}
/>
<ProFormSelect
request={async () => {
try {
const { data } = await stockcontrollerGetallstockpoints();
return (
data?.map((item) => {
return {
label: item.name,
value: item.id,
};
}) || []
);
} catch (error) {
return [];
}
}}
name="destStockPointId"
label="目标仓库"
width="lg"
placeholder="请选择仓库"
rules={[{ required: true, message: '请选择源目标仓库' }]}
/>
<ProFormTextArea name="note" label="备注" />
<ProFormList<API.PurchaseOrderItem>
name="items"
rules={[
{
required: true,
message: '至少需要一个商品',
validator: (_, value) =>
value && value.length > 0
? Promise.resolve()
: Promise.reject('至少需要一个商品'),
},
]}
creatorButtonProps={{ children: '新增', size: 'large' }}
wrapperCol={{ span: 24 }}
>
{(fields, idx, { remove }) => (
<div key={idx}>
<ProForm.Group>
<ProFormSelect
request={async ({ keyWords }) => {
if (keyWords.length < 3) return [];
try {
const { data } = await productcontrollerSearchproducts({
name: keyWords,
});
return (
data?.map((item) => {
return {
label: item.name,
value: item.sku,
};
}) || []
);
} catch (error) {
return [];
}
}}
name="productSku"
label="产品"
width="lg"
placeholder="请选择产品"
tooltip="至少输入3个字符"
fieldProps={{
showSearch: true,
}}
transform={(value) => {
return value?.value || value;
}}
debounceTime={300} // 防抖,减少请求频率
rules={[{ required: true, message: '请选择产品' }]}
onChange={(_, option) => {
form.setFieldValue(
['items', fields.key, 'productName'],
option?.title,
);
}}
/>
<ProFormText name="productName" label="产品名称" hidden={true} />
<ProFormDigit
name="quantity"
label="数量"
placeholder="请输入数量"
rules={[{ required: true, message: '请输入数量' }]}
fieldProps={{
precision: 0,
}}
/>
</ProForm.Group>
</div>
)}
</ProFormList>
</DrawerForm>
);
};
export default TransferPage;

View File

@ -0,0 +1,239 @@
import {
stockcontrollerCreatestockpoint,
stockcontrollerDelstockpoints,
stockcontrollerGetstockpoints,
stockcontrollerUpdatestockpoint,
} from '@/servers/api/stock';
import { EditOutlined, PlusOutlined } from '@ant-design/icons';
import {
ActionType,
DrawerForm,
PageContainer,
ProColumns,
ProForm,
ProFormText,
ProTable,
} from '@ant-design/pro-components';
import { App, Button, Divider, Popconfirm } from 'antd';
import { useRef } from 'react';
const ListPage: React.FC = () => {
const { message } = App.useApp();
const actionRef = useRef<ActionType>();
const columns: ProColumns<API.StockPoint>[] = [
{
title: '名称',
dataIndex: 'name',
},
{
title: '地址',
dataIndex: 'location',
},
{
title: '联系人',
dataIndex: 'contactPerson',
},
{
title: '联系电话',
dataIndex: 'contactPhone',
},
{
title: '创建时间',
dataIndex: 'createdAt',
valueType: 'dateTime',
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => (
<>
<UpdateForm tableRef={actionRef} values={record} />
<Divider type="vertical" />
<Popconfirm
title="删除"
description="确认删除?"
onConfirm={async () => {
try {
const { success, message: errMsg } =
await stockcontrollerDelstockpoints({
id: record.id as number,
});
if (!success) {
throw new Error(errMsg);
}
actionRef.current?.reload();
} catch (error: any) {
message.error(error.message);
}
}}
>
<Button type="primary" danger>
</Button>
</Popconfirm>
</>
),
},
];
return (
<PageContainer ghost>
<ProTable<API.StockPoint>
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
request={async (params) => {
const { data, success } = await stockcontrollerGetstockpoints(params);
return {
total: data?.total || 0,
data: data?.items || [],
success,
};
}}
columns={columns}
toolBarRender={() => [<CreateForm tableRef={actionRef} />]}
search={false}
/>
</PageContainer>
);
};
const CreateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
}> = ({ tableRef }) => {
const { message } = App.useApp();
return (
<DrawerForm<API.CreateStockPointDTO>
title="新建"
trigger={
<Button type="primary">
<PlusOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
try {
const { success, message: errMsg } =
await stockcontrollerCreatestockpoint(values);
if (!success) {
throw new Error(errMsg);
}
tableRef.current?.reload();
message.success('提交成功');
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProForm.Group>
<ProFormText
name="name"
label="名称"
width="lg"
placeholder="请输入名称"
rules={[{ required: true, message: '请输入名称' }]}
/>
<ProFormText
name="location"
label="地址"
width="lg"
placeholder="请输入地址"
rules={[{ required: true, message: '请输入地址' }]}
/>
<ProFormText
name="contactPerson"
label="联系人"
width="lg"
placeholder="请输入联系人"
rules={[{ required: true, message: '请输入联系人' }]}
/>
<ProFormText
name="contactPhone"
label="联系电话"
width="lg"
placeholder="请输入联系电话"
rules={[{ required: true, message: '请输入联系电话' }]}
/>
</ProForm.Group>
</DrawerForm>
);
};
const UpdateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
values: API.StockPoint;
}> = ({ tableRef, values: initialValues }) => {
const { message } = App.useApp();
return (
<DrawerForm<API.UpdateStockPointDTO>
title="编辑"
initialValues={initialValues}
trigger={
<Button type="primary">
<EditOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnClose: true,
}}
onFinish={async (values) => {
try {
const { success, message: errMsg } =
await stockcontrollerUpdatestockpoint(
{ id: initialValues.id as number },
values,
);
if (!success) {
throw new Error(errMsg);
}
message.success('提交成功');
tableRef.current?.reload();
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProForm.Group>
<ProFormText
name="name"
label="名称"
width="lg"
placeholder="请输入名称"
rules={[{ required: true, message: '请输入名称' }]}
/>
<ProFormText
name="location"
label="地址"
width="lg"
placeholder="请输入地址"
rules={[{ required: true, message: '请输入地址' }]}
/>
<ProFormText
name="contactPerson"
label="联系人"
width="lg"
placeholder="请输入联系人"
rules={[{ required: true, message: '请输入联系人' }]}
/>
<ProFormText
name="contactPhone"
label="联系电话"
width="lg"
placeholder="请输入联系电话"
rules={[{ required: true, message: '请输入联系电话' }]}
/>
</ProForm.Group>
</DrawerForm>
);
};
export default ListPage;

82
src/pages/Track/index.tsx Normal file
View File

@ -0,0 +1,82 @@
import {
logisticscontrollerGetlistbytrackingid,
logisticscontrollerGettrackingnumber,
} from '@/servers/api/logistics';
import { SearchOutlined } from '@ant-design/icons';
import { PageContainer, ProFormSelect } from '@ant-design/pro-components';
import { Col, Row } from 'antd';
import { useState } from 'react';
const TrackPage: React.FC = () => {
const [id, setId] = useState<string>();
const [data, setData] = useState([]);
return (
<PageContainer>
<ProFormSelect
showSearch={true}
debounceTime={500}
request={async ({ keyWords }) => {
if (!keyWords || keyWords.length < 3) return [];
const { data: trackList } =
await logisticscontrollerGettrackingnumber({ number: keyWords });
return trackList?.map(
(v: {
tracking_provider: string;
primary_tracking_number: string;
id: string;
}) => {
return {
label: v.tracking_provider + ' ' + v.primary_tracking_number,
value: v.id,
};
},
);
}}
fieldProps={{
prefix: '追踪号',
onChange(value: string) {
setId(value);
},
allowClear: false,
suffixIcon: (
<SearchOutlined
onClick={async (e) => {
if (!id) {
return;
}
const { data } = await logisticscontrollerGetlistbytrackingid({
shipment_id: id,
});
setData(data);
}}
/>
),
}}
/>
<Row>
<Col span={24}></Col>
<Col span={18}></Col>
<Col span={6}></Col>
{data?.orderItem?.map((v: any) => (
<>
<Col span={18}>{v.name}</Col>
<Col span={6}>{v.quantity}</Col>
</>
))}
</Row>
<Row style={{ marginTop: '30px' }}>
<Col span={18}></Col>
<Col span={6}></Col>
{data?.shipmentItem?.map((v: any) => (
<>
<Col span={18}>{v.name}</Col>
<Col span={6}>{v.quantity}</Col>
</>
))}
</Row>
</PageContainer>
);
};
export default TrackPage;

24
src/servers/api/index.ts Normal file
View File

@ -0,0 +1,24 @@
// @ts-ignore
/* eslint-disable */
// API 更新时间:
// API 唯一标识:
import * as logistics from './logistics';
import * as order from './order';
import * as product from './product';
import * as site from './site';
import * as statistics from './statistics';
import * as stock from './stock';
import * as user from './user';
import * as webhook from './webhook';
import * as wpProduct from './wpProduct';
export default {
logistics,
order,
product,
site,
statistics,
stock,
user,
webhook,
wpProduct,
};

View File

@ -0,0 +1,202 @@
// @ts-ignore
/* eslint-disable */
import { request } from 'umi';
/** 此处后端没有提供注释 POST /logistics/createShipment/${param0} */
export async function logisticscontrollerCreateshipment(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.logisticscontrollerCreateshipmentParams,
body: API.ShipmentBookDTO,
options?: { [key: string]: any },
) {
const { orderId: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/logistics/createShipment/${param0}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
params: { ...queryParams },
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /logistics/createShippingAddress */
export async function logisticscontrollerCreateshippingaddress(
body: API.ShippingAddress,
options?: { [key: string]: any },
) {
return request<API.BooleanRes>('/logistics/createShippingAddress', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 DELETE /logistics/delShippingAddress/${param0} */
export async function logisticscontrollerDelshippingaddress(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.logisticscontrollerDelshippingaddressParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/logistics/delShippingAddress/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /logistics/getListByTrackingId */
export async function logisticscontrollerGetlistbytrackingid(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.logisticscontrollerGetlistbytrackingidParams,
options?: { [key: string]: any },
) {
return request<any>('/logistics/getListByTrackingId', {
method: 'POST',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /logistics/getPaymentMethods */
export async function logisticscontrollerGetpaymentmethods(options?: {
[key: string]: any;
}) {
return request<any>('/logistics/getPaymentMethods', {
method: 'POST',
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /logistics/getRateList */
export async function logisticscontrollerGetratelist(
body: API.ShippingDetailsDTO,
options?: { [key: string]: any },
) {
return request<API.RateLitRes>('/logistics/getRateList', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /logistics/getServiceList */
export async function logisticscontrollerGetservicelist(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.logisticscontrollerGetservicelistParams,
options?: { [key: string]: any },
) {
return request<API.ServiceListRes>('/logistics/getServiceList', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /logistics/getShippingAddressList */
export async function logisticscontrollerGetshippingaddresslist(options?: {
[key: string]: any;
}) {
return request<API.ShippingAddressListRes>(
'/logistics/getShippingAddressList',
{
method: 'GET',
...(options || {}),
},
);
}
/** 此处后端没有提供注释 POST /logistics/getTrackingNumber */
export async function logisticscontrollerGettrackingnumber(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.logisticscontrollerGettrackingnumberParams,
options?: { [key: string]: any },
) {
return request<any>('/logistics/getTrackingNumber', {
method: 'POST',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /logistics/list */
export async function logisticscontrollerGetlist(options?: {
[key: string]: any;
}) {
return request<any>('/logistics/list', {
method: 'GET',
...(options || {}),
});
}
/** 此处后端没有提供注释 DELETE /logistics/shipment/${param0} */
export async function logisticscontrollerDelshipment(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.logisticscontrollerDelshipmentParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<any>(`/logistics/shipment/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /logistics/syncServices */
export async function logisticscontrollerSyncservices(options?: {
[key: string]: any;
}) {
return request<API.BooleanRes>('/logistics/syncServices', {
method: 'POST',
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /logistics/toggleActive */
export async function logisticscontrollerToggleactive(
body: Record<string, any>,
options?: { [key: string]: any },
) {
return request<any>('/logistics/toggleActive', {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 PUT /logistics/updateShippingAddress/${param0} */
export async function logisticscontrollerUpdateshippingaddress(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.logisticscontrollerUpdateshippingaddressParams,
body: API.ShippingAddress,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/logistics/updateShippingAddress/${param0}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
params: { ...queryParams },
data: body,
...(options || {}),
});
}

195
src/servers/api/order.ts Normal file
View File

@ -0,0 +1,195 @@
// @ts-ignore
/* eslint-disable */
import { request } from 'umi';
/** 此处后端没有提供注释 GET /order/${param0} */
export async function ordercontrollerGetorderdetail(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.ordercontrollerGetorderdetailParams,
options?: { [key: string]: any },
) {
const { orderId: param0, ...queryParams } = params;
return request<API.OrderDetailRes>(`/order/${param0}`, {
method: 'GET',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 DELETE /order/${param0} */
export async function ordercontrollerDelorder(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.ordercontrollerDelorderParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/order/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /order/createNote */
export async function ordercontrollerCreatenote(
body: API.CreateOrderNoteDTO,
options?: { [key: string]: any },
) {
return request<API.BooleanRes>('/order/createNote', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /order/getOrderByNumber */
export async function ordercontrollerGetorderbynumber(
body: string,
options?: { [key: string]: any },
) {
return request<any>('/order/getOrderByNumber', {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /order/getOrders */
export async function ordercontrollerGetorders(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.ordercontrollerGetordersParams,
options?: { [key: string]: any },
) {
return request<API.OrderListRes>('/order/getOrders', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /order/getOrderSales */
export async function ordercontrollerGetordersales(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.ordercontrollerGetordersalesParams,
options?: { [key: string]: any },
) {
return request<API.OrderSaleListRes>('/order/getOrderSales', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /order/order/cancel/${param0} */
export async function ordercontrollerCancelorder(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.ordercontrollerCancelorderParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<any>(`/order/order/cancel/${param0}`, {
method: 'POST',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /order/order/completed/${param0} */
export async function ordercontrollerCompletedorder(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.ordercontrollerCompletedorderParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<any>(`/order/order/completed/${param0}`, {
method: 'POST',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /order/order/create */
export async function ordercontrollerCreateorder(
body: Record<string, any>,
options?: { [key: string]: any },
) {
return request<any>('/order/order/create', {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /order/order/refund/${param0} */
export async function ordercontrollerRefundorder(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.ordercontrollerRefundorderParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<any>(`/order/order/refund/${param0}`, {
method: 'POST',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 PUT /order/order/status/${param0} */
export async function ordercontrollerChangestatus(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.ordercontrollerChangestatusParams,
body: string,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<any>(`/order/order/status/${param0}`, {
method: 'PUT',
headers: {
'Content-Type': 'text/plain',
},
params: { ...queryParams },
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /order/syncOrder/${param0} */
export async function ordercontrollerSyncorder(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.ordercontrollerSyncorderParams,
options?: { [key: string]: any },
) {
const { siteId: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/order/syncOrder/${param0}`, {
method: 'POST',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /order/syncOrder/${param1}/order/${param0} */
export async function ordercontrollerSyncorderbyid(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.ordercontrollerSyncorderbyidParams,
options?: { [key: string]: any },
) {
const { orderId: param0, siteId: param1, ...queryParams } = params;
return request<API.BooleanRes>(`/order/syncOrder/${param1}/order/${param0}`, {
method: 'POST',
params: { ...queryParams },
...(options || {}),
});
}

329
src/servers/api/product.ts Normal file
View File

@ -0,0 +1,329 @@
// @ts-ignore
/* eslint-disable */
import { request } from 'umi';
/** 此处后端没有提供注释 POST /product/ */
export async function productcontrollerCreateproduct(
body: API.CreateProductDTO,
options?: { [key: string]: any },
) {
return request<API.ProductRes>('/product/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 PUT /product/${param0} */
export async function productcontrollerUpdateproduct(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.productcontrollerUpdateproductParams,
body: API.UpdateProductDTO,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.ProductRes>(`/product/${param0}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
params: { ...queryParams },
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 DELETE /product/${param0} */
export async function productcontrollerDeleteproduct(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.productcontrollerDeleteproductParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/product/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /product/batchSetSku */
export async function productcontrollerBatchsetsku(
body: API.BatchSetSkuDTO,
options?: { [key: string]: any },
) {
return request<API.BooleanRes>('/product/batchSetSku', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /product/categorieAll */
export async function productcontrollerGetcategorieall(options?: {
[key: string]: any;
}) {
return request<any>('/product/categorieAll', {
method: 'GET',
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /product/categories */
export async function productcontrollerGetcategories(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.productcontrollerGetcategoriesParams,
options?: { [key: string]: any },
) {
return request<API.ProductCatListRes>('/product/categories', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /product/category */
export async function productcontrollerCreatecategory(
body: API.CreateCategoryDTO,
options?: { [key: string]: any },
) {
return request<API.ProductCatRes>('/product/category', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 PUT /product/category/${param0} */
export async function productcontrollerUpdatecategory(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.productcontrollerUpdatecategoryParams,
body: API.UpdateCategoryDTO,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.ProductCatRes>(`/product/category/${param0}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
params: { ...queryParams },
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 DELETE /product/category/${param0} */
export async function productcontrollerDeletecategory(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.productcontrollerDeletecategoryParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/product/category/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /product/flavors */
export async function productcontrollerGetflavors(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.productcontrollerGetflavorsParams,
options?: { [key: string]: any },
) {
return request<any>('/product/flavors', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /product/flavors */
export async function productcontrollerCreateflavors(
body: API.CreateFlavorsDTO,
options?: { [key: string]: any },
) {
return request<any>('/product/flavors', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 PUT /product/flavors/${param0} */
export async function productcontrollerUpdateflavors(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.productcontrollerUpdateflavorsParams,
body: API.UpdateFlavorsDTO,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<any>(`/product/flavors/${param0}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
params: { ...queryParams },
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 DELETE /product/flavors/${param0} */
export async function productcontrollerDeleteflavors(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.productcontrollerDeleteflavorsParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/product/flavors/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /product/flavorsAll */
export async function productcontrollerGetflavorsall(options?: {
[key: string]: any;
}) {
return request<any>('/product/flavorsAll', {
method: 'GET',
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /product/list */
export async function productcontrollerGetproductlist(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.productcontrollerGetproductlistParams,
options?: { [key: string]: any },
) {
return request<API.ProductListRes>('/product/list', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /product/search */
export async function productcontrollerSearchproducts(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.productcontrollerSearchproductsParams,
options?: { [key: string]: any },
) {
return request<API.ProductsRes>('/product/search', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /product/sku/${param0} */
export async function productcontrollerProductbysku(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.productcontrollerProductbyskuParams,
options?: { [key: string]: any },
) {
const { sku: param0, ...queryParams } = params;
return request<API.ProductRes>(`/product/sku/${param0}`, {
method: 'GET',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /product/strength */
export async function productcontrollerGetstrength(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.productcontrollerGetstrengthParams,
options?: { [key: string]: any },
) {
return request<any>('/product/strength', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /product/strength */
export async function productcontrollerCreatestrength(
body: API.CreateStrengthDTO,
options?: { [key: string]: any },
) {
return request<any>('/product/strength', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 PUT /product/strength/${param0} */
export async function productcontrollerUpdatestrength(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.productcontrollerUpdatestrengthParams,
body: API.UpdateStrengthDTO,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<any>(`/product/strength/${param0}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
params: { ...queryParams },
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 DELETE /product/strength/${param0} */
export async function productcontrollerDeletestrength(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.productcontrollerDeletestrengthParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/product/strength/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /product/strengthAll */
export async function productcontrollerGetstrengthall(options?: {
[key: string]: any;
}) {
return request<any>('/product/strengthAll', {
method: 'GET',
...(options || {}),
});
}

11
src/servers/api/site.ts Normal file
View File

@ -0,0 +1,11 @@
// @ts-ignore
/* eslint-disable */
import { request } from 'umi';
/** 此处后端没有提供注释 GET /site/all */
export async function sitecontrollerAll(options?: { [key: string]: any }) {
return request<API.WpSitesResponse>('/site/all', {
method: 'GET',
...(options || {}),
});
}

View File

@ -0,0 +1,93 @@
// @ts-ignore
/* eslint-disable */
import { request } from 'umi';
/** 此处后端没有提供注释 POST /statistics/getCustomerOrders */
export async function statisticscontrollerGetcustomerorders(
body: Record<string, any>,
options?: { [key: string]: any },
) {
return request<any>('/statistics/getCustomerOrders', {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /statistics/order */
export async function statisticscontrollerGetorderstatistics(
body: API.OrderStatisticsParams,
options?: { [key: string]: any },
) {
return request<any>('/statistics/order', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /statistics/orderByDate */
export async function statisticscontrollerGetorderbydate(
body: string,
options?: { [key: string]: any },
) {
return request<any>('/statistics/orderByDate', {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /statistics/orderByEmail */
export async function statisticscontrollerGetorderbyemail(
body: string,
options?: { [key: string]: any },
) {
return request<any>('/statistics/orderByEmail', {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /statistics/restocking */
export async function statisticscontrollerRestocking(
body: Record<string, any>,
options?: { [key: string]: any },
) {
return request<any>('/statistics/restocking', {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /statistics/stockForecast */
export async function statisticscontrollerStockforecast(
body: Record<string, any>,
options?: { [key: string]: any },
) {
return request<any>('/statistics/stockForecast', {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
data: body,
...(options || {}),
});
}

284
src/servers/api/stock.ts Normal file
View File

@ -0,0 +1,284 @@
// @ts-ignore
/* eslint-disable */
import { request } from 'umi';
/** 此处后端没有提供注释 GET /stock/ */
export async function stockcontrollerGetstocks(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.stockcontrollerGetstocksParams,
options?: { [key: string]: any },
) {
return request<API.StockListRes>('/stock/', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /stock/cancelTransfer/${param0} */
export async function stockcontrollerCanceltransfer(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.stockcontrollerCanceltransferParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/stock/cancelTransfer/${param0}`, {
method: 'POST',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /stock/lostTransfer/${param0} */
export async function stockcontrollerLosttransfer(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.stockcontrollerLosttransferParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/stock/lostTransfer/${param0}`, {
method: 'POST',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /stock/purchase-order */
export async function stockcontrollerGetpurchaseorders(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.stockcontrollerGetpurchaseordersParams,
options?: { [key: string]: any },
) {
return request<API.PurchaseOrderListRes>('/stock/purchase-order', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /stock/purchase-order */
export async function stockcontrollerCreatepurchaseorder(
body: API.CreatePurchaseOrderDTO,
options?: { [key: string]: any },
) {
return request<API.BooleanRes>('/stock/purchase-order', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 PUT /stock/purchase-order/${param0} */
export async function stockcontrollerUpdatepurchaseorder(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.stockcontrollerUpdatepurchaseorderParams,
body: API.UpdatePurchaseOrderDTO,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/stock/purchase-order/${param0}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
params: { ...queryParams },
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /stock/purchase-order/${param0} */
export async function stockcontrollerReceivepurchaseorder(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.stockcontrollerReceivepurchaseorderParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/stock/purchase-order/${param0}`, {
method: 'POST',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 DELETE /stock/purchase-order/${param0} */
export async function stockcontrollerDelpurchaseorder(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.stockcontrollerDelpurchaseorderParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/stock/purchase-order/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 PUT /stock/receiveTransfer/${param0} */
export async function stockcontrollerUpdatetransfer(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.stockcontrollerUpdatetransferParams,
body: Record<string, any>,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/stock/receiveTransfer/${param0}`, {
method: 'PUT',
headers: {
'Content-Type': 'text/plain',
},
params: { ...queryParams },
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /stock/receiveTransfer/${param0} */
export async function stockcontrollerReceivetransfer(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.stockcontrollerReceivetransferParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/stock/receiveTransfer/${param0}`, {
method: 'POST',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /stock/records */
export async function stockcontrollerGetstockrecords(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.stockcontrollerGetstockrecordsParams,
options?: { [key: string]: any },
) {
return request<API.StockRecordListRes>('/stock/records', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /stock/stock-point */
export async function stockcontrollerGetstockpoints(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.stockcontrollerGetstockpointsParams,
options?: { [key: string]: any },
) {
return request<API.StockPointListRes>('/stock/stock-point', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /stock/stock-point */
export async function stockcontrollerCreatestockpoint(
body: API.CreateStockPointDTO,
options?: { [key: string]: any },
) {
return request<API.BooleanRes>('/stock/stock-point', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 PUT /stock/stock-point/${param0} */
export async function stockcontrollerUpdatestockpoint(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.stockcontrollerUpdatestockpointParams,
body: API.UpdateStockPointDTO,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/stock/stock-point/${param0}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
params: { ...queryParams },
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 DELETE /stock/stock-point/${param0} */
export async function stockcontrollerDelstockpoints(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.stockcontrollerDelstockpointsParams,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/stock/stock-point/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /stock/stock-point/all */
export async function stockcontrollerGetallstockpoints(options?: {
[key: string]: any;
}) {
return request<API.StockPointAllRespone>('/stock/stock-point/all', {
method: 'GET',
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /stock/transfer */
export async function stockcontrollerGettransfers(options?: {
[key: string]: any;
}) {
return request<any>('/stock/transfer', {
method: 'GET',
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /stock/transfer */
export async function stockcontrollerCreatetransfer(
body: Record<string, any>,
options?: { [key: string]: any },
) {
return request<API.BooleanRes>('/stock/transfer', {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /stock/update */
export async function stockcontrollerUpdatestock(
body: API.UpdateStockDTO,
options?: { [key: string]: any },
) {
return request<API.BooleanRes>('/stock/update', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}

1469
src/servers/api/typings.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

74
src/servers/api/user.ts Normal file
View File

@ -0,0 +1,74 @@
// @ts-ignore
/* eslint-disable */
import { request } from 'umi';
/** 此处后端没有提供注释 GET /user/ */
export async function usercontrollerGetuser(options?: { [key: string]: any }) {
return request<any>('/user/', {
method: 'GET',
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /user/add */
export async function usercontrollerAdduser(
body: Record<string, any>,
options?: { [key: string]: any },
) {
return request<any>('/user/add', {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /user/list */
export async function usercontrollerListusers(options?: {
[key: string]: any;
}) {
return request<any>('/user/list', {
method: 'GET',
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /user/login */
export async function usercontrollerLogin(
body: API.LoginDTO,
options?: { [key: string]: any },
) {
return request<API.LoginRes>('/user/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /user/logout */
export async function usercontrollerLogout(options?: { [key: string]: any }) {
return request<API.BooleanRes>('/user/logout', {
method: 'POST',
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /user/toggleActive */
export async function usercontrollerToggleactive(
body: Record<string, any>,
options?: { [key: string]: any },
) {
return request<any>('/user/toggleActive', {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
data: body,
...(options || {}),
});
}

View File

@ -0,0 +1,31 @@
// @ts-ignore
/* eslint-disable */
import { request } from 'umi';
/** 此处后端没有提供注释 GET /webhook/ */
export async function webhookcontrollerTest(options?: { [key: string]: any }) {
return request<any>('/webhook/', {
method: 'GET',
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /webhook/woocommerce */
export async function webhookcontrollerHandlewoowebhook(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.webhookcontrollerHandlewoowebhookParams,
body: Record<string, any>,
options?: { [key: string]: any },
) {
return request<any>('/webhook/woocommerce', {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
params: {
...params,
},
data: body,
...(options || {}),
});
}

View File

@ -0,0 +1,100 @@
// @ts-ignore
/* eslint-disable */
import { request } from 'umi';
/** 此处后端没有提供注释 PUT /wp_product/${param0}/constitution */
export async function wpproductcontrollerSetconstitution(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.wpproductcontrollerSetconstitutionParams,
body: API.SetConstitutionDTO,
options?: { [key: string]: any },
) {
const { id: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/wp_product/${param0}/constitution`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
params: { ...queryParams },
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /wp_product/list */
export async function wpproductcontrollerGetwpproducts(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.wpproductcontrollerGetwpproductsParams,
options?: { [key: string]: any },
) {
return request<API.WpProductListRes>('/wp_product/list', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 PUT /wp_product/siteId/${param1}/products/${param0} */
export async function wpproductcontrollerUpdateproduct(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.wpproductcontrollerUpdateproductParams,
body: API.UpdateWpProductDTO,
options?: { [key: string]: any },
) {
const { productId: param0, siteId: param1, ...queryParams } = params;
return request<API.BooleanRes>(
`/wp_product/siteId/${param1}/products/${param0}`,
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
params: { ...queryParams },
data: body,
...(options || {}),
},
);
}
/** 此处后端没有提供注释 PUT /wp_product/siteId/${param2}/products/${param1}/variations/${param0} */
export async function wpproductcontrollerUpdatevariation(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.wpproductcontrollerUpdatevariationParams,
body: API.UpdateVariationDTO,
options?: { [key: string]: any },
) {
const {
variationId: param0,
productId: param1,
siteId: param2,
...queryParams
} = params;
return request<any>(
`/wp_product/siteId/${param2}/products/${param1}/variations/${param0}`,
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
params: { ...queryParams },
data: body,
...(options || {}),
},
);
}
/** 此处后端没有提供注释 POST /wp_product/sync/${param0} */
export async function wpproductcontrollerSyncproducts(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.wpproductcontrollerSyncproductsParams,
options?: { [key: string]: any },
) {
const { siteId: param0, ...queryParams } = params;
return request<API.BooleanRes>(`/wp_product/sync/${param0}`, {
method: 'POST',
params: { ...queryParams },
...(options || {}),
});
}

61
src/utils/format.ts Normal file
View File

@ -0,0 +1,61 @@
import { ProSchemaValueEnumObj } from '@ant-design/pro-components';
import { BaseType } from 'typings';
/**
* valueEnum
* @param array
* @param options
* @returns valueEnum
*/
export function transformToValueEnum<T>(
array: T[],
options: BaseType.EnumTransformOptions = {
value: 'id',
label: 'name',
status: 'status',
color: 'color',
},
): ProSchemaValueEnumObj {
const { value, label, status, color } = options;
return array.reduce((acc, item: any) => {
const key = String(item[value]);
acc[key] = {
text: String(item[label]),
...(status && item[status] ? { status: String(item[status]) } : {}),
...(color && item[color] ? { color: String(item[color]) } : {}),
};
return acc;
}, {} as ProSchemaValueEnumObj);
}
export function formatSource(type: string | undefined, utm?: string) {
if (!type) return 'Unknon';
if (type === 'admin') return 'Web Admin';
if (type === 'typein') return 'Direct';
if (type === 'utm') return 'Source: ' + utm;
return type + ': ' + utm;
}
export function formatShipmentState(state: string) {
switch (state) {
case 'draft':
return '草稿';
case 'waiting-for-scheduling':
return '等待调度';
case 'waiting-for-transit':
return '等待运输';
case 'in-transit':
return '运输中';
case 'delivered':
return '已到达';
case 'exception':
return '异常';
case 'missing':
return '丢失';
case 'cancelled':
return '取消';
default:
return '';
}
}

25
src/utils/util.ts Normal file
View File

@ -0,0 +1,25 @@
import printJS from 'print-js';
export async function printPDF(urls: string[]) {
let index = 0;
function next() {
if (index >= urls.length) return;
printJS({
printable: urls[index],
type: 'pdf',
showModal: true,
onPrintDialogClose: () => {
index++;
setTimeout(next, 1000); // 等待下一个
},
onError: (err) => {
console.error('打印失败:', err);
index++;
next();
},
});
}
next();
}

3
tsconfig.json Normal file
View File

@ -0,0 +1,3 @@
{
"extends": "./src/.umi/tsconfig.json"
}

16
typings.d.ts vendored Normal file
View File

@ -0,0 +1,16 @@
import '@umijs/max/typings';
declare namespace BaseType {
type EnumTransformOptions {
value: string; // 用于作为 value 的字段名
label: string; // 用于作为 text 的字段名
status?: string | undefined; // 可选:用于设置状态的字段名
color?: string | undefined; // 可选:用于设置颜色的字段名
}
}
declare global {
const UMI_APP_API_URL: string;
}