From a500b88b31fa9f583bb9383f649df5bbf3e7568c Mon Sep 17 00:00:00 2001 From: cll <931958862@qq.com> Date: Thu, 22 May 2025 15:09:09 +0800 Subject: [PATCH] init --- .eslintrc.js | 3 + .gitignore | 16 + .npmrc | 2 + .openapi2tsrc.ts | 4 + .prettierignore | 3 + .prettierrc | 8 + .stylelintrc.js | 3 + .umirc.ts | 172 ++ mock/userAPI.ts | 20 + src/access.ts | 9 + src/app.tsx | 128 + src/assets/.gitkeep | 0 src/components/InternationalPhoneInput.tsx | 84 + src/constants/index.ts | 93 + src/models/global.ts | 13 + src/pages/Home/index.less | 3 + src/pages/Home/index.tsx | 14 + src/pages/Login/index.tsx | 116 + src/pages/Logistics/Address/index.tsx | 405 ++++ src/pages/Logistics/List/index.tsx | 146 ++ src/pages/Logistics/Services/index.tsx | 110 + src/pages/Order/List/index.tsx | 2051 +++++++++++++++++ src/pages/Organiza/User/index.tsx | 125 + src/pages/Product/Category/index.tsx | 210 ++ src/pages/Product/Flavors/index.tsx | 208 ++ src/pages/Product/List/index.tsx | 232 ++ src/pages/Product/Strength/index.tsx | 206 ++ src/pages/Product/WpList/index.tsx | 540 +++++ src/pages/Statistics/Customer/index.tsx | 236 ++ .../Statistics/InventoryForecast/index.tsx | 201 ++ src/pages/Statistics/Order/index.tsx | 887 +++++++ src/pages/Statistics/Restocking/index.tsx | 187 ++ src/pages/Statistics/Sales/index.tsx | 185 ++ src/pages/Stock/List/index.tsx | 85 + src/pages/Stock/PurchaseOrder/index.tsx | 682 ++++++ src/pages/Stock/Record/index.tsx | 81 + src/pages/Stock/Transfer/index.tsx | 688 ++++++ src/pages/Stock/Warehouse/index.tsx | 239 ++ src/pages/Track/index.tsx | 82 + src/servers/api/index.ts | 24 + src/servers/api/logistics.ts | 202 ++ src/servers/api/order.ts | 195 ++ src/servers/api/product.ts | 329 +++ src/servers/api/site.ts | 11 + src/servers/api/statistics.ts | 93 + src/servers/api/stock.ts | 284 +++ src/servers/api/typings.d.ts | 1469 ++++++++++++ src/servers/api/user.ts | 74 + src/servers/api/webhook.ts | 31 + src/servers/api/wpProduct.ts | 100 + src/utils/format.ts | 61 + src/utils/util.ts | 25 + tsconfig.json | 3 + typings.d.ts | 16 + 54 files changed, 11394 insertions(+) create mode 100644 .eslintrc.js create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 .openapi2tsrc.ts create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 .stylelintrc.js create mode 100644 .umirc.ts create mode 100644 mock/userAPI.ts create mode 100644 src/access.ts create mode 100644 src/app.tsx create mode 100644 src/assets/.gitkeep create mode 100644 src/components/InternationalPhoneInput.tsx create mode 100644 src/constants/index.ts create mode 100644 src/models/global.ts create mode 100644 src/pages/Home/index.less create mode 100644 src/pages/Home/index.tsx create mode 100644 src/pages/Login/index.tsx create mode 100644 src/pages/Logistics/Address/index.tsx create mode 100644 src/pages/Logistics/List/index.tsx create mode 100644 src/pages/Logistics/Services/index.tsx create mode 100644 src/pages/Order/List/index.tsx create mode 100644 src/pages/Organiza/User/index.tsx create mode 100644 src/pages/Product/Category/index.tsx create mode 100644 src/pages/Product/Flavors/index.tsx create mode 100644 src/pages/Product/List/index.tsx create mode 100644 src/pages/Product/Strength/index.tsx create mode 100644 src/pages/Product/WpList/index.tsx create mode 100644 src/pages/Statistics/Customer/index.tsx create mode 100644 src/pages/Statistics/InventoryForecast/index.tsx create mode 100644 src/pages/Statistics/Order/index.tsx create mode 100644 src/pages/Statistics/Restocking/index.tsx create mode 100644 src/pages/Statistics/Sales/index.tsx create mode 100644 src/pages/Stock/List/index.tsx create mode 100644 src/pages/Stock/PurchaseOrder/index.tsx create mode 100644 src/pages/Stock/Record/index.tsx create mode 100644 src/pages/Stock/Transfer/index.tsx create mode 100644 src/pages/Stock/Warehouse/index.tsx create mode 100644 src/pages/Track/index.tsx create mode 100644 src/servers/api/index.ts create mode 100644 src/servers/api/logistics.ts create mode 100644 src/servers/api/order.ts create mode 100644 src/servers/api/product.ts create mode 100644 src/servers/api/site.ts create mode 100644 src/servers/api/statistics.ts create mode 100644 src/servers/api/stock.ts create mode 100644 src/servers/api/typings.d.ts create mode 100644 src/servers/api/user.ts create mode 100644 src/servers/api/webhook.ts create mode 100644 src/servers/api/wpProduct.ts create mode 100644 src/utils/format.ts create mode 100644 src/utils/util.ts create mode 100644 tsconfig.json create mode 100644 typings.d.ts diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..85ba500 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: require.resolve('@umijs/max/eslint'), +}; diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57ceb29 --- /dev/null +++ b/.gitignore @@ -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 \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..8f46dd2 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +registry=https://registry.npmmirror.com/ + diff --git a/.openapi2tsrc.ts b/.openapi2tsrc.ts new file mode 100644 index 0000000..27c6e5c --- /dev/null +++ b/.openapi2tsrc.ts @@ -0,0 +1,4 @@ +export default { + schemaPath: 'http://127.0.0.1:7001/swagger-ui/index.json', + serversPath: './src/servers', +}; diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..5892e28 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +node_modules +.umi +.umi-production diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..70767cd --- /dev/null +++ b/.prettierrc @@ -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"] +} diff --git a/.stylelintrc.js b/.stylelintrc.js new file mode 100644 index 0000000..08bc02c --- /dev/null +++ b/.stylelintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: require.resolve('@umijs/max/stylelint'), +}; diff --git a/.umirc.ts b/.umirc.ts new file mode 100644 index 0000000..9073e10 --- /dev/null +++ b/.umirc.ts @@ -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', +}); diff --git a/mock/userAPI.ts b/mock/userAPI.ts new file mode 100644 index 0000000..7ef8011 --- /dev/null +++ b/mock/userAPI.ts @@ -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, + }); + }, +}; diff --git a/src/access.ts b/src/access.ts new file mode 100644 index 0000000..fbe171f --- /dev/null +++ b/src/access.ts @@ -0,0 +1,9 @@ +export default (initialState: any) => { + const canSeeSuper = initialState?.user?.isSuper; + const canSeeAdmin = + initialState?.user?.isSuper || initialState?.user?.isAdmin; + return { + canSeeSuper, + canSeeAdmin, + }; +}; diff --git a/src/app.tsx b/src/app.tsx new file mode 100644 index 0000000..ad17b86 --- /dev/null +++ b/src/app.tsx @@ -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; + 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: , + onClick: async () => { + //TODO 清理服务器登陆状态 + localStorage.removeItem('token'); + history.push('/login'); + }, + }, + ]; + + return { + menu: { + locale: false, + }, + layout: 'mix', + actionsRender: () => ( + +
+ } /> + {initialState?.name} +
+
+ ), + }; +}; + +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 ( + + {container} + + ); +} diff --git a/src/assets/.gitkeep b/src/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/components/InternationalPhoneInput.tsx b/src/components/InternationalPhoneInput.tsx new file mode 100644 index 0000000..8241636 --- /dev/null +++ b/src/components/InternationalPhoneInput.tsx @@ -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 = ({ + 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 = (e) => { + triggerChange({ phone: e.target.value }); + }; + + return ( + + + + + {/* 添加更多国家代码 */} + + } + value={phone} + onChange={onPhoneChange} + placeholder="请输入联系电话" + /> + ); +}; + +export default InternationalPhoneInput; diff --git a/src/constants/index.ts b/src/constants/index.ts new file mode 100644 index 0000000..0360a09 --- /dev/null +++ b/src/constants/index.ts @@ -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', + }, +}; diff --git a/src/models/global.ts b/src/models/global.ts new file mode 100644 index 0000000..708ccff --- /dev/null +++ b/src/models/global.ts @@ -0,0 +1,13 @@ +// 全局共享数据示例 +import { DEFAULT_NAME } from '@/constants'; +import { useState } from 'react'; + +const useUser = () => { + const [name, setName] = useState(DEFAULT_NAME); + return { + name, + setName, + }; +}; + +export default useUser; diff --git a/src/pages/Home/index.less b/src/pages/Home/index.less new file mode 100644 index 0000000..06fdb67 --- /dev/null +++ b/src/pages/Home/index.less @@ -0,0 +1,3 @@ +.container { + padding-top: 80px; +} diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx new file mode 100644 index 0000000..2b2cf42 --- /dev/null +++ b/src/pages/Home/index.tsx @@ -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 ( + +
+
+ ); +}; + +export default HomePage; diff --git a/src/pages/Login/index.tsx b/src/pages/Login/index.tsx new file mode 100644 index 0000000..14bc2e3 --- /dev/null +++ b/src/pages/Login/index.tsx @@ -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 ( +
+ + + ), + }} + placeholder={'请输入用户名!'} + rules={[ + { + required: true, + message: '请输入用户名!', + }, + ]} + /> + + ), + }} + placeholder={'请输入密码!'} + rules={[ + { + required: true, + message: '请输入密码!', + }, + ]} + /> + {/*
+ + 自动登录 + + + 忘记密码 + +
*/} +
+
+ ); +}; + +export default () => { + return ( + + + + ); +}; diff --git a/src/pages/Logistics/Address/index.tsx b/src/pages/Logistics/Address/index.tsx new file mode 100644 index 0000000..375703b --- /dev/null +++ b/src/pages/Logistics/Address/index.tsx @@ -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(); + const { message } = App.useApp(); + + const columns: ProColumns[] = [ + { + 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) => ( + <> + + + { + 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); + } + }} + > + + + + ), + }, + ]; + return ( + + []} + request={async () => { + const { data, success } = + await logisticscontrollerGetshippingaddresslist(); + if (success) { + return { + data: data, + }; + } + return { + data: [], + }; + }} + columns={columns} + /> + + ); +}; + +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; +}> = ({ tableRef }) => { + const { message } = App.useApp(); + return ( + + + 新建 + + } + 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); + } + }} + > + + { + const { data = [] } = await stockcontrollerGetallstockpoints(); + return data.map((item) => ({ + label: item.name, + value: item.id, + })); + }} + /> + + + + + + + ); +}; + +const UpdateForm: React.FC<{ + tableRef: React.MutableRefObject; + value: API.ShippingAddress; +}> = ({ tableRef, value }) => { + const { message } = App.useApp(); + const { + id, + phone_number, + phone_number_country, + phone_number_extension, + ...initialValue + } = value; + return ( + + + 编辑 + + } + 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, + }, + }} + > + + { + const { data = [] } = await stockcontrollerGetallstockpoints(); + return data.map((item) => ({ + label: item.name, + value: item.id, + })); + }} + /> + + + + + + + ); +}; + +export default ListPage; diff --git a/src/pages/Logistics/List/index.tsx b/src/pages/Logistics/List/index.tsx new file mode 100644 index 0000000..b2d6176 --- /dev/null +++ b/src/pages/Logistics/List/index.tsx @@ -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(); + const { message } = App.useApp(); + const [selectedRows, setSelectedRows] = useState([]); + + const columns: ProColumns[] = [ + { + 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} + { + 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 ( + + ); + }, + }, + ]; + + const handleBatchPrint = async () => { + if (selectedRows.length === 0) { + message.warning('请选择要打印的项'); + return; + } + await printPDF( + selectedRows.map((row) => row.labels[row.labels.length - 1].url), + ); + + setSelectedRows([]); + }; + return ( + + { + 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 ( + + ); + }} + /> + + ); +}; +export default ListPage; diff --git a/src/pages/Logistics/Services/index.tsx b/src/pages/Logistics/Services/index.tsx new file mode 100644 index 0000000..79f1594 --- /dev/null +++ b/src/pages/Logistics/Services/index.tsx @@ -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(); + const { message } = App.useApp(); + + const columns: ProColumns[] = [ + { + title: '服务商 ID', + dataIndex: 'id', + hideInSearch: true, + }, + { + title: '运营商名称', + dataIndex: 'carrier_name', + }, + { + title: '服务商名称', + dataIndex: 'service_name', + hideInSearch: true, + }, + { + title: '启用', + dataIndex: 'isActive', + valueType: 'switch', + render(_, record) { + return ( + { + 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 ( + + [ + , + ]} + 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} + /> + + ); +}; + +export default ListPage; diff --git a/src/pages/Order/List/index.tsx b/src/pages/Order/List/index.tsx new file mode 100644 index 0000000..45d85df --- /dev/null +++ b/src/pages/Order/List/index.tsx @@ -0,0 +1,2051 @@ +import InternationalPhoneInput from '@/components/InternationalPhoneInput'; +import { ORDER_STATUS_ENUM } from '@/constants'; +import { + logisticscontrollerCreateshipment, + logisticscontrollerDelshipment, + logisticscontrollerGetpaymentmethods, + logisticscontrollerGetratelist, + logisticscontrollerGetshippingaddresslist, +} from '@/servers/api/logistics'; +import { + ordercontrollerCancelorder, + ordercontrollerChangestatus, + ordercontrollerCompletedorder, + ordercontrollerCreatenote, + ordercontrollerCreateorder, + ordercontrollerGetorderbynumber, + ordercontrollerGetorderdetail, + ordercontrollerGetorders, + ordercontrollerRefundorder, + ordercontrollerSyncorder, + ordercontrollerSyncorderbyid, +} from '@/servers/api/order'; +import { productcontrollerSearchproducts } from '@/servers/api/product'; +import { sitecontrollerAll } from '@/servers/api/site'; +import { stockcontrollerGetallstockpoints } from '@/servers/api/stock'; +import { formatShipmentState, formatSource } from '@/utils/format'; +import { + CodeSandboxOutlined, + CopyOutlined, + DeleteFilled, + DownOutlined, + FileDoneOutlined, + SyncOutlined, + TagsOutlined, +} from '@ant-design/icons'; +import { + ActionType, + DrawerForm, + ModalForm, + PageContainer, + ProColumns, + ProDescriptions, + ProForm, + ProFormDatePicker, + ProFormDependency, + ProFormDigit, + ProFormInstance, + ProFormItem, + ProFormList, + ProFormRadio, + ProFormSelect, + ProFormText, + ProFormTextArea, + ProTable, +} from '@ant-design/pro-components'; +import { + App, + Button, + Card, + Col, + Divider, + Drawer, + Dropdown, + Empty, + Popconfirm, + Radio, + Row, + Space, + Tabs, + TabsProps, +} from 'antd'; +import dayjs from 'dayjs'; +import React, { useMemo, useRef, useState } from 'react'; + +const ListPage: React.FC = () => { + const actionRef = useRef(); + const [activeKey, setActiveKey] = useState('all'); + const [count, setCount] = useState([]); + const tabs: TabsProps['items'] = useMemo(() => { + const total = count.reduce((acc, cur) => acc + Number(cur.count), 0); + const tabs = [ + { + key: 'pending', + label: '待确认', + }, + { + key: 'processing', + label: '待发货', + }, + { + key: 'completed', + label: '已完成', + }, + { + key: 'cancelled', + label: '已取消', + }, + { + key: 'refunded', + label: '已退款', + }, + { + key: 'failed', + label: '失败', + }, + { + key: 'after_sale_pending', + label: '售后处理中', + }, + { + key: 'pending_reshipment', + label: '待补发', + }, + // { + // key: 'pending_refund', + // label: '待退款', + // }, + ].map((v) => { + const number = count.find((el) => el.status === v.key)?.count || '0'; + return { + label: `${v.label}(${number})`, + key: v.key, + }; + }); + + return [ + { + key: 'all', + label: `全部(${total})`, + }, + ...tabs, + ]; + }, [count]); + const { message } = App.useApp(); + + const columns: ProColumns[] = [ + { + title: 'ID', + dataIndex: 'id', + hideInSearch: true, + }, + { + title: '日期', + dataIndex: 'date', + hideInTable: true, + valueType: 'dateRange', + }, + { + title: '订单号', + dataIndex: 'externalOrderId', + }, + { + title: '站点', + dataIndex: 'siteId', + valueType: 'select', + request: async () => { + const { data = [] } = await sitecontrollerAll(); + return data.map((item) => ({ + label: item.siteName, + value: item.id, + })); + }, + }, + { + title: '订单包含', + dataIndex: 'keyword', + hideInTable: true, + }, + { + title: '订单日期', + dataIndex: 'date_created', + hideInSearch: true, + valueType: 'dateTime', + }, + { + title: '金额', + dataIndex: 'total', + hideInSearch: true, + }, + { + title: '总订单数', + dataIndex: 'order_count', + hideInSearch: true, + }, + { + title: '总订单金额', + dataIndex: 'total_spent', + hideInSearch: true, + }, + { + title: '客户邮箱', + dataIndex: 'customer_email', + }, + { + title: '州', + hideInSearch: true, + render: (_, record) => record.shipping?.state || record.billing?.state, + }, + { + title: '状态', + dataIndex: 'orderStatus', + hideInSearch: true, + valueType: 'select', + valueEnum: ORDER_STATUS_ENUM, + }, + { + title: '物流', + dataIndex: 'shipmentList', + hideInSearch: true, + render: (_, record) => { + return ( +
+ {record?.shipmentList?.map((item) => { + if (!item) return; + return ( +
+ {item.tracking_provider}:{item.primary_tracking_number} ( + {formatShipmentState(item.state)}) +
+ ); + })} +
+ ); + }, + }, + { + title: 'IP', + dataIndex: 'customer_ip_address', + hideInSearch: true, + }, + { + title: '设备', + dataIndex: 'device_type', + hideInSearch: true, + }, + { + title: '来源', + hideInSearch: true, + render: (_, record) => + formatSource(record.source_type, record.utm_source), + }, + { + title: '客户备注', + dataIndex: 'customer_note', + hideInSearch: true, + }, + { + title: '操作', + dataIndex: 'option', + valueType: 'option', + fixed: 'right', + width: '200', + render: (_, record) => { + return ( + <> + {['processing', 'pending_reshipment'].includes( + record.orderStatus, + ) ? ( + <> + + + + ) : ( + <> + )} + + + { + try { + const { success, message: errMsg } = + await ordercontrollerSyncorderbyid({ + siteId: record.siteId as string, + orderId: record.externalOrderId as string, + }); + if (!success) { + throw new Error(errMsg); + } + message.success('同步成功'); + actionRef.current?.reload(); + } catch (error) { + message.error(error?.message || '同步失败'); + } + }} + > + 同步订单 + + ), + style: { + display: [ + 'after_sale_pending', + 'pending_reshipment', + ].includes(record.orderStatus) + ? 'none' + : 'block', + }, + }, + { + key: 'note', + label: , + }, + { + key: 'cancel', + label: ( + { + try { + const { success, message: errMsg } = + await ordercontrollerChangestatus( + { + id: record.id, + }, + { + status: 'after_sale_pending', + }, + ); + if (!success) { + throw new Error(errMsg); + } + actionRef.current?.reload(); + } catch (error: any) { + message.error(error.message); + } + }} + > + + + ), + style: { + display: [ + 'processing', + 'pending_reshipment', + 'completed', + 'pending_refund', + ].includes(record.orderStatus) + ? 'block' + : 'none', + }, + }, + ], + }} + > + e.preventDefault()}> + + 更多 + + + + + + ); + }, + }, + ]; + return ( + + + [ + , + , + ]} + request={async ({ date, ...param }) => { + if (param.status === 'all') { + delete param.status; + } + if (date) { + const [startDate, endDate] = date; + param.startDate = `${startDate} 00:00:00`; + param.endDate = `${endDate} 23:59:59`; + } + const { data, success } = await ordercontrollerGetorders(param); + if (success) { + setCount(data?.count || []); + return { + total: data?.total || 0, + data: data?.items || [], + }; + } + return { + data: [], + }; + }} + columns={columns} + /> + + ); +}; + +const SyncForm: React.FC<{ + tableRef: React.MutableRefObject; +}> = ({ tableRef }) => { + const { message } = App.useApp(); + return ( + + title="同步订单" + trigger={ + + } + autoFocusFirstInput + drawerProps={{ + destroyOnClose: true, + }} + onFinish={async (values) => { + try { + const { success, message: errMsg } = await ordercontrollerSyncorder( + values, + ); + if (!success) { + throw new Error(errMsg); + } + message.success('同步成功'); + tableRef.current?.reload(); + return true; + } catch (error: any) { + message.error(error.message); + } + }} + > + + { + const { data = [] } = await sitecontrollerAll(); + return data.map((item) => ({ + label: item.siteName, + value: item.id, + })); + }} + /> + + + ); +}; + +const Detail: React.FC<{ + tableRef: React.MutableRefObject; + orderId: number; + record: API.Order; +}> = ({ tableRef, orderId, record }) => { + const [visiable, setVisiable] = useState(false); + const { message } = App.useApp(); + const ref = useRef(); + + const initRequest = async () => { + const { data, success }: API.OrderDetailRes = + await ordercontrollerGetorderdetail({ + orderId, + }); + if (!success || !data) return { data: {} }; + data.sales = data.sales?.reduce( + (acc: API.OrderSale[], cur: API.OrderSale) => { + let idx = acc.findIndex((v: any) => v.productId === cur.productId); + if (idx === -1) { + acc.push(cur); + } else { + acc[idx].quantity += cur.quantity; + } + return acc; + }, + [], + ); + return { + data, + }; + }; + + return ( + <> + + setVisiable(false)} + footer={[ + , + ...(['after_sale_pending', 'pending_reshipment'].includes( + record.orderStatus, + ) + ? [] + : [ + , + , + ]), + // ...(['processing', 'pending_reshipment'].includes(record.orderStatus) + // ? [ + // , + // , + // ] + // : []), + ...([ + 'processing', + 'pending_reshipment', + 'completed', + 'pending_refund', + ].includes(record.orderStatus) + ? [ + , + { + try { + const { success, message: errMsg } = + await ordercontrollerChangestatus( + { + id: record.id, + }, + { + status: 'after_sale_pending', + }, + ); + if (!success) { + throw new Error(errMsg); + } + tableRef.current?.reload(); + } catch (error: any) { + message.error(error.message); + } + }} + > + + , + ] + : []), + ...(record.orderStatus === 'after_sale_pending' + ? [ + , + { + try { + const { success, message: errMsg } = + await ordercontrollerCancelorder({ + id: record.id, + }); + if (!success) { + throw new Error(errMsg); + } + tableRef.current?.reload(); + } catch (error: any) { + message.error(error.message); + } + }} + > + + , + , + { + try { + const { success, message: errMsg } = + await ordercontrollerRefundorder({ + id: record.id, + }); + if (!success) { + throw new Error(errMsg); + } + tableRef.current?.reload(); + } catch (error: any) { + message.error(error.message); + } + }} + > + + , + , + { + try { + const { success, message: errMsg } = + await ordercontrollerCompletedorder({ + id: record.id, + }); + if (!success) { + throw new Error(errMsg); + } + tableRef.current?.reload(); + } catch (error: any) { + message.error(error.message); + } + }} + > + + , + , + { + try { + const { success, message: errMsg } = + await ordercontrollerChangestatus( + { + id: record.id, + }, + { + status: 'pending_reshipment', + }, + ); + if (!success) { + throw new Error(errMsg); + } + tableRef.current?.reload(); + } catch (error: any) { + message.error(error.message); + } + }} + > + + , + ] + : []), + ]} + > + + { + const { data = [] } = await sitecontrollerAll(); + return data.map((item) => ({ + label: item.siteName, + value: item.id, + })); + }} + /> + + + + + + + + + formatSource(record.source_type, record.utm_source) + } + /> + + + + { + return ( +
+
+ company: + + {record?.shipping?.company || + record?.billing?.company || + '-'} + +
+
+ first_name: + + {record?.shipping?.first_name || + record?.billing?.first_name || + '-'} + +
+
+ last_name: + + {record?.shipping?.last_name || + record?.billing?.last_name || + '-'} + +
+
+ country: + + {record?.shipping?.country || + record?.billing?.country || + '-'} + +
+
+ state: + + {record?.shipping?.state || record?.billing?.state || '-'} + +
+
+ city: + + {record?.shipping?.city || record?.billing?.city || '-'} + +
+
+ postcode: + + {record?.shipping?.postcode || + record?.billing?.postcode || + '-'} + +
+
+ phone: + + {record?.shipping?.phone || record?.billing?.phone || '-'} + +
+
+ address_1: + + {record?.shipping?.address_1 || + record?.billing?.address_1 || + '-'} + +
+
+ ); + }} + /> + { + return ( +
    + {record?.items?.map((item: any) => ( +
  • + {item.name}:{item.quantity} +
  • + ))} +
+ ); + }} + /> + { + return ( +
    + {record?.sales?.map((item: any) => ( +
  • + {item.name}:{item.quantity} +
  • + ))} +
+ ); + }} + /> + { + if (!record.notes || record.notes.length === 0) + return ; + return ( +
+ {record.notes.map((note: any) => ( +
+
+ {note.username} + {note.createdAt} +
+
{note.content}
+
+ ))} +
+ ); + }} + /> + { + if (!record.shipment || record.shipment.length === 0) { + return ; + } + return ( +
+ {record.shipment.map((v) => ( + + {v.tracking_provider} + {v.primary_tracking_number} + { + try { + await navigator.clipboard.writeText( + v.tracking_url, + ); + message.success('复制成功!'); + } catch (err) { + message.error('复制失败!'); + } + }} + /> + + } + actions={ + v.state === 'waiting-for-scheduling' || + v.state === 'waiting-for-transit' + ? [ + { + try { + const { success, message: errMsg } = + await logisticscontrollerDelshipment({ + id: v.id, + }); + if (!success) { + throw new Error(errMsg); + } + tableRef.current?.reload(); + initRequest(); + } catch (error: any) { + message.error(error.message); + } + }} + > + + 取消运单 + , + ] + : [] + } + > +
订单号: {v?.orderIds?.join(',')}
+ {v?.items?.map((item) => ( +
+ {item.name}: {item.quantity} +
+ ))} +
+ ))} +
+ ); + }} + /> +
+
+ + ); +}; + +const OrderNote: React.FC<{ + id: number; + descRef?: React.MutableRefObject; +}> = ({ id, descRef }) => { + const { message } = App.useApp(); + return ( + + + 备注 + + } + onFinish={async (values: any) => { + try { + const { success, message: errMsg } = await ordercontrollerCreatenote({ + ...values, + orderId: id, + }); + if (!success) { + throw new Error(errMsg); + } + descRef?.current?.reload(); + message.success('提交成功'); + return true; + } catch (error: any) { + message.error(error.message); + } + }} + > + + + ); +}; + +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 Shipping: React.FC<{ + id: number; + tableRef?: React.MutableRefObject; + descRef?: React.MutableRefObject; + reShipping?: boolean; +}> = ({ id, tableRef, descRef, reShipping = false }) => { + const [options, setOptions] = useState([]); + const formRef = useRef(); + + const [rates, setRates] = useState([]); + const [ratesLoading, setRatesLoading] = useState(false); + const { message } = App.useApp(); + const [serviceType, setServiceType] = useState(''); + + return ( + + + 创建运单 + + } + request={async () => { + const { data, success }: API.OrderDetailRes = + await ordercontrollerGetorderdetail({ + orderId: id, + }); + if (!success || !data) return {}; + data.sales = data.sales?.reduce( + (acc: API.OrderSale[], cur: API.OrderSale) => { + let idx = acc.findIndex((v: any) => v.productId === cur.productId); + if (idx === -1) { + acc.push(cur); + } else { + acc[idx].quantity += cur.quantity; + } + return acc; + }, + [], + ); + setOptions( + data.sales?.map((item) => ({ + label: item.name, + value: item.sku, + })) || [], + ); + if (reShipping) data.sales = [{}]; + let shipmentInfo = localStorage.getItem('shipmentInfo'); + if (shipmentInfo) shipmentInfo = JSON.parse(shipmentInfo); + return { + ...data, + payment_method_id: shipmentInfo?.payment_method_id, + stockPointId: shipmentInfo?.stockPointId, + details: { + destination: { + name: data?.shipping?.company || data?.billing?.company || ' ', + address: { + address_line_1: + data?.shipping?.address_1 || data?.billing?.address_1, + city: data?.shipping?.city || data?.billing?.city, + region: data?.shipping?.state || data?.billing?.state, + postal_code: + data?.shipping?.postcode || data?.billing?.postcode, + }, + contact_name: + data?.shipping?.first_name || data?.shipping?.last_name + ? `${data?.shipping?.first_name} ${data?.shipping?.last_name}` + : `${data?.billing?.first_name} ${data?.billing?.last_name}`, + phone_number: { + phone: data?.shipping?.phone || data?.billing?.phone, + }, + email_addresses: data?.shipping?.email || data?.billing?.email, + signature_requirement: 'not-required', + }, + origin: { + name: data?.siteName, + email_addresses: data?.email, + contact_name: data?.siteName, + phone_number: shipmentInfo?.phone_number, + address: { + region: shipmentInfo?.region, + city: shipmentInfo?.city, + postal_code: shipmentInfo?.postal_code, + address_line_1: shipmentInfo?.address_line_1, + }, + }, + packaging_type: 'package', + expected_ship_date: dayjs(), + packaging_properties: { + packages: [ + { + measurements: { + weight: { + unit: 'lb', + value: 1, + }, + cuboid: { + unit: 'in', + l: 6, + w: 4, + h: 4, + }, + }, + description: 'food', + }, + ], + }, + }, + }; + }} + onFinish={async ({ customer_note, notes, items, details, ...data }) => { + details.origin.email_addresses = + details.origin.email_addresses.split(','); + details.destination.email_addresses = + details.destination.email_addresses.split(','); + details.destination.phone_number.number = + details.destination.phone_number.phone; + details.origin.phone_number.number = details.origin.phone_number.phone; + try { + const { success, message: errMsg } = + await logisticscontrollerCreateshipment( + { orderId: id }, + { + service_type: serviceType, + details, + ...data, + }, + ); + if (!success) throw new Error(errMsg); + message.success('创建成功'); + tableRef?.current?.reload(); + descRef?.current?.reload(); + + localStorage.setItem( + 'shipmentInfo', + JSON.stringify({ + payment_method_id: data.payment_method_id, + stockPointId: data.stockPointId, + region: details.origin.address.region, + city: details.origin.address.city, + postal_code: details.origin.address.postal_code, + address_line_1: details.origin.address.address_line_1, + phone_number: details.origin.phone_number, + }), + ); + return true; + } catch (error) { + message.error(error?.message || '创建失败'); + } + }} + onFinishFailed={() => { + const element = document.querySelector('.ant-form-item-explain-error'); + if (element) { + element.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + }} + > + + []} + readonly + > + + + + + { + if (!number) return []; + const { data, success } = await ordercontrollerGetorderbynumber({ + number, + }); + if (success) { + return data.map((v) => ({ + label: `${v.siteName} ${v.externalOrderId}`, + value: v.id, + })); + } + return []; + }} + /> + + + { + const { data, success } = + await logisticscontrollerGetpaymentmethods(); + if (success) { + return data.map((v) => ({ + label: v.label, + value: v.id, + })); + } + return []; + }} + /> + + + + + []} + > + + + + + + + + + // value && value.length > 0 + // ? Promise.resolve() + // : Promise.reject('至少需要一个商品'), + // }, + // ]} + > + + { + if (!keyWords || keyWords.length < 3) return options; + try { + const { data } = await productcontrollerSearchproducts({ + name: keyWords, + }); + return ( + data?.map((item) => { + return { + label: item?.name, + value: item?.sku, + }; + }) || options + ); + } catch (error) { + return options; + } + }} + name="sku" + label="产品" + placeholder="请选择产品" + tooltip="至少输入3个字符" + fieldProps={{ + showSearch: true, + filterOption: false, + }} + debounceTime={300} // 防抖,减少请求频率 + rules={[{ required: true, message: '请选择产品' }]} + /> + + + + + + + + { + formRef?.current?.setFieldsValue({ + stockPointId, + details: { + origin: { + address, + phone_number: { + phone: phone_number, + extension: phone_number_extension, + }, + }, + }, + }); + }} + /> + } + > + { + const { data = [] } = await stockcontrollerGetallstockpoints(); + return data.map((item) => ({ + label: item.name, + value: item.id, + })); + }} + /> + + + + + + + + + + + { + return current && current < dayjs().startOf('day'); + }, + }} + transform={(value) => { + return { + details: { + expected_ship_date: { + year: dayjs(value).year(), + month: dayjs(value).month() + 1, + day: dayjs(value).date(), + }, + }, + }; + }} + /> + + + {({ details: { packaging_type } }) => { + if (packaging_type === 'package') { + return ( + + value && value.length > 0 + ? Promise.resolve() + : Promise.reject('至少选择一个包裹'), + }, + ]} + > + {(f, idx, action) => { + return ( + + + { + action.setCurrentRowData({ + measurements: { + weight: { + unit: 'lb', + value: 1, + }, + cuboid: { + unit: 'in', + l: 6, + w: 4, + h: 4, + }, + }, + }); + }} + > + 尺寸1 + + { + action.setCurrentRowData({ + measurements: { + weight: { + unit: 'lb', + value: 5, + }, + cuboid: { + unit: 'in', + l: 8, + w: 6, + h: 6, + }, + }, + }); + }} + > + 尺寸2 + + { + action.setCurrentRowData({ + measurements: { + weight: { + unit: 'lb', + value: 5, + }, + cuboid: { + unit: 'in', + l: 12, + w: 8, + h: 6, + }, + }, + }); + }} + > + 尺寸3 + + + + ); + }} + + + + + + + + + + + + + ); + } + if (packaging_type === 'courier-pak') { + return ( + + value && value.length > 0 + ? Promise.resolve() + : Promise.reject('至少选择一个'), + }, + ]} + > + + + + + + + ); + } + }} + + + { + console.log(e.target.value); + const type = rates.find( + (v) => v.service_id === e.target.value, + )?.type; + setServiceType(type); + }, + }} + options={rates + ?.sort((a, b) => Number(a?.total?.value) - Number(b?.total?.value)) + ?.map((rate) => { + return { + label: `${rate.carrier_name} ${rate.service_name} : ${ + rate?.total?.value / 100 + }${rate?.total?.currency}(${rate.transit_time_days}天)`, + value: rate.service_id, + }; + })} + /> + + ); +}; + +const CreateOrder: React.FC<{ + tableRef?: React.MutableRefObject; +}> = ({ tableRef }) => { + const formRef = useRef(); + const { message } = App.useApp(); + + return ( + + + 创建订单 + + } + params={{ + source_type: 'admin', + }} + onFinish={async ({ items, details, ...data }) => { + try { + const { success, message: errMsg } = await ordercontrollerCreateorder( + { + ...data, + customer_email: data?.billing?.email, + }, + ); + if (!success) throw new Error(errMsg); + message.success('创建成功'); + tableRef?.current?.reload(); + + return true; + } catch (error) { + message.error(error?.message || '创建失败'); + } + }} + onFinishFailed={() => { + const element = document.querySelector('.ant-form-item-explain-error'); + if (element) { + element.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + }} + > + + + { + if (!keyWords || keyWords.length < 3) return options; + try { + const { data } = await productcontrollerSearchproducts({ + name: keyWords, + }); + return ( + data?.map((item) => { + return { + label: item?.name, + value: item?.sku, + }; + }) || options + ); + } catch (error) { + return options; + } + }} + name="sku" + label="产品" + placeholder="请选择产品" + tooltip="至少输入3个字符" + fieldProps={{ + showSearch: true, + filterOption: false, + }} + debounceTime={300} // 防抖,减少请求频率 + rules={[{ required: true, message: '请选择产品' }]} + /> + + + + + + + + {/* */} + + ); +}; + +const AddressPicker: React.FC<{ + value?: any; + onChange?: (value: any) => void; +}> = ({ onChange, value }) => { + const [selectedRow, setSelectedRow] = useState(null); + const { message } = App.useApp(); + const columns: ProColumns[] = [ + { + 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, + }, + ]; + return ( + 选择地址} + modalProps={{ destroyOnClose: true }} + onFinish={async () => { + if (!selectedRow) { + message.error('请选择地址'); + return false; + } + if (onChange) onChange(selectedRow); + return true; + }} + > + { + const { data, success } = + await logisticscontrollerGetshippingaddresslist(); + if (success) { + return { + data: data, + }; + } + return { + data: [], + }; + }} + columns={columns} + search={false} + rowSelection={{ + type: 'radio', + onChange: (_, selectedRows) => { + setSelectedRow(selectedRows[0]); + }, + }} + /> + + ); +}; + +export default ListPage; diff --git a/src/pages/Organiza/User/index.tsx b/src/pages/Organiza/User/index.tsx new file mode 100644 index 0000000..8a13c3d --- /dev/null +++ b/src/pages/Organiza/User/index.tsx @@ -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(); + const columns: ProColumns[] = [ + { + title: '用户名', + dataIndex: 'username', + }, + { + title: '激活', + dataIndex: 'isActive', + valueEnum: { + true: { + text: '是', + }, + false: { + text: '否', + }, + }, + }, + { + title: '超管', + dataIndex: 'isSuper', + valueEnum: { + true: { + text: '是', + }, + false: { + text: '否', + }, + }, + }, + ]; + return ( + + { + const { data, success } = await usercontrollerListusers(params); + + return { + total: data?.total || 0, + data: data?.items || [], + success, + }; + }} + columns={columns} + toolBarRender={() => []} + /> + + ); +}; + +const CreateForm: React.FC<{ + tableRef: React.MutableRefObject; +}> = ({ tableRef }) => { + const { message } = App.useApp(); + return ( + + + 新建 + + } + 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); + } + }} + > + + + + + + ); +}; + +export default ListPage; diff --git a/src/pages/Product/Category/index.tsx b/src/pages/Product/Category/index.tsx new file mode 100644 index 0000000..38f04b7 --- /dev/null +++ b/src/pages/Product/Category/index.tsx @@ -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(); + const { message } = App.useApp(); + const columns: ProColumns[] = [ + { + 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) => ( + <> + {/* + */} + { + 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); + } + }} + > + + + + ), + }, + ]; + + return ( + + + headerTitle="查询表格" + actionRef={actionRef} + rowKey="id" + toolBarRender={() => []} + request={async (params) => { + const { data, success } = await productcontrollerGetcategories( + params, + ); + return { + total: data?.total || 0, + data: data?.items || [], + success, + }; + }} + columns={columns} + /> + + ); +}; + +const CreateForm: React.FC<{ + tableRef: React.MutableRefObject; +}> = ({ tableRef }) => { + const { message } = App.useApp(); + return ( + + title="新建" + trigger={ + + } + 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); + } + }} + > + + + + ); +}; + +const UpdateForm: React.FC<{ + tableRef: React.MutableRefObject; + values: API.Category; +}> = ({ tableRef, values: initialValues }) => { + const { message } = App.useApp(); + return ( + + title="编辑" + initialValues={initialValues} + trigger={ + + } + 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); + } + }} + > + + + + + ); +}; + +export default List; diff --git a/src/pages/Product/Flavors/index.tsx b/src/pages/Product/Flavors/index.tsx new file mode 100644 index 0000000..40c8f7e --- /dev/null +++ b/src/pages/Product/Flavors/index.tsx @@ -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(); + const { message } = App.useApp(); + const columns: ProColumns[] = [ + { + 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) => ( + <> + {/* + */} + { + 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); + } + }} + > + + + + ), + }, + ]; + + return ( + + + headerTitle="查询表格" + actionRef={actionRef} + rowKey="id" + toolBarRender={() => []} + request={async (params) => { + const { data, success } = await productcontrollerGetflavors(params); + return { + total: data?.total || 0, + data: data?.items || [], + success, + }; + }} + columns={columns} + /> + + ); +}; + +const CreateForm: React.FC<{ + tableRef: React.MutableRefObject; +}> = ({ tableRef }) => { + const { message } = App.useApp(); + return ( + + title="新建" + trigger={ + + } + 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); + } + }} + > + + + + ); +}; + +const UpdateForm: React.FC<{ + tableRef: React.MutableRefObject; + values: API.Category; +}> = ({ tableRef, values: initialValues }) => { + const { message } = App.useApp(); + return ( + + title="编辑" + initialValues={initialValues} + trigger={ + + } + 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); + } + }} + > + + + + + ); +}; + +export default List; diff --git a/src/pages/Product/List/index.tsx b/src/pages/Product/List/index.tsx new file mode 100644 index 0000000..6399b03 --- /dev/null +++ b/src/pages/Product/List/index.tsx @@ -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(); + + const { message } = App.useApp(); + const columns: ProColumns[] = [ + { + 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) => ( + <> + { + 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); + } + }} + > + + + + ), + }, + ]; + + return ( + + + headerTitle="查询表格" + actionRef={actionRef} + rowKey="id" + toolBarRender={() => []} + 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), + }} + /> + + ); +}; + +const CreateForm: React.FC<{ + tableRef: React.MutableRefObject; +}> = ({ tableRef }) => { + const { message } = App.useApp(); + return ( + + title="新建" + trigger={ + + } + 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); + } + }} + > + + + + { + const { data = [] } = await productcontrollerGetcategorieall(); + return data.map((item) => ({ + label: item.name, + value: item.id, + })); + }} + rules={[{ required: true, message: '请选择产品分类' }]} + /> + { + const { data = [] } = await productcontrollerGetstrengthall(); + return data.map((item) => ({ + label: item.name, + value: item.id, + })); + }} + rules={[{ required: true, message: '请选择强度' }]} + /> + { + const { data = [] } = await productcontrollerGetflavorsall(); + return data.map((item) => ({ + label: item.name, + value: item.id, + })); + }} + rules={[{ required: true, message: '请选择口味' }]} + /> + + + + ); +}; + +export default List; diff --git a/src/pages/Product/Strength/index.tsx b/src/pages/Product/Strength/index.tsx new file mode 100644 index 0000000..d7eb539 --- /dev/null +++ b/src/pages/Product/Strength/index.tsx @@ -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(); + const { message } = App.useApp(); + const columns: ProColumns[] = [ + { + 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) => ( + <> + {/* + */} + { + 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); + } + }} + > + + + + ), + }, + ]; + + return ( + + + headerTitle="查询表格" + actionRef={actionRef} + rowKey="id" + toolBarRender={() => []} + request={async (params) => { + const { data, success } = await productcontrollerGetstrength(params); + return { + total: data?.total || 0, + data: data?.items || [], + success, + }; + }} + columns={columns} + /> + + ); +}; + +const CreateForm: React.FC<{ + tableRef: React.MutableRefObject; +}> = ({ tableRef }) => { + const { message } = App.useApp(); + return ( + + title="新建" + trigger={ + + } + 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); + } + }} + > + + + + ); +}; + +// const UpdateForm: React.FC<{ +// tableRef: React.MutableRefObject; +// values: API.Category; +// }> = ({ tableRef, values: initialValues }) => { +// const { message } = App.useApp(); +// return ( +// +// title="编辑" +// initialValues={initialValues} +// trigger={ +// +// } +// 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); +// } +// }} +// > +// +// +// +// +// ); +// }; + +export default List; diff --git a/src/pages/Product/WpList/index.tsx b/src/pages/Product/WpList/index.tsx new file mode 100644 index 0000000..c57bb13 --- /dev/null +++ b/src/pages/Product/WpList/index.tsx @@ -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(); + const columns: ProColumns[] = [ + { + 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) => ( + <> + + {record.type === 'simple' && record.sku ? ( + <> + + + + ) : ( + <> + )} + + ), + }, + ]; + const varColumns: ProColumns[] = [ + { + 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) => ( + <> + + {record.sku ? ( + <> + + + + ) : ( + <> + )} + + ), + }, + ]; + + return ( + + + 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={() => []} + expandable={{ + rowExpandable: (record) => record.type === 'variable', + expandedRowRender: (record) => ( + + rowKey="id" + dataSource={record.variations} + pagination={false} + search={false} + options={false} + columns={varColumns} + /> + ), + }} + /> + + ); +}; + +const SyncForm: React.FC<{ + tableRef: React.MutableRefObject; +}> = ({ tableRef }) => { + const { message } = App.useApp(); + return ( + + title="同步产品" + trigger={ + + } + 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); + } + }} + > + + { + const { data = [] } = await sitecontrollerAll(); + return data.map((item) => ({ + label: item.siteName, + value: item.id, + })); + }} + /> + + + ); +}; + +const UpdateForm: React.FC<{ + tableRef: React.MutableRefObject; + values: API.WpProductDTO; +}> = ({ tableRef, values: initialValues }) => { + const { message } = App.useApp(); + return ( + + title="编辑产品" + initialValues={initialValues} + trigger={ + + } + 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); + } + }} + > + + + { + const { data = [] } = await sitecontrollerAll(); + return data.map((item) => ({ + label: item.siteName, + value: item.id, + })); + }} + name="siteId" + disabled + /> + + {initialValues.type === 'simple' ? ( + <> + + + + ) : ( + <> + )} + + + ); +}; + +const UpdateVaritation: React.FC<{ + tableRef: React.MutableRefObject; + values: API.VariationDTO; +}> = ({ tableRef, values: initialValues }) => { + const { message } = App.useApp(); + return ( + + title="编辑变体" + initialValues={initialValues} + trigger={ + + } + 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); + } + }} + > + + + + + + + + ); +}; + +const SetComponent: React.FC<{ + tableRef: React.MutableRefObject; + 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 ( + + title={name} + form={form} + trigger={ + + } + 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(); + }} + > + + + name="constitution" + rules={[ + { + required: true, + message: '至少需要一个商品', + validator: (_, value) => + value && value.length > 0 + ? Promise.resolve() + : Promise.reject('至少需要一个商品'), + }, + ]} + creatorButtonProps={{ children: '新增' }} + > + {(fields, idx, { remove }) => ( +
+ { + 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: '请选择产品' }]} + /> + + +
+ )} + +
+ + ); +}; + +export default List; diff --git a/src/pages/Statistics/Customer/index.tsx b/src/pages/Statistics/Customer/index.tsx new file mode 100644 index 0000000..c47680b --- /dev/null +++ b/src/pages/Statistics/Customer/index.tsx @@ -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 ( + + + { + setMonth(values.month); + }} + > + + + { + const { data, success } = + await statisticscontrollerGetcustomerorders(params); + return { data }; + }} + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { + return ( +
+ {record?.first_hot_purchase?.map((v) => ( +
+ 产品名称:{v.name} 用户数:{v.user_count} +
+ ))} +
+ ); + }} + /> + { + return ( +
+ {record?.second_hot_purchase?.map((v) => ( +
+ 产品名称:{v.name} 用户数:{v.user_count} +
+ ))} +
+ ); + }} + /> + { + return ( +
+ {record?.third_hot_purchase?.map((v) => ( +
+ 产品名称:{v.name} 用户数:{v.user_count} +
+ ))} +
+ ); + }} + /> +
+
+
+ ); +}; + +export default ListPage; diff --git a/src/pages/Statistics/InventoryForecast/index.tsx b/src/pages/Statistics/InventoryForecast/index.tsx new file mode 100644 index 0000000..401f5de --- /dev/null +++ b/src/pages/Statistics/InventoryForecast/index.tsx @@ -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(); + const [points, setPoints] = useState([]); + 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 {record.caTotalStock}; + }, + }, + { + 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 ( + + ); + }, + }, + { + title: 'B端实补数量', + dataIndex: 'restockQuantityReal', + hideInSearch: true, + render(_, record) { + return ; + }, + }, + { + title: '加拿大剩余天数', + dataIndex: 'caAvailableDays', + hideInSearch: true, + render(_, record) { + if (!record.caAvailableDays || record.caAvailableDays > 40) { + return record.caAvailableDays; + } + return {record.caAvailableDays}; + }, + }, + { + title: '剩余天数', + dataIndex: 'availableDays', + hideInSearch: true, + render(_, record) { + if (!record.availableDays || record.availableDays > 70) { + return record.availableDays; + } + return {record.availableDays}; + }, + }, + { + 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 ( + + ); + }, + }, + ]; + return ( + + { + const { data, success } = await statisticscontrollerStockforecast( + param, + ); + if (success) { + return { + total: data?.total || 0, + data: data?.items || [], + }; + } + return { + data: [], + }; + }} + columns={columns} + dateFormatter="number" + /> + + ); +}; + +export default ListPage; diff --git a/src/pages/Statistics/Order/index.tsx b/src/pages/Statistics/Order/index.tsx new file mode 100644 index 0000000..fed66cc --- /dev/null +++ b/src/pages/Statistics/Order/index.tsx @@ -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() ? ( + + {part} + + ) : ( + part + ), + ); +}; + +const ListPage: React.FC = () => { + const [xAxis, setXAxis] = useState([]); + const [series, setSeries] = useState([]); + const [selectedDate, setSelectedDate] = useState(null); + + const option = useMemo( + () => ({ + tooltip: { + trigger: 'axis', + formatter: function (params) { + const items = params.map((item) => { + return `${item.marker} ${item.seriesName}: ${item.value}`; + }); + + // 每4个一行 + const rows = []; + for (let i = 0; i < items.length; i += 4) { + rows.push(items.slice(i, i + 4).join('')); + } + + return rows.join('
'); + }, + }, + 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 ( + + { + 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), + }, + ]); + } + }} + > + + {/* */} + { + const { data = [] } = await sitecontrollerAll(); + return data.map((item) => ({ + label: item.siteName, + value: item.id, + })); + }} + /> + {/* + + */} + + {series?.length ? ( + { + if (params.componentType === 'series') { + setSelectedDate(params.name); + } + }, + }} + /> + ) : ( + <> + )} + + + ); +}; + +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 ( + { + 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 ( +
+ {record.orderItems?.map((item) => ( + //
{highlightText(item.name, keyword)}
+
{item.name}
+ ))} +
+ ); + }, + 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 ; + }, + }, + ]} + dataSource={orders} + onChange={handleTableChange} + /> + ); +}; + +const HistoryOrder: React.FC<{ + email: string; +}> = ({ email }) => { + return ( + 历史订单} + modalProps={{ destroyOnClose: true, footer: null }} + width="80vw" + > + { + 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 ( +
+ {record.orderItems?.map((item) => ( +
+ ${item.total} : {item.name} * {item.quantity} +
+ ))} +
+ ); + }, + }, + ]} + request={async () => { + const { data, success } = await statisticscontrollerGetorderbyemail({ + email, + }); + return { + data, + success, + }; + }} + /> +
+ ); +}; + +export default ListPage; diff --git a/src/pages/Statistics/Restocking/index.tsx b/src/pages/Statistics/Restocking/index.tsx new file mode 100644 index 0000000..94d2e16 --- /dev/null +++ b/src/pages/Statistics/Restocking/index.tsx @@ -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(); + 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 ( +
+
+
{base}
+
{base}
+
{base}
+
+
+
+ ); + }, + })), + { + title: '安全补充系数', + hideInSearch: true, + render(_, record) { + return ( + + ); + }, + }, + { + title: '', + hideInSearch: true, + render(_, record) { + const base = record.lastMonthSales; + return ( +
+
{count * base}
+
{2 * count * base}
+
+ ); + }, + }, + { + 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 ( + + ); + }, + }, + ]; + return ( + + { + const { data, success } = await statisticscontrollerRestocking(param); + if (success) { + return { + total: data?.total || 0, + data: data?.items || [], + }; + } + return { + data: [], + }; + }} + columns={columns} + dateFormatter="number" + toolBarRender={() => [ + setCount(e.target.value), + value: count, + }} + />, + ]} + /> + + ); +}; + +export default ListPage; diff --git a/src/pages/Statistics/Sales/index.tsx b/src/pages/Statistics/Sales/index.tsx new file mode 100644 index 0000000..64ad8cb --- /dev/null +++ b/src/pages/Statistics/Sales/index.tsx @@ -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(); + const [total, setTotal] = useState(0); + const [isSource, setIsSource] = useState(false); + const [yooneTotal, setYooneTotal] = useState({}); + + const columns: ProColumns[] = [ + { + 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 ( + + { + 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={() => [ + setIsSource(!isSource), + }} + />, + ]} + /> +
+
+ YOONE:{' '} + {(yooneTotal.yoone3Quantity || 0) + + (yooneTotal.yoone6Quantity || 0) + + (yooneTotal.yoone9Quantity || 0) + + (yooneTotal.yoone12Quantity || 0) + + (yooneTotal.yoone15Quantity || 0)} +
+
YOONE 3MG: {yooneTotal.yoone3Quantity || 0}
+
YOONE 6MG: {yooneTotal.yoone6Quantity || 0}
+
YOONE 9MG: {yooneTotal.yoone9Quantity || 0}
+
YOONE 12MG: {yooneTotal.yoone12Quantity || 0}
+
YOONE 15MG: {yooneTotal.yoone15Quantity || 0}
+
+
+ ); +}; + +export default ListPage; diff --git a/src/pages/Stock/List/index.tsx b/src/pages/Stock/List/index.tsx new file mode 100644 index 0000000..e51b62c --- /dev/null +++ b/src/pages/Stock/List/index.tsx @@ -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(); + const [points, setPoints] = useState([]); + useEffect(() => { + stockcontrollerGetallstockpoints().then(({ data }) => { + setPoints(data as API.StockPoint[]); + }); + }, []); + const columns: ProColumns[] = [ + { + 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 ( + + + 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={() => []} + /> + + ); +}; + +export default ListPage; diff --git a/src/pages/Stock/PurchaseOrder/index.tsx b/src/pages/Stock/PurchaseOrder/index.tsx new file mode 100644 index 0000000..79b54ef --- /dev/null +++ b/src/pages/Stock/PurchaseOrder/index.tsx @@ -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(); + const columns: ProColumns[] = [ + { + 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' && ( + + )} + {record.status === 'draft' ? ( + <> + + { + 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); + } + }} + > + + + + ) : record.status === 'submitted' ? ( + <> + + { + 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); + } + }} + > + + + + ) : ( + + )} + + ), + }, + ]; + + return ( + + + 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={() => []} + /> + + ); +}; + +const CreateForm: React.FC<{ + tableRef: React.MutableRefObject; +}> = ({ tableRef }) => { + const { message } = App.useApp(); + const [form] = Form.useForm(); + return ( + + title="新建" + trigger={ + + } + 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); + } + }} + > + { + 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: '请选择仓库' }]} + /> + + + + + {({ items }) => { + return '数量:' + items?.reduce((acc, cur) => acc + cur.quantity, 0); + }} + + + 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 }) => ( +
+ { + 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, + ); + }} + /> +
+ )} + + + ); +}; + +const UpdateForm: React.FC<{ + tableRef: React.MutableRefObject; + 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 ( + + title="编辑" + form={form} + initialValues={initialValues} + trigger={ + + } + 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); + } + }} + > + + { + 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: '请选择仓库' }]} + /> + + + + + {({ items }) => { + return ( + '数量:' + items?.reduce((acc, cur) => acc + cur.quantity, 0) + ); + }} + + + 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 }) => ( +
+ { + 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, + ); + }} + /> +
+ )} + +
+ + ); +}; + +const DetailForm: React.FC<{ + tableRef: React.MutableRefObject; + 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 ( + + title="详情" + form={form} + initialValues={initialValues} + trigger={} + autoFocusFirstInput + drawerProps={{ + destroyOnClose: true, + }} + readonly={true} + layout="vertical" + > + { + 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: '请选择仓库' }]} + /> + + + + + + 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 }) => ( +
+ + { + 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, + ); + }} + /> + +
+ )} + + + ); +}; + +export default PurchaseOrderPage; diff --git a/src/pages/Stock/Record/index.tsx b/src/pages/Stock/Record/index.tsx new file mode 100644 index 0000000..244c3f1 --- /dev/null +++ b/src/pages/Stock/Record/index.tsx @@ -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(); + const columns: ProColumns[] = [ + { + title: '仓库', + dataIndex: 'stockPointName', + hideInSearch: true, + }, + { + title: '产品名称', + dataIndex: 'productName', + }, + { + title: 'SKU', + dataIndex: 'productSku', + hideInSearch: true, + }, + { + title: '库存', + hideInSearch: true, + render: (_, record: API.StockRecordDTO) => ( + + {record?.operationType === 'in' ? '+' : '-'} + {record.quantityChange} + + ), + }, + { + title: '操作人', + dataIndex: 'operatorName', + hideInSearch: true, + }, + { + title: '备注', + dataIndex: 'note', + hideInSearch: true, + }, + { + title: '创建时间', + dataIndex: 'createdAt', + valueType: 'dateTime', + hideInSearch: true, + }, + ]; + + return ( + + + 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={() => []} + /> + + ); +}; + +export default ListPage; diff --git a/src/pages/Stock/Transfer/index.tsx b/src/pages/Stock/Transfer/index.tsx new file mode 100644 index 0000000..5b19845 --- /dev/null +++ b/src/pages/Stock/Transfer/index.tsx @@ -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(); + 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 ? ( + <> + + + { + 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); + } + }} + > + + + + { + 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); + } + }} + > + + + + { + 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); + } + }} + > + + + + ) : ( + + )} + + ), + }, + ]; + + return ( + + { + const { data, success } = await stockcontrollerGettransfers(params); + return { + total: data?.total || 0, + data: data?.items || [], + success, + }; + }} + columns={columns} + toolBarRender={() => []} + /> + + ); +}; + +const CreateForm: React.FC<{ + tableRef: React.MutableRefObject; +}> = ({ tableRef }) => { + const { message } = App.useApp(); + const [form] = Form.useForm(); + return ( + + + 新建 + + } + 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); + } + }} + > + + { + 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: '请选择源仓库' }]} + /> + { + 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: '请选择源目标仓库' }]} + /> + + + {({ items }) => { + return '数量:' + items?.reduce((acc, cur) => acc + cur.quantity, 0); + }} + + + value && value.length > 0 + ? Promise.resolve() + : Promise.reject('至少需要一个商品'), + }, + ]} + creatorButtonProps={{ children: '新增', size: 'large' }} + wrapperCol={{ span: 24 }} + > + {(fields, idx, { remove }) => ( +
+ { + 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, + ); + }} + /> +
+ )} +
+
+ ); +}; + +const UpdateForm: React.FC<{ + tableRef: React.MutableRefObject; + 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 ( + + title="编辑" + form={form} + initialValues={initialValues} + trigger={ + + } + 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); + } + }} + > + { + 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: '请选择源仓库' }]} + /> + { + 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: '请选择源目标仓库' }]} + /> + + + {({ items }) => { + return '数量:' + items?.reduce((acc, cur) => acc + cur.quantity, 0); + }} + + + value && value.length > 0 + ? Promise.resolve() + : Promise.reject('至少需要一个商品'), + }, + ]} + creatorButtonProps={{ children: '新增', size: 'large' }} + wrapperCol={{ span: 24 }} + > + {(fields, idx, { remove }) => ( +
+ { + 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, + ); + }} + /> +
+ )} +
+ + ); +}; + +const DetailForm: React.FC<{ + tableRef: React.MutableRefObject; + values: Record; +}> = ({ 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 ( + 详情} + autoFocusFirstInput + drawerProps={{ + destroyOnClose: true, + }} + readonly={true} + layout="vertical" + > + + { + 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: '请选择源仓库' }]} + /> + { + 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: '请选择源目标仓库' }]} + /> + + + 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 }) => ( +
+ + { + 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, + ); + }} + /> + +
+ )} + +
+ ); +}; + +export default TransferPage; diff --git a/src/pages/Stock/Warehouse/index.tsx b/src/pages/Stock/Warehouse/index.tsx new file mode 100644 index 0000000..544334d --- /dev/null +++ b/src/pages/Stock/Warehouse/index.tsx @@ -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(); + const columns: ProColumns[] = [ + { + title: '名称', + dataIndex: 'name', + }, + { + title: '地址', + dataIndex: 'location', + }, + { + title: '联系人', + dataIndex: 'contactPerson', + }, + { + title: '联系电话', + dataIndex: 'contactPhone', + }, + { + title: '创建时间', + dataIndex: 'createdAt', + valueType: 'dateTime', + }, + { + title: '操作', + dataIndex: 'option', + valueType: 'option', + render: (_, record) => ( + <> + + + { + 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); + } + }} + > + + + + ), + }, + ]; + + return ( + + + 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={() => []} + search={false} + /> + + ); +}; + +const CreateForm: React.FC<{ + tableRef: React.MutableRefObject; +}> = ({ tableRef }) => { + const { message } = App.useApp(); + return ( + + title="新建" + trigger={ + + } + 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); + } + }} + > + + + + + + + + ); +}; + +const UpdateForm: React.FC<{ + tableRef: React.MutableRefObject; + values: API.StockPoint; +}> = ({ tableRef, values: initialValues }) => { + const { message } = App.useApp(); + return ( + + title="编辑" + initialValues={initialValues} + trigger={ + + } + 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); + } + }} + > + + + + + + + + ); +}; + +export default ListPage; diff --git a/src/pages/Track/index.tsx b/src/pages/Track/index.tsx new file mode 100644 index 0000000..be6b401 --- /dev/null +++ b/src/pages/Track/index.tsx @@ -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(); + const [data, setData] = useState([]); + return ( + + { + 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: ( + { + if (!id) { + return; + } + const { data } = await logisticscontrollerGetlistbytrackingid({ + shipment_id: id, + }); + setData(data); + }} + /> + ), + }} + /> + + 原订单 + 产品 + 数量 + {data?.orderItem?.map((v: any) => ( + <> + {v.name} + {v.quantity} + + ))} + + + + 产品 + 数量 + {data?.shipmentItem?.map((v: any) => ( + <> + {v.name} + {v.quantity} + + ))} + + + ); +}; + +export default TrackPage; diff --git a/src/servers/api/index.ts b/src/servers/api/index.ts new file mode 100644 index 0000000..800eb60 --- /dev/null +++ b/src/servers/api/index.ts @@ -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, +}; diff --git a/src/servers/api/logistics.ts b/src/servers/api/logistics.ts new file mode 100644 index 0000000..8a4c32d --- /dev/null +++ b/src/servers/api/logistics.ts @@ -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(`/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('/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(`/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('/logistics/getListByTrackingId', { + method: 'POST', + params: { + ...params, + }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /logistics/getPaymentMethods */ +export async function logisticscontrollerGetpaymentmethods(options?: { + [key: string]: any; +}) { + return request('/logistics/getPaymentMethods', { + method: 'POST', + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /logistics/getRateList */ +export async function logisticscontrollerGetratelist( + body: API.ShippingDetailsDTO, + options?: { [key: string]: any }, +) { + return request('/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('/logistics/getServiceList', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 GET /logistics/getShippingAddressList */ +export async function logisticscontrollerGetshippingaddresslist(options?: { + [key: string]: any; +}) { + return request( + '/logistics/getShippingAddressList', + { + method: 'GET', + ...(options || {}), + }, + ); +} + +/** 此处后端没有提供注释 POST /logistics/getTrackingNumber */ +export async function logisticscontrollerGettrackingnumber( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.logisticscontrollerGettrackingnumberParams, + options?: { [key: string]: any }, +) { + return request('/logistics/getTrackingNumber', { + method: 'POST', + params: { + ...params, + }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 GET /logistics/list */ +export async function logisticscontrollerGetlist(options?: { + [key: string]: any; +}) { + return request('/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(`/logistics/shipment/${param0}`, { + method: 'DELETE', + params: { ...queryParams }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /logistics/syncServices */ +export async function logisticscontrollerSyncservices(options?: { + [key: string]: any; +}) { + return request('/logistics/syncServices', { + method: 'POST', + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /logistics/toggleActive */ +export async function logisticscontrollerToggleactive( + body: Record, + options?: { [key: string]: any }, +) { + return request('/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(`/logistics/updateShippingAddress/${param0}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + params: { ...queryParams }, + data: body, + ...(options || {}), + }); +} diff --git a/src/servers/api/order.ts b/src/servers/api/order.ts new file mode 100644 index 0000000..5f9efb5 --- /dev/null +++ b/src/servers/api/order.ts @@ -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(`/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(`/order/${param0}`, { + method: 'DELETE', + params: { ...queryParams }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /order/createNote */ +export async function ordercontrollerCreatenote( + body: API.CreateOrderNoteDTO, + options?: { [key: string]: any }, +) { + return request('/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('/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('/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('/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(`/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(`/order/order/completed/${param0}`, { + method: 'POST', + params: { ...queryParams }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /order/order/create */ +export async function ordercontrollerCreateorder( + body: Record, + options?: { [key: string]: any }, +) { + return request('/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(`/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(`/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(`/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(`/order/syncOrder/${param1}/order/${param0}`, { + method: 'POST', + params: { ...queryParams }, + ...(options || {}), + }); +} diff --git a/src/servers/api/product.ts b/src/servers/api/product.ts new file mode 100644 index 0000000..1ca3032 --- /dev/null +++ b/src/servers/api/product.ts @@ -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('/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(`/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(`/product/${param0}`, { + method: 'DELETE', + params: { ...queryParams }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /product/batchSetSku */ +export async function productcontrollerBatchsetsku( + body: API.BatchSetSkuDTO, + options?: { [key: string]: any }, +) { + return request('/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('/product/categorieAll', { + method: 'GET', + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 GET /product/categories */ +export async function productcontrollerGetcategories( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.productcontrollerGetcategoriesParams, + options?: { [key: string]: any }, +) { + return request('/product/categories', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /product/category */ +export async function productcontrollerCreatecategory( + body: API.CreateCategoryDTO, + options?: { [key: string]: any }, +) { + return request('/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(`/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(`/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('/product/flavors', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /product/flavors */ +export async function productcontrollerCreateflavors( + body: API.CreateFlavorsDTO, + options?: { [key: string]: any }, +) { + return request('/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(`/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(`/product/flavors/${param0}`, { + method: 'DELETE', + params: { ...queryParams }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 GET /product/flavorsAll */ +export async function productcontrollerGetflavorsall(options?: { + [key: string]: any; +}) { + return request('/product/flavorsAll', { + method: 'GET', + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 GET /product/list */ +export async function productcontrollerGetproductlist( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.productcontrollerGetproductlistParams, + options?: { [key: string]: any }, +) { + return request('/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('/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(`/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('/product/strength', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /product/strength */ +export async function productcontrollerCreatestrength( + body: API.CreateStrengthDTO, + options?: { [key: string]: any }, +) { + return request('/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(`/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(`/product/strength/${param0}`, { + method: 'DELETE', + params: { ...queryParams }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 GET /product/strengthAll */ +export async function productcontrollerGetstrengthall(options?: { + [key: string]: any; +}) { + return request('/product/strengthAll', { + method: 'GET', + ...(options || {}), + }); +} diff --git a/src/servers/api/site.ts b/src/servers/api/site.ts new file mode 100644 index 0000000..a234ee2 --- /dev/null +++ b/src/servers/api/site.ts @@ -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('/site/all', { + method: 'GET', + ...(options || {}), + }); +} diff --git a/src/servers/api/statistics.ts b/src/servers/api/statistics.ts new file mode 100644 index 0000000..17884ae --- /dev/null +++ b/src/servers/api/statistics.ts @@ -0,0 +1,93 @@ +// @ts-ignore +/* eslint-disable */ +import { request } from 'umi'; + +/** 此处后端没有提供注释 POST /statistics/getCustomerOrders */ +export async function statisticscontrollerGetcustomerorders( + body: Record, + options?: { [key: string]: any }, +) { + return request('/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('/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('/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('/statistics/orderByEmail', { + method: 'POST', + headers: { + 'Content-Type': 'text/plain', + }, + data: body, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /statistics/restocking */ +export async function statisticscontrollerRestocking( + body: Record, + options?: { [key: string]: any }, +) { + return request('/statistics/restocking', { + method: 'POST', + headers: { + 'Content-Type': 'text/plain', + }, + data: body, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /statistics/stockForecast */ +export async function statisticscontrollerStockforecast( + body: Record, + options?: { [key: string]: any }, +) { + return request('/statistics/stockForecast', { + method: 'POST', + headers: { + 'Content-Type': 'text/plain', + }, + data: body, + ...(options || {}), + }); +} diff --git a/src/servers/api/stock.ts b/src/servers/api/stock.ts new file mode 100644 index 0000000..dcee54e --- /dev/null +++ b/src/servers/api/stock.ts @@ -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('/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(`/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(`/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('/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('/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(`/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(`/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(`/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, + options?: { [key: string]: any }, +) { + const { id: param0, ...queryParams } = params; + return request(`/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(`/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('/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('/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('/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(`/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(`/stock/stock-point/${param0}`, { + method: 'DELETE', + params: { ...queryParams }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 GET /stock/stock-point/all */ +export async function stockcontrollerGetallstockpoints(options?: { + [key: string]: any; +}) { + return request('/stock/stock-point/all', { + method: 'GET', + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 GET /stock/transfer */ +export async function stockcontrollerGettransfers(options?: { + [key: string]: any; +}) { + return request('/stock/transfer', { + method: 'GET', + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /stock/transfer */ +export async function stockcontrollerCreatetransfer( + body: Record, + options?: { [key: string]: any }, +) { + return request('/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('/stock/update', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} diff --git a/src/servers/api/typings.d.ts b/src/servers/api/typings.d.ts new file mode 100644 index 0000000..2b78cad --- /dev/null +++ b/src/servers/api/typings.d.ts @@ -0,0 +1,1469 @@ +declare namespace API { + type Address = { + address_line_1?: string; + city?: string; + region?: string; + country?: string; + postal_code?: string; + }; + + type BatchSetSkuDTO = { + /** sku 数据列表 */ + skus?: SkuItemDTO[]; + }; + + type BooleanRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: boolean; + }; + + type Category = { + /** 分类 ID */ + id: number; + /** 分类名称 */ + name: string; + /** 唯一识别key */ + unique_key: string; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + }; + + type CategoryPaginatedResponse = { + /** 当前页码 */ + page?: number; + /** 每页大小 */ + pageSize?: number; + /** 总记录数 */ + total?: number; + /** 数据列表 */ + items?: Category[]; + }; + + type CreateCategoryDTO = { + /** 分类名称 */ + name: string; + }; + + type CreateFlavorsDTO = { + /** 分类名称 */ + name: string; + }; + + type CreateOrderNoteDTO = { + orderId?: number; + content?: string; + }; + + type CreateProductDTO = { + /** 产品名称 */ + name: string; + /** 产品描述 */ + description?: string; + /** sku */ + sku?: string; + /** 分类 ID */ + categoryId?: number; + }; + + type CreatePurchaseOrderDTO = { + stockPointId?: number; + expectedArrivalTime?: string; + status?: 'draft' | 'submitted' | 'received'; + note?: string; + items?: PurchaseOrderItem[]; + }; + + type CreateStockPointDTO = { + name?: string; + location?: string; + contactPerson?: string; + contactPhone?: string; + }; + + type CreateStrengthDTO = { + /** 分类名称 */ + name: string; + }; + + type Cubid = { + w?: number; + h?: number; + l?: number; + unit?: string; + }; + + type Date = { + year?: string; + month?: string; + day?: string; + }; + + type Destination = { + name?: string; + address?: Address; + phone_number?: PhoneNumber; + email_addresses?: any; + ready_at?: Time; + ready_until?: Time; + SignatureRequirementEnum?: any; + }; + + type Location = { + name?: string; + address?: Address; + phone_number?: PhoneNumber; + email_addresses?: any; + }; + + type LoginDTO = { + username?: string; + password?: string; + }; + + type LoginRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: LoginResDTO; + }; + + type LoginResDTO = { + token?: string; + userId?: number; + username?: string; + permissions?: string[]; + }; + + type logisticscontrollerCreateshipmentParams = { + orderId: number; + }; + + type logisticscontrollerDelshipmentParams = { + id: string; + }; + + type logisticscontrollerDelshippingaddressParams = { + id: number; + }; + + type logisticscontrollerGetlistbytrackingidParams = { + shipment_id?: string; + }; + + type logisticscontrollerGetservicelistParams = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + carrier_name?: string; + isActive?: boolean; + }; + + type logisticscontrollerGettrackingnumberParams = { + number?: string; + }; + + type logisticscontrollerUpdateshippingaddressParams = { + id: number; + }; + + type Measurements = { + cuboid?: Cubid; + weight?: Cubid; + }; + + type Money = { + currency?: string; + value?: string; + }; + + type Order = { + id?: number; + siteId?: string; + externalOrderId?: string; + status?: any; + orderStatus?: any; + currency?: string; + currency_symbol?: string; + prices_include_tax?: boolean; + date_created?: string; + date_modified?: string; + discount_total?: number; + discount_tax?: number; + shipping_total?: number; + shipping_tax?: number; + cart_tax?: number; + total?: number; + total_tax?: number; + customer_id?: number; + customer_email?: string; + order_key?: string; + billing?: OrderAddress; + shipping?: OrderAddress; + payment_method?: string; + payment_method_title?: string; + transaction_id?: string; + customer_ip_address?: string; + customer_user_agent?: string; + created_via?: string; + customer_note?: string; + date_completed?: string; + date_paid?: string; + cart_hash?: string; + number?: string; + meta_data?: any; + payment_url?: string; + is_editable?: boolean; + needs_payment?: boolean; + needs_processing?: boolean; + device_type?: string; + source_type?: string; + utm_source?: string; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + }; + + type OrderAddress = { + first_name?: string; + last_name?: string; + company?: string; + address_1?: string; + address_2?: string; + city?: string; + state?: string; + postcode?: string; + country?: string; + email?: string; + phone?: string; + }; + + type ordercontrollerCancelorderParams = { + id: number; + }; + + type ordercontrollerChangestatusParams = { + id: number; + }; + + type ordercontrollerCompletedorderParams = { + id: number; + }; + + type ordercontrollerDelorderParams = { + id: number; + }; + + type ordercontrollerGetorderdetailParams = { + orderId: number; + }; + + type ordercontrollerGetordersalesParams = { + isSource?: boolean; + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + siteId?: string; + name?: string; + startDate?: string; + endDate?: string; + }; + + type ordercontrollerGetordersParams = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + externalOrderId?: string; + siteId?: string; + customer_email?: string; + keyword?: string; + startDate?: string; + endDate?: string; + status?: + | 'pending' + | 'processing' + | 'completed' + | 'cancelled' + | 'refunded' + | 'failed' + | 'after_sale_pending' + | 'pending_reshipment' + | 'pending_refund'; + }; + + type ordercontrollerRefundorderParams = { + id: number; + }; + + type ordercontrollerSyncorderbyidParams = { + orderId: string; + siteId: string; + }; + + type ordercontrollerSyncorderParams = { + siteId: string; + }; + + type OrderDetail = { + id?: number; + siteId?: string; + externalOrderId?: string; + status?: any; + orderStatus?: any; + currency?: string; + currency_symbol?: string; + prices_include_tax?: boolean; + date_created?: string; + date_modified?: string; + discount_total?: number; + discount_tax?: number; + shipping_total?: number; + shipping_tax?: number; + cart_tax?: number; + total?: number; + total_tax?: number; + customer_id?: number; + customer_email?: string; + order_key?: string; + billing?: OrderAddress; + shipping?: OrderAddress; + payment_method?: string; + payment_method_title?: string; + transaction_id?: string; + customer_ip_address?: string; + customer_user_agent?: string; + created_via?: string; + customer_note?: string; + date_completed?: string; + date_paid?: string; + cart_hash?: string; + number?: string; + meta_data?: any; + payment_url?: string; + is_editable?: boolean; + needs_payment?: boolean; + needs_processing?: boolean; + device_type?: string; + source_type?: string; + utm_source?: string; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + items?: OrderItem[]; + sales?: OrderSale[]; + refundItems?: OrderRefundItem[]; + trackings?: Tracking[]; + notes?: OrderNote[]; + }; + + type OrderDetailRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: OrderDetail; + }; + + type OrderItem = { + id?: number; + name?: string; + siteId?: string; + orderId?: number; + externalOrderId?: string; + externalOrderItemId?: string; + externalProductId?: string; + externalVariationId?: string; + quantity?: number; + subtotal?: number; + subtotal_tax?: number; + total?: number; + total_tax?: number; + sku?: string; + price?: number; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + }; + + type OrderListRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: OrderPaginatedRespone; + }; + + type OrderNote = { + userId?: number; + orderId?: number; + content?: string; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + }; + + type OrderPaginatedRespone = { + /** 当前页码 */ + page?: number; + /** 每页大小 */ + pageSize?: number; + /** 总记录数 */ + total?: number; + /** 数据列表 */ + items?: Order[]; + count?: OrderStatusCountDTO[]; + }; + + type OrderRefundItem = { + id?: number; + refundId?: number; + siteId?: string; + externalRefundId?: string; + externalRefundItemId?: string; + externalProductId?: string; + externalVariationId?: string; + name?: string; + quantity?: number; + tax_class?: string; + subtotal?: number; + subtotal_tax?: number; + total?: number; + total_tax?: number; + sku?: string; + price?: number; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + }; + + type OrderSale = { + id?: number; + orderId?: number; + siteId?: string; + externalOrderItemId?: string; + productId?: number; + name?: string; + /** sku */ + sku?: string; + quantity?: number; + isPackage?: boolean; + /** 创建时间 */ + createdAt?: string; + /** 更新时间 */ + updatedAt?: string; + }; + + type OrderSaleDTO = { + id?: number; + orderId?: number; + siteId?: string; + externalOrderItemId?: string; + productId?: number; + name?: string; + /** sku */ + sku?: string; + quantity?: number; + isPackage?: boolean; + /** 创建时间 */ + createdAt?: string; + /** 更新时间 */ + updatedAt?: string; + totalQuantity?: number; + }; + + type OrderSaleListRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: OrderSalePaginatedRespone; + }; + + type OrderSalePaginatedRespone = { + /** 当前页码 */ + page?: number; + /** 每页大小 */ + pageSize?: number; + /** 总记录数 */ + total?: number; + /** 数据列表 */ + items?: OrderSaleDTO[]; + }; + + type OrderStatisticsParams = { + startDate?: string; + endDate?: string; + keyword?: string; + siteId?: string; + purchaseType?: 'all' | 'first_purchase' | 'repeat_purchase'; + orderType?: 'all' | 'cpc' | 'non_cpc'; + brand?: 'all' | 'zyn' | 'yoone' | 'zolt'; + }; + + type OrderStatusCountDTO = { + status?: string; + count?: number; + }; + + type Package = { + measurements?: Measurements; + description?: string; + }; + + type PackagingPackage = { + packages?: Package[]; + }; + + type PhoneNumber = { + number?: string; + extension?: string; + }; + + type Product = { + /** ID */ + id: number; + /** 产品名称 */ + name: string; + /** 产品描述 */ + description?: string; + /** 分类 ID */ + categoryId?: number; + flavorsId?: number; + strengthId?: number; + /** sku */ + sku?: string; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + }; + + type ProductCatListRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: CategoryPaginatedResponse; + }; + + type ProductCatRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: Category; + }; + + type productcontrollerDeletecategoryParams = { + id: number; + }; + + type productcontrollerDeleteflavorsParams = { + id: number; + }; + + type productcontrollerDeleteproductParams = { + id: number; + }; + + type productcontrollerDeletestrengthParams = { + id: number; + }; + + type productcontrollerGetcategoriesParams = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + /** 关键字 */ + name?: string; + }; + + type productcontrollerGetflavorsParams = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + /** 关键字 */ + name?: string; + }; + + type productcontrollerGetproductlistParams = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + /** 关键字 */ + name?: string; + /** 分类 ID */ + categoryId?: number; + }; + + type productcontrollerGetstrengthParams = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + /** 关键字 */ + name?: string; + }; + + type productcontrollerProductbyskuParams = { + sku: string; + }; + + type productcontrollerSearchproductsParams = { + name?: string; + }; + + type productcontrollerUpdatecategoryParams = { + id: number; + }; + + type productcontrollerUpdateflavorsParams = { + id: number; + }; + + type productcontrollerUpdateproductParams = { + id: number; + }; + + type productcontrollerUpdatestrengthParams = { + id: number; + }; + + type ProductListRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: ProductPaginatedResponse; + }; + + type ProductPaginatedResponse = { + /** 当前页码 */ + page?: number; + /** 每页大小 */ + pageSize?: number; + /** 总记录数 */ + total?: number; + /** 数据列表 */ + items?: Product[]; + }; + + type ProductRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: Product; + }; + + type ProductsRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: Product[]; + }; + + type PurchaseOrderDTO = { + id?: number; + stockPointId?: number; + orderNumber?: string; + status?: any; + note?: string; + /** 预计时间 */ + expectedArrivalTime: string; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + items?: PurchaseOrderItem[]; + }; + + type PurchaseOrderItem = { + id?: number; + productSku?: string; + productName?: string; + quantity?: number; + price?: number; + purchaseOrderId?: number; + }; + + type PurchaseOrderListRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: PurchaseOrderPaginatedRespone; + }; + + type PurchaseOrderPaginatedRespone = { + /** 当前页码 */ + page?: number; + /** 每页大小 */ + pageSize?: number; + /** 总记录数 */ + total?: number; + /** 数据列表 */ + items?: PurchaseOrderDTO[]; + }; + + type QueryCategoryDTO = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + /** 关键字 */ + name?: string; + }; + + type QueryFlavorsDTO = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + /** 关键字 */ + name?: string; + }; + + type QueryOrderDTO = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + externalOrderId?: string; + siteId?: string; + customer_email?: string; + keyword?: string; + startDate?: string; + endDate?: string; + status?: + | 'pending' + | 'processing' + | 'completed' + | 'cancelled' + | 'refunded' + | 'failed' + | 'after_sale_pending' + | 'pending_reshipment' + | 'pending_refund'; + }; + + type QueryOrderSalesDTO = { + isSource?: boolean; + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + siteId?: string; + name?: string; + startDate?: string; + endDate?: string; + }; + + type QueryPointDTO = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + }; + + type QueryProductDTO = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + /** 关键字 */ + name?: string; + /** 分类 ID */ + categoryId?: number; + }; + + type QueryPurchaseOrderDTO = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + orderNumber?: string; + stockPointId?: number; + }; + + type QueryServiceDTO = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + carrier_name?: string; + isActive?: boolean; + }; + + type QueryStockDTO = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + productName?: string; + }; + + type QueryStockRecordDTO = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + stockPointId?: number; + productSku?: string; + productName?: string; + }; + + type QueryStrengthDTO = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + /** 关键字 */ + name?: string; + }; + + type QueryWpProductDTO = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + /** 产品名 */ + name?: string; + /** 站点ID */ + siteId?: string; + /** 产品状态 */ + status?: + | 'publish' + | 'draft' + | 'pending' + | 'private' + | 'trash' + | 'auto-draft' + | 'future' + | 'inherit'; + }; + + type RateDTO = { + carrier_name?: string; + service_name?: string; + service_id?: string; + valid_until?: Date; + total?: Money; + base?: Money; + surcharges?: Surcharges[]; + taxes?: Money[]; + transit_time_days?: number; + transit_time_not_available?: boolean; + }; + + type RateLitRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: RateDTO[]; + }; + + type Service = { + id?: string; + carrier_name?: string; + service_name?: string; + isActive?: boolean; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + }; + + type ServiceListRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: Service[]; + }; + + type SetConstitutionDTO = { + isProduct?: boolean; + /** 构成成分 */ + constitution?: { sku?: string; quantity?: number }[]; + }; + + type ShipmentBookDTO = { + sales?: OrderSale[]; + payment_method_id?: string; + service_id?: string; + service_type?: string; + details?: ShippingDetailsDTO; + stockPointId?: number; + orderIds?: number[]; + }; + + type ShipmentItem = { + id?: number; + shipment_id?: string; + productId?: number; + name?: string; + /** sku */ + sku?: string; + quantity?: number; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + }; + + type ShippingAddress = { + id?: number; + name?: string; + stockPointId?: number; + address?: Address; + phone_number?: string; + phone_number_extension?: string; + phone_number_country?: string; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + }; + + type ShippingAddressListRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: ShippingAddress[]; + }; + + type ShippingDetailsDTO = { + origin?: Location; + destination?: Destination; + expected_ship_date?: Date; + packaging_type?: 'pallet' | 'package' | 'courier-pak' | 'envelope'; + packaging_properties?: PackagingPackage[]; + reference_codes?: any; + }; + + type SiteConfig = { + /** 站点 ID */ + id?: string; + /** 站点 URL */ + wpApiUrl?: string; + /** 站点 rest key */ + consumerKey?: string; + /** 站点 rest 秘钥 */ + consumerSecret?: string; + /** 站点名 */ + siteName?: string; + /** 站点邮箱 */ + email?: string; + /** 站点邮箱密码 */ + emailPswd?: string; + }; + + type SkuItemDTO = { + /** 产品 ID */ + productId?: number; + /** sku 编码 */ + sku?: string; + }; + + type stockcontrollerCanceltransferParams = { + id: number; + }; + + type stockcontrollerDelpurchaseorderParams = { + id: number; + }; + + type stockcontrollerDelstockpointsParams = { + id: number; + }; + + type stockcontrollerGetpurchaseordersParams = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + orderNumber?: string; + stockPointId?: number; + }; + + type stockcontrollerGetstockpointsParams = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + }; + + type stockcontrollerGetstockrecordsParams = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + stockPointId?: number; + productSku?: string; + productName?: string; + }; + + type stockcontrollerGetstocksParams = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + productName?: string; + }; + + type stockcontrollerLosttransferParams = { + id: number; + }; + + type stockcontrollerReceivepurchaseorderParams = { + id: number; + }; + + type stockcontrollerReceivetransferParams = { + id: number; + }; + + type stockcontrollerUpdatepurchaseorderParams = { + id: number; + }; + + type stockcontrollerUpdatestockpointParams = { + id: number; + }; + + type stockcontrollerUpdatetransferParams = { + id: number; + }; + + type StockDTO = { + id?: number; + stockPointId?: number; + productSku?: string; + quantity?: number; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + productName?: string; + stockPoint?: Record[]; + }; + + type StockListRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: StockPaginatedRespone; + }; + + type StockPaginatedRespone = { + /** 当前页码 */ + page?: number; + /** 每页大小 */ + pageSize?: number; + /** 总记录数 */ + total?: number; + /** 数据列表 */ + items?: StockDTO[]; + }; + + type StockPoint = { + id?: number; + name?: string; + location?: string; + contactPerson?: string; + contactPhone?: string; + ignore?: boolean; + inCanada?: boolean; + isB?: boolean; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + }; + + type StockPointAllRespone = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: StockPoint[]; + }; + + type StockPointListRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: StockPointPaginatedRespone; + }; + + type StockPointPaginatedRespone = { + /** 当前页码 */ + page?: number; + /** 每页大小 */ + pageSize?: number; + /** 总记录数 */ + total?: number; + /** 数据列表 */ + items?: StockPoint[]; + }; + + type StockRecordDTO = { + id?: number; + stockPointId?: number; + productSku?: string; + operationType?: any; + quantityChange?: number; + operatorId?: number; + /** 创建时间 */ + createdAt: string; + note?: string; + productName?: string; + }; + + type StockRecordListRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: StockRecordPaginatedRespone; + }; + + type StockRecordPaginatedRespone = { + /** 当前页码 */ + page?: number; + /** 每页大小 */ + pageSize?: number; + /** 总记录数 */ + total?: number; + /** 数据列表 */ + items?: StockRecordDTO[]; + }; + + type Surcharges = { + type?: string; + amount?: Money; + }; + + type Time = { + hour?: string; + minute?: string; + }; + + type Tracking = { + id?: string; + tracking_provider?: string; + unique_id?: string; + transaction_number?: string; + primary_tracking_number?: string; + tracking_numbers?: string[]; + tracking_url?: string; + return_tracking_number?: string; + bol_number?: string; + pickup_confirmation_number?: string; + customs_invoice_url?: string; + rate?: Record; + labels?: any; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + products?: ShipmentItem[]; + }; + + type UpdateCategoryDTO = { + /** 分类名称 */ + name?: string; + }; + + type UpdateFlavorsDTO = { + /** 分类名称 */ + name?: string; + }; + + type UpdateProductDTO = { + /** 产品名称 */ + name?: string; + /** 产品描述 */ + description?: string; + /** sku */ + sku?: string; + /** 分类 ID */ + categoryId?: number; + }; + + type UpdatePurchaseOrderDTO = { + stockPointId?: number; + expectedArrivalTime?: string; + status?: 'draft' | 'submitted' | 'received'; + note?: string; + items?: PurchaseOrderItem[]; + }; + + type UpdateStockDTO = { + stockPointId?: number; + productSku?: string; + quantityChange?: number; + operationType?: 'in' | 'out'; + operatorId?: number; + note?: string; + }; + + type UpdateStockPointDTO = { + name?: string; + location?: string; + contactPerson?: string; + contactPhone?: string; + }; + + type UpdateStrengthDTO = { + /** 分类名称 */ + name?: string; + }; + + type UpdateVariationDTO = { + /** 产品名称 */ + name?: string; + /** SKU */ + sku?: string; + /** 常规价格 */ + regular_price?: number; + /** 销售价格 */ + sale_price?: number; + /** 是否促销中 */ + on_sale?: boolean; + }; + + type UpdateWpProductDTO = { + /** 变体名称 */ + name?: string; + /** SKU */ + sku?: string; + /** 常规价格 */ + regular_price?: number; + /** 销售价格 */ + sale_price?: number; + /** 是否促销中 */ + on_sale?: boolean; + }; + + type VariationDTO = { + /** ID */ + id: number; + /** wp网站ID */ + siteId: string; + /** wp产品ID */ + externalProductId: string; + /** wp变体ID */ + externalVariationId: string; + /** 对应WP产品表的ID */ + productId: number; + /** sku */ + sku?: string; + /** 变体名称 */ + name: string; + /** 常规价格 */ + regular_price?: number; + /** 销售价格 */ + sale_price?: number; + /** 是否促销中 */ + on_sale?: boolean; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + /** 变体构成成分 */ + constitution?: { sku?: string; quantity?: number }[]; + }; + + type webhookcontrollerHandlewoowebhookParams = { + siteId?: string; + }; + + type wpproductcontrollerGetwpproductsParams = { + /** 页码 */ + current?: number; + /** 每页大小 */ + pageSize?: number; + /** 产品名 */ + name?: string; + /** 站点ID */ + siteId?: string; + /** 产品状态 */ + status?: + | 'publish' + | 'draft' + | 'pending' + | 'private' + | 'trash' + | 'auto-draft' + | 'future' + | 'inherit'; + }; + + type wpproductcontrollerSetconstitutionParams = { + id: number; + }; + + type wpproductcontrollerSyncproductsParams = { + siteId: string; + }; + + type wpproductcontrollerUpdateproductParams = { + productId: string; + siteId: string; + }; + + type wpproductcontrollerUpdatevariationParams = { + variationId: string; + productId: string; + siteId: string; + }; + + type WpProductDTO = { + /** ID */ + id: number; + /** wp网站ID */ + siteId: string; + /** wp产品ID */ + externalProductId: string; + /** sku */ + sku?: string; + /** 产品名称 */ + name: string; + /** 产品状态 */ + status?: + | 'publish' + | 'draft' + | 'pending' + | 'private' + | 'trash' + | 'auto-draft' + | 'future' + | 'inherit'; + /** 常规价格 */ + regular_price?: number; + /** 销售价格 */ + sale_price?: number; + /** 是否促销中 */ + on_sale?: boolean; + /** 产品类型 */ + type?: 'simple' | 'variable'; + /** 创建时间 */ + createdAt: string; + /** 更新时间 */ + updatedAt: string; + /** 产品构成成分 */ + constitution?: { sku?: string; quantity?: number }[]; + /** 变体列表 */ + variations?: VariationDTO[]; + }; + + type WpProductListRes = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: WpProductPaginatedResponse; + }; + + type WpProductPaginatedResponse = { + /** 当前页码 */ + page?: number; + /** 每页大小 */ + pageSize?: number; + /** 总记录数 */ + total?: number; + /** 数据列表 */ + items?: WpProductDTO[]; + }; + + type WpSitesResponse = { + /** 状态码 */ + code?: number; + /** 是否成功 */ + success?: boolean; + /** 消息内容 */ + message?: string; + /** 响应数据 */ + data?: SiteConfig[]; + }; +} diff --git a/src/servers/api/user.ts b/src/servers/api/user.ts new file mode 100644 index 0000000..e264b03 --- /dev/null +++ b/src/servers/api/user.ts @@ -0,0 +1,74 @@ +// @ts-ignore +/* eslint-disable */ +import { request } from 'umi'; + +/** 此处后端没有提供注释 GET /user/ */ +export async function usercontrollerGetuser(options?: { [key: string]: any }) { + return request('/user/', { + method: 'GET', + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /user/add */ +export async function usercontrollerAdduser( + body: Record, + options?: { [key: string]: any }, +) { + return request('/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('/user/list', { + method: 'GET', + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /user/login */ +export async function usercontrollerLogin( + body: API.LoginDTO, + options?: { [key: string]: any }, +) { + return request('/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('/user/logout', { + method: 'POST', + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /user/toggleActive */ +export async function usercontrollerToggleactive( + body: Record, + options?: { [key: string]: any }, +) { + return request('/user/toggleActive', { + method: 'POST', + headers: { + 'Content-Type': 'text/plain', + }, + data: body, + ...(options || {}), + }); +} diff --git a/src/servers/api/webhook.ts b/src/servers/api/webhook.ts new file mode 100644 index 0000000..7bc69dd --- /dev/null +++ b/src/servers/api/webhook.ts @@ -0,0 +1,31 @@ +// @ts-ignore +/* eslint-disable */ +import { request } from 'umi'; + +/** 此处后端没有提供注释 GET /webhook/ */ +export async function webhookcontrollerTest(options?: { [key: string]: any }) { + return request('/webhook/', { + method: 'GET', + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /webhook/woocommerce */ +export async function webhookcontrollerHandlewoowebhook( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.webhookcontrollerHandlewoowebhookParams, + body: Record, + options?: { [key: string]: any }, +) { + return request('/webhook/woocommerce', { + method: 'POST', + headers: { + 'Content-Type': 'text/plain', + }, + params: { + ...params, + }, + data: body, + ...(options || {}), + }); +} diff --git a/src/servers/api/wpProduct.ts b/src/servers/api/wpProduct.ts new file mode 100644 index 0000000..c1bcb06 --- /dev/null +++ b/src/servers/api/wpProduct.ts @@ -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(`/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('/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( + `/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( + `/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(`/wp_product/sync/${param0}`, { + method: 'POST', + params: { ...queryParams }, + ...(options || {}), + }); +} diff --git a/src/utils/format.ts b/src/utils/format.ts new file mode 100644 index 0000000..53120bf --- /dev/null +++ b/src/utils/format.ts @@ -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( + 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 ''; + } +} diff --git a/src/utils/util.ts b/src/utils/util.ts new file mode 100644 index 0000000..c5ddf9d --- /dev/null +++ b/src/utils/util.ts @@ -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(); +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..133cfd8 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "./src/.umi/tsconfig.json" +} diff --git a/typings.d.ts b/typings.d.ts new file mode 100644 index 0000000..82c7dc7 --- /dev/null +++ b/typings.d.ts @@ -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; + } \ No newline at end of file