react-toolkits 0.2.11 → 0.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-toolkits",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
4
4
  "sideEffects": [
5
5
  "**/*.css"
6
6
  ],
@@ -20,20 +20,6 @@
20
20
  "module": "./dist/index.esm.js",
21
21
  "default": "./dist/index.esm.js"
22
22
  }
23
- },
24
- "./components": {
25
- "import": {
26
- "types": "./dist/components/index.d.mts",
27
- "module": "./dist/components/index.esm.js",
28
- "default": "./dist/components/index.esm.js"
29
- }
30
- },
31
- "./hooks": {
32
- "import": {
33
- "types": "./dist/hooks/index.d.mts",
34
- "module": "./dist/hooks/index.esm.js",
35
- "default": "./dist/hooks/index.esm.js"
36
- }
37
23
  }
38
24
  },
39
25
  "typesVersions": {},
@@ -54,6 +40,7 @@
54
40
  "antd": "^5.7.3",
55
41
  "axios": "^1.4.0",
56
42
  "dayjs": "^1.11.9",
43
+ "events": "^3.3.0",
57
44
  "jwt-decode": "^3.1.2",
58
45
  "lodash-es": "^4.17.21",
59
46
  "swr": "^2.2.0",
@@ -85,6 +72,6 @@
85
72
  },
86
73
  "scripts": {
87
74
  "build": "tsup",
88
- "check-types": "tsc --noEmit"
75
+ "lint": "eslint --fix --ext .ts,.tsx,.js,.jsx ."
89
76
  }
90
77
  }
@@ -1,146 +0,0 @@
1
- import * as react from 'react';
2
- import { FC, PropsWithChildren, ReactElement, ForwardedRef, ReactNode } from 'react';
3
- import * as react_jsx_runtime from 'react/jsx-runtime';
4
- import * as antd from 'antd';
5
- import { FormProps, FormInstance, ModalProps, ButtonProps } from 'antd';
6
- import { Merge } from 'ts-essentials';
7
- import { TableProps } from 'antd/es/table';
8
- import { AxiosRequestConfig } from 'axios';
9
- import { MenuDividerType, MenuItemType, SubMenuType, MenuItemGroupType } from 'antd/es/menu/hooks/useItems';
10
-
11
- interface DynamicTagsProps {
12
- initialTags?: string[];
13
- addable?: boolean;
14
- removable?: boolean;
15
- addCallback?: (addedTag: string) => Promise<boolean>;
16
- removeCallback?: (removedTag: string) => Promise<boolean>;
17
- }
18
- declare const DynamicTags: FC<DynamicTagsProps>;
19
-
20
- interface FilterFormProps<Values> extends Pick<FormProps<Values>, 'initialValues' | 'requiredMark' | 'onError' | 'onChange' | 'onValuesChange' | 'onFinish' | 'onFinishFailed' | 'layout' | 'labelCol'> {
21
- form?: FormInstance<Values>;
22
- onReset?: () => void;
23
- confirmText?: react.ReactNode;
24
- }
25
- declare const FilterForm: <Values = unknown>(props: PropsWithChildren<FilterFormProps<Values>>) => react_jsx_runtime.JSX.Element;
26
-
27
- type RecursivePartial<T> = T extends object ? {
28
- [P in keyof T]?: T[P] extends (infer U)[] ? RecursivePartial<U>[] : T[P] extends object ? RecursivePartial<T[P]> : T[P];
29
- } : unknown;
30
- interface FormModalProps<T> extends Pick<ModalProps, 'width' | 'title' | 'open' | 'afterClose' | 'bodyStyle' | 'maskClosable'>, Pick<FormProps, 'labelCol' | 'layout' | 'colon'> {
31
- form?: FormInstance<T>;
32
- children?: ReactElement | ReactElement[];
33
- footer?: ModalProps['footer'];
34
- closeFn?: VoidFunction;
35
- initialValues?: RecursivePartial<T>;
36
- onConfirm?: (values: T) => Promise<void>;
37
- }
38
- interface FormModalRef<T = object> {
39
- setFieldsValue: (values: RecursivePartial<T>) => void;
40
- }
41
- declare const FormModal: <T extends object>(props: FormModalProps<T> & {
42
- ref?: ForwardedRef<FormModalRef<T>> | undefined;
43
- }) => ReactElement;
44
-
45
- type UseFormModalProps<T> = Merge<Omit<FormModalProps<T>, 'open' | 'onCancel' | 'closeFn' | 'children' | 'form'>, {
46
- content: FormModalProps<T>['children'];
47
- }>;
48
- declare function useFormModal<T extends object>(props: UseFormModalProps<T>): {
49
- Modal: react.ReactPortal;
50
- showModal: (options?: {
51
- initialValues?: RecursivePartial<T> | undefined;
52
- title?: FormModalProps<T>['title'];
53
- } | undefined) => void;
54
- closeModal: () => void;
55
- form: antd.FormInstance<T>;
56
- };
57
-
58
- interface HighlightTextsProps extends PropsWithChildren {
59
- texts: Array<string | number>;
60
- }
61
- declare const Highlight: (props: HighlightTextsProps) => react_jsx_runtime.JSX.Element;
62
-
63
- interface PermissionButtonProps extends Omit<ButtonProps, 'disabled'> {
64
- code: string;
65
- showLoading?: boolean;
66
- }
67
- declare const PermissionButton: FC<PropsWithChildren<PermissionButtonProps>>;
68
-
69
- interface ListResponse<T> {
70
- List: T[];
71
- Page?: number;
72
- Total: number;
73
- }
74
- type PaginationParams = {
75
- page: number;
76
- size: number;
77
- };
78
-
79
- type QueryListKey = Omit<AxiosRequestConfig, 'data' | 'params'>;
80
- declare enum QueryListAction {
81
- Submit = "submit",
82
- Reset = "reset"
83
- }
84
- interface QueryListProps<Item, Values, Response> extends Pick<TableProps<Item>, 'columns' | 'rowKey' | 'tableLayout' | 'expandable' | 'rowSelection' | 'bordered'>, Pick<FormProps<Values>, 'initialValues' | 'labelCol'> {
85
- form?: FormInstance<Values>;
86
- swrKey: QueryListKey;
87
- confirmText?: ReactNode;
88
- code?: string;
89
- renderForm?: (form: FormInstance<Values>) => ReactNode;
90
- transformArg?: (arg: Merge<Values, PaginationParams>) => unknown;
91
- transformResponse?: (response: Response) => ListResponse<Item>;
92
- afterQuerySuccess?: (response: ListResponse<Item>, action?: QueryListAction) => void;
93
- }
94
- declare const QueryList: <Item extends object, Values = {}, Response_1 = ListResponse<Item>>(props: QueryListProps<Item, Values, Response_1>) => react_jsx_runtime.JSX.Element;
95
-
96
- interface GameType {
97
- id: string;
98
- name: string;
99
- area: 'cn' | 'global';
100
- Ctime: string;
101
- }
102
- declare const GameSelect: () => react_jsx_runtime.JSX.Element | null;
103
-
104
- type MenuItemType2 = Merge<MenuItemType, {
105
- code /** 权限编号 **/?: string;
106
- route /** 前端路由地址 **/?: string;
107
- }>;
108
- type SubMenuType2 = Merge<SubMenuType, {
109
- children?: ItemType2[];
110
- }>;
111
- type MenuItemGroupType2 = Merge<MenuItemGroupType, {
112
- children?: ItemType2[];
113
- }>;
114
- type ItemType2 = MenuItemType2 | SubMenuType2 | MenuItemGroupType2 | MenuDividerType | null;
115
- declare const NavMenu: () => react_jsx_runtime.JSX.Element;
116
-
117
- interface ReactToolkitsState {
118
- title: string;
119
- isPermissionV2: boolean;
120
- isGlobalNS: boolean;
121
- game: GameType | null;
122
- setGame: (game: GameType | null) => void;
123
- openKeys: string[];
124
- selectedKeys: string[];
125
- setOpenKeys: (keys: string[]) => void;
126
- setSelectedKeys: (keys: string[]) => void;
127
- menuItems: ItemType2[];
128
- onlyDomesticGames: boolean;
129
- }
130
- declare function useReactToolkitsContext<T>(selector: (state: ReactToolkitsState) => T, equalityFn?: (left: T, right: T) => boolean): T;
131
-
132
- declare const ReactToolkitsProvider: FC<PropsWithChildren<Partial<Pick<ReactToolkitsState, 'isPermissionV2' | 'isGlobalNS' | 'menuItems' | 'title' | 'onlyDomesticGames'>>>>;
133
-
134
- declare const UserWidget: FC;
135
-
136
- interface LayoutProps extends PropsWithChildren {
137
- extra?: react.ReactNode[];
138
- }
139
- declare const Layout: FC<LayoutProps>;
140
-
141
- interface PermissionGuardProps {
142
- code: string;
143
- }
144
- declare const PermissionGuard: FC<PropsWithChildren<PermissionGuardProps>>;
145
-
146
- export { DynamicTags, DynamicTagsProps, FilterForm, FilterFormProps, FormModal, FormModalProps, FormModalRef, GameSelect, Highlight, HighlightTextsProps, ItemType2, Layout, LayoutProps, NavMenu, PermissionButton, PermissionButtonProps, PermissionGuard, PermissionGuardProps, QueryList, QueryListAction, QueryListKey, QueryListProps, ReactToolkitsProvider, UseFormModalProps, UserWidget, useFormModal, useReactToolkitsContext };
@@ -1,24 +0,0 @@
1
- import { PlusOutlined, LogoutOutlined, UserOutlined } from '@ant-design/icons';
2
- import * as H from 'antd';
3
- import { Form, Button, Modal, theme, Space, Input, Tag, Row, Col, Tooltip, Table, Result, Select, Dropdown, Menu, Divider, Spin, Typography, Card, Empty } from 'antd';
4
- import * as Oe from 'react';
5
- import { forwardRef, createContext, useId, useRef, useState, useImperativeHandle, useCallback, useMemo, useContext, useEffect, Suspense } from 'react';
6
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
- import { createPortal, flushSync } from 'react-dom';
8
- import { createRoot } from 'react-dom/client';
9
- import { create, useStore } from 'zustand';
10
- import { persist, createJSONStorage } from 'zustand/middleware';
11
- import Lt from 'jwt-decode';
12
- import Vt from 'axios';
13
- import Gt from 'swr/immutable';
14
- import zt from 'swr/mutation';
15
- import { useNavigate, useLocation, Link } from 'react-router-dom';
16
- import Ne from 'antd/es/typography/Link';
17
- import { SWRConfig } from 'swr';
18
- import Eo from './logo-L6MFCL6M.png';
19
-
20
- var _e=Object.defineProperty,$e=Object.defineProperties;var Je=Object.getOwnPropertyDescriptors;var $=Object.getOwnPropertySymbols;var Pe=Object.prototype.hasOwnProperty,Te=Object.prototype.propertyIsEnumerable;var he=(t,e,o)=>e in t?_e(t,e,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[e]=o,y=(t,e)=>{for(var o in e||(e={}))Pe.call(e,o)&&he(t,o,e[o]);if($)for(var o of $(e))Te.call(e,o)&&he(t,o,e[o]);return t},T=(t,e)=>$e(t,Je(e));var x=(t,e)=>{var o={};for(var r in t)Pe.call(t,r)&&e.indexOf(r)<0&&(o[r]=t[r]);if(t!=null&&$)for(var r of $(t))e.indexOf(r)<0&&Te.call(t,r)&&(o[r]=t[r]);return o};var R=(t,e,o)=>new Promise((r,i)=>{var n=l=>{try{a(o.next(l));}catch(m){i(m);}},s=l=>{try{a(o.throw(l));}catch(m){i(m);}},a=l=>l.done?r(l.value):Promise.resolve(l.value).then(n,s);a((o=o.apply(t,e)).next());});var Ye=t=>{let{initialTags:e,addable:o,removable:r,addCallback:i,removeCallback:n}=t,{token:s}=theme.useToken(),[a,l]=useState([]),[m,d]=useState(!1),[p,P]=useState(""),[c,f]=useState(-1),[C,I]=useState(""),M=useRef(null),L=useRef(null);useEffect(()=>{l(e!=null?e:[]);},[e]),useEffect(()=>{var u;m&&((u=M.current)==null||u.focus());},[m]),useEffect(()=>{var u;(u=L.current)==null||u.focus();},[p]);let A=u=>R(void 0,null,function*(){if(yield n==null?void 0:n(u)){let O=a.filter(qe=>qe!==u);l(O);}}),w=()=>{d(!0);},z=u=>{P(u.target.value);},k=()=>R(void 0,null,function*(){p&&a.indexOf(p)===-1&&(yield i==null?void 0:i(p))&&l([...a,p]),d(!1),P("");}),V=u=>{I(u.target.value);},G=()=>{let u=[...a];u[c]=C,l(u),f(-1),P("");},U={width:78,verticalAlign:"top"},_={background:s.colorBgContainer,borderStyle:"dashed"};return jsxs(Space,{wrap:!0,size:[0,8],children:[jsx(Space,{wrap:!0,size:[0,8],children:a.map((u,S)=>c===S?jsx(Input,{ref:L,size:"small",style:U,value:C,onChange:V,onBlur:G,onPressEnter:G},u):jsx(Tag,{closable:r,style:{userSelect:"none"},onClose:O=>R(void 0,null,function*(){O.preventDefault(),yield A(u);}),children:jsx("span",{onDoubleClick:O=>{S!==0&&(f(S),I(u),O.preventDefault());},children:u})},u))}),o&&(m?jsx(Input,{ref:M,type:"text",size:"small",style:U,value:p,onChange:z,onBlur:k,onPressEnter:k}):jsxs(Tag,{style:_,onClick:w,children:[jsx(PlusOutlined,{}),"\xA0\u6DFB\u52A0"]}))]})},Ze=Ye;var st=t=>{let l=t,{children:e,confirmText:o,form:r,onReset:i}=l,n=x(l,["children","confirmText","form","onReset"]),{token:s}=theme.useToken(),a={maxWidth:"none",background:s.colorFillAlter,borderWidth:s.lineWidth,borderStyle:s.lineType,borderColor:s.colorBorder,borderRadius:s.borderRadiusLG,padding:24,marginBottom:24};return jsx(Form,T(y({},n),{form:r,autoComplete:"off",children:e&&jsx("div",{style:a,children:jsxs(Row,{gutter:18,children:[e,jsx(Col,{flex:"auto"}),jsx(Col,{flex:"auto",span:24,style:{textAlign:"right"},children:jsxs(Space,{children:[jsx(Button,{type:"primary",htmlType:"submit",children:o||"\u67E5\u8BE2"}),jsx(Button,{htmlType:"reset",onClick:i,children:"\u91CD\u7F6E"})]})})]})})}))},Y=st;var ut=(t,e)=>{let{form:o,width:r,children:i,title:n,open:s,footer:a,layout:l,labelCol:m,bodyStyle:d,initialValues:p,maskClosable:P,closeFn:c,onConfirm:f}=t,[C]=Form.useForm(o),I=useId(),M=useRef(null),[L,A]=useState(!1),w=typeof a=="object"?a:[jsx(Button,{onClick:()=>{c==null||c();},children:"\u53D6\u6D88"},"cancel"),jsx(Button,{form:I,type:"primary",htmlType:"submit",loading:L,children:"\u786E\u5B9A"},"submit")],z=m||{flex:!l||l==="horizontal"?"120px":"0"},k=V=>R(void 0,null,function*(){try{A(!0),yield f==null?void 0:f(V),c==null||c(),C.resetFields();}finally{A(!1);}});return useImperativeHandle(e,()=>({setFieldsValue(V){var G;(G=M.current)==null||G.setFieldsValue(V);}})),jsx(Modal,{destroyOnClose:!0,bodyStyle:d,style:{textAlign:"start"},width:r,open:s,title:n,forceRender:!0,getContainer:!1,maskClosable:P,footer:w,onCancel:c,children:jsx(Form,{form:C,ref:M,id:I,autoComplete:"off",labelAlign:"right",labelWrap:!0,layout:l,initialValues:p,labelCol:z,onFinish:k,children:i})})},ct=forwardRef(ut),Z=ct;function Pt(t){let c=t,{content:e,onConfirm:o}=c,r=x(c,["content","onConfirm"]),[i,n]=useState(!1),[s,a]=useState(),l=useRef(null),[m]=Form.useForm(),d=f=>{var C,I;a((C=f==null?void 0:f.title)!=null?C:r.title),f!=null&&f.initialValues&&((I=l.current)==null||I.setFieldsValue(f==null?void 0:f.initialValues)),n(!0);},p=useCallback(()=>{n(!1);},[]);return {Modal:useMemo(()=>createPortal(jsx(Z,T(y({},r),{ref:l,form:m,open:i,closeFn:p,title:s,onConfirm:o,children:e})),document.body),[s,e,r,m,i,p,o]),showModal:d,closeModal:p,form:m}}var St=t=>{let e=/(<[^>]*>)/;return t.split(e).filter(o=>o!=="")};function xt(t){let e=document.createElement("div"),o=createRoot(e);return new Promise(r=>{setTimeout(()=>{flushSync(()=>{o.render(t);}),r(e.innerHTML);});})}var Ft=t=>{let{texts:e,children:o}=t,[r,i]=useState("");return useEffect(()=>{xt(o).then(n=>{let s=St(n);for(let a of e)for(let l=0;l<s.length;l++)s[l]=s[l].replace(String(a),`<span style='color: #DC143C;'>${a}</span>`);i(s.join(""));});},[o,e]),jsx("p",{dangerouslySetInnerHTML:{__html:r}})},It=Ft;var D=create()(persist((t,e)=>({token:"",getUser:()=>{try{return Lt(e().token)}catch(o){return null}},setToken:o=>t({token:o}),clearToken:()=>{t({token:""}),D.persist.clearStorage();}}),{name:"token",partialize:t=>({token:t.token})}));var Le=create((t,e)=>({data:new Map,getPaginationData:o=>{var i,n,s;let r=(i=e().data.get(o))==null?void 0:i.pagination;return {page:(n=r==null?void 0:r.page)!=null?n:1,size:(s=r==null?void 0:r.size)!=null?s:10}},setPaginationData:(o,r)=>{var i,n;t({data:new Map(e().data).set(o,T(y({},e().data.get(o)),{pagination:{page:(i=r==null?void 0:r.page)!=null?i:e().getPaginationData(o).page,size:(n=r==null?void 0:r.size)!=null?n:e().getPaginationData(o).size}}))});},refresh:(o,r)=>{var n,s,a;let i=(n=e().data.get(o))==null?void 0:n.refresh;i&&i({page:(s=r==null?void 0:r.page)!=null?s:e().getPaginationData(o).page,size:(a=r==null?void 0:r.size)!=null?a:e().getPaginationData(o).size});},setRefresh:(o,r)=>{let i=e().data;t({data:new Map(i).set(o,T(y({},i.get(o)),{refresh:r}))});}}));var v=class extends Error{constructor(o,r,i=!1){super(o);this.code=r,this.skip=i;}};function B(){let t=D(s=>s.token),{game:e,isGlobalNS:o,isPermissionV2:r}=b(s=>s),i={withCredentials:!0},n=Vt.create(i);return n.interceptors.request.use(s=>{let a=s.headers;return a.set("Authorization",`Bearer ${t}`),r&&(a.has("App-ID")||a.set("App-ID",o?"global":e==null?void 0:e.id)),s}),n.interceptors.response.use(s=>{if(s.headers["content-type"].includes("application/octet-stream"))return s;if(s.data.code===0||s.data.status===0)return s.data.data;throw new v(s.data.msg,0)},s=>{throw s.response?s.response.status===401?new v("\u672A\u767B\u5F55\u6216\u767B\u5F55\u5DF2\u8FC7\u671F",s.response.status):s.response.status===403?new v("\u65E0\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u8FDB\u884C\u6388\u6743",s.response.status):[404,405].includes(s.response.status)?new v("Not Found or Method not Allowed",s.response.status,!0):s.response.status===412?new v("\u672A\u6CE8\u518C\u7528\u6237",s.response.status):s.response.status===504?new v("\u8BF7\u6C42\u8D85\u65F6",s.response.status):new v(s.response.message,s.response.status):new v("\u65E0\u54CD\u5E94")}),n}function ee(t,e=!1){let o=B(),i=b(a=>a.isPermissionV2)?"/api/usystem/user/checkV2":"/api/usystem/user/check",{data:n,isLoading:s}=Gt(t.length>0?{method:"POST",url:i,data:{permissions:t},headers:e?{"App-ID":"global"}:{}}:null,a=>o.request(a).then(l=>l.has_all?t.reduce((m,d)=>(m[d]=!0,m),{}):t.reduce((m,d)=>(m[d]=l[d],m),{})),{suspense:!0,shouldRetryOnError:!1});return {data:n,isLoading:s}}function E(t){var r;let{data:e,isLoading:o}=ee(t?[t]:[]);return t?{accessible:(r=e==null?void 0:e[t])!=null?r:!1,isValidating:o}:{accessible:!0,isValidating:!1}}var Kt=t=>{let a=t,{children:e,code:o,showLoading:r}=a,i=x(a,["children","code","showLoading"]),{accessible:n,isValidating:s}=E(o);return s?jsx(Button,T(y({loading:r,disabled:!r},i),{children:e})):n?jsx(Button,T(y({},i),{children:e})):jsx(Tooltip,{defaultOpen:!1,title:"\u65E0\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u8FDB\u884C\u6388\u6743",children:jsx(Button,T(y({disabled:!0},i),{children:e}))})},Nt=Kt;var Ge=(o=>(o.Submit="submit",o.Reset="reset",o))(Ge||{}),Ot=t=>{let _=t,{form:e,code:o,confirmText:r,labelCol:i,swrKey:n,initialValues:s,renderForm:a,transformArg:l,transformResponse:m,afterQuerySuccess:d}=_,p=x(_,["form","code","confirmText","labelCol","swrKey","initialValues","renderForm","transformArg","transformResponse","afterQuerySuccess"]),{accessible:P}=E(o!=null?o:""),[c]=Form.useForm(e),{setRefresh:f,getPaginationData:C,setPaginationData:I}=Le(u=>u),M=C(n),L=useRef(),A=B(),{data:w,isMutating:z,trigger:k}=zt(n,(O,qe)=>R(void 0,[O,qe],function*(u,{arg:S}){var ue,ce,de;yield c.validateFields();let He={page:(ue=S==null?void 0:S.page)!=null?ue:M.page,size:(ce=S==null?void 0:S.size)!=null?ce:M.size};I(n,S);let Ue=c.getFieldsValue(),pe=y(y({},Ue),He);return A.request(T(y({},u),{[u.method==="POST"?"data":"params"]:(de=l==null?void 0:l(pe))!=null?de:pe})).then(fe=>{var ge;let ye=(ge=m==null?void 0:m(fe))!=null?ge:fe;return d==null||d(ye,L.current),ye}).finally(()=>{L.current=void 0;})})),V=()=>R(void 0,null,function*(){L.current="submit",yield k({page:1});}),G=useCallback(()=>R(void 0,null,function*(){try{L.current="reset",c.resetFields(),yield c.validateFields(),yield k({page:1});}catch(u){console.log("\u8868\u5355\u6821\u9A8C\u5931\u8D25");}}),[c,k]),U=useCallback((u,S)=>R(void 0,null,function*(){yield k({page:u,size:S});}),[k]);return useEffect(()=>{f(n,k);},[n,k,f]),useEffect(()=>{R(void 0,null,function*(){try{yield c.validateFields(),yield k();}catch(u){c.resetFields();}});},[c,k]),P?jsxs(Fragment,{children:[jsx(Y,{initialValues:s,form:c,labelCol:i,confirmText:r,onFinish:V,onReset:G,children:a==null?void 0:a(c)}),jsx(Table,T(y({},p),{dataSource:w==null?void 0:w.List,loading:z,pagination:{showSizeChanger:!0,showQuickJumper:!0,current:M.page,pageSize:M.size,total:w==null?void 0:w.Total,onChange:U}}))]}):jsx(Result,{status:403,subTitle:"\u65E0\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u8FDB\u884C\u6388\u6743"})},qt=Ot;var Zt={getItem:t=>sessionStorage.getItem(t)||localStorage.getItem(t),setItem:(t,e)=>{localStorage.setItem(t,e),sessionStorage.setItem(t,e);},removeItem:t=>R(void 0,null,function*(){localStorage.removeItem(t),sessionStorage.removeItem(t);})},Ae=()=>create()(persist(t=>({title:"",isPermissionV2:!1,isGlobalNS:!1,game:null,setGame:e=>t({game:e}),openKeys:[],setOpenKeys:e=>t({openKeys:e}),selectedKeys:[],setSelectedKeys:e=>t({selectedKeys:e}),menuItems:[],onlyDomesticGames:!1}),{name:"ReactToolkits",storage:createJSONStorage(()=>Zt),partialize:t=>({title:t.title,game:t.game,openKeys:t.openKeys,selectedKeys:t.selectedKeys})})),re=createContext(null);function b(t,e){let o=useContext(re);if(!o)throw new Error("Missing ReactToolkitsContext.Provider in the tree");return useStore(o,t,e)}var oo=t=>{let i=t,{children:e}=i,o=x(i,["children"]),r=useRef();return r.current||(r.current=Ae()),useEffect(()=>{var n;(n=r.current)==null||n.setState(o);},[o]),jsx(re.Provider,{value:r.current,children:e})},ro=oo;var{Text:uo}=Typography;function co(){let{isPermissionV2:t,isGlobalNS:e}=b(s=>s),o=D(s=>s.getUser()),r=B(),{data:i,isLoading:n}=Gt(t&&!e&&o?`/api/usystem/game/all?user=${o.authorityId}`:null,s=>r.get(s,{headers:{"App-ID":"global"}}));return {games:i,isLoading:n}}var fo=()=>{let{game:t,setGame:e,isGlobalNS:o,isPermissionV2:r,onlyDomesticGames:i}=b(m=>m),{games:n,isLoading:s}=co(),a=useMemo(()=>{var m;return (m=(n!=null?n:[]).filter(d=>!i||d.area==="cn"))==null?void 0:m.map(d=>({label:d.name,value:d.id}))},[n,i]),l=useCallback(m=>R(void 0,null,function*(){var p;let d=(p=(n!=null?n:[]).find(P=>P.id===m))!=null?p:null;e(d);}),[n,e]);return !r||o?null:jsxs(Space,{children:[jsx(uo,{children:"\u5F53\u524D\u6E38\u620F"}),jsx(Select,{showSearch:!0,optionFilterProp:"label",value:t==null?void 0:t.id,placeholder:"\u8BF7\u9009\u62E9\u6E38\u620F",loading:s,style:{width:"200px"},options:a,onChange:l})]})},se=fo;var bo=t=>{let e=useNavigate(),o=D(i=>i.clearToken),r=D(i=>i.getUser());return jsx(Dropdown,{menu:{selectable:!0,items:[{key:"1",label:jsx(Ne,{onClick:()=>{o(),e("/login");},children:"\u767B\u51FA"}),icon:jsx(LogoutOutlined,{})}]},placement:"bottomRight",children:jsx(Ne,{children:jsxs(Space,{align:"center",children:[jsx("span",{children:r==null?void 0:r.authorityId}),jsx(UserOutlined,{style:{fontSize:"16px"}})]})})})},ne=bo;var Mo=(t,e)=>t?e?jsx(Link,{to:e,children:t}):t:jsx(Fragment,{});function Ee(t,e){let o=[];for(let n=0;n<t.length;n++)if(t[n]===null)o[n]=null;else if(t[n].type==="divider")o[n]=y({},t[n]);else if(t[n].children){let r=t[n],{children:s}=r,a=x(r,["children"]);o[n]=T(y({},a),{children:Ee(s!=null?s:[],e)});}else {let i=t[n],{route:s,label:a,code:l}=i,m=x(i,["route","label","code"]),d=!l||!e||e[l];o[n]=d?T(y({},m),{label:Mo(a,s)}):null;}return o}function Qe(t,e=[],o=[]){for(let r of t){let i=r.children;if(Array.isArray(i)){let n=r.type!=="group"&&r.key?[...o,r.key]:o;Qe(i,e,n);}else e.push(Object.assign(r,{keypath:o}));}return e}var wo=()=>{let t=useLocation(),e=b(p=>p.menuItems),o=useMemo(()=>Qe(e!=null?e:[]),[e]),r=o.map(p=>p.code).filter(Boolean),{data:i}=ee(r,!0),n=useMemo(()=>Ee(e!=null?e:[],i),[e,i]),{openKeys:s,selectedKeys:a,setOpenKeys:l,setSelectedKeys:m}=b(p=>p),d=useCallback(p=>{var f;let P=p==null?void 0:p.find(C=>(s==null?void 0:s.indexOf(C))===-1),c=o.find(C=>P===C.key);l((f=c==null?void 0:c.keypath)!=null?f:[P]);},[o,s,l]);return useEffect(()=>{let p=o.find(P=>t.pathname===P.route);if(p){let P=p.key,c=p.keypath;m([P]),l(c);}},[o,t,l,m]),jsx(Menu,{style:{borderRight:"none"},items:n,mode:"inline",openKeys:s,selectedKeys:a,onOpenChange:d})},ae=wo;var Do=t=>{let{children:e}=t,{game:o,isPermissionV2:r,isGlobalNS:i}=b(n=>n);return r&&!i&&!o?jsx(Card,{children:jsx(Empty,{image:Empty.PRESENTED_IMAGE_SIMPLE,description:"\u8BF7\u9009\u62E9\u6E38\u620F"})}):jsx(Fragment,{children:e})},ze=Do;var {Spin:Qo,theme:Wo}=H,{Header:zo,Sider:Oo,Content:qo}=H.Layout,Ho=t=>{let{children:e,extra:o}=t,{token:{colorBgContainer:r,colorBorder:i}}=Wo.useToken(),{title:n,game:s}=b(a=>a);return jsxs(H.Layout,{hasSider:!0,className:"h-screen",children:[jsxs(Oo,{width:256,style:{overflow:"auto",height:"100vh",position:"fixed",left:0,top:0,bottom:0,borderRightWidth:1,borderRightStyle:"solid",borderRightColor:i},theme:"light",children:[jsxs("div",{className:"flex items-end px-6 py-4",children:[jsx("img",{src:Eo,alt:"logo",className:"w-8 h-8"}),jsx(Link,{className:"font-bold text-lg ml-2",to:"/",children:n})]}),jsx(ae,{})]}),jsxs(H.Layout,{className:"ml-64",children:[jsx(zo,{style:{padding:"0 24px",background:r,borderBottomWidth:1,borderBottomStyle:"solid",borderBottomColor:i},children:jsxs("div",{className:"flex justify-between items-center h-full",children:[jsx("div",{children:jsx(se,{})}),jsxs(Space,{size:"small",split:jsx(Divider,{type:"vertical"}),children:[o,jsx(ne,{})]})]})}),jsx(qo,{className:"p-6 bg-gray-50",style:{overflow:"overlay"},children:jsx(Suspense,{fallback:jsx(Qo,{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"50vh"}}),children:jsx(SWRConfig,{value:{revalidateOnMount:!0},children:jsx(ze,{children:Oe.createElement("div",{key:s==null?void 0:s.id},e)})})})})]})]})},Uo=Ho;var Jo=t=>{let{code:e,children:o}=t,{accessible:r,isValidating:i}=E(e);return i?jsx(Spin,{style:{display:"flex",justifyContent:"center",alignItems:"center",height:200}}):r?jsx(Fragment,{children:o}):jsx(Result,{status:"403",subTitle:"\u65E0\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u8FDB\u884C\u6388\u6743"})},jo=Jo;
21
-
22
- export { Ze as DynamicTags, Y as FilterForm, Z as FormModal, se as GameSelect, It as Highlight, Uo as Layout, ae as NavMenu, Nt as PermissionButton, jo as PermissionGuard, qt as QueryList, Ge as QueryListAction, ro as ReactToolkitsProvider, ne as UserWidget, Pt as useFormModal, b as useReactToolkitsContext };
23
- //# sourceMappingURL=out.js.map
24
- //# sourceMappingURL=index.esm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/components/DynamicTags/index.tsx","../../src/components/FilterForm/index.tsx","../../src/components/FormModal/index.tsx","../../src/components/FormModal/hooks.tsx","../../src/components/Highlight/index.tsx","../../src/stores/token.ts","../../src/stores/query-list.ts","../../src/hooks/use-http-client.ts","../../src/hooks/use-permission.ts","../../src/components/PermissionButton/index.tsx","../../src/components/QueryList/index.tsx","../../src/components/ReactToolkitsProvider/context.ts","../../src/components/ReactToolkitsProvider/index.tsx","../../src/components/GameSelect/index.tsx","../../src/components/UserWidget/index.tsx","../../src/components/NavMenu/index.tsx","../../src/components/Layout/index.tsx","../../src/components/RequireGame/index.tsx","../../src/components/PermissionGuard/index.tsx"],"names":["PlusOutlined","Input","Space","Tag","theme","useEffect","useRef","useState","jsx","jsxs","DynamicTags","props","initialTags","addable","removable","addCallback","removeCallback","token","tags","setTags","inputVisible","setInputVisible","inputValue","setInputValue","editInputIndex","setEditInputIndex","editInputValue","setEditInputValue","inputRef","editInputRef","_a","handleClose","removedTag","__async","newTags","tag","showInput","handleInputChange","e","handleInputConfirm","handleEditInputChange","handleEditInputConfirm","tagInputStyle","tagPlusStyle","index","DynamicTags_default","Button","Col","Form","Row","FilterForm","children","confirmText","form","onReset","restProps","__objRest","formStyle","__spreadProps","__spreadValues","FilterForm_default","Modal","forwardRef","useId","useImperativeHandle","InternalFormModal","ref","width","title","open","footer","layout","labelCol","bodyStyle","initialValues","maskClosable","closeFn","onConfirm","internalForm","id","formRef","confirmLoading","setConfirmLoading","footerProp","labelColProp","onFinish","values","FormModal","FormModal_default","useCallback","useMemo","createPortal","useFormModal","content","setOpen","setTitle","showModal","options","_b","closeModal","flushSync","createRoot","splitByTags","str","regex","part","renderToString","node","container","root","resolve","Highlight","texts","htmlString","setHtmlString","result","text","Highlight_default","create","persist","jwtDecode","useTokenStore","set","get","_","state","useQueryListStore","key","_c","pagination","refresh","data","axios","HttpClientError","message","code","skip","useHttpClient","game","isGlobalNS","isPermissionV2","useReactToolkitsContext","defaultOptions","instance","config","headers","response","error","useSWRImmutable","usePermissions","codes","httpClient","url","isLoading","res","acc","curr","usePermission","Tooltip","PermissionButton","showLoading","accessible","isValidating","PermissionButton_default","Result","Table","useSWRMutation","Fragment","QueryListAction","QueryList","swrKey","renderForm","transformArg","transformResponse","afterQuerySuccess","tableProps","setRefresh","getPaginationData","setPaginationData","paginationData","actionRef","isMutating","trigger","_0","_1","arg","newPaginationData","_arg","list","onPaginationChange","currentPage","currentSize","QueryList_default","useStore","createContext","useContext","createJSONStorage","mixedStorage","name","value","createReactToolkitsStore","keys","ReactToolkitsContext","selector","equalityFn","store","ReactToolkitsProvider","storeRef","ReactToolkitsProvider_default","Select","Typography","Text","useGames","user","GameSelect","setGame","onlyDomesticGames","games","item","onGameChange","matchGame","GameSelect_default","useNavigate","Dropdown","Link","LogoutOutlined","UserOutlined","UserWidget","navigate","clearToken","UserWidget_default","Menu","useLocation","withLink","label","route","transformItems","items","permissions","i","isPass","flatItems","keypath","_keys","NavMenu","location","flattenItems","internalItems","openKeys","selectedKeys","setOpenKeys","setSelectedKeys","onOpenChange","latestOpenKey","match","NavMenu_default","Antd","Divider","React","Suspense","SWRConfig","logo","Card","Empty","RequireGame","RequireGame_default","Spin","Header","Sider","Content","Layout","extra","colorBgContainer","colorBorder","Layout_default","PermissionGuard","PermissionGuard_default"],"mappings":"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","sourcesContent":["import { PlusOutlined } from '@ant-design/icons'\nimport type { InputRef } from 'antd'\nimport { Input, Space, Tag, theme } from 'antd'\nimport type { FC } from 'react'\nimport { useEffect, useRef, useState } from 'react'\n\nexport interface DynamicTagsProps {\n initialTags?: string[]\n addable?: boolean\n removable?: boolean\n // 返回 Promise。如果返回 Promise.resolve(true),则添加; 如果返回 Promise.resolve(false) 或 Promise.reject,则不添加\n addCallback?: (addedTag: string) => Promise<boolean>\n // 返回 Promise。如果返回 Promise.resolve(true),则删除; 如果返回 Promise.resolve(false) 或 Promise.reject,则不删除\n removeCallback?: (removedTag: string) => Promise<boolean>\n}\n\nconst DynamicTags: FC<DynamicTagsProps> = props => {\n const { initialTags, addable, removable, addCallback, removeCallback } = props\n const { token } = theme.useToken()\n const [tags, setTags] = useState<string[]>([])\n const [inputVisible, setInputVisible] = useState(false)\n const [inputValue, setInputValue] = useState('')\n const [editInputIndex, setEditInputIndex] = useState(-1)\n const [editInputValue, setEditInputValue] = useState<string>('')\n const inputRef = useRef<InputRef>(null)\n const editInputRef = useRef<InputRef>(null)\n\n useEffect(() => {\n setTags(initialTags ?? [])\n }, [initialTags])\n\n useEffect(() => {\n if (inputVisible) {\n inputRef.current?.focus()\n }\n }, [inputVisible])\n\n useEffect(() => {\n editInputRef.current?.focus()\n }, [inputValue])\n\n const handleClose = async (removedTag: string) => {\n const success = await removeCallback?.(removedTag)\n\n if (success) {\n const newTags = tags.filter(tag => tag !== removedTag)\n setTags(newTags)\n }\n }\n\n const showInput = () => {\n setInputVisible(true)\n }\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n setInputValue(e.target.value)\n }\n\n const handleInputConfirm = async () => {\n if (inputValue && tags.indexOf(inputValue) === -1) {\n const success = await addCallback?.(inputValue)\n\n if (success) {\n setTags([...tags, inputValue])\n }\n }\n\n setInputVisible(false)\n setInputValue('')\n }\n\n const handleEditInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n setEditInputValue(e.target.value)\n }\n\n const handleEditInputConfirm = () => {\n const newTags = [...tags]\n newTags[editInputIndex] = editInputValue\n setTags(newTags)\n setEditInputIndex(-1)\n setInputValue('')\n }\n\n const tagInputStyle: React.CSSProperties = {\n width: 78,\n verticalAlign: 'top',\n }\n\n const tagPlusStyle: React.CSSProperties = {\n background: token.colorBgContainer,\n borderStyle: 'dashed',\n }\n\n return (\n <Space wrap size={[0, 8]}>\n <Space wrap size={[0, 8]}>\n {tags.map((tag, index) => {\n if (editInputIndex === index) {\n return (\n <Input\n ref={editInputRef}\n key={tag}\n size=\"small\"\n style={tagInputStyle}\n value={editInputValue}\n onChange={handleEditInputChange}\n onBlur={handleEditInputConfirm}\n onPressEnter={handleEditInputConfirm}\n />\n )\n }\n\n return (\n <Tag\n key={tag}\n closable={removable}\n style={{ userSelect: 'none' }}\n onClose={async e => {\n e.preventDefault()\n await handleClose(tag)\n }}\n >\n <span\n onDoubleClick={e => {\n if (index !== 0) {\n setEditInputIndex(index)\n setEditInputValue(tag)\n e.preventDefault()\n }\n }}\n >\n {tag}\n </span>\n </Tag>\n )\n })}\n </Space>\n {addable &&\n (inputVisible ? (\n <Input\n ref={inputRef}\n type=\"text\"\n size=\"small\"\n style={tagInputStyle}\n value={inputValue}\n onChange={handleInputChange}\n onBlur={handleInputConfirm}\n onPressEnter={handleInputConfirm}\n />\n ) : (\n <Tag style={tagPlusStyle} onClick={showInput}>\n <PlusOutlined />\n &nbsp;添加\n </Tag>\n ))}\n </Space>\n )\n}\n\nexport default DynamicTags\n","import type { FormInstance, FormProps } from 'antd'\nimport { Button, Col, Form, Row, Space, theme } from 'antd'\nimport type { PropsWithChildren } from 'react'\nimport * as React from 'react'\n\nexport interface FilterFormProps<Values>\n extends Pick<\n FormProps<Values>,\n | 'initialValues'\n | 'requiredMark'\n | 'onError'\n | 'onChange'\n | 'onValuesChange'\n | 'onFinish'\n | 'onFinishFailed'\n | 'layout'\n | 'labelCol'\n > {\n form?: FormInstance<Values>\n onReset?: () => void\n confirmText?: React.ReactNode\n}\n\nconst FilterForm = <Values = unknown,>(props: PropsWithChildren<FilterFormProps<Values>>) => {\n const { children, confirmText, form, onReset, ...restProps } = props\n const { token } = theme.useToken()\n\n const formStyle = {\n maxWidth: 'none',\n background: token.colorFillAlter,\n borderWidth: token.lineWidth,\n borderStyle: token.lineType,\n borderColor: token.colorBorder,\n borderRadius: token.borderRadiusLG,\n padding: 24,\n marginBottom: 24,\n }\n\n return (\n <Form {...restProps} form={form} autoComplete=\"off\">\n {children && (\n <div style={formStyle}>\n <Row gutter={18}>\n {children}\n <Col flex=\"auto\" />\n <Col flex=\"auto\" span={24} style={{ textAlign: 'right' }}>\n <Space>\n <Button type=\"primary\" htmlType=\"submit\">\n {confirmText || '查询'}\n </Button>\n <Button htmlType=\"reset\" onClick={onReset}>\n 重置\n </Button>\n </Space>\n </Col>\n </Row>\n </div>\n )}\n </Form>\n )\n}\n\nexport default FilterForm\n","/* eslint-disable react/jsx-indent */\nimport type { FormInstance, FormProps, ModalProps } from 'antd'\nimport { Button, Form, Modal } from 'antd'\nimport type { ForwardedRef, ReactElement } from 'react'\nimport { forwardRef, useId, useImperativeHandle, useMemo, useRef, useState } from 'react'\n\nexport type RecursivePartial<T> = T extends object\n ? {\n [P in keyof T]?: T[P] extends (infer U)[]\n ? RecursivePartial<U>[]\n : T[P] extends object\n ? RecursivePartial<T[P]>\n : T[P]\n }\n : unknown\n\nexport interface FormModalProps<T>\n extends Pick<ModalProps, 'width' | 'title' | 'open' | 'afterClose' | 'bodyStyle' | 'maskClosable'>,\n Pick<FormProps, 'labelCol' | 'layout' | 'colon'> {\n form?: FormInstance<T>\n children?: ReactElement | ReactElement[]\n footer?: ModalProps['footer']\n closeFn?: VoidFunction\n initialValues?: RecursivePartial<T>\n onConfirm?: (values: T) => Promise<void>\n}\n\nexport interface FormModalRef<T = object> {\n setFieldsValue: (values: RecursivePartial<T>) => void\n}\n\nconst InternalFormModal = <T extends object>(props: FormModalProps<T>, ref: ForwardedRef<FormModalRef<T>>) => {\n const {\n form,\n width,\n children,\n title,\n open,\n footer,\n layout,\n labelCol,\n bodyStyle,\n initialValues,\n maskClosable,\n closeFn,\n onConfirm,\n } = props\n const [internalForm] = Form.useForm(form)\n const id = useId()\n const formRef = useRef<FormInstance<T>>(null)\n const [confirmLoading, setConfirmLoading] = useState(false)\n const footerProp =\n typeof footer === 'object'\n ? footer\n : [\n <Button\n key=\"cancel\"\n onClick={() => {\n closeFn?.()\n }}\n >\n 取消\n </Button>,\n <Button key=\"submit\" form={id} type=\"primary\" htmlType=\"submit\" loading={confirmLoading}>\n 确定\n </Button>,\n ]\n\n const labelColProp = labelCol || {\n flex: !layout || layout === 'horizontal' ? '120px' : '0',\n }\n\n const onFinish = async (values: T) => {\n try {\n setConfirmLoading(true)\n await onConfirm?.(values)\n closeFn?.()\n internalForm.resetFields()\n } finally {\n setConfirmLoading(false)\n }\n }\n\n useImperativeHandle(ref, () => {\n return {\n setFieldsValue(values) {\n formRef.current?.setFieldsValue(values)\n },\n }\n })\n\n return (\n <Modal\n destroyOnClose\n bodyStyle={bodyStyle}\n style={{ textAlign: 'start' }}\n width={width}\n open={open}\n title={title}\n forceRender={true}\n getContainer={false}\n maskClosable={maskClosable}\n footer={footerProp}\n onCancel={closeFn}\n >\n <Form\n form={internalForm}\n ref={formRef}\n id={id}\n autoComplete=\"off\"\n labelAlign=\"right\"\n labelWrap={true}\n layout={layout}\n initialValues={initialValues}\n labelCol={labelColProp}\n onFinish={onFinish}\n >\n {children}\n </Form>\n </Modal>\n )\n}\n\nconst FormModal = forwardRef(InternalFormModal) as <T extends object>(\n props: FormModalProps<T> & { ref?: ForwardedRef<FormModalRef<T>> },\n) => ReactElement\n\nexport default FormModal\n","import type { FormModalProps, FormModalRef, RecursivePartial } from './index'\nimport FormModal from './index'\nimport { useCallback, useMemo, useRef, useState } from 'react'\nimport type { Merge } from 'ts-essentials'\nimport { createPortal } from 'react-dom'\nimport { Form } from 'antd'\n\nexport type UseFormModalProps<T> = Merge<\n Omit<FormModalProps<T>, 'open' | 'onCancel' | 'closeFn' | 'children' | 'form'>,\n {\n content: FormModalProps<T>['children']\n }\n>\n\nexport function useFormModal<T extends object>(props: UseFormModalProps<T>) {\n const { content, onConfirm, ...restProps } = props\n const [open, setOpen] = useState(false)\n const [title, setTitle] = useState<FormModalProps<T>['title']>()\n const formRef = useRef<FormModalRef>(null)\n const [form] = Form.useForm<T>()\n\n const showModal = (options?: { initialValues?: RecursivePartial<T>; title?: FormModalProps<T>['title'] }) => {\n setTitle(options?.title ?? restProps.title)\n\n if (options?.initialValues) {\n formRef.current?.setFieldsValue(options?.initialValues)\n }\n\n setOpen(true)\n }\n\n const closeModal = useCallback(() => {\n setOpen(false)\n }, [])\n\n const Modal = useMemo(\n () =>\n createPortal(\n <FormModal\n {...restProps}\n ref={formRef}\n form={form}\n open={open}\n closeFn={closeModal}\n title={title}\n onConfirm={onConfirm}\n >\n {content}\n </FormModal>,\n document.body,\n ),\n [title, content, restProps, form, open, closeModal, onConfirm],\n )\n\n return {\n Modal,\n showModal,\n closeModal,\n form,\n }\n}\n","import type { PropsWithChildren, ReactNode } from 'react'\nimport { useEffect, useState } from 'react'\nimport { flushSync } from 'react-dom'\nimport { createRoot } from 'react-dom/client'\n\nconst splitByTags = (str: string) => {\n const regex = /(<[^>]*>)/\n return str.split(regex).filter(part => part !== '')\n}\n\nfunction renderToString(node: ReactNode): Promise<string> {\n const container = document.createElement('div')\n const root = createRoot(container)\n\n return new Promise(resolve => {\n setTimeout(() => {\n flushSync(() => {\n root.render(node)\n })\n resolve(container.innerHTML)\n })\n })\n}\n\nexport interface HighlightTextsProps extends PropsWithChildren {\n texts: Array<string | number>\n}\n\nconst Highlight = (props: HighlightTextsProps) => {\n const { texts, children } = props\n const [htmlString, setHtmlString] = useState<string>('')\n\n useEffect(() => {\n renderToString(children).then(str => {\n const result = splitByTags(str)\n\n for (const text of texts) {\n for (let index = 0; index < result.length; index++) {\n // TODO: 忽略 HTML tag\n result[index] = result[index].replace(String(text), `<span style='color: #DC143C;'>${text}</span>`)\n }\n }\n\n setHtmlString(result.join(''))\n })\n }, [children, texts])\n\n return <p dangerouslySetInnerHTML={{ __html: htmlString }}></p>\n}\n\nexport default Highlight\n","import { create } from 'zustand'\nimport { persist } from 'zustand/middleware'\nimport jwtDecode from 'jwt-decode'\n\ninterface UserInfo {\n authorityId: string\n exp: number\n}\n\nexport interface TokenState {\n token: string\n getUser: () => UserInfo | null\n setToken: (token: string) => void\n clearToken: () => void\n}\n\nexport const useTokenStore = create<TokenState>()(\n persist(\n (set, get) => ({\n token: '',\n getUser: () => {\n try {\n return jwtDecode(get().token) as UserInfo\n } catch (_) {\n return null\n }\n },\n setToken: token => set({ token }),\n clearToken: () => {\n set({ token: '' })\n useTokenStore.persist.clearStorage()\n },\n }),\n {\n name: 'token',\n partialize: state => ({ token: state.token }),\n },\n ),\n)\n","import type { QueryListKey } from '@/components/QueryList'\nimport type { PaginationParams } from '@/types'\nimport { create } from 'zustand'\n\ntype RefreshFunction = (arg?: Partial<PaginationParams>) => void\n\nexport interface QueryListState {\n data: Map<\n QueryListKey,\n {\n pagination?: PaginationParams\n refresh?: RefreshFunction\n }\n >\n getPaginationData: (key: QueryListKey) => PaginationParams\n setPaginationData: (key: QueryListKey, pagination?: Partial<PaginationParams>) => void\n refresh: (key: QueryListKey, arg?: Partial<PaginationParams>) => void\n setRefresh: (key: QueryListKey, trigger: RefreshFunction) => void\n}\n\nexport const useQueryListStore = create<QueryListState>((set, get) => ({\n data: new Map(),\n getPaginationData: (key: QueryListKey) => {\n const pagination = get().data.get(key)?.pagination\n return {\n page: pagination?.page ?? 1,\n size: pagination?.size ?? 10,\n }\n },\n setPaginationData: (key: QueryListKey, pagination?: Partial<PaginationParams>) => {\n set({\n data: new Map(get().data).set(key, {\n ...get().data.get(key),\n pagination: {\n page: pagination?.page ?? get().getPaginationData(key).page,\n size: pagination?.size ?? get().getPaginationData(key).size,\n },\n }),\n })\n },\n refresh: (key: QueryListKey, pagination?: Partial<PaginationParams>) => {\n const refresh = get().data.get(key)?.refresh\n\n if (refresh) {\n refresh({\n page: pagination?.page ?? get().getPaginationData(key).page,\n size: pagination?.size ?? get().getPaginationData(key).size,\n })\n }\n },\n setRefresh: (key: QueryListKey, refresh: RefreshFunction) => {\n const data = get().data\n\n set({\n data: new Map(data).set(key, {\n ...data.get(key),\n refresh,\n }),\n })\n },\n}))\n","import { useTokenStore } from '@/stores'\nimport type { AxiosInstance, AxiosRequestConfig } from 'axios'\nimport axios from 'axios'\nimport type { Merge } from 'ts-essentials'\nimport { useReactToolkitsContext } from '@/components' // 覆盖 AxiosInstance 各种请求方法的返回值,为了方便我们在 interceptors.response 里把 AxiosResponse 直接打平成后端返回的数据,去掉了 axios 的封装。\n\n// 覆盖 AxiosInstance 各种请求方法的返回值,为了方便我们在 interceptors.response 里把 AxiosResponse 直接打平成后端返回的数据,去掉了 axios 的封装。\ntype ShimmedAxiosInstance = Merge<\n AxiosInstance,\n {\n request<T = unknown, D = unknown>(config: AxiosRequestConfig<D>): Promise<T>\n get<T = unknown, D = unknown>(url: string, config?: AxiosRequestConfig<D>): Promise<T>\n delete<T = unknown, D = unknown>(url: string, config?: AxiosRequestConfig<D>): Promise<T>\n head<T = unknown, D = unknown>(url: string, config?: AxiosRequestConfig<D>): Promise<T>\n post<T = unknown, D = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig<D>): Promise<T>\n put<T = unknown, D = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig<D>): Promise<T>\n patch<T = unknown, D = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig<D>): Promise<T>\n }\n>\n\nexport class HttpClientError extends Error {\n code?: number\n // 跳过错误提示\n skip: boolean\n\n constructor(message: string, code?: number, skip = false) {\n super(message)\n this.code = code\n this.skip = skip\n }\n}\n\nexport function useHttpClient() {\n const token = useTokenStore(state => state.token)\n const { game, isGlobalNS, isPermissionV2 } = useReactToolkitsContext(state => state)\n\n const defaultOptions: AxiosRequestConfig = {\n withCredentials: true,\n }\n\n const instance = axios.create(defaultOptions) as ShimmedAxiosInstance\n\n instance.interceptors.request.use(config => {\n const headers = config.headers\n headers.set('Authorization', `Bearer ${token}`)\n\n if (isPermissionV2) {\n if (!headers.has('App-ID')) {\n headers.set('App-ID', isGlobalNS ? 'global' : game?.id)\n }\n }\n\n return config\n })\n\n instance.interceptors.response.use(\n response => {\n const contentType = response.headers['content-type']\n if (contentType.includes('application/octet-stream')) {\n return response\n } else {\n if (response.data.code === 0 || response.data.status === 0) {\n return response.data.data\n }\n\n throw new HttpClientError(response.data.msg, 0)\n }\n },\n error => {\n if (error.response) {\n // 请求成功发出且服务器也响应了状态码,但状态码超出了 2xx 的范围\n if (error.response.status === 401) {\n throw new HttpClientError('未登录或登录已过期', error.response.status)\n } else if (error.response.status === 403) {\n throw new HttpClientError('无权限,请联系管理员进行授权', error.response.status)\n } else if ([404, 405].includes(error.response.status)) {\n throw new HttpClientError('Not Found or Method not Allowed', error.response.status, true)\n } else if (error.response.status === 412) {\n throw new HttpClientError('未注册用户', error.response.status)\n } else if (error.response.status === 504) {\n throw new HttpClientError('请求超时', error.response.status)\n } else {\n throw new HttpClientError(error.response.message, error.response.status)\n }\n }\n\n throw new HttpClientError('无响应')\n },\n )\n\n return instance\n}\n","import useSWRImmutable from 'swr/immutable'\nimport { useHttpClient } from './use-http-client'\nimport { useReactToolkitsContext } from '@/components'\n\nexport interface PermissionCheckResult {\n [k: string]: boolean\n}\n\nexport function usePermissions(codes: string[], isGlobalNS = false) {\n const httpClient = useHttpClient()\n const isPermissionV2 = useReactToolkitsContext(state => state.isPermissionV2)\n const url = isPermissionV2 ? '/api/usystem/user/checkV2' : '/api/usystem/user/check'\n\n const { data, isLoading } = useSWRImmutable(\n codes.length > 0\n ? {\n method: 'POST',\n url,\n data: { permissions: codes },\n headers: isGlobalNS\n ? {\n 'App-ID': 'global',\n }\n : {},\n }\n : null,\n config =>\n httpClient.request<PermissionCheckResult>(config).then(res => {\n if (res.has_all) {\n return codes.reduce(\n (acc, curr) => {\n acc[curr] = true\n return acc\n },\n {} as Record<string, boolean>,\n )\n }\n\n return codes.reduce(\n (acc, curr) => {\n acc[curr] = (res as Record<string, boolean>)[curr]\n return acc\n },\n {} as Record<string, boolean>,\n )\n }),\n {\n suspense: true,\n shouldRetryOnError: false,\n },\n )\n\n return { data, isLoading }\n}\n\nexport function usePermission(code: string) {\n const { data, isLoading } = usePermissions(code ? [code] : [])\n\n if (!code) {\n return {\n accessible: true,\n isValidating: false,\n }\n }\n\n return {\n accessible: data?.[code] ?? false,\n isValidating: isLoading,\n }\n}\n","import { usePermission } from '@/hooks'\nimport type { ButtonProps } from 'antd'\nimport { Button, Tooltip } from 'antd'\nimport type { FC, PropsWithChildren } from 'react'\n\nexport interface PermissionButtonProps extends Omit<ButtonProps, 'disabled'> {\n code: string\n showLoading?: boolean\n}\n\nconst PermissionButton: FC<PropsWithChildren<PermissionButtonProps>> = props => {\n const { children, code, showLoading, ...restProps } = props\n const { accessible, isValidating } = usePermission(code)\n\n if (isValidating) {\n return (\n <Button loading={showLoading} disabled={!showLoading} {...restProps}>\n {children}\n </Button>\n )\n }\n\n if (!accessible) {\n return (\n <Tooltip defaultOpen={false} title=\"无权限,请联系管理员进行授权\">\n <Button disabled {...restProps}>\n {children}\n </Button>\n </Tooltip>\n )\n }\n\n return <Button {...restProps}>{children}</Button>\n}\n\nexport default PermissionButton\n","import { useHttpClient, usePermission } from '@/hooks'\nimport { useQueryListStore } from '@/stores'\nimport type { ListResponse, PaginationParams } from '@/types'\nimport type { FormInstance, FormProps } from 'antd'\nimport { Form, Result, Table } from 'antd'\nimport type { TableProps } from 'antd/es/table'\nimport type { AxiosRequestConfig } from 'axios'\nimport type { ReactNode } from 'react'\nimport { useCallback, useEffect, useMemo, useRef } from 'react'\nimport useSWRMutation from 'swr/mutation'\nimport FilterForm from '../FilterForm'\nimport type { Merge } from 'ts-essentials'\n\nexport type QueryListKey = Omit<AxiosRequestConfig, 'data' | 'params'>\n\nexport enum QueryListAction {\n Submit = 'submit',\n Reset = 'reset',\n}\n\nexport interface QueryListProps<Item, Values, Response>\n extends Pick<TableProps<Item>, 'columns' | 'rowKey' | 'tableLayout' | 'expandable' | 'rowSelection' | 'bordered'>,\n Pick<FormProps<Values>, 'initialValues' | 'labelCol'> {\n // 由于表单的值和分页数据是封装在组件内部的,不便于在组件外部构造 swr key,\n // 所以组件内部的 useSWRMutation hook 使用的 key 是不包含表单值和分页参数的。\n // 因此 swr 并未按照分页缓存数据。\n form?: FormInstance<Values>\n swrKey: QueryListKey\n confirmText?: ReactNode\n code?: string\n renderForm?: (form: FormInstance<Values>) => ReactNode\n // 把表单的值和分页数据转换成请求参数\n transformArg?: (arg: Merge<Values, PaginationParams>) => unknown\n // 当请求的返回值不满足时进行转换\n transformResponse?: (response: Response) => ListResponse<Item>\n afterQuerySuccess?: (response: ListResponse<Item>, action?: QueryListAction) => void\n}\n\nconst QueryList = <Item extends object, Values = NonNullable<unknown>, Response = ListResponse<Item>>(\n props: QueryListProps<Item, Values, Response>,\n) => {\n const {\n form,\n code,\n confirmText,\n labelCol,\n swrKey,\n initialValues,\n renderForm,\n transformArg,\n transformResponse,\n afterQuerySuccess,\n ...tableProps\n } = props\n const { accessible } = usePermission(code ?? '')\n const [internalForm] = Form.useForm(form)\n const { setRefresh, getPaginationData, setPaginationData } = useQueryListStore(state => state)\n const paginationData = getPaginationData(swrKey)\n const actionRef = useRef<QueryListAction>()\n\n const httpClient = useHttpClient()\n\n // TODO: 使用 useSWR 重构\n const { data, isMutating, trigger } = useSWRMutation(\n swrKey,\n async (key, { arg }: { arg?: Partial<PaginationParams> }) => {\n await internalForm.validateFields()\n\n const newPaginationData = {\n page: arg?.page ?? paginationData.page,\n size: arg?.size ?? paginationData.size,\n }\n\n setPaginationData(swrKey, arg)\n\n const values = internalForm.getFieldsValue()\n\n const _arg = {\n ...values,\n ...newPaginationData,\n }\n\n return httpClient\n .request<Response>({\n ...key,\n [key.method === 'POST' ? 'data' : 'params']: transformArg?.(_arg) ?? _arg,\n })\n .then(response => {\n const list = transformResponse?.(response) ?? (response as ListResponse<Item>)\n afterQuerySuccess?.(list, actionRef.current)\n return list\n })\n .finally(() => {\n actionRef.current = undefined\n })\n },\n )\n\n const onFinish = async () => {\n actionRef.current = QueryListAction.Submit\n await trigger({ page: 1 })\n }\n\n const onReset = useCallback(async () => {\n try {\n actionRef.current = QueryListAction.Reset\n internalForm.resetFields()\n await internalForm.validateFields()\n await trigger({ page: 1 })\n } catch (_) {\n console.log('表单校验失败')\n }\n }, [internalForm, trigger])\n\n const onPaginationChange = useCallback(\n async (currentPage: number, currentSize: number) => {\n await trigger({\n page: currentPage,\n size: currentSize,\n })\n },\n [trigger],\n )\n\n useEffect(() => {\n setRefresh(swrKey, trigger)\n }, [swrKey, trigger, setRefresh])\n\n useEffect(() => {\n ;(async () => {\n try {\n await internalForm.validateFields()\n await trigger()\n } catch (_) {\n internalForm.resetFields()\n }\n })()\n }, [internalForm, trigger])\n\n if (!accessible) {\n return <Result status={403} subTitle=\"无权限,请联系管理员进行授权\" />\n }\n\n return (\n <>\n <FilterForm<Values>\n initialValues={initialValues}\n form={internalForm}\n labelCol={labelCol}\n confirmText={confirmText}\n onFinish={onFinish}\n onReset={onReset}\n >\n {renderForm?.(internalForm)}\n </FilterForm>\n <Table\n {...tableProps}\n dataSource={data?.List}\n loading={isMutating}\n pagination={{\n showSizeChanger: true,\n showQuickJumper: true,\n current: paginationData.page,\n pageSize: paginationData.size,\n total: data?.Total,\n onChange: onPaginationChange,\n }}\n />\n </>\n )\n}\n\nexport default QueryList\n","import { create, useStore } from 'zustand'\nimport { createContext, useContext } from 'react'\nimport type { StateStorage } from 'zustand/middleware'\nimport { createJSONStorage, persist } from 'zustand/middleware'\nimport type { GameType } from '../GameSelect'\nimport type { ItemType2 } from '../NavMenu'\n\n// SessionStorage 在同一域下的不同页面间是隔离的,用于防止多开页面时的数据冲突\nconst mixedStorage: StateStorage = {\n getItem: (name: string): string | null => {\n return sessionStorage.getItem(name) || localStorage.getItem(name)\n },\n setItem: (name: string, value: string) => {\n localStorage.setItem(name, value)\n sessionStorage.setItem(name, value)\n },\n removeItem: async (name: string) => {\n localStorage.removeItem(name)\n sessionStorage.removeItem(name)\n },\n}\n\nexport interface ReactToolkitsState {\n title: string\n isPermissionV2: boolean\n isGlobalNS: boolean\n game: GameType | null\n setGame: (game: GameType | null) => void\n openKeys: string[]\n selectedKeys: string[]\n setOpenKeys: (keys: string[]) => void\n setSelectedKeys: (keys: string[]) => void\n menuItems: ItemType2[]\n onlyDomesticGames: boolean\n}\n\nexport type ReactToolkitsStore = ReturnType<typeof createReactToolkitsStore>\n\nexport const createReactToolkitsStore = () => {\n return create<ReactToolkitsState>()(\n persist(\n set => ({\n title: '',\n isPermissionV2: false,\n isGlobalNS: false,\n game: null,\n setGame: game => set({ game }),\n openKeys: [],\n setOpenKeys: keys => set({ openKeys: keys }),\n selectedKeys: [],\n setSelectedKeys: keys => set({ selectedKeys: keys }),\n menuItems: [],\n onlyDomesticGames: false,\n }),\n {\n name: 'ReactToolkits',\n storage: createJSONStorage(() => mixedStorage),\n partialize: state => ({\n title: state.title,\n game: state.game,\n openKeys: state.openKeys,\n selectedKeys: state.selectedKeys,\n }),\n },\n ),\n )\n}\n\nexport const ReactToolkitsContext = createContext<ReactToolkitsStore | null>(null)\n\nexport function useReactToolkitsContext<T>(\n selector: (state: ReactToolkitsState) => T,\n equalityFn?: (left: T, right: T) => boolean,\n): T {\n const store = useContext(ReactToolkitsContext)\n if (!store) throw new Error('Missing ReactToolkitsContext.Provider in the tree')\n return useStore(store, selector, equalityFn)\n}\n","import type { FC, PropsWithChildren } from 'react'\nimport { useEffect, useRef } from 'react'\nimport type { ReactToolkitsState, ReactToolkitsStore } from './context'\nimport { createReactToolkitsStore, ReactToolkitsContext } from './context'\n\n// TODO: 合并嵌套 ReactToolkitsProvider 的配置\nconst ReactToolkitsProvider: FC<\n PropsWithChildren<\n Partial<Pick<ReactToolkitsState, 'isPermissionV2' | 'isGlobalNS' | 'menuItems' | 'title' | 'onlyDomesticGames'>>\n >\n> = props => {\n const { children, ...restProps } = props\n const storeRef = useRef<ReactToolkitsStore>()\n\n if (!storeRef.current) {\n storeRef.current = createReactToolkitsStore()\n }\n\n useEffect(() => {\n storeRef.current?.setState(restProps)\n }, [restProps])\n\n return <ReactToolkitsContext.Provider value={storeRef.current}>{children}</ReactToolkitsContext.Provider>\n}\n\nexport default ReactToolkitsProvider\n","import { Select, Space, Typography } from 'antd'\nimport { useCallback, useMemo } from 'react'\nimport { useTokenStore } from '@/stores'\nimport useSWRImmutable from 'swr/immutable'\nimport { useReactToolkitsContext } from '@/components'\nimport { useHttpClient } from '@/hooks'\n\nconst { Text } = Typography\n\nexport interface GameType {\n id: string\n name: string\n area: 'cn' | 'global'\n Ctime: string\n}\n\nfunction useGames() {\n const { isPermissionV2, isGlobalNS } = useReactToolkitsContext(state => state)\n const user = useTokenStore(state => state.getUser())\n const httpClient = useHttpClient()\n\n const { data, isLoading } = useSWRImmutable<GameType[]>(\n isPermissionV2 && !isGlobalNS && user ? `/api/usystem/game/all?user=${user.authorityId}` : null,\n url =>\n httpClient.get(url, {\n headers: {\n 'App-ID': 'global',\n },\n }),\n )\n\n return {\n games: data,\n isLoading,\n }\n}\n\nconst GameSelect = () => {\n const { game, setGame, isGlobalNS, isPermissionV2, onlyDomesticGames } = useReactToolkitsContext(state => state)\n const { games, isLoading } = useGames()\n\n const options = useMemo(\n () =>\n (games ?? [])\n .filter(item => !onlyDomesticGames || item.area === 'cn')\n ?.map(item => ({\n label: item.name,\n value: item.id,\n })),\n [games, onlyDomesticGames],\n )\n\n const onGameChange = useCallback(\n async (id: string) => {\n const matchGame = (games ?? []).find(item => item.id === id) ?? null\n setGame(matchGame)\n },\n [games, setGame],\n )\n\n if (!isPermissionV2 || isGlobalNS) {\n return null\n }\n\n return (\n <Space>\n <Text>当前游戏</Text>\n <Select\n showSearch\n optionFilterProp=\"label\"\n value={game?.id}\n placeholder=\"请选择游戏\"\n loading={isLoading}\n style={{ width: '200px' }}\n options={options}\n onChange={onGameChange}\n />\n </Space>\n )\n}\n\nexport default GameSelect\n","import type { FC } from 'react'\nimport { useNavigate } from 'react-router-dom'\nimport { Dropdown, Space } from 'antd'\nimport Link from 'antd/es/typography/Link'\nimport { LogoutOutlined, UserOutlined } from '@ant-design/icons'\nimport { useTokenStore } from '@/stores'\n\nconst UserWidget: FC = props => {\n const navigate = useNavigate()\n const clearToken = useTokenStore(state => state.clearToken)\n const user = useTokenStore(state => state.getUser())\n\n return (\n <Dropdown\n menu={{\n selectable: true,\n items: [\n {\n key: '1',\n label: (\n <Link\n onClick={() => {\n clearToken()\n navigate('/login')\n }}\n >\n 登出\n </Link>\n ),\n icon: <LogoutOutlined />,\n },\n ],\n }}\n placement=\"bottomRight\"\n >\n <Link>\n <Space align=\"center\">\n <span>{user?.authorityId}</span>\n <UserOutlined style={{ fontSize: '16px' }} />\n </Space>\n </Link>\n </Dropdown>\n )\n}\n\nexport default UserWidget\n","import {usePermissions} from '@/hooks'\nimport {Menu} from 'antd'\nimport type {\n ItemType,\n MenuDividerType,\n MenuItemGroupType,\n MenuItemType,\n SubMenuType,\n} from 'antd/es/menu/hooks/useItems'\nimport type {ReactNode} from 'react'\nimport {useCallback, useEffect, useMemo} from 'react'\nimport {Link, useLocation} from 'react-router-dom'\nimport type {Merge} from 'ts-essentials'\nimport {useReactToolkitsContext} from '@/components'\n\n// 扩展 antd Menu 的类型,使其支持一些我们想要的自定义字段。\ntype MenuItemType2 = Merge<\n MenuItemType,\n {\n code /** 权限编号 **/?: string\n route /** 前端路由地址 **/?: string\n }\n>\n\ntype SubMenuType2 = Merge<\n SubMenuType,\n {\n children?: ItemType2[]\n }\n>\n\ntype MenuItemGroupType2 = Merge<MenuItemGroupType, { children?: ItemType2[] }>\n\nexport type ItemType2 = MenuItemType2 | SubMenuType2 | MenuItemGroupType2 | MenuDividerType | null\n\nconst withLink = (label?: ReactNode, route?: string): ReactNode => {\n if (!label) {\n return <></>\n }\n\n if (route) {\n return <Link to={route}>{label}</Link>\n }\n\n return label\n}\n\nfunction transformItems(items: ItemType2[], permissions?: Record<string, boolean>) {\n const result: ItemType[] = []\n\n for (let i = 0; i < items.length; i++) {\n if (items[i] === null) {\n result[i] = null\n } else if ((items[i] as MenuDividerType).type === 'divider') {\n result[i] = { ...items[i] } as MenuDividerType\n } else {\n if ((items[i] as SubMenuType2 | MenuItemGroupType2).children) {\n const { children, ...restProps } = items[i] as SubMenuType2 | MenuItemGroupType2\n result[i] = {\n ...restProps,\n children: transformItems(children ?? [], permissions),\n } as SubMenuType | MenuItemGroupType\n } else {\n const { route, label, code, ...restProps } = items[i] as MenuItemType2\n const isPass = !code || !permissions || permissions[code]\n\n result[i] = isPass\n ? ({\n ...restProps,\n label: withLink(label, route),\n } as MenuItemType)\n : null\n }\n }\n }\n\n return result\n}\n\n// 拍平导航配置,并且注入 keypath 字段\nfunction flatItems(\n items: ItemType2[],\n result: Merge<MenuItemType2, { keypath?: string[] }>[] = [],\n keypath: string[] = [],\n) {\n for (const item of items) {\n const children = (item as SubMenuType2 | MenuItemGroupType2)!.children as ItemType2[]\n\n if (Array.isArray(children)) {\n const _keys =\n (item as MenuItemGroupType2)!.type !== 'group' && item!.key ? [...keypath, item!.key as string] : keypath\n flatItems(children, result, _keys)\n } else {\n result.push(Object.assign(item as MenuItemType2, { keypath }))\n }\n }\n\n return result\n}\n\nconst NavMenu = () => {\n const location = useLocation()\n const items = useReactToolkitsContext(state => state.menuItems)\n const flattenItems = useMemo(() => flatItems(items ?? []), [items])\n const codes = flattenItems.map(item => item.code).filter(Boolean) as string[]\n const { data: permissions } = usePermissions(codes, true)\n const internalItems = useMemo(() => transformItems(items ?? [], permissions), [items, permissions])\n const { openKeys, selectedKeys, setOpenKeys, setSelectedKeys } = useReactToolkitsContext(state => state)\n\n const onOpenChange = useCallback(\n (keys: string[]) => {\n const latestOpenKey = keys?.find(key => openKeys?.indexOf(key) === -1)\n const match = flattenItems.find(item => latestOpenKey === item.key)\n setOpenKeys((match?.keypath ?? [latestOpenKey]) as string[])\n },\n [flattenItems, openKeys, setOpenKeys],\n )\n\n useEffect(() => {\n const match = flattenItems.find(item => location.pathname === item.route)\n\n if (match) {\n const key = match.key as string\n const keypath = match.keypath as string[]\n setSelectedKeys([key])\n setOpenKeys(keypath)\n }\n }, [flattenItems, location, setOpenKeys, setSelectedKeys])\n\n return (\n <Menu\n style={{ borderRight: 'none' }}\n items={internalItems}\n mode=\"inline\"\n openKeys={openKeys}\n selectedKeys={selectedKeys}\n onOpenChange={onOpenChange}\n />\n )\n}\n\nexport default NavMenu\n","import * as Antd from 'antd'\nimport { Divider, Space } from 'antd'\nimport type { FC, PropsWithChildren } from 'react'\nimport * as React from 'react'\nimport { Suspense } from 'react'\nimport { Link } from 'react-router-dom'\nimport { GameSelect, NavMenu, useReactToolkitsContext, UserWidget } from '@/components'\nimport { SWRConfig } from 'swr'\nimport logo from './logo.png'\nimport RequireGame from '@/components/RequireGame'\n\nconst { Spin, theme } = Antd\nconst { Header, Sider, Content } = Antd.Layout\n\nexport interface LayoutProps extends PropsWithChildren {\n extra?: React.ReactNode[]\n}\n\nconst Layout: FC<LayoutProps> = props => {\n const { children, extra } = props\n const {\n token: { colorBgContainer, colorBorder },\n } = theme.useToken()\n const { title, game } = useReactToolkitsContext(state => state)\n\n return (\n <Antd.Layout hasSider className=\"h-screen\">\n <Sider\n width={256}\n style={{\n overflow: 'auto',\n height: '100vh',\n position: 'fixed',\n left: 0,\n top: 0,\n bottom: 0,\n borderRightWidth: 1,\n borderRightStyle: 'solid',\n borderRightColor: colorBorder,\n }}\n theme=\"light\"\n >\n <div className=\"flex items-end px-6 py-4\">\n <img src={logo} alt=\"logo\" className=\"w-8 h-8\" />\n <Link className=\"font-bold text-lg ml-2\" to=\"/\">\n {title}\n </Link>\n </div>\n <NavMenu />\n </Sider>\n <Antd.Layout className=\"ml-64\">\n <Header\n style={{\n padding: '0 24px',\n background: colorBgContainer,\n borderBottomWidth: 1,\n borderBottomStyle: 'solid',\n borderBottomColor: colorBorder,\n }}\n >\n <div className=\"flex justify-between items-center h-full\">\n <div>\n <GameSelect />\n </div>\n <Space size=\"small\" split={<Divider type=\"vertical\" />}>\n {extra}\n <UserWidget />\n </Space>\n </div>\n </Header>\n <Content className=\"p-6 bg-gray-50\" style={{ overflow: 'overlay' }}>\n <Suspense\n fallback={\n <Spin\n style={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n height: '50vh',\n }}\n />\n }\n >\n <SWRConfig\n value={{\n // GameSelect 组件内的 game 变化时,会触发 children 的重新渲染\n // 为了避免 SWR 使用缓存导致数据不更新,需要设置 revalidateOnMount 为 true\n revalidateOnMount: true,\n }}\n >\n <RequireGame>{React.createElement('div', { key: game?.id }, children)}</RequireGame>\n </SWRConfig>\n </Suspense>\n </Content>\n </Antd.Layout>\n </Antd.Layout>\n )\n}\n\nexport default Layout\n","import { Card, Empty } from 'antd'\nimport type { FC, PropsWithChildren } from 'react'\nimport { useReactToolkitsContext } from '@/components'\n\nconst RequireGame: FC<PropsWithChildren> = props => {\n const { children } = props\n const { game, isPermissionV2, isGlobalNS } = useReactToolkitsContext(state => state)\n\n if (isPermissionV2 && !isGlobalNS && !game) {\n return (\n <Card>\n <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description=\"请选择游戏\" />\n </Card>\n )\n }\n\n return <>{children}</>\n}\n\nexport default RequireGame\n","import { Result, Spin } from 'antd'\nimport type { FC, PropsWithChildren } from 'react'\nimport { usePermission } from '@/hooks'\n\nexport interface PermissionGuardProps {\n code: string\n}\n\nconst PermissionGuard: FC<PropsWithChildren<PermissionGuardProps>> = props => {\n const { code, children } = props\n const { accessible, isValidating } = usePermission(code)\n\n if (isValidating) {\n return (\n <Spin\n style={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n height: 200,\n }}\n />\n )\n }\n\n if (!accessible) {\n return <Result status=\"403\" subTitle=\"无权限,请联系管理员进行授权\" />\n }\n\n return <>{children}</>\n}\n\nexport default PermissionGuard\n"]}
Binary file
@@ -1,32 +0,0 @@
1
- import { AxiosInstance, AxiosRequestConfig } from 'axios';
2
- import { Merge } from 'ts-essentials';
3
-
4
- type ShimmedAxiosInstance = Merge<AxiosInstance, {
5
- request<T = unknown, D = unknown>(config: AxiosRequestConfig<D>): Promise<T>;
6
- get<T = unknown, D = unknown>(url: string, config?: AxiosRequestConfig<D>): Promise<T>;
7
- delete<T = unknown, D = unknown>(url: string, config?: AxiosRequestConfig<D>): Promise<T>;
8
- head<T = unknown, D = unknown>(url: string, config?: AxiosRequestConfig<D>): Promise<T>;
9
- post<T = unknown, D = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig<D>): Promise<T>;
10
- put<T = unknown, D = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig<D>): Promise<T>;
11
- patch<T = unknown, D = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig<D>): Promise<T>;
12
- }>;
13
- declare class HttpClientError extends Error {
14
- code?: number;
15
- skip: boolean;
16
- constructor(message: string, code?: number, skip?: boolean);
17
- }
18
- declare function useHttpClient(): ShimmedAxiosInstance;
19
-
20
- interface PermissionCheckResult {
21
- [k: string]: boolean;
22
- }
23
- declare function usePermissions(codes: string[], isGlobalNS?: boolean): {
24
- data: Record<string, boolean>;
25
- isLoading: false;
26
- };
27
- declare function usePermission(code: string): {
28
- accessible: boolean;
29
- isValidating: boolean;
30
- };
31
-
32
- export { HttpClientError, PermissionCheckResult, useHttpClient, usePermission, usePermissions };
@@ -1,12 +0,0 @@
1
- import { create, useStore } from 'zustand';
2
- import { persist } from 'zustand/middleware';
3
- import h from 'jwt-decode';
4
- import R from 'axios';
5
- import { createContext, useContext } from 'react';
6
- import I from 'swr/immutable';
7
-
8
- var g=create()(persist((t,o)=>({token:"",getUser:()=>{try{return h(o().token)}catch(s){return null}},setToken:s=>t({token:s}),clearToken:()=>{t({token:""}),g.persist.clearStorage();}}),{name:"token",partialize:t=>({token:t.token})}));var S=createContext(null);function c(t,o){let s=useContext(S);if(!s)throw new Error("Missing ReactToolkitsContext.Provider in the tree");return useStore(s,t,o)}var r=class extends Error{constructor(s,i,a=!1){super(s);this.code=i,this.skip=a;}};function d(){let t=g(e=>e.token),{game:o,isGlobalNS:s,isPermissionV2:i}=c(e=>e),a={withCredentials:!0},m=R.create(a);return m.interceptors.request.use(e=>{let n=e.headers;return n.set("Authorization",`Bearer ${t}`),i&&(n.has("App-ID")||n.set("App-ID",s?"global":o==null?void 0:o.id)),e}),m.interceptors.response.use(e=>{if(e.headers["content-type"].includes("application/octet-stream"))return e;if(e.data.code===0||e.data.status===0)return e.data.data;throw new r(e.data.msg,0)},e=>{throw e.response?e.response.status===401?new r("\u672A\u767B\u5F55\u6216\u767B\u5F55\u5DF2\u8FC7\u671F",e.response.status):e.response.status===403?new r("\u65E0\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u8FDB\u884C\u6388\u6743",e.response.status):[404,405].includes(e.response.status)?new r("Not Found or Method not Allowed",e.response.status,!0):e.response.status===412?new r("\u672A\u6CE8\u518C\u7528\u6237",e.response.status):e.response.status===504?new r("\u8BF7\u6C42\u8D85\u65F6",e.response.status):new r(e.response.message,e.response.status):new r("\u65E0\u54CD\u5E94")}),m}function D(t,o=!1){let s=d(),a=c(n=>n.isPermissionV2)?"/api/usystem/user/checkV2":"/api/usystem/user/check",{data:m,isLoading:e}=I(t.length>0?{method:"POST",url:a,data:{permissions:t},headers:o?{"App-ID":"global"}:{}}:null,n=>s.request(n).then(y=>y.has_all?t.reduce((p,f)=>(p[f]=!0,p),{}):t.reduce((p,f)=>(p[f]=y[f],p),{})),{suspense:!0,shouldRetryOnError:!1});return {data:m,isLoading:e}}function ee(t){var i;let{data:o,isLoading:s}=D(t?[t]:[]);return t?{accessible:(i=o==null?void 0:o[t])!=null?i:!1,isValidating:s}:{accessible:!0,isValidating:!1}}
9
-
10
- export { r as HttpClientError, d as useHttpClient, ee as usePermission, D as usePermissions };
11
- //# sourceMappingURL=out.js.map
12
- //# sourceMappingURL=index.esm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/stores/token.ts","../../src/hooks/use-http-client.ts","../../src/components/ReactToolkitsProvider/context.ts","../../src/hooks/use-permission.ts"],"names":["create","persist","jwtDecode","useTokenStore","set","get","_","token","state","axios","useStore","createContext","useContext","createJSONStorage","ReactToolkitsContext","useReactToolkitsContext","selector","equalityFn","store","HttpClientError","message","code","skip","useHttpClient","game","isGlobalNS","isPermissionV2","defaultOptions","instance","config","headers","response","error","useSWRImmutable","usePermissions","codes","httpClient","url","data","isLoading","res","acc","curr","usePermission","_a"],"mappings":"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","sourcesContent":["import { create } from 'zustand'\nimport { persist } from 'zustand/middleware'\nimport jwtDecode from 'jwt-decode'\n\ninterface UserInfo {\n authorityId: string\n exp: number\n}\n\nexport interface TokenState {\n token: string\n getUser: () => UserInfo | null\n setToken: (token: string) => void\n clearToken: () => void\n}\n\nexport const useTokenStore = create<TokenState>()(\n persist(\n (set, get) => ({\n token: '',\n getUser: () => {\n try {\n return jwtDecode(get().token) as UserInfo\n } catch (_) {\n return null\n }\n },\n setToken: token => set({ token }),\n clearToken: () => {\n set({ token: '' })\n useTokenStore.persist.clearStorage()\n },\n }),\n {\n name: 'token',\n partialize: state => ({ token: state.token }),\n },\n ),\n)\n","import { useTokenStore } from '@/stores'\nimport type { AxiosInstance, AxiosRequestConfig } from 'axios'\nimport axios from 'axios'\nimport type { Merge } from 'ts-essentials'\nimport { useReactToolkitsContext } from '@/components' // 覆盖 AxiosInstance 各种请求方法的返回值,为了方便我们在 interceptors.response 里把 AxiosResponse 直接打平成后端返回的数据,去掉了 axios 的封装。\n\n// 覆盖 AxiosInstance 各种请求方法的返回值,为了方便我们在 interceptors.response 里把 AxiosResponse 直接打平成后端返回的数据,去掉了 axios 的封装。\ntype ShimmedAxiosInstance = Merge<\n AxiosInstance,\n {\n request<T = unknown, D = unknown>(config: AxiosRequestConfig<D>): Promise<T>\n get<T = unknown, D = unknown>(url: string, config?: AxiosRequestConfig<D>): Promise<T>\n delete<T = unknown, D = unknown>(url: string, config?: AxiosRequestConfig<D>): Promise<T>\n head<T = unknown, D = unknown>(url: string, config?: AxiosRequestConfig<D>): Promise<T>\n post<T = unknown, D = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig<D>): Promise<T>\n put<T = unknown, D = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig<D>): Promise<T>\n patch<T = unknown, D = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig<D>): Promise<T>\n }\n>\n\nexport class HttpClientError extends Error {\n code?: number\n // 跳过错误提示\n skip: boolean\n\n constructor(message: string, code?: number, skip = false) {\n super(message)\n this.code = code\n this.skip = skip\n }\n}\n\nexport function useHttpClient() {\n const token = useTokenStore(state => state.token)\n const { game, isGlobalNS, isPermissionV2 } = useReactToolkitsContext(state => state)\n\n const defaultOptions: AxiosRequestConfig = {\n withCredentials: true,\n }\n\n const instance = axios.create(defaultOptions) as ShimmedAxiosInstance\n\n instance.interceptors.request.use(config => {\n const headers = config.headers\n headers.set('Authorization', `Bearer ${token}`)\n\n if (isPermissionV2) {\n if (!headers.has('App-ID')) {\n headers.set('App-ID', isGlobalNS ? 'global' : game?.id)\n }\n }\n\n return config\n })\n\n instance.interceptors.response.use(\n response => {\n const contentType = response.headers['content-type']\n if (contentType.includes('application/octet-stream')) {\n return response\n } else {\n if (response.data.code === 0 || response.data.status === 0) {\n return response.data.data\n }\n\n throw new HttpClientError(response.data.msg, 0)\n }\n },\n error => {\n if (error.response) {\n // 请求成功发出且服务器也响应了状态码,但状态码超出了 2xx 的范围\n if (error.response.status === 401) {\n throw new HttpClientError('未登录或登录已过期', error.response.status)\n } else if (error.response.status === 403) {\n throw new HttpClientError('无权限,请联系管理员进行授权', error.response.status)\n } else if ([404, 405].includes(error.response.status)) {\n throw new HttpClientError('Not Found or Method not Allowed', error.response.status, true)\n } else if (error.response.status === 412) {\n throw new HttpClientError('未注册用户', error.response.status)\n } else if (error.response.status === 504) {\n throw new HttpClientError('请求超时', error.response.status)\n } else {\n throw new HttpClientError(error.response.message, error.response.status)\n }\n }\n\n throw new HttpClientError('无响应')\n },\n )\n\n return instance\n}\n","import { create, useStore } from 'zustand'\nimport { createContext, useContext } from 'react'\nimport type { StateStorage } from 'zustand/middleware'\nimport { createJSONStorage, persist } from 'zustand/middleware'\nimport type { GameType } from '../GameSelect'\nimport type { ItemType2 } from '../NavMenu'\n\n// SessionStorage 在同一域下的不同页面间是隔离的,用于防止多开页面时的数据冲突\nconst mixedStorage: StateStorage = {\n getItem: (name: string): string | null => {\n return sessionStorage.getItem(name) || localStorage.getItem(name)\n },\n setItem: (name: string, value: string) => {\n localStorage.setItem(name, value)\n sessionStorage.setItem(name, value)\n },\n removeItem: async (name: string) => {\n localStorage.removeItem(name)\n sessionStorage.removeItem(name)\n },\n}\n\nexport interface ReactToolkitsState {\n title: string\n isPermissionV2: boolean\n isGlobalNS: boolean\n game: GameType | null\n setGame: (game: GameType | null) => void\n openKeys: string[]\n selectedKeys: string[]\n setOpenKeys: (keys: string[]) => void\n setSelectedKeys: (keys: string[]) => void\n menuItems: ItemType2[]\n onlyDomesticGames: boolean\n}\n\nexport type ReactToolkitsStore = ReturnType<typeof createReactToolkitsStore>\n\nexport const createReactToolkitsStore = () => {\n return create<ReactToolkitsState>()(\n persist(\n set => ({\n title: '',\n isPermissionV2: false,\n isGlobalNS: false,\n game: null,\n setGame: game => set({ game }),\n openKeys: [],\n setOpenKeys: keys => set({ openKeys: keys }),\n selectedKeys: [],\n setSelectedKeys: keys => set({ selectedKeys: keys }),\n menuItems: [],\n onlyDomesticGames: false,\n }),\n {\n name: 'ReactToolkits',\n storage: createJSONStorage(() => mixedStorage),\n partialize: state => ({\n title: state.title,\n game: state.game,\n openKeys: state.openKeys,\n selectedKeys: state.selectedKeys,\n }),\n },\n ),\n )\n}\n\nexport const ReactToolkitsContext = createContext<ReactToolkitsStore | null>(null)\n\nexport function useReactToolkitsContext<T>(\n selector: (state: ReactToolkitsState) => T,\n equalityFn?: (left: T, right: T) => boolean,\n): T {\n const store = useContext(ReactToolkitsContext)\n if (!store) throw new Error('Missing ReactToolkitsContext.Provider in the tree')\n return useStore(store, selector, equalityFn)\n}\n","import useSWRImmutable from 'swr/immutable'\nimport { useHttpClient } from './use-http-client'\nimport { useReactToolkitsContext } from '@/components'\n\nexport interface PermissionCheckResult {\n [k: string]: boolean\n}\n\nexport function usePermissions(codes: string[], isGlobalNS = false) {\n const httpClient = useHttpClient()\n const isPermissionV2 = useReactToolkitsContext(state => state.isPermissionV2)\n const url = isPermissionV2 ? '/api/usystem/user/checkV2' : '/api/usystem/user/check'\n\n const { data, isLoading } = useSWRImmutable(\n codes.length > 0\n ? {\n method: 'POST',\n url,\n data: { permissions: codes },\n headers: isGlobalNS\n ? {\n 'App-ID': 'global',\n }\n : {},\n }\n : null,\n config =>\n httpClient.request<PermissionCheckResult>(config).then(res => {\n if (res.has_all) {\n return codes.reduce(\n (acc, curr) => {\n acc[curr] = true\n return acc\n },\n {} as Record<string, boolean>,\n )\n }\n\n return codes.reduce(\n (acc, curr) => {\n acc[curr] = (res as Record<string, boolean>)[curr]\n return acc\n },\n {} as Record<string, boolean>,\n )\n }),\n {\n suspense: true,\n shouldRetryOnError: false,\n },\n )\n\n return { data, isLoading }\n}\n\nexport function usePermission(code: string) {\n const { data, isLoading } = usePermissions(code ? [code] : [])\n\n if (!code) {\n return {\n accessible: true,\n isValidating: false,\n }\n }\n\n return {\n accessible: data?.[code] ?? false,\n isValidating: isLoading,\n }\n}\n"]}