@@ -49,7 +49,7 @@ const SlideMenu = () => { | |||||
const treeMenuData = useCallback((menus: MenuType[]): ItemType[] => { | const treeMenuData = useCallback((menus: MenuType[]): ItemType[] => { | ||||
return (menus).map((menu: MenuType) => { | return (menus).map((menu: MenuType) => { | ||||
const children = menu?.children?.filter(menu => menu.visible) || []; | const children = menu?.children?.filter(menu => menu.visible) || []; | ||||
const type = ''//(children.length > 0 && (menu.parentPaths?.length??0 > 0)) ? 'group': '' | |||||
const type = (children.length > 0 && (menu.parentPaths?.length??0 > 0)) ? 'group': '' | |||||
return { | return { | ||||
type: type, | type: type, | ||||
key: menu.path, | key: menu.path, | ||||
@@ -14,3 +14,15 @@ export interface DataDictDetailVO { | |||||
label: string; | label: string; | ||||
value: string; | value: string; | ||||
} | } | ||||
export interface ShopeeTemplateVO { | |||||
id: number; | |||||
categoryName: string; | |||||
createName: string; | |||||
createTime: string; | |||||
platformCode: string; | |||||
remark: string; | |||||
shopName: string; | |||||
templateName: string; | |||||
} |
@@ -0,0 +1,215 @@ | |||||
import { Space, Table, Form, Button, Card, Input, TreeSelect } from 'antd'; | |||||
import type { ColumnsType } from 'antd/es/table'; | |||||
import { t } from '@/utils/i18n'; | |||||
import React, { useState } from 'react'; | |||||
import { useNavigate } from 'react-router-dom'; | |||||
import { | |||||
ExclamationCircleFilled, | |||||
PlusOutlined, | |||||
CarryOutOutlined, | |||||
SearchOutlined, | |||||
UndoOutlined | |||||
} from '@ant-design/icons'; | |||||
import { antdUtils } from '@/utils/antd'; | |||||
import { ShopeeTemplateVO } from '@/models'; | |||||
const treeData = [ | |||||
{ | |||||
value: 'parent 1', | |||||
title: 'parent 1', | |||||
icon: <CarryOutOutlined />, | |||||
children: [ | |||||
{ | |||||
value: 'parent 1-0', | |||||
title: 'parent 1-0', | |||||
icon: <CarryOutOutlined />, | |||||
children: [ | |||||
{ | |||||
value: 'leaf1', | |||||
title: 'leaf1', | |||||
icon: <CarryOutOutlined />, | |||||
}, | |||||
{ | |||||
value: 'leaf2', | |||||
title: 'leaf2', | |||||
icon: <CarryOutOutlined />, | |||||
}, | |||||
], | |||||
}, | |||||
{ | |||||
value: 'parent 1-1', | |||||
title: 'parent 1-1', | |||||
icon: <CarryOutOutlined />, | |||||
children: [ | |||||
{ | |||||
value: 'sss', | |||||
title: 'sss', | |||||
icon: <CarryOutOutlined />, | |||||
}, | |||||
], | |||||
}, | |||||
], | |||||
}, | |||||
]; | |||||
export default () => { | |||||
const data: ShopeeTemplateVO[] = [ | |||||
{ | |||||
"id": 78, | |||||
"platformCode": "Shopee", | |||||
"shopName": "Trista", | |||||
"categoryName": "T-Shirts", | |||||
"templateName": "T-SHIRT", | |||||
"remark": "1", | |||||
"createName": "admin", | |||||
"createTime": "2023-06-15 14:45:15" | |||||
}, | |||||
{ | |||||
"id": 77, | |||||
"platformCode": "Shopee", | |||||
"shopName": "Trista", | |||||
"categoryName": "T-Shirts", | |||||
"templateName": "T-SHIRT", | |||||
"remark": "1", | |||||
"createName": "admin", | |||||
"createTime": "2023-06-15 14:44:46" | |||||
}, | |||||
{ | |||||
"id": 76, | |||||
"platformCode": "Shopee", | |||||
"shopName": "Trista", | |||||
"categoryName": "T-Shirts", | |||||
"templateName": "T-SHIRT", | |||||
"remark": "", | |||||
"createName": "admin", | |||||
"createTime": "2023-06-15 14:42:24" | |||||
} | |||||
]; | |||||
const showDeleteConfirm = (item: ShopeeTemplateVO) => { | |||||
antdUtils.modal?.confirm({ | |||||
title: `确认删除标题为: ${item.shopName} 的模板吗?`, | |||||
icon: <ExclamationCircleFilled />, | |||||
content: `请注意删除以后不可恢复!`, | |||||
okText: '删除', | |||||
okType: 'danger', | |||||
cancelText: '取消', | |||||
onOk() { | |||||
return new Promise((resolve, reject) => { | |||||
setTimeout(() => { | |||||
antdUtils.message?.open({ | |||||
type: 'success', | |||||
content: '删除成功', | |||||
}); | |||||
resolve(null) | |||||
}, 1000); | |||||
}).catch(() => antdUtils.message?.open({ | |||||
type: 'error', | |||||
content: '操作失败', | |||||
})); | |||||
}, | |||||
onCancel() { | |||||
}, | |||||
}); | |||||
}; | |||||
const columns: ColumnsType<ShopeeTemplateVO> = [ | |||||
{ | |||||
title: '店铺', | |||||
dataIndex: 'shopName', | |||||
key: 'shopName', | |||||
}, | |||||
{ | |||||
title: '模板名称', | |||||
dataIndex: 'templateName', | |||||
key: 'templateName', | |||||
}, | |||||
{ | |||||
title: '类目', | |||||
key: 'categoryName', | |||||
dataIndex: 'categoryName' | |||||
}, | |||||
{ | |||||
title: '备注', | |||||
dataIndex: 'remark', | |||||
key: 'remark', | |||||
}, | |||||
{ | |||||
title: '创建人', | |||||
dataIndex: 'createName', | |||||
key: 'createName', | |||||
}, | |||||
{ | |||||
title: '创建时间', | |||||
key: 'createTime', | |||||
dataIndex: 'createTime' | |||||
}, | |||||
{ | |||||
title: t("QkOmYwne" /* 操作 */), | |||||
key: 'action', | |||||
render: (_, record) => ( | |||||
<Space size="middle"> | |||||
<a onClick={() => { | |||||
}}>编辑</a> | |||||
<a onClick={() => { | |||||
}}>复制</a> | |||||
<a onClick={() => { | |||||
showDeleteConfirm(record) | |||||
}}>删除</a> | |||||
</Space> | |||||
), | |||||
}, | |||||
]; | |||||
const [searchFrom] = Form.useForm(); | |||||
const navigate = useNavigate(); | |||||
const [treeLine, setTreeLine] = useState(true); | |||||
const [showLeafIcon, setShowLeafIcon] = useState(false); | |||||
const [showIcon, setShowIcon] = useState<boolean>(false); | |||||
return ( | |||||
<div> | |||||
<div> | |||||
<Card className='mt-[4px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]' bodyStyle={{ paddingTop: 4, paddingBottom: 4 }}> | |||||
<div className='flex justify-between content-center'> | |||||
<div className='flex justify-normal items-center'> | |||||
<Form layout='inline' form={searchFrom}> | |||||
<Form.Item name="name" label="商品类目"> | |||||
<TreeSelect | |||||
treeDataSimpleMode | |||||
style={{ width: '100%' }} | |||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} | |||||
treeLine={treeLine && { showLeafIcon }} | |||||
treeData={treeData} | |||||
treeIcon={showIcon} | |||||
size='large' | |||||
placeholder="请选择类目" | |||||
/> | |||||
</Form.Item> | |||||
<Form.Item className='w-[250px]' name="status" label="店铺"> | |||||
<Input placeholder='请输入店铺名称' /> | |||||
</Form.Item> | |||||
</Form> | |||||
<Space.Compact className="ml-5"> | |||||
<Button type='primary' size='large' icon={<SearchOutlined />}> 搜索 </Button> | |||||
<Button type='primary' size='large' icon={<UndoOutlined />}> 重置 </Button> | |||||
</Space.Compact> | |||||
</div> | |||||
<div className="py-[4px]"> | |||||
<Button className="ml-5" type='primary' size='large' icon={<PlusOutlined />}> 新增模板 </Button> | |||||
</div> | |||||
</div> | |||||
</Card> | |||||
<Card className='mt-[4px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]'> | |||||
<Table rowKey="id" scroll={{ x: true }} columns={columns} dataSource={data} className='bg-transparent' | |||||
pagination={{ position: ['bottomRight'] }} | |||||
/> | |||||
</Card> | |||||
</div> | |||||
</div> | |||||
); | |||||
}; | |||||
@@ -1,9 +0,0 @@ | |||||
import { Empty } from 'antd'; | |||||
const CustomMade = () => { | |||||
return ( | |||||
<Empty /> | |||||
); | |||||
}; | |||||
export default CustomMade; |
@@ -39,11 +39,11 @@ export default () => { | |||||
cancelText: '取消', | cancelText: '取消', | ||||
onOk() { | onOk() { | ||||
return new Promise(async (resolve) => { | return new Promise(async (resolve) => { | ||||
const [error, { code, msg} ] = await deleteApi({ id: data.id }); | |||||
if(error || code !== 0) { | |||||
antdUtils.message?.open({ type: 'error', content: msg??'操作失败'}) | |||||
const [error, { code, msg }] = await deleteApi({ id: data.id }); | |||||
if (error || code !== 0) { | |||||
antdUtils.message?.open({ type: 'error', content: msg ?? '操作失败' }) | |||||
} else { | } else { | ||||
antdUtils.message?.open({ type: 'success', content: '删除成功'}) | |||||
antdUtils.message?.open({ type: 'success', content: '删除成功' }) | |||||
} | } | ||||
await load(); | await load(); | ||||
resolve('') | resolve('') | ||||
@@ -109,16 +109,16 @@ export default () => { | |||||
title: t("QkOmYwne" /* 操作 */), | title: t("QkOmYwne" /* 操作 */), | ||||
key: 'action', | key: 'action', | ||||
render: (value: DepartmentVO, record) => ( | render: (value: DepartmentVO, record) => ( | ||||
<Space size="small" split={( <Divider type='vertical' />)}> | |||||
<Space size="small" split={(<Divider type='vertical' />)}> | |||||
<a onClick={() => { | <a onClick={() => { | ||||
seEditData(value); | |||||
seEditorVisable(true); | |||||
}}> | |||||
seEditData(value); | |||||
seEditorVisable(true); | |||||
}}> | |||||
编辑 | 编辑 | ||||
</a> | </a> | ||||
<a onClick={() => { | <a onClick={() => { | ||||
showDeleteConfirm(value) | |||||
}}> | |||||
showDeleteConfirm(value) | |||||
}}> | |||||
删除 | 删除 | ||||
</a> | </a> | ||||
</Space> | </Space> | ||||
@@ -141,7 +141,7 @@ export default () => { | |||||
<Card className='mt-[4px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]' bodyStyle={{ paddingTop: 4, paddingBottom: 4 }}> | <Card className='mt-[4px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]' bodyStyle={{ paddingTop: 4, paddingBottom: 4 }}> | ||||
<div className='flex justify-between content-center'> | <div className='flex justify-between content-center'> | ||||
<div className='flex justify-normal items-center'> | <div className='flex justify-normal items-center'> | ||||
<Form layout='inline' form={searchFrom}> | |||||
<Form layout='inline' form={searchFrom}> | |||||
<Form.Item name="name" label="部门名称"> | <Form.Item name="name" label="部门名称"> | ||||
<Input className='w-[150px]' placeholder='请输入名称' allowClear /> | <Input className='w-[150px]' placeholder='请输入名称' allowClear /> | ||||
</Form.Item> | </Form.Item> | ||||
@@ -160,9 +160,9 @@ export default () => { | |||||
</div> | </div> | ||||
<div className="py-[4px]"> | <div className="py-[4px]"> | ||||
<Button className="ml-5" type='primary' size='large' icon={<PlusOutlined />} onClick={() => { | <Button className="ml-5" type='primary' size='large' icon={<PlusOutlined />} onClick={() => { | ||||
seEditData(undefined); | |||||
seEditorVisable(true); | |||||
}}> 新增部门 </Button> | |||||
seEditData(undefined); | |||||
seEditorVisable(true); | |||||
}}> 新增部门 </Button> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</Card> | </Card> | ||||
@@ -172,7 +172,7 @@ export default () => { | |||||
columns={columns} | columns={columns} | ||||
dataSource={dataSource} | dataSource={dataSource} | ||||
className='bg-transparent' | className='bg-transparent' | ||||
pagination={false}/> | |||||
pagination={false} /> | |||||
</Card> | </Card> | ||||
</div> | </div> | ||||
<DepartmentEditor | <DepartmentEditor | ||||
@@ -136,7 +136,7 @@ class Request { | |||||
private async responseSuccessInterceptor( | private async responseSuccessInterceptor( | ||||
response: AxiosResponse<any, any> | response: AxiosResponse<any, any> | ||||
): Promise<any> { | ): Promise<any> { | ||||
if (response.config.url !== refreshTokenUrl) { | |||||
if (!response.config.url?.startsWith(refreshTokenUrl)) { | |||||
if(response.data && response.data.code && response.data.code === 401) { | if(response.data && response.data.code && response.data.code === 401) { | ||||
return new Promise((resolve) => { | return new Promise((resolve) => { | ||||
this.requestQueue.unshift({resolve, config: response.config, type: 'response'}); | this.requestQueue.unshift({resolve, config: response.config, type: 'response'}); | ||||