Commit 2e674eb70aab8799fb7f6d129359529ec7003a73

Authored by sanmu
1 parent ce613aab

feat: update order

.umirc.ts
... ... @@ -23,26 +23,24 @@ export default defineConfig({
23 23 path: '/',
24 24 redirect: '/order',
25 25 },
26   - // {
27   - // name: '首页',
28   - // path: '/home',
29   - // component: './Home',
30   - // },
31   - // {
32   - // name: '权限演示',
33   - // path: '/access',
34   - // component: './Access',
35   - // },
36   - // {
37   - // name: '用户',
38   - // path: '/user',
39   - // component: './User',
40   - // },
  26 + {
  27 + name: '登录',
  28 + path: '/login',
  29 + component: './Login',
  30 + layout: false,
  31 + },
  32 +
41 33 {
42 34 name: '订单管理',
43 35 path: '/order',
44 36 component: './Order',
45 37 },
  38 + {
  39 + name: '打印',
  40 + path: '/print',
  41 + component: './OrderPrint',
  42 + layout: false,
  43 + },
46 44 ],
47 45  
48 46 npmClient: 'pnpm',
... ...
.vscode/settings.json
1 1 {
2   - "cSpell.words": ["antd", "zhusen"]
  2 + "cSpell.words": ["antd", "Popconfirm", "zhusen"]
3 3 }
... ...
README.md
... ... @@ -26,3 +26,7 @@
26 26 ```
27 27 { title: '昵称', dataIndex: 'nickName', valueType: 'text', },
28 28 ```
  29 +
  30 +# 校验没生效
  31 +
  32 +chmod +x .husky/commit-msg chmod +x .husky/pre-commit
... ...
package-lock.json
... ... @@ -17,6 +17,7 @@
17 17 },
18 18 "devDependencies": {
19 19 "@inspir/pluto": "^1.0.5",
  20 + "@types/lodash": "^4.14.201",
20 21 "@types/react": "^18.2.31",
21 22 "@types/react-dom": "^18.2.14",
22 23 "husky": "^8.0.3",
... ... @@ -3065,6 +3066,12 @@
3065 3066 "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
3066 3067 "dev": true
3067 3068 },
  3069 + "node_modules/@types/lodash": {
  3070 + "version": "4.14.201",
  3071 + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.201.tgz",
  3072 + "integrity": "sha512-y9euML0cim1JrykNxADLfaG0FgD1g/yTHwUs/Jg9ZIU7WKj2/4IW9Lbb1WZbvck78W/lfGXFfe+u2EGfIJXdLQ==",
  3073 + "dev": true
  3074 + },
3068 3075 "node_modules/@types/minimist": {
3069 3076 "version": "1.2.5",
3070 3077 "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz",
... ... @@ -21520,6 +21527,12 @@
21520 21527 "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
21521 21528 "dev": true
21522 21529 },
  21530 + "@types/lodash": {
  21531 + "version": "4.14.201",
  21532 + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.201.tgz",
  21533 + "integrity": "sha512-y9euML0cim1JrykNxADLfaG0FgD1g/yTHwUs/Jg9ZIU7WKj2/4IW9Lbb1WZbvck78W/lfGXFfe+u2EGfIJXdLQ==",
  21534 + "dev": true
  21535 + },
21523 21536 "@types/minimist": {
21524 21537 "version": "1.2.5",
21525 21538 "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz",
... ...
package.json
... ... @@ -22,6 +22,7 @@
22 22 },
23 23 "devDependencies": {
24 24 "@inspir/pluto": "^1.0.5",
  25 + "@types/lodash": "^4.14.201",
25 26 "@types/react": "^18.2.31",
26 27 "@types/react-dom": "^18.2.14",
27 28 "husky": "^8.0.3",
... ...
pnpm-lock.yaml
... ... @@ -31,6 +31,9 @@ devDependencies:
31 31 '@inspir/pluto':
32 32 specifier: ^1.0.5
33 33 version: registry.npmjs.org/@inspir/pluto@1.0.5
  34 + '@types/lodash':
  35 + specifier: ^4.14.201
  36 + version: registry.npmjs.org/@types/lodash@4.14.201
34 37 '@types/react':
35 38 specifier: ^18.2.31
36 39 version: registry.npmjs.org/@types/react@18.2.31
... ... @@ -4280,6 +4283,12 @@ packages:
4280 4283 '@types/node': registry.npmjs.org/@types/node@20.8.8
4281 4284 dev: true
4282 4285  
  4286 + registry.npmjs.org/@types/lodash@4.14.201:
  4287 + resolution: {integrity: sha512-y9euML0cim1JrykNxADLfaG0FgD1g/yTHwUs/Jg9ZIU7WKj2/4IW9Lbb1WZbvck78W/lfGXFfe+u2EGfIJXdLQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@types/lodash/-/lodash-4.14.201.tgz}
  4288 + name: '@types/lodash'
  4289 + version: 4.14.201
  4290 + dev: true
  4291 +
4283 4292 registry.npmjs.org/@types/minimist@1.2.4:
4284 4293 resolution: {integrity: sha512-Kfe/D3hxHTusnPNRbycJE1N77WHDsdS4AjUYIzlDzhDrS47NrwuL3YW4VITxwR7KCVpzwgy4Rbj829KSSQmwXQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@types/minimist/-/minimist-1.2.4.tgz}
4285 4294 name: '@types/minimist'
... ...
request.json
... ... @@ -24,39 +24,76 @@
24 24 "name": "root",
25 25 "in": "body",
26 26 "schema": {
  27 + "$schema": "http://json-schema.org/draft-04/schema#",
27 28 "type": "object",
28   - "title": "title",
29 29 "properties": {
  30 + "bank": {
  31 + "type": "string"
  32 + },
  33 + "beginTime": {
  34 + "type": "string"
  35 + },
30 36 "current": {
31   - "type": "number",
32   - "title": "当前页码",
33   - "description": "当前页码"
  37 + "type": "number"
34 38 },
35   - "size": {
36   - "type": "string",
37   - "title": "每页条数",
38   - "description": "每页条数"
  39 + "customerContactNumber": {
  40 + "type": "string"
39 41 },
40   - "search": {
41   - "type": "object",
42   - "properties": {
43   - "mainOrderId": {
44   - "type": "string",
45   - "title": "主订单id",
46   - "description": "主订单id"
47   - },
48   - "productName": {
49   - "type": "string",
50   - "title": "商品名称",
51   - "description": "商品名称"
52   - }
53   - },
54   - "required": ["mainOrderId", "productName"],
55   - "title": "查询参数",
56   - "description": "查询参数"
  42 + "customerName": {
  43 + "type": "string"
  44 + },
  45 + "customerShippingAddress": {
  46 + "type": "string"
  47 + },
  48 + "endTime": {
  49 + "type": "string"
  50 + },
  51 + "id": {
  52 + "type": "number"
  53 + },
  54 + "institution": {
  55 + "type": "string"
  56 + },
  57 + "institutionContactName": {
  58 + "type": "string"
  59 + },
  60 + "invoicingStatus": {
  61 + "type": "string"
  62 + },
  63 + "logisticsMethod": {
  64 + "type": "string"
  65 + },
  66 + "orderStatus": {
  67 + "type": "string"
  68 + },
  69 + "pageSize": {
  70 + "type": "number"
  71 + },
  72 + "parameters": {
  73 + "type": "string"
  74 + },
  75 + "paymentChannel": {
  76 + "type": "string"
  77 + },
  78 + "paymentMethod": {
  79 + "type": "string"
  80 + },
  81 + "paymentTransactionId": {
  82 + "type": "string"
  83 + },
  84 + "productBelongBusiness": {
  85 + "type": "string"
  86 + },
  87 + "productName": {
  88 + "type": "string"
  89 + },
  90 + "salesCode": {
  91 + "type": "string"
  92 + },
  93 + "total": {
  94 + "type": "number"
57 95 }
58   - },
59   - "required": ["current", "size", "search"]
  96 + }
60 97 }
61 98 }
62 99 ],
... ... @@ -70,204 +107,115 @@
70 107 "data": {
71 108 "type": "object",
72 109 "properties": {
73   - "current": {
74   - "type": "number"
75   - },
76   - "pages": {
77   - "type": "number"
78   - },
79   - "records": {
  110 + "data": {
80 111 "type": "array",
81 112 "items": {
82 113 "type": "object",
83 114 "properties": {
84   - "main_order_id": {
85   - "type": "number"
  115 + "bank": {
  116 + "type": "string"
86 117 },
87   - "sales_code": {
  118 + "bankAccountNumber": {
88 119 "type": "string"
89 120 },
90   - "customer_name": {
  121 + "createTime": {
91 122 "type": "string"
92 123 },
93   - "customer_contact_number": {
  124 + "customerContactNumber": {
94 125 "type": "string"
95 126 },
96   - "customer_shipping_address": {
  127 + "customerName": {
97 128 "type": "string"
98 129 },
99   - "institution_contact_name": {
  130 + "customerShippingAddress": {
100 131 "type": "string"
101 132 },
  133 + "id": {
  134 + "type": "number"
  135 + },
102 136 "institution": {
103 137 "type": "string"
104 138 },
105   - "main_order_create_time": {
  139 + "institutionContactName": {
106 140 "type": "string"
107 141 },
108   - "main_order_update_time": {
  142 + "invoiceIdentificationNumber": {
109 143 "type": "string"
110 144 },
111   - "main_order_create_by_name": {
  145 + "notes": {
112 146 "type": "string"
113 147 },
114   - "main_order_update_by_name": {
115   - "type": "null"
116   - },
117   - "btns": {
118   - "type": "string",
119   - "description": "权限按钮"
  148 + "salesCode": {
  149 + "type": "string"
120 150 },
121   - "sub_orders": {
  151 + "subOrderInformationLists": {
122 152 "type": "array",
123 153 "items": {
124 154 "type": "object",
125 155 "properties": {
126   - "sub_order_id": {
127   - "type": "number"
128   - },
129   - "product_code": {
  156 + "id": {
130 157 "type": "number"
131 158 },
132   - "product_name": {
  159 + "invoicingStatus": {
133 160 "type": "string"
134 161 },
135   - "quantity": {
136   - "type": "number"
137   - },
138   - "product_price": {
  162 + "mainOrderId": {
139 163 "type": "number"
140 164 },
141   - "unit": {
  165 + "orderStatus": {
142 166 "type": "string"
143 167 },
144 168 "parameters": {
145   - "type": ["null", "string"]
146   - },
147   - "total_payment": {
148   - "type": "number"
149   - },
150   - "sub_order_payment": {
151   - "type": "number"
152   - },
153   - "is_cancel": {
154   - "type": "number"
155   - },
156   - "logistics_status": {
157 169 "type": "string"
158 170 },
159   - "payment_status": {
  171 + "paymentChannel": {
160 172 "type": "string"
161 173 },
162   - "payment_method": {
  174 + "productCode": {
163 175 "type": "string"
164 176 },
165   - "payment_channel": {
  177 + "productName": {
166 178 "type": "string"
167 179 },
168   - "payment_transaction_id": {
169   - "type": ["string", "null"]
170   - },
171   - "invoice_information": {
172   - "type": ["string", "null"]
173   - },
174   - "invoicing_status": {
175   - "type": "string"
176   - },
177   - "product_belong_department": {
178   - "type": "string"
179   - },
180   - "waybill_number": {
181   - "type": ["number", "null"]
182   - },
183   - "notes": {
184   - "type": ["string", "null"]
185   - },
186   - "examine_notes": {
187   - "type": ["null", "string"]
188   - },
189   - "order_status": {
190   - "type": "string"
191   - },
192   - "sub_order_create_time": {
193   - "type": "string"
194   - },
195   - "sub_order_update_time": {
196   - "type": "string"
197   - },
198   - "sub_order_create_by_name": {
  180 + "quantity": {
199 181 "type": "string"
200 182 },
201   - "sub_order_update_by_name": {
202   - "type": "null"
203   - },
204   - "btns": {
205   - "type": "string",
206   - "description": "权限按钮"
  183 + "subOrderPayment": {
  184 + "type": "number"
207 185 }
208 186 },
209 187 "required": [
210   - "sub_order_id",
211   - "product_code",
212   - "product_name",
213   - "quantity",
214   - "product_price",
215   - "unit",
  188 + "id",
  189 + "invoicingStatus",
  190 + "mainOrderId",
  191 + "orderStatus",
216 192 "parameters",
217   - "total_payment",
218   - "sub_order_payment",
219   - "is_cancel",
220   - "logistics_status",
221   - "payment_status",
222   - "payment_method",
223   - "payment_channel",
224   - "payment_transaction_id",
225   - "invoice_information",
226   - "invoicing_status",
227   - "product_belong_department",
228   - "waybill_number",
229   - "notes",
230   - "examine_notes",
231   - "order_status",
232   - "sub_order_create_time",
233   - "sub_order_update_time",
234   - "sub_order_create_by_name",
235   - "sub_order_update_by_name",
236   - "btns"
  193 + "paymentChannel",
  194 + "productCode",
  195 + "productName",
  196 + "quantity",
  197 + "subOrderPayment"
237 198 ]
238 199 }
  200 + },
  201 + "totalPayment": {
  202 + "type": "number"
239 203 }
240   - },
241   - "required": [
242   - "main_order_id",
243   - "sales_code",
244   - "customer_name",
245   - "customer_contact_number",
246   - "customer_shipping_address",
247   - "institution_contact_name",
248   - "institution",
249   - "main_order_create_time",
250   - "main_order_update_time",
251   - "main_order_create_by_name",
252   - "main_order_update_by_name",
253   - "sub_orders",
254   - "btns"
255   - ]
  204 + }
256 205 }
257 206 },
258   - "total": {
  207 + "pageSize": {
259 208 "type": "number"
260 209 },
261   - "size": {
  210 + "total": {
262 211 "type": "number"
263 212 }
264   - },
265   - "required": ["size"]
  213 + }
266 214 },
267 215 "message": {
268 216 "type": "string"
269 217 },
270   - "code": {
  218 + "result": {
271 219 "type": "number"
272 220 }
273 221 }
... ... @@ -297,6 +245,11 @@
297 245 "$schema": "http://json-schema.org/draft-04/schema#",
298 246 "type": "object",
299 247 "properties": {
  248 + "id": {
  249 + "type": "string",
  250 + "title": "订单编号",
  251 + "description": "订单编号"
  252 + },
300 253 "sales_code": {
301 254 "type": "string"
302 255 },
... ... @@ -320,6 +273,11 @@
320 273 "items": {
321 274 "type": "object",
322 275 "properties": {
  276 + "id": {
  277 + "type": "string",
  278 + "title": "子订单编号",
  279 + "description": "子订单编号"
  280 + },
323 281 "product_code": {
324 282 "type": "number"
325 283 },
... ... @@ -384,7 +342,8 @@
384 342 "payment_method",
385 343 "payment_channel",
386 344 "invoicing_status",
387   - "product_belong_department"
  345 + "product_belong_department",
  346 + "id"
388 347 ]
389 348 }
390 349 }
... ... @@ -396,7 +355,8 @@
396 355 "customer_shipping_address",
397 356 "institution_contact_name",
398 357 "sub_orders",
399   - "institution"
  358 + "institution",
  359 + "id"
400 360 ]
401 361 }
402 362 }
... ... @@ -554,7 +514,7 @@
554 514 }
555 515 }
556 516 }
557   - },
558   - "definitions": {}
559   - }
  517 + }
  518 + },
  519 + "definitions": {}
560 520 }
... ...
src/app.ts
... ... @@ -6,11 +6,12 @@ import '@inspir/assembly-css/dist/special.css';
6 6 import { message } from 'antd';
7 7 import { RESPONSE_CODE } from './constants/enum';
8 8  
9   -// import './style/global.less';
  9 +import './style/global.css';
10 10  
11 11 // 全局初始化数据配置,用于 Layout 用户信息和权限初始化
12 12 // 更多信息见文档:https://umijs.org/docs/api/runtime-config#getinitialstate
13 13 export async function getInitialState(): Promise<{ name: string }> {
  14 + // getUserInfo();
14 15 return { name: '@umijs/max' };
15 16 }
16 17  
... ...
src/components/ButtomConfirm/index.tsx 0 → 100644
  1 +import { Button, Popconfirm } from 'antd';
  2 +
  3 +const ButtonConfirm = ({
  4 + title,
  5 + description,
  6 + text,
  7 + className,
  8 + onConfirm,
  9 +}: {
  10 + title: string;
  11 + text: string;
  12 + description?: string;
  13 + className?: string;
  14 + onConfirm?: () => void;
  15 +}) => {
  16 + return (
  17 + <Popconfirm
  18 + placement="topLeft"
  19 + title={title}
  20 + description={description}
  21 + onConfirm={onConfirm}
  22 + okText="确认"
  23 + cancelText="取消"
  24 + >
  25 + <Button type="link" className={className}>
  26 + {text}
  27 + </Button>
  28 + </Popconfirm>
  29 + );
  30 +};
  31 +
  32 +export default ButtonConfirm;
... ...
src/models/user.ts
... ... @@ -2,9 +2,7 @@ import { useState } from &#39;react&#39;;
2 2  
3 3 // src/models/userModel.ts
4 4 export default function Page() {
5   - const [list, setList] = useState([]);
  5 + const { token, setToken } = useState('');
6 6  
7   - const getList = async () => {};
8   -
9   - return { list, getList };
  7 + return { token, setToken };
10 8 }
... ...
src/pages/Login/index.tsx 0 → 100644
  1 +import { LockOutlined, MobileOutlined, UserOutlined } from '@ant-design/icons';
  2 +import {
  3 + LoginForm,
  4 + ProConfigProvider,
  5 + ProFormCaptcha,
  6 + ProFormCheckbox,
  7 + ProFormText,
  8 +} from '@ant-design/pro-components';
  9 +import { history } from '@umijs/max';
  10 +import { Tabs, message, theme } from 'antd';
  11 +import { useState } from 'react';
  12 +
  13 +type LoginType = 'phone' | 'account';
  14 +
  15 +export default () => {
  16 + const { token } = theme.useToken();
  17 + const [loginType, setLoginType] = useState<LoginType>('phone');
  18 +
  19 + return (
  20 + <ProConfigProvider hashed={false}>
  21 + <div
  22 + style={{ backgroundColor: token.colorBgContainer }}
  23 + className="h-[100vh]"
  24 + >
  25 + <div className="flex items-center justify-center">
  26 + <LoginForm
  27 + title="订单管理"
  28 + onFinish={async () => {
  29 + history.push('/order');
  30 + }}
  31 + >
  32 + <Tabs
  33 + centered
  34 + activeKey={loginType}
  35 + onChange={(activeKey) => setLoginType(activeKey as LoginType)}
  36 + >
  37 + <Tabs.TabPane key={'account'} tab={'账号密码登录'} />
  38 + <Tabs.TabPane key={'phone'} tab={'手机号登录'} />
  39 + </Tabs>
  40 + {loginType === 'account' && (
  41 + <>
  42 + <ProFormText
  43 + name="username"
  44 + fieldProps={{
  45 + size: 'large',
  46 + prefix: <UserOutlined className={'prefixIcon'} />,
  47 + }}
  48 + placeholder={'用户名'}
  49 + rules={[
  50 + {
  51 + required: true,
  52 + message: '请输入用户名!',
  53 + },
  54 + ]}
  55 + />
  56 + <ProFormText.Password
  57 + name="password"
  58 + fieldProps={{
  59 + size: 'large',
  60 + prefix: <LockOutlined className={'prefixIcon'} />,
  61 + }}
  62 + placeholder={'密码'}
  63 + rules={[
  64 + {
  65 + required: true,
  66 + message: '请输入密码!',
  67 + },
  68 + ]}
  69 + />
  70 + </>
  71 + )}
  72 + {loginType === 'phone' && (
  73 + <>
  74 + <ProFormText
  75 + fieldProps={{
  76 + size: 'large',
  77 + prefix: <MobileOutlined className={'prefixIcon'} />,
  78 + }}
  79 + name="mobile"
  80 + placeholder={'手机号'}
  81 + rules={[
  82 + {
  83 + required: true,
  84 + message: '请输入手机号!',
  85 + },
  86 + {
  87 + pattern: /^1\d{10}$/,
  88 + message: '手机号格式错误!',
  89 + },
  90 + ]}
  91 + />
  92 + <ProFormCaptcha
  93 + fieldProps={{
  94 + size: 'large',
  95 + prefix: <LockOutlined className={'prefixIcon'} />,
  96 + }}
  97 + captchaProps={{
  98 + size: 'large',
  99 + }}
  100 + placeholder={'请输入验证码'}
  101 + captchaTextRender={(timing, count) => {
  102 + if (timing) {
  103 + return `${count} ${'获取验证码'}`;
  104 + }
  105 + return '获取验证码';
  106 + }}
  107 + name="captcha"
  108 + rules={[
  109 + {
  110 + required: true,
  111 + message: '请输入验证码!',
  112 + },
  113 + ]}
  114 + onGetCaptcha={async () => {
  115 + message.success('获取验证码成功!验证码为:1234');
  116 + }}
  117 + />
  118 + </>
  119 + )}
  120 + <div
  121 + style={{
  122 + marginBlockEnd: 24,
  123 + }}
  124 + >
  125 + <ProFormCheckbox noStyle name="autoLogin">
  126 + 自动登录
  127 + </ProFormCheckbox>
  128 + {/* <a
  129 + style={{
  130 + float: 'right',
  131 + }}
  132 + >
  133 + 忘记密码
  134 + </a> */}
  135 + </div>
  136 + </LoginForm>
  137 + </div>
  138 + </div>
  139 + </ProConfigProvider>
  140 + );
  141 +};
... ...
src/pages/Order/components/CheckModal.tsx 0 → 100644
  1 +import { ModalForm, ProFormTextArea } from '@ant-design/pro-components';
  2 +import { Form, message } from 'antd';
  3 +
  4 +export default ({ setCheckVisible }) => {
  5 + const [form] = Form.useForm<{ name: string; company: string }>();
  6 + return (
  7 + <ModalForm<{
  8 + name: string;
  9 + company: string;
  10 + }>
  11 + width={500}
  12 + open
  13 + title="审核"
  14 + form={form}
  15 + autoFocusFirstInput
  16 + modalProps={{
  17 + okText: '通过',
  18 + cancelText: '驳回',
  19 + destroyOnClose: true,
  20 + onCancel: () => {
  21 + setCheckVisible(false);
  22 + },
  23 + }}
  24 + submitTimeout={2000}
  25 + onFinish={async (values) => {
  26 + console.log(values.name);
  27 + message.success('提交成功');
  28 + return true;
  29 + }}
  30 + >
  31 + <div>请特别注意订单总金额与订单金额。</div>
  32 + <ProFormTextArea
  33 + width="lg"
  34 + name="name"
  35 + placeholder="若驳回,请填写驳回理由"
  36 + />
  37 + </ModalForm>
  38 + );
  39 +};
... ...
src/pages/Order/components/DeliverModal.tsx 0 → 100644
  1 +import {
  2 + ProColumns,
  3 + ProForm,
  4 + ProFormText,
  5 + ProTable,
  6 +} from '@ant-design/pro-components';
  7 +import { Button, Input, InputNumber, Modal } from 'antd';
  8 +import { cloneDeep } from 'lodash';
  9 +import { useEffect, useRef, useState } from 'react';
  10 +
  11 +const DeliverModal = ({ data: propsData, onClose }) => {
  12 + const [data, setData] = useState(propsData || {});
  13 + const form = useRef();
  14 +
  15 + useEffect(() => {
  16 + setData(propsData);
  17 + }, [propsData]);
  18 +
  19 + const handleChange = (key: string, index: number) => (e) => {
  20 + const newData = cloneDeep(data);
  21 + newData[index][key] = e.target.value;
  22 + setData(newData);
  23 + };
  24 + const columns: ProColumns<any>[] = [
  25 + {
  26 + title: '商品编号',
  27 + width: 80,
  28 + dataIndex: 'name',
  29 + },
  30 + {
  31 + title: '商品名称',
  32 + dataIndex: 'containers',
  33 + align: 'right',
  34 + },
  35 + {
  36 + title: '商品数量',
  37 + width: 80,
  38 + dataIndex: 'status',
  39 + },
  40 + {
  41 + title: '物流方式',
  42 + width: 180,
  43 + key: 'paymentChannel',
  44 + render: (_, record, index) => (
  45 + <Input
  46 + value={record.paymentChannel}
  47 + onChange={handleChange('paymentChannel', index)}
  48 + />
  49 + ),
  50 + },
  51 + {
  52 + title: '物流单号',
  53 + width: 180,
  54 + key: 'productCode',
  55 + render: (_, record, index) => (
  56 + <InputNumber
  57 + value={record.productCode}
  58 + onChange={handleChange('productCode', index)}
  59 + />
  60 + ),
  61 + },
  62 + ];
  63 +
  64 + return (
  65 + <Modal
  66 + open
  67 + width={800}
  68 + title="发货"
  69 + onOk={() => {
  70 + console.log(data);
  71 + onClose();
  72 + }}
  73 + onCancel={() => {
  74 + onClose();
  75 + }}
  76 + >
  77 + <strong>将物流方式和物流单号更新到下方所有订单</strong>
  78 + <ProForm
  79 + layout="inline"
  80 + submitter={false}
  81 + className="mb-8"
  82 + formRef={form}
  83 + >
  84 + <ProFormText name="paymentChannel" label="物流方式"></ProFormText>
  85 + <ProFormText name="productCode" label="物流单号"></ProFormText>
  86 + <Button
  87 + type="primary"
  88 + onClick={() => {
  89 + const values = form.current.getFieldsValue();
  90 + let newData = cloneDeep(data);
  91 + newData = newData.map((item) => ({
  92 + ...item,
  93 + paymentChannel: values.paymentChannel,
  94 + productCode: values.productCode, // 物流单号?
  95 + }));
  96 + setData(newData);
  97 + }}
  98 + >
  99 + 批量更新
  100 + </Button>
  101 + </ProForm>
  102 + <ProTable<any>
  103 + className="px-0"
  104 + dataSource={data}
  105 + rowKey="key"
  106 + pagination={false}
  107 + columns={columns}
  108 + search={false}
  109 + dateFormatter="string"
  110 + options={false}
  111 + />
  112 + </Modal>
  113 + );
  114 +};
  115 +
  116 +export default DeliverModal;
... ...
src/pages/Order/components/OrderDrawer.tsx
1   -// import { PlusOutlined } from '@ant-design/icons';
2   -import { useRef,useState,Key } from 'react';
3 1 import { postErpOrderAdd } from '@/services';
4   -import { DrawerForm, ProFormText, ProFormList, ProFormGroup, ProCard, FormListActionType } from '@ant-design/pro-components';
  2 +import {
  3 + DrawerForm,
  4 + FormListActionType,
  5 + ProCard,
  6 + ProFormGroup,
  7 + ProFormList,
  8 + ProFormText,
  9 +} from '@ant-design/pro-components';
5 10 import { Form, message } from 'antd';
  11 +import { useEffect, useRef } from 'react';
  12 +import { useFieldAuth } from '../hooks';
  13 +import { OPERATION_TYPE } from '../type.d';
6 14  
7   -const waitTime = (time: number = 100) => {
8   - return new Promise((resolve) => {
9   - setTimeout(() => {
10   - resolve(true);
11   - }, time);
  15 +export default ({ onClose, data }) => {
  16 + const { authFields } = useFieldAuth({
  17 + operation: data?.id ? OPERATION_TYPE.EDIT : OPERATION_TYPE.CREATE,
12 18 });
13   -};
14   -
15   -
16   -
17   -export default ({ onClose }) => {
18   - const [expandedRowKeys, setExpandedRowKeys] = useState<readonly Key[]>([]);
19 19 const [form] = Form.useForm<{ name: string; company: string }>();
20 20 const actionRef = useRef<
21 21 FormListActionType<{
... ... @@ -23,8 +23,12 @@ export default ({ onClose }) =&gt; {
23 23 }>
24 24 >();
25 25 //作为商品行号
26   - const rowRumber = useRef(0);
27   -
  26 + const rowNumber = useRef(0);
  27 +
  28 + useEffect(() => {
  29 + form.setFieldsValue({ ...data });
  30 + }, [data]);
  31 +
28 32 return (
29 33 <DrawerForm<{
30 34 name: string;
... ... @@ -58,7 +62,7 @@ export default ({ onClose }) =&gt; {
58 62 return true;
59 63 }}
60 64 onOpenChange={(val) => {
61   - !val && onClose();
  65 + return !val && onClose();
62 66 }}
63 67 >
64 68 <h2>订单基本信息</h2>
... ... @@ -67,18 +71,21 @@ export default ({ onClose }) =&gt; {
67 71 width="lg"
68 72 label="订单编号"
69 73 placeholder="请输入订单编号"
  74 + disabled={authFields.id}
70 75 />
71 76 <ProFormText
72 77 width="lg"
73 78 name="salesCode"
74 79 label="销售代号"
75 80 placeholder="请输入销售代号"
  81 + disabled={authFields.salesCode}
76 82 />
77 83 <ProFormText
78 84 name="customerName"
79 85 width="lg"
80 86 label="收货人"
81 87 placeholder="请输入收货人"
  88 + disabled={authFields.customerName}
82 89 />
83 90 <ProFormText
84 91 width="lg"
... ... @@ -182,14 +189,23 @@ export default ({ onClose }) =&gt; {
182 189  
183 190 <h2>商品信息</h2>
184 191 <ProFormList
185   - name="subOrders"
  192 + name="subOrderInformationLists"
186 193 label=""
187   - initialValue={[{ productCode: "", productName: "", quantity: "", productPrice: "", parameters: "", subOrderPayment: "" }]}
  194 + initialValue={[
  195 + {
  196 + productCode: '',
  197 + productName: '',
  198 + quantity: '',
  199 + productPrice: '',
  200 + parameters: '',
  201 + subOrderPayment: '',
  202 + },
  203 + ]}
188 204 actionGuard={{
189 205 beforeAddRow: async (defaultValue, insertIndex) => {
190 206 return new Promise((resolve) => {
191 207 console.log(defaultValue, insertIndex);
192   - rowRumber.current=1;
  208 + rowNumber.current = 1;
193 209 setTimeout(() => resolve(true), 1000);
194 210 });
195 211 },
... ... @@ -200,18 +216,17 @@ export default ({ onClose }) =&gt; {
200 216 resolve(false);
201 217 return;
202 218 }
203   - rowRumber.current=1;
  219 + rowNumber.current = 1;
204 220 setTimeout(() => resolve(true), 1000);
205 221 });
206 222 },
207 223 }}
208   - itemRender={({ listDom, action }, { record }) => {
209   - const list = actionRef.current?.getList();
  224 + itemRender={({ listDom, action }) => {
210 225 return (
211 226 <ProCard
212 227 bordered
213 228 extra={action}
214   - title={"商品"+(rowRumber.current++)}
  229 + title={'商品' + rowNumber.current++}
215 230 style={{
216 231 marginBlockEnd: 8,
217 232 }}
... ...
src/pages/Order/constant.ts 0 → 100644
  1 +export const MAIN_ORDER_COLUMNS = [
  2 + {
  3 + title: '订单列表',
  4 + width: 120,
  5 + dataIndex: 'name',
  6 + search: false,
  7 + },
  8 + {
  9 + title: '订单编号',
  10 + dataIndex: 'id',
  11 + valueType: 'text',
  12 + hideInTable: true,
  13 + },
  14 + {
  15 + title: '销售代表',
  16 + dataIndex: 'salesCode',
  17 + valueType: 'text',
  18 + hideInTable: true,
  19 + },
  20 + {
  21 + title: '收货人',
  22 + dataIndex: 'customerName',
  23 + valueType: 'text',
  24 + hideInTable: true,
  25 + },
  26 + {
  27 + title: '收货人联系电话',
  28 + dataIndex: 'customerContactNumber',
  29 + valueType: 'text',
  30 + hideInTable: true,
  31 + },
  32 + {
  33 + title: '单位',
  34 + dataIndex: 'institution',
  35 + valueType: 'text',
  36 + hideInTable: true,
  37 + },
  38 + {
  39 + title: '单位联系人',
  40 + dataIndex: 'institutionContactName',
  41 + valueType: 'text',
  42 + hideInTable: true,
  43 + },
  44 + {
  45 + title: '收货人地址',
  46 + dataIndex: 'customerShippingAddress',
  47 + valueType: 'text',
  48 + hideInTable: true,
  49 + },
  50 + {
  51 + title: '商品名称',
  52 + dataIndex: 'productName',
  53 + valueType: 'text',
  54 + hideInTable: true,
  55 + },
  56 + {
  57 + title: '商品参数',
  58 + dataIndex: 'parameters',
  59 + valueType: 'text',
  60 + hideInTable: true,
  61 + },
  62 + {
  63 + title: '订单状态',
  64 + dataIndex: 'orderStatus',
  65 + valueType: 'text',
  66 + hideInTable: true,
  67 + },
  68 + {
  69 + title: '支付方式',
  70 + dataIndex: 'paymentStatus',
  71 + valueType: 'text',
  72 + hideInTable: true,
  73 + },
  74 + {
  75 + title: '物流方式',
  76 + dataIndex: 'logisticsMethod',
  77 + valueType: 'text',
  78 + hideInTable: true,
  79 + },
  80 + {
  81 + title: '支付渠道',
  82 + dataIndex: 'paymentChannel',
  83 + valueType: 'text',
  84 + hideInTable: true,
  85 + },
  86 + {
  87 + title: '银行名称',
  88 + dataIndex: 'bank',
  89 + valueType: 'text',
  90 + hideInTable: true,
  91 + },
  92 + {
  93 + title: '支付流水',
  94 + dataIndex: 'paymentTransactionId',
  95 + valueType: 'text',
  96 + hideInTable: true,
  97 + },
  98 + {
  99 + title: '所属部门',
  100 + dataIndex: 'productBelongBusiness',
  101 + valueType: 'text',
  102 + hideInTable: true,
  103 + },
  104 + {
  105 + title: '创建日期',
  106 + dataIndex: 'createTime',
  107 + valueType: 'dateRange',
  108 + hideInTable: true,
  109 + search: {
  110 + transform: (value) => {
  111 + return {
  112 + startTime: value[0],
  113 + endTime: value[1],
  114 + };
  115 + },
  116 + },
  117 + },
  118 + {
  119 + title: '开票状态',
  120 + dataIndex: 'invoicingStatus',
  121 + valueType: 'text',
  122 + hideInTable: true,
  123 + },
  124 + {
  125 + title: '开票日期',
  126 + dataIndex: 'invoicingTime',
  127 + valueType: 'dateRange',
  128 + hideInTable: true,
  129 + search: {
  130 + transform: (value) => {
  131 + return {
  132 + startTime: value[0],
  133 + endTime: value[1],
  134 + };
  135 + },
  136 + },
  137 + },
  138 +];
  139 +
  140 +export const SUB_ORDER_COLUMNS = [
  141 + { title: 'ID', dataIndex: 'id', key: 'id' },
  142 + { title: '商品编码', dataIndex: 'productCode', key: 'productCode' },
  143 + { title: '商品名称', dataIndex: 'productName', key: 'productName' },
  144 + { title: '商品参数', dataIndex: 'parameters', key: 'parameters' },
  145 + { title: '商品数量', dataIndex: 'quantity', key: 'quantity' },
  146 + {
  147 + title: '子订单金额(¥)',
  148 + dataIndex: 'subOrderPayment',
  149 + key: 'subOrderPayment',
  150 + },
  151 + {
  152 + title: '支付方式',
  153 + dataIndex: 'paymentMethod',
  154 + key: 'paymentMethod',
  155 + },
  156 + {
  157 + title: '支付渠道',
  158 + dataIndex: 'paymentChannel',
  159 + key: 'paymentChannel',
  160 + },
  161 + {
  162 + title: '支付流水',
  163 + dataIndex: 'paymentTransactionId',
  164 + key: 'paymentTransactionId',
  165 + },
  166 + {
  167 + title: '物流方式',
  168 + dataIndex: 'logisticsMethod',
  169 + key: 'logisticsMethod',
  170 + },
  171 + { title: '物流单号', dataIndex: 'serialNumber', key: 'serialNumber' },
  172 + {
  173 + title: '开票状态',
  174 + dataIndex: 'invoicingStatus',
  175 + key: 'invoicingStatus',
  176 + component: 'tag',
  177 + },
  178 + {
  179 + title: '订单状态',
  180 + dataIndex: 'orderStatus',
  181 + key: 'orderStatus',
  182 + component: 'tag',
  183 + },
  184 +];
... ...
src/pages/Order/hooks.ts 0 → 100644
  1 +import { useModel } from 'umi';
  2 +import { OPERATION_TYPE, ROLE } from './type.d';
  3 +
  4 +function setAllValuesToTrue(obj: Record<string, boolean | object>) {
  5 + return Object.keys(obj).reduce(
  6 + (result, key) => {
  7 + if (typeof obj[key] === 'object') {
  8 + result[key] = setAllValuesToTrue(obj[key] as Record<string, object>);
  9 + } else {
  10 + result[key] = true;
  11 + }
  12 + return result;
  13 + },
  14 + {} as Record<string, boolean | object>,
  15 + );
  16 +}
  17 +
  18 +// 获取用户可编辑字段
  19 +export const useFieldAuth = ({ operation }: { operation: OPERATION_TYPE }) => {
  20 + const { role } = useModel('user');
  21 +
  22 + let authFields = {
  23 + bank: false,
  24 + bankAccountNumber: false,
  25 + createTime: false,
  26 + customerContactNumber: false,
  27 + customerName: false,
  28 + customerShippingAddress: false,
  29 + id: false,
  30 + institution: false,
  31 + institutionContactName: false,
  32 + invoiceIdentificationNumber: false,
  33 + notes: false,
  34 + salesCode: false,
  35 + subOrderInformationLists: {
  36 + id: false,
  37 + invoicingStatus: false,
  38 + mainOrderId: false,
  39 + orderStatus: false,
  40 + parameters: false,
  41 + paymentChannel: false,
  42 + productCode: false,
  43 + productName: false,
  44 + quantity: false,
  45 + subOrderPayment: false,
  46 + },
  47 + } as Record<string, boolean | object>;
  48 +
  49 + if (operation === OPERATION_TYPE.CREATE) {
  50 + return authFields;
  51 + } else if (operation === OPERATION_TYPE.EDIT) {
  52 + if (role === ROLE.ADMIN) {
  53 + return authFields;
  54 + } else if (role === ROLE.SALESMAN) {
  55 + // 将所有的字段设置为没有权限编辑
  56 + authFields = setAllValuesToTrue(authFields);
  57 + // 筛选字段为可编辑
  58 + authFields = {
  59 + ...authFields,
  60 + invoiceInformation: false,
  61 + };
  62 + }
  63 + }
  64 + return { authFields };
  65 +};
... ...
src/pages/Order/index.tsx
  1 +import ButtonConfirm from '@/components/ButtomConfirm';
1 2 import { postErpOrderListByPage } from '@/services';
2 3 import {
3 4 PageContainer,
4 5 ProColumns,
5 6 ProTable,
6 7 } from '@ant-design/pro-components';
7   -import { Button, Checkbox, Divider, Flex, Space } from 'antd';
8   -import React, { Key, useState } from 'react';
  8 +import { Button, Divider, Flex, Space, Tag, message } from 'antd';
  9 +import { Key, useState } from 'react';
  10 +import CheckModal from './components/CheckModal';
  11 +import DeliverModal from './components/DeliverModal';
9 12 import OrderDrawer from './components/OrderDrawer';
  13 +import { MAIN_ORDER_COLUMNS, SUB_ORDER_COLUMNS } from './constant';
10 14 import './index.less';
  15 +import { OrderListItemType, OrderType } from './type.d';
11 16  
12   -const TableList: React.FC<unknown> = () => {
  17 +const OrderPage = () => {
13 18 const [orderDrawerVisible, setOrderDrawerVisible] = useState<boolean>(false);
  19 + const [checkVisible, setCheckVisible] = useState<boolean>(false);
  20 + const [deliverVisible, setDeliverVisible] = useState<boolean>(false);
14 21 const [expandedRowKeys, setExpandedRowKeys] = useState<Key[]>([]);
15   - const [selectedItems, setSelectedItems] = useState([]);
16   - const [orderRow, setOrderRow] = useState<[]>([]);
  22 + const [orderRow, setOrderRow] = useState<Partial<OrderType>>({});
17 23 const [subOrderShowText, setSubOrderShowText] = useState('订单详情');
18 24  
19   - const onCheckboxChange = (itemKey: never) => {
20   - const newSelectedItems = selectedItems.includes(itemKey)
21   - ? selectedItems.filter((key) => key !== itemKey)
22   - : [...selectedItems, itemKey];
  25 + const [selectedRows, setSelectedRows] = useState({});
  26 + const [selectedRowObj, setSelectedRowObj] = useState({});
23 27  
24   - setSelectedItems(newSelectedItems);
25   - };
  28 + // const onCheckboxChange = (itemKey: number) => {
  29 + // const newSelectedItems = selectedItems.includes(itemKey)
  30 + // ? selectedItems.filter((key) => key !== itemKey)
  31 + // : [...selectedItems, itemKey];
26 32  
27   - const a = 2;
28   - if (a == 2) {
29   - }
  33 + // setSelectedItems(newSelectedItems);
  34 + // };
30 35  
31 36 // 主订单内容渲染
32   - const MainOrderColunmRender = ({ record }) => {
  37 + const MainOrderColumnRender = ({ record }: { record: OrderListItemType }) => {
  38 + const handleExpand = (key: number) => {
  39 + if (expandedRowKeys.includes(key)) {
  40 + setSubOrderShowText('查看详情');
  41 + } else {
  42 + setSubOrderShowText('收起详情');
  43 + }
  44 + const newExpandedRowKeys = expandedRowKeys.includes(key)
  45 + ? expandedRowKeys.filter((k) => k !== key)
  46 + : [...expandedRowKeys, key];
  47 +
  48 + setExpandedRowKeys(newExpandedRowKeys);
  49 + };
33 50 return (
34 51 <Flex vertical={true}>
35 52 {/* 编号、时间、销售信息 */}
36 53 <Flex justify="space-between" className="px-2 py-4 bg-gray-100">
37   - <Checkbox
38   - onChange={() => onCheckboxChange(record.id)}
39   - checked={selectedItems.includes(record.id)}
40   - >
41   - <Flex wrap="wrap" gap="middle">
42   - <div>{record.createTime}</div>
43   - <div>订单编号:{record.id}</div>
44   - </Flex>
45   - </Checkbox>
  54 + {/* <Checkbox
  55 + onChange={() => onCheckboxChange(record.main_order_id)}
  56 + checked={selectedItems.includes(record.main_order_id)}
  57 + > */}
  58 + <Flex wrap="wrap" gap="middle">
  59 + <div>{record.createTime}</div>
  60 + <div>订单编号:{record.main_order_id}</div>
  61 + </Flex>
  62 + {/* </Checkbox> */}
46 63 </Flex>
47 64 {/* 收货、开票、备注信息 */}
48 65 <Flex justify="space-between" className="px-2 py-4">
49 66 <Space split={<Divider type="vertical" align="center" />}>
50 67 <Space.Compact direction="vertical" className="gap-2">
51 68 <div>
52   - 收货信息:收货人:{record.customerName} 联系方式:
53   - {record.customerContactNumber} 单位联系人:
54   - {record.institutionContactName} 单位名称:{record.institution}{' '}
55   - 收货地址:{record.customerShippingAddress}
  69 + 收货信息:
  70 + <Space
  71 + split={<span className="text-blue-300">|</span>}
  72 + className="ml-2"
  73 + >
  74 + <span>收货人:{record.customerName}</span>
  75 + <span>
  76 + 联系方式:
  77 + {record.customerContactNumber}
  78 + </span>
  79 + <span>
  80 + 单位联系人:
  81 + {record.institutionContactName}
  82 + </span>
  83 + <span>单位名称:{record.institution}</span>
  84 + <span> 收货地址:{record.customerShippingAddress}</span>
  85 + </Space>
56 86 </div>
57 87 <div>
58   - 开票信息:开户银行:{record.bank} 银行账号:
59   - {record.bankAccountNumber} 识别号:
60   - {record.invoiceIdentificationNumber}
  88 + 开票信息:
  89 + <Space
  90 + split={<span className="text-blue-300">|</span>}
  91 + className="ml-2"
  92 + >
  93 + <span>开户银行:{record.bank}</span>
  94 + <span>
  95 + 银行账号:
  96 + {record.bankAccountNumber}
  97 + </span>
  98 + <span>
  99 + 识别号:
  100 + {record.invoiceIdentificationNumber}
  101 + </span>
  102 + </Space>
61 103 </div>
62 104 <div>
63   - 备&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注:{record.notes}
  105 + 备&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注:
  106 + <span className="ml-2">{record.notes}</span>
64 107 </div>
65 108 </Space.Compact>
66 109 </Space>
... ... @@ -70,37 +113,66 @@ const TableList: React.FC&lt;unknown&gt; = () =&gt; {
70 113 <div>
71 114 总金额:<span className="text-lg">{record.totalPayment}¥</span>
72 115 </div>
73   - <div>
74   - <Button className="p-0 pe-2" type="link">
75   - 确认收货
76   - </Button>
77   - <Button className="p-0 pe-2" type="link">
  116 + <Space>
  117 + <Button
  118 + className="p-0"
  119 + type="link"
  120 + onClick={() => {
  121 + if (!selectedRowObj[record.id]?.length) {
  122 + return message.error('请选择选择子订单');
  123 + }
  124 + setSelectedRows(selectedRowObj[record.id]);
  125 + setDeliverVisible(true);
  126 + }}
  127 + >
78 128 发货
79 129 </Button>
80   - <Button className="p-0 pe-2" type="link">
  130 + <Button
  131 + className="p-0"
  132 + type="link"
  133 + onClick={() => {
  134 + window.print();
  135 + }}
  136 + >
81 137 打印
82 138 </Button>
83   - <Button className="p-0 pe-2" type="link">
84   - 开票
85   - </Button>
  139 + <ButtonConfirm
  140 + className="p-0"
  141 + title="确认开票?"
  142 + text="开票"
  143 + onConfirm={() => {}}
  144 + />
86 145 <Button
87   - className="p-0 pe-2"
  146 + className="p-0"
88 147 type="link"
89   - onClick={() => setOrderDrawerVisible(true)}
  148 + onClick={() => {
  149 + setOrderDrawerVisible(true);
  150 + setOrderRow(record);
  151 + }}
90 152 >
91 153 编辑
92 154 </Button>
93   - <Button className="p-0 pe-2" type="link">
  155 + <Button
  156 + className="p-0"
  157 + type="link"
  158 + onClick={() => {
  159 + setCheckVisible(true);
  160 + }}
  161 + >
94 162 审核
95 163 </Button>
96   - <Button className="p-0" type="link">
97   - 作废
98   - </Button>
99   - </div>
  164 + <ButtonConfirm
  165 + className="p-0"
  166 + title="确认作废?"
  167 + text="作废"
  168 + onConfirm={() => {}}
  169 + />
  170 + </Space>
100 171 </Space.Compact>
101 172 <Space.Compact direction="vertical">
102 173 <Button
103 174 type="primary"
  175 + // todo change main_order_id
104 176 onClick={() => handleExpand(record.id)}
105 177 size="small"
106 178 >
... ... @@ -112,264 +184,98 @@ const TableList: React.FC&lt;unknown&gt; = () =&gt; {
112 184 </Flex>
113 185 );
114 186 };
115   - const [data, setData] = useState([]);
116   -
117   - const tableListDataSource: TableListItem[] = [];
118 187  
119 188 // 主订单列表
120   - const mainOrdersColumns: ProColumns<TableListItem>[] = [
121   - {
122   - title: '订单列表',
123   - width: 120,
124   - dataIndex: 'name',
125   - search: false,
126   - render: (text, record) => {
127   - return <MainOrderColunmRender record={record} />;
128   - },
129   - },
130   - {
131   - title: '订单编号',
132   - dataIndex: 'id',
133   - valueType: 'text',
134   - hideInTable: true,
135   - },
136   - {
137   - title: '销售代表',
138   - dataIndex: 'salesCode',
139   - valueType: 'text',
140   - hideInTable: true,
141   - },
142   - {
143   - title: '收货人',
144   - dataIndex: 'customerName',
145   - valueType: 'text',
146   - hideInTable: true,
147   - },
148   - {
149   - title: '收货人联系电话',
150   - dataIndex: 'customerContactNumber',
151   - valueType: 'text',
152   - hideInTable: true,
153   - },
154   - {
155   - title: '单位',
156   - dataIndex: 'institution',
157   - valueType: 'text',
158   - hideInTable: true,
159   - },
160   - {
161   - title: '单位联系人',
162   - dataIndex: 'institutionContactName',
163   - valueType: 'text',
164   - hideInTable: true,
165   - },
166   - {
167   - title: '收货人地址',
168   - dataIndex: 'customerShippingAddress',
169   - valueType: 'text',
170   - hideInTable: true,
171   - },
172   - {
173   - title: '商品名称',
174   - dataIndex: 'productName',
175   - valueType: 'text',
176   - hideInTable: true,
177   - },
178   - {
179   - title: '商品参数',
180   - dataIndex: 'parameters',
181   - valueType: 'text',
182   - hideInTable: true,
183   - },
184   - {
185   - title: '订单状态',
186   - dataIndex: 'orderStatus',
187   - valueType: 'text',
188   - hideInTable: true,
189   - },
190   - {
191   - title: '支付方式',
192   - dataIndex: 'paymentStatus',
193   - valueType: 'text',
194   - hideInTable: true,
195   - },
196   - {
197   - title: '物流方式',
198   - dataIndex: 'logisticsMethod',
199   - valueType: 'text',
200   - hideInTable: true,
201   - },
202   - {
203   - title: '支付渠道',
204   - dataIndex: 'paymentChannel',
205   - valueType: 'text',
206   - hideInTable: true,
207   - },
208   - {
209   - title: '银行名称',
210   - dataIndex: 'bank',
211   - valueType: 'text',
212   - hideInTable: true,
213   - },
214   - {
215   - title: '支付流水',
216   - dataIndex: 'paymentTransactionId',
217   - valueType: 'text',
218   - hideInTable: true,
219   - },
220   - {
221   - title: '所属部门',
222   - dataIndex: 'productBelongBusiness',
223   - valueType: 'text',
224   - hideInTable: true,
225   - },
226   - {
227   - title: '创建日期',
228   - dataIndex: 'createTime',
229   - valueType: 'dateRange',
230   - hideInTable: true,
231   - search: {
232   - transform: (value) => {
233   - return {
234   - startTime: value[0],
235   - endTime: value[1],
236   - };
237   - },
238   - },
239   - },
240   - {
241   - title: '开票状态',
242   - dataIndex: 'invoicingStatus',
243   - valueType: 'text',
244   - hideInTable: true,
245   - },
246   - {
247   - title: '开票日期',
248   - dataIndex: 'invoicingTime',
249   - valueType: 'dateRange',
250   - hideInTable: true,
251   - search: {
252   - transform: (value) => {
253   - return {
254   - startTime: value[0],
255   - endTime: value[1],
256   - };
257   - },
258   - },
  189 + const mainOrdersColumns: ProColumns<OrderType>[] = MAIN_ORDER_COLUMNS.map(
  190 + (item) => {
  191 + if (item.dataIndex === 'name') {
  192 + return {
  193 + ...item,
  194 + render: (text, record) => {
  195 + return <MainOrderColumnRender record={record} />;
  196 + },
  197 + };
  198 + }
  199 + return item;
259 200 },
260   - ];
261   - const handleExpand = (key: number) => {
262   - if (expandedRowKeys.includes(key)) {
263   - setSubOrderShowText('订单详情');
264   - } else {
265   - setSubOrderShowText('收起订单');
266   - }
267   - const newExpandedRowKeys = expandedRowKeys.includes(key)
268   - ? expandedRowKeys.filter((k) => k !== key)
269   - : [...expandedRowKeys, key];
270   -
271   - setExpandedRowKeys(newExpandedRowKeys);
272   - };
  201 + );
273 202  
274 203 const expandedRowRender = (record) => {
275 204 let subOrders = record.subOrderInformationLists;
276   - console.log(subOrders);
  205 +
277 206 return (
278 207 <ProTable
279   - columns={[
280   - { title: 'ID', dataIndex: 'id', key: 'id' },
281   - { title: '商品编码', dataIndex: 'productCode', key: 'productCode' },
282   - { title: '商品名称', dataIndex: 'productName', key: 'productName' },
283   - { title: '商品参数', dataIndex: 'parameters', key: 'parameters' },
284   - { title: '商品数量', dataIndex: 'quantity', key: 'quantity' },
285   - {
286   - title: '子订单金额(¥)',
287   - dataIndex: 'subOrderPayment',
288   - key: 'subOrderPayment',
289   - },
290   - {
291   - title: '支付方式',
292   - dataIndex: 'paymentMethod',
293   - key: 'paymentMethod',
294   - },
295   - {
296   - title: '支付渠道',
297   - dataIndex: 'paymentChannel',
298   - key: 'paymentChannel',
299   - },
300   - {
301   - title: '支付流水',
302   - dataIndex: 'paymentTransactionId',
303   - key: 'paymentTransactionId',
304   - },
305   - {
306   - title: '物流方式',
307   - dataIndex: 'logisticsMethod',
308   - key: 'logisticsMethod',
309   - },
310   - { title: '物流单号', dataIndex: 'serialNumber', key: 'serialNumber' },
311   - {
312   - title: '开票状态',
313   - dataIndex: 'invoicingStatus',
314   - key: 'invoicingStatus',
315   - },
316   - { title: '订单状态', dataIndex: 'orderStatus', key: 'orderStatus' },
317   - {
318   - title: '操作',
319   - dataIndex: 'operation',
320   - key: 'operation',
321   - align: 'center',
  208 + columns={(SUB_ORDER_COLUMNS as any)
  209 + .map((item) => {
  210 + if (item.component === 'tag') {
  211 + return {
  212 + ...item,
  213 + render: (text: string) => {
  214 + let color = 'gold';
  215 + if (text === '已开票' || text === '已审核') {
  216 + color = 'green';
  217 + }
  218 + return <Tag color={color}>{text}</Tag>;
  219 + },
  220 + };
  221 + }
  222 + return item;
  223 + })
  224 + .concat([
  225 + {
  226 + title: '操作',
  227 + dataIndex: 'operation',
  228 + key: 'operation',
  229 + align: 'center',
  230 + render: () => (
  231 + <Flex>
  232 + <Button type="link" size="small">
  233 + 编辑
  234 + </Button>
  235 + <Button
  236 + type="link"
  237 + size="small"
  238 + onClick={() => {
  239 + setCheckVisible(true);
  240 + setOrderRow(record);
  241 + }}
  242 + >
  243 + 审核
  244 + </Button>
322 245  
323   - render: () => (
324   - <Flex>
325   - <Button
326   - type="link"
327   - size="small"
328   - style={{ paddingLeft: 0, paddingRight: '4px' }}
329   - >
330   - 编辑
331   - </Button>
332   - <Button
333   - type="link"
334   - size="small"
335   - style={{ paddingLeft: 0, paddingRight: '4px' }}
336   - >
337   - 审核
338   - </Button>
339   - <Button
340   - type="link"
341   - size="small"
342   - style={{ paddingLeft: 0, paddingRight: '4px' }}
343   - >
344   - 备注
  246 + <Button type="link" size="small">
  247 + 备注
  248 + </Button>
  249 + <Button type="link" size="small">
  250 + 作废
  251 + </Button>
  252 + </Flex>
  253 + ),
  254 + },
  255 + {
  256 + title: '备注',
  257 + dataIndex: 'notes',
  258 + key: 'notes',
  259 + align: 'center',
  260 + render: () => (
  261 + <Button type="dashed" size="small">
  262 + 详情
345 263 </Button>
346   - <Button
347   - type="link"
348   - size="small"
349   - style={{ paddingLeft: 0, paddingRight: 0 }}
350   - >
351   - 作废
352   - </Button>
353   - </Flex>
354   - ),
355   - },
356   - {
357   - title: '备注',
358   - dataIndex: 'notes',
359   - key: 'notes',
360   - align: 'center',
361   - render: () => [
362   - <Button type="dashed" size="small">
363   - 详情
364   - </Button>,
365   - ],
366   - },
367   - ]}
  264 + ),
  265 + },
  266 + ])}
368 267 rowSelection={{
  268 + onChange: (selectedRowKeys: any, selectedRows: any) => {
  269 + console.log(selectedRowKeys, selectedRows);
  270 + setSelectedRowObj({
  271 + ...setSelectedRowObj,
  272 + [record.id]: selectedRows,
  273 + });
  274 + },
369 275 // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
370 276 // 注释该行则默认不显示下拉选项
371 277 // selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
372   - defaultSelectedRowKeys: [],
  278 + // defaultSelectedRowKeys: [],
373 279 }}
374 280 rowKey="id"
375 281 headerTitle={false}
... ... @@ -389,7 +295,6 @@ const TableList: React.FC&lt;unknown&gt; = () =&gt; {
389 295 >
390 296 <ProTable
391 297 expandIconColumnIndex={-1}
392   - // dataSource={data}
393 298 columns={mainOrdersColumns}
394 299 rowKey="id"
395 300 pagination={{
... ... @@ -397,7 +302,6 @@ const TableList: React.FC&lt;unknown&gt; = () =&gt; {
397 302 }}
398 303 expandedRowKeys={expandedRowKeys}
399 304 expandable={{ expandedRowRender }}
400   - search={false}
401 305 dateFormatter="string"
402 306 options={false}
403 307 headerTitle="订单列表"
... ... @@ -407,7 +311,7 @@ const TableList: React.FC&lt;unknown&gt; = () =&gt; {
407 311 request={async (
408 312 // 第一个参数 params 查询表单和 params 参数的结合
409 313 // 第一个参数中一定会有 pageSize 和 current ,这两个参数是 antd 的规范
410   - params: T & {
  314 + params: {
411 315 pageSize: 10;
412 316 current: 1;
413 317 },
... ... @@ -420,7 +324,7 @@ const TableList: React.FC&lt;unknown&gt; = () =&gt; {
420 324 // @ts-ignore
421 325 sorter,
422 326 filter,
423   - body: JSON.stringify(params),
  327 + data: params,
424 328 });
425 329 console.log(data);
426 330 return {
... ... @@ -447,8 +351,29 @@ const TableList: React.FC&lt;unknown&gt; = () =&gt; {
447 351 }}
448 352 />
449 353 )}
  354 +
  355 + {checkVisible && (
  356 + <CheckModal
  357 + data={orderRow}
  358 + setCheckVisible={setCheckVisible}
  359 + onClose={() => {
  360 + setCheckVisible(false);
  361 + setOrderRow({});
  362 + }}
  363 + />
  364 + )}
  365 +
  366 + {deliverVisible && (
  367 + <DeliverModal
  368 + data={selectedRows}
  369 + onClose={() => {
  370 + setCheckVisible(false);
  371 + setOrderRow({});
  372 + }}
  373 + />
  374 + )}
450 375 </PageContainer>
451 376 );
452 377 };
453 378  
454   -export default TableList;
  379 +export default OrderPage;
... ...
src/pages/Order/type.d.ts 0 → 100644
  1 +export enum ROLE {
  2 + ADMIN = 'admin', // 管理
  3 + SALESMAN = 'salesman', //销售
  4 + FINANCE = 'finance', // 财务
  5 +}
  6 +
  7 +export enum OPERATION_TYPE {
  8 + CREATE = 'create',
  9 + EDIT = 'edit',
  10 + READ = 'read',
  11 +}
  12 +
  13 +export interface OrderType {
  14 + id: string;
  15 +}
  16 +
  17 +export interface OrderListItemType {
  18 + main_order_id: number;
  19 + sales_code: string;
  20 + customer_name: string;
  21 + customer_contact_number: string;
  22 + customer_shipping_address: string;
  23 + institution_contact_name: string;
  24 + institution: string;
  25 + main_order_create_time: string;
  26 + main_order_update_time: string;
  27 + main_order_create_by_name: string;
  28 + main_order_update_by_name: any;
  29 + sub_orders: {
  30 + sub_order_id: number;
  31 + product_code: number;
  32 + product_name: string;
  33 + quantity: number;
  34 + product_price: number;
  35 + unit: string;
  36 + parameters: any;
  37 + total_payment: number;
  38 + sub_order_payment: number;
  39 + is_cancel: number;
  40 + logistics_status: string;
  41 + payment_status: string;
  42 + payment_method: string;
  43 + payment_channel: string;
  44 + payment_transaction_id: any;
  45 + invoice_information: any;
  46 + invoicing_status: string;
  47 + product_belong_department: string;
  48 + waybill_number: any;
  49 + notes: any;
  50 + examine_notes: any;
  51 + order_status: string;
  52 + sub_order_create_time: string;
  53 + sub_order_update_time: string;
  54 + sub_order_create_by_name: string;
  55 + sub_order_update_by_name: any;
  56 + }[];
  57 +}
... ...
src/pages/OrderPrint/index.tsx 0 → 100644
  1 +// App.js
  2 +
  3 +function Header() {
  4 + return (
  5 + <div className="flex items-start justify-between mb-6">
  6 + <div className="text-sm">
  7 + <p className="font-medium">网址: www.canrd.com</p>
  8 + </div>
  9 + <h1 className="text-3xl font-bold text-center">发票</h1>
  10 + <div className="text-sm text-right">
  11 + <p className="font-medium">QQ: 2902385824</p>
  12 + </div>
  13 + </div>
  14 + );
  15 +}
  16 +
  17 +function InvoiceDetails() {
  18 + return (
  19 + <div className="grid grid-cols-2 gap-4 mb-6 text-sm">
  20 + <div>
  21 + <p>单位名称: 某某科技有限公司</p>
  22 + <p>联系电话: 18583817221</p>
  23 + </div>
  24 + <div className="text-right">
  25 + <p>编号: Canrd-DZ-2023-1101-004</p>
  26 + <p>开票日期: 2023年11月1日</p>
  27 + </div>
  28 + </div>
  29 + );
  30 +}
  31 +
  32 +function ProductsTable() {
  33 + return (
  34 + <div className="mb-6">
  35 + <table className="w-full text-sm border border-gray-300 table-fixed">
  36 + <thead>
  37 + <tr className="bg-gray-200">
  38 + <th className="w-1/4 p-2 border border-gray-300 border-solid">
  39 + 名称
  40 + </th>
  41 + <th className="w-1/6 p-2 border border-gray-300 border-solid">
  42 + 规格
  43 + </th>
  44 + <th className="w-1/6 p-2 border border-gray-300 border-solid">
  45 + 单位
  46 + </th>
  47 + <th className="w-1/12 p-2 border border-gray-300 border-solid">
  48 + 数量
  49 + </th>
  50 + <th className="w-1/6 p-2 border border-gray-300 border-solid">
  51 + 单价
  52 + </th>
  53 + <th className="w-1/6 p-2 border border-gray-300 border-solid">
  54 + 金额
  55 + </th>
  56 + <th className="w-1/4 p-2 border border-gray-300 border-solid">
  57 + 备注
  58 + </th>
  59 + </tr>
  60 + </thead>
  61 + <tbody>
  62 + <tr>
  63 + <td className="p-2 whitespace-normal border border-gray-300 border-solid">
  64 + 产品名称可能非常长,所以这里会自动换行
  65 + </td>
  66 + <td className="p-2 border border-gray-300 border-solid">
  67 + 规格型号
  68 + </td>
  69 + <td className="p-2 border border-gray-300 border-solid">单位</td>
  70 + <td className="p-2 border border-gray-300 border-solid">1</td>
  71 + <td className="p-2 border border-gray-300 border-solid">400</td>
  72 + <td className="p-2 border border-gray-300 border-solid">400</td>
  73 + <td className="p-2 whitespace-normal border border-gray-300 border-solid">
  74 + 备注信息可能也会很长,需要自动换行来适应内容
  75 + </td>
  76 + </tr>
  77 + {/* 其他行 */}
  78 + </tbody>
  79 + </table>
  80 + </div>
  81 + );
  82 +}
  83 +
  84 +function Footer() {
  85 + return (
  86 + <div className="text-sm">
  87 + <p>备注: 一些备注文本...</p>
  88 + <div className="flex items-center justify-between mt-4">
  89 + <div>
  90 + <p>销售人员: 签字</p>
  91 + </div>
  92 + <div>
  93 + <p>业务员: 签字</p>
  94 + </div>
  95 + <div>
  96 + <p>开票人: 签字</p>
  97 + <p className="font-medium">总计: ¥400</p>
  98 + </div>
  99 + </div>
  100 + </div>
  101 + );
  102 +}
  103 +
  104 +function App() {
  105 + return (
  106 + <div className="flex items-center justify-center min-h-screen bg-gray-100">
  107 + <div className="w-full max-w-4xl p-10 bg-white border border-gray-300">
  108 + <Header />
  109 + <InvoiceDetails />
  110 + <ProductsTable />
  111 + <Footer />
  112 + </div>
  113 + </div>
  114 + );
  115 +}
  116 +
  117 +export default App;
... ...
src/services/request.ts
... ... @@ -3,33 +3,34 @@
3 3 /** Do not modify manually.
4 4 content is generated automatically by `ts-gear`. */
5 5 import { request as requester } from 'umi';
6   -// import type {} from "./definition";
  6 +import type {} from './definition';
7 7  
8 8 /** @description request parameter type for postErpOrderListByPage */
9 9 export interface PostErpOrderListByPageOption {
10 10 body?: {
11 11 root?: {
12   - /**
13   - @description
14   - 当前页码 */
15   - current: number;
16   - /**
17   - @description
18   - 每页条数 */
19   - size: string;
20   - /**
21   - @description
22   - 查询参数 */
23   - search: {
24   - /**
25   - @description
26   - 主订单id */
27   - mainOrderId: string;
28   - /**
29   - @description
30   - 商品名称 */
31   - productName: string;
32   - };
  12 + bank?: string;
  13 + beginTime?: string;
  14 + current?: number;
  15 + customerContactNumber?: string;
  16 + customerName?: string;
  17 + customerShippingAddress?: string;
  18 + endTime?: string;
  19 + id?: number;
  20 + institution?: string;
  21 + institutionContactName?: string;
  22 + invoicingStatus?: string;
  23 + logisticsMethod?: string;
  24 + orderStatus?: string;
  25 + pageSize?: number;
  26 + parameters?: string;
  27 + paymentChannel?: string;
  28 + paymentMethod?: string;
  29 + paymentTransactionId?: string;
  30 + productBelongBusiness?: string;
  31 + productName?: string;
  32 + salesCode?: string;
  33 + total?: number;
33 34 };
34 35 };
35 36 }
... ... @@ -42,62 +43,38 @@ export interface PostErpOrderListByPageResponse {
42 43 */
43 44 200: {
44 45 data?: {
45   - current?: number;
46   - pages?: number;
47   - records?: Array<{
48   - main_order_id: number;
49   - sales_code: string;
50   - customer_name: string;
51   - customer_contact_number: string;
52   - customer_shipping_address: string;
53   - institution_contact_name: string;
54   - institution: string;
55   - main_order_create_time: string;
56   - main_order_update_time: string;
57   - main_order_create_by_name: string;
58   - main_order_update_by_name: any;
59   - /**
60   - @description
61   - 权限按钮 */
62   - btns: string;
63   - sub_orders: Array<{
64   - sub_order_id: number;
65   - product_code: number;
66   - product_name: string;
67   - quantity: number;
68   - product_price: number;
69   - unit: string;
70   - parameters: any;
71   - total_payment: number;
72   - sub_order_payment: number;
73   - is_cancel: number;
74   - logistics_status: string;
75   - payment_status: string;
76   - payment_method: string;
77   - payment_channel: string;
78   - payment_transaction_id: any;
79   - invoice_information: any;
80   - invoicing_status: string;
81   - product_belong_department: string;
82   - waybill_number: any;
83   - notes: any;
84   - examine_notes: any;
85   - order_status: string;
86   - sub_order_create_time: string;
87   - sub_order_update_time: string;
88   - sub_order_create_by_name: string;
89   - sub_order_update_by_name: any;
90   - /**
91   - @description
92   - 权限按钮 */
93   - btns: string;
  46 + data?: Array<{
  47 + bank?: string;
  48 + bankAccountNumber?: string;
  49 + createTime?: string;
  50 + customerContactNumber?: string;
  51 + customerName?: string;
  52 + customerShippingAddress?: string;
  53 + id?: number;
  54 + institution?: string;
  55 + institutionContactName?: string;
  56 + invoiceIdentificationNumber?: string;
  57 + notes?: string;
  58 + salesCode?: string;
  59 + subOrderInformationLists?: Array<{
  60 + id: number;
  61 + invoicingStatus: string;
  62 + mainOrderId: number;
  63 + orderStatus: string;
  64 + parameters: string;
  65 + paymentChannel: string;
  66 + productCode: string;
  67 + productName: string;
  68 + quantity: string;
  69 + subOrderPayment: number;
94 70 }>;
  71 + totalPayment?: number;
95 72 }>;
  73 + pageSize?: number;
96 74 total?: number;
97   - size: number;
98 75 };
99 76 message?: string;
100   - code?: number;
  77 + result?: number;
101 78 };
102 79 }
103 80  
... ... @@ -146,6 +123,10 @@ export interface PostErpOrderAddOption {
146 123 export interface PostErpOrderAddOption {
147 124 body?: {
148 125 root?: {
  126 + /**
  127 + @description
  128 + 订单编号 */
  129 + id: string;
149 130 sales_code: string;
150 131 customer_name: string;
151 132 customer_contact_number: string;
... ... @@ -153,6 +134,10 @@ export interface PostErpOrderAddOption {
153 134 institution_contact_name: string;
154 135 institution: string;
155 136 sub_orders: Array<{
  137 + /**
  138 + @description
  139 + 子订单编号 */
  140 + id: string;
156 141 product_code: number;
157 142 product_name: string;
158 143 quantity: number;
... ...
src/style/global.css 0 → 100644
  1 +.ant-pro-form-login-container {
  2 + align-items: center;
  3 + justify-content: center;
  4 + height: 100vh;
  5 +}
... ...
src/style/global.less deleted 100644 → 0
1   -button,
2   -[type='button'],
3   -[type='reset'],
4   -[type='submit'] {
5   - background-color: auto;
6   -}
src/tsg.config.ts
... ... @@ -33,7 +33,7 @@ const projects: Project[] = [
33 33 * openapi 文档地址,可以是远程的json文件,也可以是本地的json文件
34 34 * 如果使用本地文件,相对路径以当前'tsg.config.ts'为基准
35 35 * */
36   - source: 'http://172.18.192.1:8000/request.json',
  36 + source: 'http://localhost:8000/request.json',
37 37  
38 38 // source: 'https://petstore3.swagger.io/api/v3/openapi.json',
39 39 // source: './fixture/pet.json',
... ...