|
@@ -1,4 +1,4 @@
|
|
-import { Table } from 'antd'
|
|
|
|
|
|
+import { Button, Table } from 'antd'
|
|
import LeftMenu from './Components/LeftMenu'
|
|
import LeftMenu from './Components/LeftMenu'
|
|
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc'
|
|
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc'
|
|
import { arrayMoveImmutable } from 'array-move'
|
|
import { arrayMoveImmutable } from 'array-move'
|
|
@@ -7,49 +7,90 @@ import type { SortableContainerProps, SortEnd } from 'react-sortable-hoc'
|
|
|
|
|
|
import { useState } from 'react'
|
|
import { useState } from 'react'
|
|
import { useRequest } from 'umi'
|
|
import { useRequest } from 'umi'
|
|
-import { addDataSource, queryDataSource } from '@/services/api/schema'
|
|
|
|
|
|
+import {
|
|
|
|
+ addDataSource,
|
|
|
|
+ addDataSourceItem,
|
|
|
|
+ queryDataSource,
|
|
|
|
+ updateDataSourceItem
|
|
|
|
+} from '@/services/api/schema'
|
|
import { MenuOutlined } from '@ant-design/icons'
|
|
import { MenuOutlined } from '@ant-design/icons'
|
|
|
|
+import classNames from 'classnames'
|
|
|
|
+import { ModalForm, ProFormRadio, ProFormText } from '@ant-design/pro-form'
|
|
|
|
+import ProTable from '@ant-design/pro-table'
|
|
|
|
+import { ModalType } from '@/utils/enum'
|
|
|
|
|
|
const DragHandle = SortableHandle(() => <MenuOutlined style={{ cursor: 'grab', color: '#999' }} />)
|
|
const DragHandle = SortableHandle(() => <MenuOutlined style={{ cursor: 'grab', color: '#999' }} />)
|
|
|
|
|
|
-const columns: ColumnsType<DataType> = [
|
|
|
|
- {
|
|
|
|
- title: 'Sort',
|
|
|
|
- dataIndex: 'sort',
|
|
|
|
- width: 30,
|
|
|
|
- className: 'drag-visible',
|
|
|
|
- render: () => <DragHandle />
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- title: 'Name',
|
|
|
|
- dataIndex: 'name',
|
|
|
|
- className: 'drag-visible'
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- title: 'Age',
|
|
|
|
- dataIndex: 'age'
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- title: 'Address',
|
|
|
|
- dataIndex: 'address'
|
|
|
|
- }
|
|
|
|
-]
|
|
|
|
-
|
|
|
|
const SortableItem = SortableElement((props: React.HTMLAttributes<HTMLTableRowElement>) => (
|
|
const SortableItem = SortableElement((props: React.HTMLAttributes<HTMLTableRowElement>) => (
|
|
<tr {...props} />
|
|
<tr {...props} />
|
|
))
|
|
))
|
|
const SortableBody = SortableContainer((props: React.HTMLAttributes<HTMLTableSectionElement>) => (
|
|
const SortableBody = SortableContainer((props: React.HTMLAttributes<HTMLTableSectionElement>) => (
|
|
<tbody {...props} />
|
|
<tbody {...props} />
|
|
))
|
|
))
|
|
|
|
+
|
|
|
|
+type iState = {
|
|
|
|
+ menuData: API.DataSourceMenuItem[]
|
|
|
|
+ activeID: Nullable<string>
|
|
|
|
+ modalType: ModalType
|
|
|
|
+ visible: boolean
|
|
|
|
+}
|
|
const Option = () => {
|
|
const Option = () => {
|
|
- const [menuData, setMenuData] = useState<API.DataSourceMenuItem[]>([])
|
|
|
|
- const [activeID, setActiveID] = useState<Nullable<string>>(null)
|
|
|
|
|
|
+ const [state, setState] = useState<iState>({
|
|
|
|
+ menuData: [],
|
|
|
|
+ activeID: null,
|
|
|
|
+ visible: false,
|
|
|
|
+ modalType: ModalType.ADD
|
|
|
|
+ })
|
|
|
|
+
|
|
const { run: tryFetchList } = useRequest(queryDataSource, {
|
|
const { run: tryFetchList } = useRequest(queryDataSource, {
|
|
onSuccess: (result: API.DataSourceMenuItem) => {
|
|
onSuccess: (result: API.DataSourceMenuItem) => {
|
|
- setMenuData(result)
|
|
|
|
|
|
+ setState({ ...state, menuData: result })
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
|
|
|
|
+ const { run: tryAddItem } = useRequest(addDataSourceItem, {
|
|
|
|
+ manual: true,
|
|
|
|
+ onSuccess: () => tryFetchList()
|
|
|
|
+ })
|
|
|
|
+ const { run: tryUpdateItem } = useRequest(updateDataSourceItem, {
|
|
|
|
+ manual: true,
|
|
|
|
+ onSuccess: () => tryFetchList()
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ const columns: ColumnsType<API.DataSourceItem> = [
|
|
|
|
+ {
|
|
|
|
+ title: '排序',
|
|
|
|
+ dataIndex: 'sort',
|
|
|
|
+ width: 30,
|
|
|
|
+ render: () => <DragHandle />
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: '选项名称',
|
|
|
|
+ dataIndex: 'name'
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: '状态',
|
|
|
|
+ dataIndex: 'enable',
|
|
|
|
+ render: text => (
|
|
|
|
+ <div>
|
|
|
|
+ <span
|
|
|
|
+ className={classNames('w-4 h-4 rounded-1/2', text ? 'bg-green-500' : 'bg-red-500')}
|
|
|
|
+ />
|
|
|
|
+ <span className="ml-1">{text ? '已启用' : '已停用'}</span>
|
|
|
|
+ </div>
|
|
|
|
+ )
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ title: '操作',
|
|
|
|
+ dataIndex: 'opreate',
|
|
|
|
+ render: (_, record) => (
|
|
|
|
+ <Button type="text" onClick={() => setState({ ...state, modalType: ModalType.UPDATE })}>
|
|
|
|
+ 编辑
|
|
|
|
+ </Button>
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ ]
|
|
|
|
+
|
|
const onSortEnd = ({ oldIndex, newIndex }: SortEnd) => {
|
|
const onSortEnd = ({ oldIndex, newIndex }: SortEnd) => {
|
|
if (oldIndex !== newIndex) {
|
|
if (oldIndex !== newIndex) {
|
|
const newData = arrayMoveImmutable(dataSource.slice(), oldIndex, newIndex).filter(
|
|
const newData = arrayMoveImmutable(dataSource.slice(), oldIndex, newIndex).filter(
|
|
@@ -63,7 +104,7 @@ const Option = () => {
|
|
}
|
|
}
|
|
return item
|
|
return item
|
|
})
|
|
})
|
|
- setMenuData(newMenuData)
|
|
|
|
|
|
+ setState({ ...state, menuData: newMenuData })
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -87,15 +128,40 @@ const Option = () => {
|
|
return (
|
|
return (
|
|
<div className="flex flex-nowrap h-full">
|
|
<div className="flex flex-nowrap h-full">
|
|
<LeftMenu
|
|
<LeftMenu
|
|
- onSelect={(key: string) => setActiveID(key)}
|
|
|
|
- options={menuData}
|
|
|
|
|
|
+ onSelect={(key: string) => setState({ ...state, activeID: key })}
|
|
|
|
+ options={state.menuData}
|
|
initFn={() => tryFetchList()}
|
|
initFn={() => tryFetchList()}
|
|
/>
|
|
/>
|
|
<div className="ml-6 shadow-hex-3e2c5a" style={{ width: 'calc(100% - 12rem)' }}>
|
|
<div className="ml-6 shadow-hex-3e2c5a" style={{ width: 'calc(100% - 12rem)' }}>
|
|
- <Table<API.DataSourceItem>
|
|
|
|
|
|
+ <ProTable<API.DataSourceItem>
|
|
columns={columns}
|
|
columns={columns}
|
|
- dataSource={menuData.find(item => item.ID === activeID)?.items || []}
|
|
|
|
|
|
+ search={false}
|
|
|
|
+ dataSource={state.menuData.find(item => item.ID === state.activeID)?.items || []}
|
|
rowKey="ID"
|
|
rowKey="ID"
|
|
|
|
+ toolbar={{
|
|
|
|
+ actions: [
|
|
|
|
+ <ModalForm
|
|
|
|
+ key="form"
|
|
|
|
+ visible={state.visible}
|
|
|
|
+ onVisibleChange={visible => setState({ ...state, visible })}
|
|
|
|
+ onFinish={async values => {}}>
|
|
|
|
+ <ProFormText
|
|
|
|
+ name="label"
|
|
|
|
+ label="选项名称"
|
|
|
|
+ rules={[{ required: true, message: '请输入选项名称' }]}
|
|
|
|
+ />
|
|
|
|
+ <ProFormRadio.Group
|
|
|
|
+ name="enable"
|
|
|
|
+ label="状态"
|
|
|
|
+ options={[
|
|
|
|
+ { label: '启用', value: true },
|
|
|
|
+ { label: '停用', value: false }
|
|
|
|
+ ]}
|
|
|
|
+ rules={[{ required: true, message: '请选择启用/停用' }]}
|
|
|
|
+ />
|
|
|
|
+ </ModalForm>
|
|
|
|
+ ]
|
|
|
|
+ }}
|
|
components={{
|
|
components={{
|
|
body: {
|
|
body: {
|
|
wrapper: DraggableContainer,
|
|
wrapper: DraggableContainer,
|