hooks.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import {useContext, useContextSection} from '@hooks';
  2. import {context} from '../context';
  3. import {Modal, TabPaneProps, TabsProps} from 'antd';
  4. import {ReactNode} from 'react';
  5. import css from './index.module.css';
  6. import {useStore} from 'zustand';
  7. import {tabStore} from '@stores';
  8. import {useContextMenu, ItemParams} from 'react-contexify';
  9. import {DragEndEvent} from '@dnd-kit/core';
  10. import {arrayMove} from '@dnd-kit/sortable';
  11. export type Tab = {
  12. key: string;
  13. label: ReactNode;
  14. } & Omit<TabPaneProps, 'tab'>;
  15. export function useTabItems() {
  16. const {host} = location;
  17. const tabs = useContextSection(context, function ([tabs]) {
  18. return tabs.map<Tab>(function (tab) {
  19. return {
  20. ...tab,
  21. originalTab: tab,
  22. forceRender: true,
  23. closable: tab.key !== '-1',
  24. animated: true,
  25. children: (
  26. <iframe
  27. src={`http://${host}${tab.url}`}
  28. className={css.iframe}
  29. data-url={tab.url}
  30. />
  31. ),
  32. };
  33. });
  34. });
  35. const [originalTab, dispatch] = useContext(context);
  36. function onDragEnd({active, over}: DragEndEvent) {
  37. if (!over) return;
  38. const {id: fromId} = active,
  39. {id: toId} = over;
  40. const fromIdx = originalTab.findIndex(val => val.key === fromId),
  41. toIdx = originalTab.findIndex(val => val.key === toId);
  42. dispatch({
  43. type: 'SORT',
  44. payload: arrayMove(originalTab, fromIdx, toIdx),
  45. });
  46. }
  47. return [tabs, onDragEnd] as const;
  48. }
  49. export function useTabActive() {
  50. const dispatch = useContextSection(context, state => state[1]);
  51. const {key: activeKey, dispatch: setActiveKey} = useStore(tabStore);
  52. function onClear() {
  53. Modal.confirm({
  54. title: '清除标签页',
  55. content: '你确定要关闭所有标签页吗?',
  56. onOk() {
  57. dispatch({type: 'CLEAR'});
  58. },
  59. });
  60. }
  61. const onEdit: TabsProps['onEdit'] = function (target, action) {
  62. if (action === 'remove' && typeof target === 'string') {
  63. dispatch({type: 'REMOVE', payload: target});
  64. }
  65. };
  66. return [activeKey, {onChange: setActiveKey, onClear, onEdit}] as const;
  67. }
  68. export function useMenu() {
  69. const {show} = useContextMenu({id: 'content_menu'});
  70. const dispatch = useContextSection(context, state => state[1]);
  71. function onMenuitemClick(e: ItemParams<{key: string}, any>) {
  72. const {props, id} = e;
  73. if (!id || !props?.key) return;
  74. const {key} = props;
  75. switch (id) {
  76. case 'clear':
  77. dispatch({type: 'CLEAR'});
  78. break;
  79. case 'remove':
  80. dispatch({type: 'REMOVE', payload: key});
  81. break;
  82. case 'remove_other':
  83. dispatch({type: 'REMOVE_OTHER', payload: key});
  84. break;
  85. case 'remove_right':
  86. dispatch({type: 'REMOVE_RIGHT', payload: key});
  87. break;
  88. }
  89. }
  90. return {show, onMenuitemClick};
  91. }