123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- import { Button, message } from 'antd'
- import LeftMenu from './Components/LeftMenu'
- import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc'
- import { arrayMoveImmutable } from 'array-move'
- import type { ColumnsType } from 'antd/lib/table'
- import type { SortableContainerProps, SortEnd } from 'react-sortable-hoc'
- import { useRef, useState } from 'react'
- import { useRequest } from 'umi'
- import type { ProFormInstance } from '@ant-design/pro-form'
- import { addDataSourceItem, queryDataSource, updateDataSourceItem } from '@/services/api/schema'
- import { MenuOutlined, PlusOutlined } 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'
- enum OptionModalType {
- ADD,
- UPDATE
- }
- const DragHandle = SortableHandle(() => <MenuOutlined style={{ cursor: 'grab', color: '#999' }} />)
- const SortableItem = SortableElement((props: React.HTMLAttributes<HTMLTableRowElement>) => (
- <tr {...props} />
- ))
- const SortableBody = SortableContainer((props: React.HTMLAttributes<HTMLTableSectionElement>) => (
- <tbody {...props} />
- ))
- type iState = {
- menuData: API.DataSourceMenuItem[]
- activeID: Nullable<string>
- current: API.DataSourceItem[]
- modalType: ModalType
- menuDataItems: API.DataSourceItem[]
- items: API.DataSourceItem[]
- }
- const Option = () => {
- const formRef = useRef<ProFormInstance>(null)
- const [state, setState] = useState<iState>({
- menuData: [],
- activeID: null,
- modalVisible: false,
- modalType: OptionModalType.ADD,
- menuDataItems: [],
- items: [],
- current: {
- ID: null,
- name: null,
- enable: true
- }
- })
- console.log(state.menuDataItems)
- const { run: tryFetchList } = useRequest(queryDataSource, {
- onSuccess: (result: API.DataSourceMenuItem) => {
- setState({ ...state, menuData: result })
- }
- })
- const { run: tryAddDataSourceItem } = useRequest(
- (params: API.DataSourceItem) => addDataSourceItem(params),
- {
- manual: true,
- onSuccess: async () => {
- await tryFetchList()
- }
- }
- )
- const { run: tryUpdateDataSourceItem } = useRequest(
- (params: API.DataSourceItem) => updateDataSourceItem(params),
- {
- manual: true,
- onSuccess: async () => {
- await tryFetchList()
- }
- }
- )
- const onSelect = (key: string, node) => {
- setState({ ...state, activeID: key, menuDataItems: node.node.items })
- }
- const columns: ColumnsType<API.DataSourceItem> = [
- {
- title: '排序',
- dataIndex: 'sort',
- width: 50,
- render: () => <DragHandle />
- },
- {
- title: '序号',
- dataIndex: 'num',
- width: 50,
- render: (num, record, index) => `${index + 1}`
- },
- {
- title: '选项名称',
- dataIndex: 'name'
- },
- {
- title: '状态',
- dataIndex: 'enable',
- render: text => (
- <div className="flex items-center">
- <span
- className={classNames(
- 'w-3 h-3 rounded-1/2 inline-flex',
- text ? 'bg-green-500' : 'bg-red-500'
- )}
- />
- <span className="ml-1">{text ? '已启用' : '已停用'}</span>
- </div>
- )
- },
- {
- title: '操作',
- dataIndex: 'opreate',
- render: (_, record) => (
- <div
- className="text-primary cursor-pointer hover:text-hex-967bbd"
- onClick={() => {
- setTimeout(() => {
- formRef.current?.setFieldsValue({ ...record })
- }, 80)
- setState({
- ...state,
- modalType: ModalType.UPDATE,
- modalVisible: true,
- current: {
- ID: record.ID,
- name: record.name,
- enable: record.enable
- }
- })
- }}>
- 编辑
- </div>
- )
- }
- ]
- const onSortEnd = ({ oldIndex, newIndex }: SortEnd) => {
- if (oldIndex !== newIndex) {
- const newData = arrayMoveImmutable(dataSource.slice(), oldIndex, newIndex).filter(
- (el: DataType) => !!el
- )
- const newMenuData = menuData.map(item => {
- const newItem = { ...item }
- if (item.ID === state.activeID) {
- newItem.items = newData
- return newItem
- }
- return item
- })
- setState({ ...state, menuData: newMenuData })
- }
- }
- const DraggableContainer = (props: SortableContainerProps) => (
- <SortableBody
- useDragHandle
- disableAutoscroll
- helperClass="row-dragging"
- onSortEnd={onSortEnd}
- {...props}
- />
- )
- const DraggableBodyRow = ({ className, style, ...restProps }) => {
- const index = state.menuData
- .find(item => item.ID === state.activeID)
- ?.items.findIndex(x => x.index === restProps['data-row-key'])
- return <SortableItem index={index} {...restProps} />
- }
- return (
- <div className="flex flex-nowrap h-full">
- <LeftMenu
- onSelect={onSelect}
- showDelIcon={!state.menuDataItems.length}
- options={state.menuData}
- initFn={() => tryFetchList()}
- />
- <div className="ml-6 shadow-hex-3e2c5a" style={{ width: 'calc(100% - 12rem)' }}>
- <ProTable<API.DataSourceItem>
- columns={columns}
- search={false}
- dataSource={state.menuData.find(item => item.ID === state.activeID)?.items || []}
- rowKey="ID"
- toolbar={{
- actions: [
- <Button
- key="btn-key"
- size="small"
- type="primary"
- onClick={() => {
- setState({
- ...state,
- modalType: OptionModalType.ADD,
- modalVisible: true
- })
- }}
- ghost>
- <PlusOutlined />
- 添加选项
- </Button>
- ]
- }}
- components={{
- body: {
- wrapper: DraggableContainer,
- row: DraggableBodyRow
- }
- }}
- />
- <ModalForm
- labelCol={{ span: 6 }}
- key="form"
- width="30%"
- title={`${state.modalType === OptionModalType.ADD ? '添加' : '编辑'}选项`}
- formRef={formRef}
- layout="horizontal"
- visible={state.modalVisible}
- onVisibleChange={visible => {
- setState({ ...state, modalVisible: visible })
- setTimeout(() => {
- if (!visible) formRef.current?.resetFields()
- }, 80)
- }}
- initialValues={{ enable: true }}
- onFinish={async values => {
- try {
- if (state.modalType === OptionModalType.ADD) {
- await tryAddDataSourceItem({ ...values, dataSourceID: state.activeID })
- setState({
- ...state,
- menuDataItems: state.menuData.find(i => i.ID === state.activeID)?.items
- })
- } else {
- const newItemData = state.menuDataItems.map(item => {
- if (item.ID === state.current.ID) {
- const newItem = { ...values }
- return newItem
- }
- return item
- })
- setState({ ...state, items: newItemData })
- await tryUpdateDataSourceItem({
- ID: state.activeID,
- items: newItemData
- })
- }
- message.success(`${state.modalType === OptionModalType.ADD ? '新增' : '编辑'}成功`)
- return true
- } catch (error) {
- message.error(error)
- return false
- }
- }}>
- <ProFormText name="ID" hidden />
- <ProFormText
- name="name"
- label="选项名称"
- rules={[{ required: true, message: '请输入选项名称' }]}
- />
- <ProFormRadio.Group
- name="enable"
- label="状态"
- options={[
- { label: '启用', value: true },
- { label: '停用', value: false }
- ]}
- rules={[{ required: true, message: '请选择启用/停用' }]}
- />
- </ModalForm>
- </div>
- </div>
- )
- }
- export default Option
|