umi#history TypeScript Examples

The following examples show how to use umi#history. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx    From anew-server with MIT License 6 votes vote down vote up
goto = () => {
  if (!history) return;
  setTimeout(() => {
    const { query } = history.location;
    const { redirect } = query as {
      redirect: string;
    };
    history.push(redirect || '/');
  }, 10);
}
Example #2
Source File: app.tsx    From ql with MIT License 6 votes vote down vote up
export function render(oldRender: any) {
  request
    .get(`${config.apiPrefix}user`)
    .then((data) => {
      if (data.data && data.data.username) {
        return oldRender();
      }
      localStorage.removeItem(config.authKey);
      history.push('/login');
      oldRender();
    })
    .catch((e) => {
      console.log(e);
      if (e.response && e.response.status === 401) {
        localStorage.removeItem(config.authKey);
        history.push('/login');
        oldRender();
      }
    });
}
Example #3
Source File: StaffAdminAvatarDropdown.tsx    From dashboard with Apache License 2.0 6 votes vote down vote up
onMenuClick = (event: { key: React.Key; keyPath: React.Key[]; item: React.ReactInstance }) => {
    const { key } = event;

    if (key === 'settings'){
      history.push('/staff-admin/company-management/role')
      return;
    }

    if (key === 'logout') {
      const { dispatch } = this.props;

      if (dispatch) {
        dispatch({
          type: 'staffAdmin/logout',
        });
      }

      return;
    }

    history.push(`/staff-admin/${key}`);
  };
Example #4
Source File: index.tsx    From sidebar with Apache License 2.0 6 votes vote down vote up
BottomNavBar: React.FC<BottomNavBarProps> = (props) => {
  const {links} = props;
  return (
    <div className={styles.bottomNavbar}>
      <Row className={styles.navList}>
        {links.map((link, index) => {
          const isActive = window.location.href.includes(link.url);
          const id = link.url + link.title;
          const span = Math.floor((24 / links.length));
          return (
            <Col key={id} className={styles.navItem} span={span}>
              <Button
                type={'link'}
                onClick={() => {
                  if (!isActive) {
                    history.push(link.url)
                  }
                }}
                icon={getIcon(link.icon)}
                block={true}
                disabled={link.disabled || false}
                className={(link.disabled ? 'disabled' : '') + (isActive ? ' active' : '')}
              >{link.title}</Button>
              {index < links.length - 1 && (
                <Divider type={'vertical'}/>
              )}
            </Col>
          );
        })}
      </Row>
    </div>
  );
}
Example #5
Source File: app.tsx    From ant-design-pro-V5-multitab with MIT License 6 votes vote down vote up
export async function getInitialState(): Promise<{
    settings?: LayoutSettings;
    currentUser?: API.CurrentUser;
    collapsed?: boolean | undefined
    fetchUserInfo?: () => Promise<API.CurrentUser | undefined>;
}> {
    const fetchUserInfo = async () => {
        try {
            const currentUser = await queryCurrent();
            return currentUser;
        } catch (error) {
            history.push('/user/login');
        }
        return undefined;
    };
    // 如果是登录页面,不执行
    if (history.location.pathname !== '/user/login') {
        const currentUser = await fetchUserInfo();
        return {
            fetchUserInfo,
            currentUser,
            settings: defaultSettings,
            collapsed: false
        };
    }
    return {
        fetchUserInfo,
        settings: defaultSettings,
        collapsed: false
    };
}
Example #6
Source File: index.tsx    From scorpio-h5-design with MIT License 6 votes vote down vote up
export default function(props: {
  children: React.ReactChild;
}) {

  const onMenuClick = function(key: string) {
    history.push(key);
  };

  return (
    <div className="layout-manage">
      <div className="layout-manage-left">
        <Menu
          defaultSelectedKeys={['1']}
          defaultOpenKeys={['sub1']}
          mode="inline"
          onSelect={(info) => { onMenuClick(info.key as string); }}
        >
          <Menu.Item key="/manage/page" icon={<PieChartOutlined />}>
            页面搭建
          </Menu.Item>
          {/* <Menu.Item key="/manage/pageTemplate" icon={<PieChartOutlined />}>
            页面模板
          </Menu.Item> */}
          <Menu.Item key="/manage/category" icon={<PieChartOutlined />}>
            组件分类
          </Menu.Item>
          <Menu.Item key="/manage/component" icon={<PieChartOutlined />}>
            组件开发(dev)
          </Menu.Item>
        </Menu>
      </div>
      <div className="layout-manage-right">
        {props.children}
      </div>
    </div>
  );
}
Example #7
Source File: 404.tsx    From ui-visualization with MIT License 6 votes vote down vote up
NoFoundPage: React.FC<{}> = () => (
  <Result
    status="404"
    title="404"
    subTitle="Sorry, the page you visited does not exist."
    extra={
      <Button type="primary" onClick={() => history.push('/')}>
        Back Home
      </Button>
    }
  />
)
Example #8
Source File: AvatarDropdown.tsx    From anew-server with MIT License 6 votes vote down vote up
loginOut = async () => {
  await AuthLogout();
  localStorage.removeItem('token');
  localStorage.removeItem('expires');
  const { query = {}, pathname } = history.location;
  const { redirect } = query;
  // Note: There may be security issues, please note
  if (window.location.pathname !== '/user/login' && !redirect) {
    history.replace({
      pathname: '/user/login',
      search: stringify({
        redirect: pathname,
      }),
    });
  }
}
Example #9
Source File: app.tsx    From admin-fe with MIT License 6 votes vote down vote up
export async function render(oldRender: Function) {
    function redirectToLogin() {
        history.push('/login')
        oldRender()
    }

    try {
        const data = await getAdminInfo()
        if (data == null) redirectToLogin()
        oldRender()
    } catch (ex) {
        console.error(ex)
        redirectToLogin()
    }
}
Example #10
Source File: AvatarDropdown.tsx    From ant-design-pro-V4 with MIT License 6 votes vote down vote up
onMenuClick = (event: { key: React.Key; keyPath: React.Key[]; item: React.ReactInstance }) => {
    const { key } = event;

    if (key === 'todo') {
      history.push('/todo');
      return
    }
    if (key === 'logout') {
      const { dispatch } = this.props;

      if (dispatch) {
        dispatch({
          type: 'login/logout',
        });
      }

      return;
    }

    history.push(`/account/${key}`);
  };
Example #11
Source File: app.tsx    From anew-server with MIT License 6 votes vote down vote up
errResponseInterceptor = async (response: Response, options: RequestOptionsInit) => {
  const data: API.Result = await response.clone().json();
  if (!response) {
    message.error('您的网络发生异常,无法连接服务器');
    return response;
  }
  if (!data.status) {
    message.error(data.message);
    if (data.code === 401) {
      localStorage.removeItem('token');
      localStorage.removeItem('expires');
      history.push('/user/login')
    }
  } else {
    if (data.code !== 200) {
      message.error(data.message);
    }
  }
  return response;
}
Example #12
Source File: 404.tsx    From ant-design-pro-V4 with MIT License 6 votes vote down vote up
NoFoundPage: React.FC = () => (
  <Result
    status="404"
    title="404"
    subTitle="Sorry, the page you visited does not exist."
    extra={
      <Button type="primary" onClick={() => history.push('/')}>
        Back Home
      </Button>
    }
  />
)
Example #13
Source File: AvatarDropdown.tsx    From ant-design-pro-V5-multitab with MIT License 5 votes vote down vote up
AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
  const { initialState, setInitialState } = useModel('@@initialState');

  const onMenuClick = useCallback(
    (event: {
      key: React.Key;
      keyPath: React.Key[];
      item: React.ReactInstance;
      domEvent: React.MouseEvent<HTMLElement>;
    }) => {
      const { key } = event;
      if (key === 'logout' && initialState) {
        setInitialState({ ...initialState, currentUser: undefined });
        loginOut();
        return;
      }
      history.push(`/account/${key}`);
    },
    [initialState, setInitialState],
  );

  const loading = (
    <span className={`${styles.action} ${styles.account}`}>
      <Spin
        size="small"
        style={{
          marginLeft: 8,
          marginRight: 8,
        }}
      />
    </span>
  );

  if (!initialState) {
    return loading;
  }

  const { currentUser } = initialState;

  if (!currentUser || !currentUser.name) {
    return loading;
  }

  const menuHeaderDropdown = (
    <Menu className={styles.menu} selectedKeys={[]} onClick={onMenuClick}>
      {menu && (
        <Menu.Item key="center">
          <UserOutlined />
          个人中心
        </Menu.Item>
      )}
      {menu && (
        <Menu.Item key="settings">
          <SettingOutlined />
          个人设置
        </Menu.Item>
      )}
      {menu && <Menu.Divider />}

      <Menu.Item key="logout">
        <LogoutOutlined />
        退出登录
      </Menu.Item>
    </Menu>
  );
  return (
    <HeaderDropdown overlay={menuHeaderDropdown}>
      <span className={`${styles.action} ${styles.account}`}>
        <Avatar size="small" className={styles.avatar} src={currentUser.avatar} alt="avatar" />
        <span className={`${styles.name} anticon`}>{currentUser.name}</span>
      </span>
    </HeaderDropdown>
  );
}
Example #14
Source File: app.tsx    From anew-server with MIT License 5 votes vote down vote up
layout: RunTimeLayoutConfig = ({ initialState }) => {
  return {
    rightContentRender: () => <RightContent />,
    disableContentMargin: false,
    waterMarkProps: {
      content: initialState?.currentUser?.name,
    },
    footerRender: () => <Footer />,
    onPageChange: () => {
      const { location } = history;
      // 如果没有登录,重定向到 login
      if (!initialState?.currentUser && location.pathname !== loginPath) {
        history.push(loginPath);
      }
    },
    menu: {
      // 每当 initialState?.currentUser?.userid 发生修改时重新执行 request
      params: {
        userId: initialState?.currentUser?.id,
      },
      request: async (params, defaultMenuData) => {
        if (!params.userId) return []
        const menuData = await (await GetMenuTree()).data;
        return menuData;
      },
    },
    // links: isDev
    //   ? [
    //     <Link to="/umi/plugin/openapi" target="_blank">
    //       <LinkOutlined />
    //       <span>OpenAPI 文档</span>
    //     </Link>,
    //     <Link to="/~docs">
    //       <BookOutlined />
    //       <span>业务组件文档</span>
    //     </Link>,
    //   ]
    //   : [],
    menuHeaderRender: undefined,
    // 自定义 403 页面
    // unAccessible: <div>unAccessible</div>,
    ...initialState?.settings,
  };
}
Example #15
Source File: app.tsx    From ant-design-pro-V5-multitab with MIT License 5 votes vote down vote up
layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => {
    return {
        rightContentRender: () => <RightContent />,
        disableContentMargin: true,
        footerRender: () => <Footer />,
        headerRender: () => <HeaderRender />,
        headerHeight: 93,
        onPageChange: () => {
            const { location } = history;
            // 如果没有登录,重定向到 login
            if (!initialState?.currentUser && location.pathname !== '/user/login') {
                history.push('/user/login');
            }
        },
        onCollapse: (collapsed) => {
            setInitialState({ ...initialState, collapsed })
        },
        // menuHeaderRender: (logo, title, props) => {
        //   console.log(logo);
        //   console.log(title);
        //   console.log(props);
        // },
        // patchMenus: (menuData: Array<any>) => {
        //     let menuArr: Array<any> = [];
        //     menuData.forEach((item) => {
        //         if (item.path === "/") {
        //             menuArr = [...menuArr, ...item.children]
        //         } else {
        //             menuArr.push(item)
        //         }
        //     })
        //     return menuArr
        // },
        // childrenRender: (children) => {
        //     return (
        //         <AliveScope>
        //             {children}
        //         </AliveScope>
        //     )
        // },
        // 自定义 403 页面
        // unAccessible: <div>unAccessible</div>,
        ...initialState?.settings,
    };
}
Example #16
Source File: app.tsx    From anew-server with MIT License 5 votes vote down vote up
/**
 * @see  https://umijs.org/zh-CN/plugins/plugin-initial-state
 * */
export async function getInitialState(): Promise<{
  settings?: Partial<LayoutSettings>;
  currentUser?: API.UserInfo;
  DictObj?: any;
  fetchUserInfo?: () => Promise<API.UserInfo | undefined>;
  fetchDictInfo?: () => Promise<any | undefined>;
}> {
  const fetchUserInfo = async () => {
    try {
      const currentUser: API.UserInfo = await (await getUserInfo()).data;
      return currentUser;
    } catch (error) {
      history.push(loginPath);
    }
    return undefined;
  };
  // 初始化字典信息
  const fetchDictInfo = async () => {
    try {
      const DictObj: any = (await queryDictsByAllType({ all_type: true })).data
      return DictObj;
    } catch (error) {
      history.push(loginPath);
    }
    return undefined;
  };
  // 如果是登录页面,不执行
  if (history.location.pathname !== loginPath) {
    const currentUser = await fetchUserInfo();
    const DictObj = await fetchDictInfo();
    return {
      fetchUserInfo,
      currentUser,
      DictObj,
      settings: {},
    };
  }
  return {
    fetchUserInfo,
    fetchDictInfo,
    settings: {},
  };
}
Example #17
Source File: edit.tsx    From dashboard with Apache License 2.0 5 votes vote down vote up
CreateRole: React.FC = () => {
  const [currentRole, setCurrentRole] = useState<RoleItem>({
    is_default: False,
  });
  const [itemID, setItemID] = useState<string>('');
  const roleFormRef = useRef<FormInstance>();

  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const id = params.get('id');
    if (id) {
      setItemID(id);
    } else {
      message.error('传入参数请带上ID');
    }
  }, []);

  useEffect(() => {
    if (itemID) {
      const hide = message.loading('加载数据中');
      Get(itemID).then((res) => {
        hide();
        if (res.code === 0) {
          setCurrentRole(res.data);
          roleFormRef.current?.setFieldsValue(res.data);
        } else {
          message.error(res.message);
        }
      });
    }
  }, [itemID]);

  return (
    <PageContainer
      onBack={() => history.goBack()}
      backIcon={<LeftOutlined />}
      header={{
        title: '修改角色',
      }}
    >
      <ProCard>
        <RoleForm
          // @ts-ignore
          formRef={roleFormRef}
          mode={'edit'}
          onFinish={async (values) => {
            const hide = message.loading('处理中');
            const res: CommonResp = await Update(values);
            hide();
            if (res.code === 0) {
              history.push('/staff-admin/company-management/role');
              message.success('修改成功');
              return true;
            }

            if (res.message) {
              message.error(res.message);
              return false;
            }

            message.error('修改失败');
            return false;
          }}
          currentItem={currentRole}
        />
      </ProCard>
    </PageContainer>
  );
}
Example #18
Source File: index.tsx    From ql with MIT License 5 votes vote down vote up
Login = () => {
  const handleOk = (values: any) => {
    request
      .post(`${config.apiPrefix}login`, {
        data: {
          username: values.username,
          password: values.password,
        },
      })
      .then((data) => {
        if (data.code === 200) {
          localStorage.setItem(config.authKey, data.token);
          history.push('/crontab');
        } else if (data.code === 100) {
          message.warn(data.msg);
        } else {
          message.error(data.msg);
        }
      })
      .catch(function (error) {
        console.log(error);
      });
  };

  useEffect(() => {
    const isAuth = localStorage.getItem(config.authKey);
    if (isAuth) {
      history.push('/crontab');
    }
  }, []);

  return (
    <div className={styles.container}>
      <div className={styles.content}>
        <div className={styles.top}>
          <div className={styles.header}>
            <img
              alt="logo"
              className={styles.logo}
              src="https://qinglong.whyour.cn/qinglong.png"
            />
            <span className={styles.title}>{config.siteName}</span>
          </div>
        </div>
        <div className={styles.main}>
          <Form onFinish={handleOk}>
            <FormItem
              name="username"
              rules={[{ required: true, message: '请输入用户名' }]}
              hasFeedback
            >
              <Input placeholder="用户名" autoFocus />
            </FormItem>
            <FormItem
              name="password"
              rules={[{ required: true, message: '请输入密码' }]}
              hasFeedback
            >
              <Input type="password" placeholder="密码" />
            </FormItem>
            <Row>
              <Button
                type="primary"
                htmlType="submit"
                style={{ width: '100%' }}
              >
                登录
              </Button>
            </Row>
          </Form>
        </div>
      </div>
    </div>
  );
}
Example #19
Source File: create.tsx    From dashboard with Apache License 2.0 5 votes vote down vote up
CreateContactWay: React.FC = () => {
  const [allStaffs, setAllStaffs] = useState<StaffOption[]>([]);
  const [allTagGroups, setAllTagGroups] = useState<CustomerTagGroupItem[]>([]);

  useEffect(() => {
    QueryCustomerTagGroups({page_size: 5000}).then((res) => {
      if (res.code === 0) {
        setAllTagGroups(res?.data?.items);
      } else {
        message.error(res.message);
      }
    });
  }, []);

  useEffect(() => {
    QuerySimpleStaffs({ page_size: 5000 }).then((res) => {
      if (res.code === 0) {
        setAllStaffs(
          res?.data?.items?.map((item: SimpleStaffInterface) => {
            return {
              label: item.name,
              value: item.ext_id,
              ...item,
            };
          }) || [],
        );
      } else {
        message.error(res.message);
      }
    });
  }, []);

  return (
    <PageContainer
      onBack={() => history.goBack()}
      backIcon={<LeftOutlined />}
      header={{
        title: '创建渠道活码',
      }}
    >
      <ProCard>
        <ContactWayForm
          mode={'create'}
          onFinish={async (values) => {
            const params = { ...values };
            const hide = message.loading('处理中');
            const res: CommonResp = await Create(params);
            hide();
            if (res.code === 0) {
              history.push('/staff-admin/customer-growth/contact-way');
              message.success('添加成功');
              return true;
            }

            if (res.message) {
              message.error(res.message);
              return false;
            }

            message.error('添加失败');
            return false;
          }}
          staffs={allStaffs}
          tagGroups={allTagGroups}
        />
      </ProCard>
    </PageContainer>
  );
}
Example #20
Source File: bridge.ts    From scorpio-h5-design with MIT License 5 votes vote down vote up
export function isMobile(){
  const {pathname} = history.location;
  return pathname === '/mobile';
}
Example #21
Source File: login.ts    From ant-design-pro-V4 with MIT License 5 votes vote down vote up
Model: LoginModelType = {
  namespace: 'login',

  state: {
    status: undefined,
  },

  effects: {
    *login({ payload }, { call, put }) {
      const response = yield call(fakeAccountLogin, payload);
      yield put({
        type: 'changeLoginStatus',
        payload: response,
      });
      // Login successfully
      if (response.status === 'ok') {
        const urlParams = new URL(window.location.href);
        const params = getPageQuery();
        message.success('? ? ?  登录成功!');
        let { redirect } = params as { redirect: string };
        if (redirect) {
          const redirectUrlParams = new URL(redirect);
          if (redirectUrlParams.origin === urlParams.origin) {
            redirect = redirect.substr(urlParams.origin.length);
            if (window.routerBase !== '/') {
              redirect = redirect.replace(window.routerBase, '/');
            }
            if (redirect.match(/^\/.*#/)) {
              redirect = redirect.substr(redirect.indexOf('#') + 1);
            }
          } else {
            window.location.href = '/';
            return;
          }
        }
        history.replace(redirect || '/');
      }
    },

    logout() {
      const { redirect } = getPageQuery();
      // Note: There may be security issues, please note
      if (window.location.pathname !== '/user/login' && !redirect) {
        history.replace({
          pathname: '/user/login',
          search: stringify({
            redirect: window.location.href,
          }),
        });
      }
    },
  },

  reducers: {
    changeLoginStatus(state, { payload }) {
      setAuthority(payload.currentAuthority);
      return {
        ...state,
        status: payload.status,
        type: payload.type,
      };
    },
  },
}
Example #22
Source File: login.ts    From ui-visualization with MIT License 5 votes vote down vote up
Model: LoginModelType = {
  namespace: 'login',

  state: {
    status: undefined,
  },

  effects: {
    *login({ payload }, { call, put }) {
      const response = yield call(fakeAccountLogin, payload);
      yield put({
        type: 'changeLoginStatus',
        payload: response,
      });
      // Login successfully
      if (response.status === 'ok') {
        const urlParams = new URL(window.location.href);
        const params = getPageQuery();
        let { redirect } = params as { redirect: string };
        if (redirect) {
          const redirectUrlParams = new URL(redirect);
          if (redirectUrlParams.origin === urlParams.origin) {
            redirect = redirect.substr(urlParams.origin.length);
            if (redirect.match(/^\/.*#/)) {
              redirect = redirect.substr(redirect.indexOf('#') + 1);
            }
          } else {
            window.location.href = '/';
            return;
          }
        }
        history.replace(redirect || '/');
      }
    },

    logout() {
      const { redirect } = getPageQuery();
      // Note: There may be security issues, please note
      if (window.location.pathname !== '/user/login' && !redirect) {
        history.replace({
          pathname: '/user/login',
          search: stringify({
            redirect: window.location.href,
          }),
        });
      }
    },
  },

  reducers: {
    changeLoginStatus(state, { payload }) {
      setAuthority(payload.currentAuthority);
      return {
        ...state,
        status: payload.status,
        type: payload.type,
      };
    },
  },
}
Example #23
Source File: app.ts    From scorpio-h5-design with MIT License 5 votes vote down vote up
history.listen((location: any, action: any) => {
  if (location.pathname !== '/design') {
    doChildrenDestroy();
  }
});
Example #24
Source File: create.tsx    From dashboard with Apache License 2.0 5 votes vote down vote up
CreateCustomerMassMsg: React.FC = () => {
  const [currentCustomerMassMsg] = useState<CustomerMassMsgItem>();
  const formRef = useRef<FormInstance>();

  return (
    <PageContainer
      onBack={() => history.goBack()}
      backIcon={<LeftOutlined />}
      header={{
        title: '创建群发',
      }}
    >
      <ProCard>
        <CustomerMassMsgForm
          formRef={formRef}
          mode={'create'}
          onFinish={async (values) => {
            const params = { ...values };
            const hide = message.loading('处理中');
            const res: CommonResp = await Create(params);
            hide();
            if (res.code === 0) {
              history.push('/staff-admin/customer-conversion/customer-mass-msg');
              message.success('添加成功');
              return true;
            }

            if (res.message) {
              message.error(res.message);
              return false;
            }

            message.error('添加失败');
            return false;
          }}
          initialValues={currentCustomerMassMsg}
        />
      </ProCard>
    </PageContainer>
  );
}
Example #25
Source File: index.tsx    From scorpio-h5-design with MIT License 4 votes vote down vote up
ComponentDetail = function() {
  const { setStateByObjectKeys, pageSchema, selectComponent } = useModel('bridge');
  const component = selectComponent as IComponentSchema;
  const { onSubmit, loading } = Model.useContainer();
  const SchemaRef = useRef<{ getValue: () => any }>(null);

  function onTabChange(key: string) {
    if (key === 'form') {
      component.generatorSchema = SchemaRef.current?.getValue();
      const state = {
        pageSchema: [...pageSchema],
      };
      setStateByObjectKeys(state);
      onChildrenReady(() => {
        syncState({
          payload: state,
          type: IMessageType.syncState,
        });
      });
    }
  }

  async function handelSubmit() {
    component.generatorSchema = SchemaRef.current?.getValue();
    const dataURL = await window.postmate_mobile.get(childrenModel.CAPTURE);
    if (dataURL) {
      const file = dataURLtoFile(dataURL, new Date().getTime().toString());
      const fileName = `${uuidv4()}.png`;
      await ossClient.put(`design/${fileName}`, file);
      component.cover = `https://scorpio-design.lxzyl.cn/design/${fileName}`;
    }
    onSubmit();
  }

  const OperationsSlot = {
    right: (
      <Space className="manage-component-detail-tabs-extBtn">
        <Button onClick={() => history.goBack()}>返回</Button>
        <Button type="primary" onClick={handelSubmit}>保存</Button>
      </Space>
    ),
  };

  const debouncedloading = useDebounce(loading, { wait: 500 });

  return (

    <Spin
      spinning={debouncedloading}
      wrapperClassName="blur-loading"
      indicator={<Loading />}
    >
      <div className="manage-component-detail">
        <div className="left">
          <MobileSimulator loading={loading}/>
        </div>
        <div className="right">
          <Tabs
            className="manage-component-detail-tabs"
            defaultActiveKey="1"
            onChange={onTabChange}
            tabBarExtraContent={OperationsSlot}
          >
            <TabPane tab="schema可视化配置" key="schema">
              <Schema ref={SchemaRef} />
            </TabPane>
            <TabPane tab="schema手动编辑" key="code">
              <Code />
            </TabPane>
            <TabPane tab="组件属性配置" key="form">
              <Form />
            </TabPane>
            <TabPane tab="容器属性配置" key="container">
              <BaseLayoutConfig />
            </TabPane>
          </Tabs>
        </div>
      </div>
    </Spin>
  );
}
Example #26
Source File: index.tsx    From ql with MIT License 4 votes vote down vote up
export default function (props: any) {
  const logout = () => {
    request.post(`${config.apiPrefix}logout`).then(() => {
      localStorage.removeItem(config.authKey);
      history.push('/login');
    });
  };

  useEffect(() => {
    const isAuth = localStorage.getItem(config.authKey);
    if (!isAuth) {
      history.push('/login');
    }
    vhCheck();
  }, []);

  useEffect(() => {
    if (props.location.pathname === '/') {
      history.push('/crontab');
    }
  }, [props.location.pathname]);

  useEffect(() => {
    const theme = localStorage.getItem('qinglong_dark_theme') || 'auto';
    setFetchMethod(window.fetch);
    if (theme === 'dark') {
      enableDarkMode({
        brightness: 100,
        contrast: 90,
        sepia: 10,
      });
    } else if (theme === 'light') {
      disableDarkMode();
    } else {
      followSystemColorScheme({
        brightness: 100,
        contrast: 90,
        sepia: 10,
      });
    }
  }, []);

  if (props.location.pathname === '/login') {
    return props.children;
  }

  const isFirefox = navigator.userAgent.includes('Firefox');
  const isSafari =
    navigator.userAgent.includes('Safari') &&
    !navigator.userAgent.includes('Chrome');
  return (
    <ProLayout
      selectedKeys={[props.location.pathname]}
      title={
        <>
          控制面板
          <a href={changeLog} target="_blank" rel="noopener noreferrer">
            <span
              style={{
                fontSize: isFirefox ? 9 : 12,
                color: '#666',
                marginLeft: 5,
                zoom: isSafari ? 0.66 : 0.8,
              }}
            >
              {version}
            </span>
          </a>
        </>
      }
      menuItemRender={(menuItemProps: any, defaultDom: any) => {
        if (
          menuItemProps.isUrl ||
          !menuItemProps.path ||
          location.pathname === menuItemProps.path
        ) {
          return defaultDom;
        }
        return <Link to={menuItemProps.path}>{defaultDom}</Link>;
      }}
      postMenuData={(menuData) => {
        return [
          ...(menuData || []),
          {
            icon: <LogoutOutlined />,
            name: '退出登录',
            path: 'logout',
            onTitleClick: () => logout(),
          },
        ];
      }}
      pageTitleRender={() => '控制面板'}
      {...defaultProps}
    >
      {props.children}
    </ProLayout>
  );
}
Example #27
Source File: BasicLayout.tsx    From ant-design-pro-V4 with MIT License 4 votes vote down vote up
BasicLayout: React.FC<BasicLayoutProps> = (props) => {
  const {
    dispatch,
    children,
    settings,
    location = {
      pathname: '/',
    },
  } = props;

  const menuDataRef = useRef<MenuDataItem[]>([]);

  useEffect(() => {
    if (dispatch) {
      dispatch({
        type: 'user/fetchCurrent',
      });
    }
  }, []);
  /** Init variables */

  const handleMenuCollapse = (payload: boolean): void => {
    if (dispatch) {
      dispatch({
        type: 'global/changeLayoutCollapsed',
        payload,
      });
    }
  };
  // get children authority
  const authorized = useMemo(
    () =>
      getMatchMenu(location.pathname || '/', menuDataRef.current).pop() || {
        authority: undefined,
      },
    [location.pathname],
  );

  const { formatMessage } = useIntl();

  return (
    <ProLayout
      logo={logo}
      formatMessage={formatMessage}
      {...props}
      {...settings}
      onCollapse={handleMenuCollapse}
      onMenuHeaderClick={() => history.push('/')}
      menuItemRender={(menuItemProps, defaultDom) => {
        if (
          menuItemProps.isUrl ||
          !menuItemProps.path ||
          location.pathname === menuItemProps.path
        ) {
          return defaultDom;
        }
        return <Link to={menuItemProps.path}>{defaultDom}</Link>;
      }}
      breadcrumbRender={(routers = []) => [
        {
          path: '/',
          breadcrumbName: formatMessage({ id: 'menu.home' }),
        },
        ...routers,
      ]}
      itemRender={(route, params, routes, paths) => {
        const first = routes.indexOf(route) === 0;
        return first ? (
          <Link to={paths.join('/')}>{route.breadcrumbName}</Link>
        ) : (
          <span>{route.breadcrumbName}</span>
        );
      }}
      footerRender={() => {
        if (settings.footerRender || settings.footerRender === undefined) {
          return defaultFooterDom;
        }
        return null;
      }}
      menuDataRender={menuDataRender}
      rightContentRender={() => <RightContent />}
      postMenuData={(menuData) => {
        menuDataRef.current = menuData || [];
        return menuData || [];
      }}
      waterMarkProps={{
        content: 'Ant Design Pro',
        fontColor: 'rgba(24,144,255,0.15)',
      }}
    >
      <Authorized authority={authorized!.authority} noMatch={noMatch}>
        {children}
      </Authorized>
    </ProLayout>
  );
}
Example #28
Source File: index.tsx    From ant-design-pro-V5-multitab with MIT License 4 votes vote down vote up
Tabs = () => {
    const { initialState } = useModel<any>("@@initialState");
    const { collapsed } = initialState;
    const { tabList, dispatch, active, showTabs, tabsWidth, tabWidth, tarnslateX } = useModel("system");
    const { dropScope, clear } = useAliveController();

    const onSortEnd = ({ oldIndex, newIndex }: { oldIndex: number, newIndex: number }) => {
        const dataSource = JSON.parse(JSON.stringify(tabList))
        const activeItem = dataSource[active as number]
        dataSource.splice(newIndex, 0, dataSource.splice(oldIndex, 1)[0]);
        const movedActiveIndex = dataSource.findIndex((item: string) => item === activeItem)
        dispatch({ type: "CHANGESTATE", payload: { tabList: dataSource, active: movedActiveIndex } })
    }


    // 当前的索引值active showTabs一排能展示多少个
    // 计算应该在菜单展示的菜单有哪些

    const arr: any[] = []
    if (tabList.length > showTabs) {
        // 前面隐藏的元素
        const beforeTab = Math.floor(tarnslateX / tabWidth);
        // 后面隐藏的元素
        const afterTab = Math.floor(tarnslateX / tabWidth) + showTabs
        tabList.forEach((item, index) => {
            if (index < beforeTab) {
                arr.push(item)
            }
            if (index >= afterTab) {
                arr.push(item)
            }
        })
    }


    const menuMore = (
        <Menu onClick={(e) => {
            // 判断点击多余tab的展示移动距离是多少 
            // 计算超出了多少
            // tabsWidth tabWidth showTabs 100是右边操作的距离目前写死
            const isBeyondDistance = ((showTabs as number) * (tabWidth as number)) - (tabsWidth as number) + 100;
            // TODO 找到当前点击的索引值
            const curClickIndex = tabList?.findIndex(item => item.pathname === e.key) as number;
            // 能展示多少个
            const totalShowIndex = (showTabs as number) - 1;
            if (curClickIndex > totalShowIndex) {
                // 计算移动的距离
                const x = (curClickIndex - totalShowIndex) * (tabWidth as number) + isBeyondDistance
                dispatch({ type: 'CHANGESTATE', payload: { tarnslateX: x, active: curClickIndex } })
            } else {
                dispatch({ type: 'CHANGESTATE', payload: { tarnslateX: tabWidth * curClickIndex, active: curClickIndex } })
            }
            history.push({ ...tabList[curClickIndex] })
        }}>
            {
                arr.map(item => {
                    return <Menu.Item key={item.pathname}> {item.title}</Menu.Item>
                })
            }
        </Menu>
    );
    const menu = (
        <Menu onClick={(e) => {
            let activeIndex: number = 0;
            const localTablist = JSON.parse(JSON.stringify(tabList))
            switch (e.key) {
                case "closeCurrent": {
                    const currentName = localTablist[active].keepAliveName
                    if (active > 0) {
                        activeIndex = active - 1
                        const timer = setTimeout(() => {
                            clearTimeout(timer)
                            history.push(tabList[activeIndex])
                        }, 10)
                    } else {
                        activeIndex = 0
                        const timer = setTimeout(() => {
                            clearTimeout(timer)
                            history.push(localTablist[activeIndex])
                        }, 10)
                    }
                    const unlisten = history.listen(() => {
                        unlisten()
                        const dropTimer = setTimeout(() => {
                            clearTimeout(dropTimer)
                            dropScope(currentName)
                        }, 10)
                    })
                    localTablist.splice(active, 1)
                    dispatch({ type: "CHANGESTATE", payload: { tabList: localTablist, active: activeIndex, tarnslateX: 0 } })
                    break;
                }
                case "closeOther": {
                    const needDelete = localTablist.filter((item: any, index: number) => index !== active);
                    const needUpdate = localTablist.filter((item: any, index: number) => index === active);
                    needDelete.forEach((item: any) => dropScope(item.keepAliveName));
                    dispatch({ type: "CHANGESTATE", payload: { tabList: needUpdate, active: 0, tarnslateX: 0 } })
                    break;
                }
                case "closeAll": {
                    const unlisten = history.listen(() => {
                        unlisten()
                        const dropTimer = setTimeout(() => {
                            clearTimeout(dropTimer)
                            clear()
                        }, 10)
                    })
                    const timer = setTimeout(() => {
                        clearTimeout(timer)
                        history.push("/")
                    }, 10)
                    dispatch({ type: "CHANGESTATE", payload: { tabList: [], active: 0, tarnslateX: 0 } })
                    break;
                }
                case "closeLeft": {
                    const needDelete = localTablist.filter((item: any, index: number) => index < active);
                    const needUpdate = localTablist.filter((item: any, index: number) => index >= active);
                    needDelete.forEach((item: any) => dropScope(item.keepAliveName));
                    dispatch({ type: "CHANGESTATE", payload: { tabList: needUpdate, active: 0, tarnslateX: 0 } })
                    break;
                }
                case "closeRight": {
                    const needDelete = localTablist.filter((item: any, index: number) => index > active);
                    const needUpdate = localTablist.filter((item: any, index: number) => index <= active);
                    needDelete.forEach((item: any) => dropScope(item.keepAliveName));
                    dispatch({ type: "CHANGESTATE", payload: { tabList: needUpdate, tarnslateX: 0 } })
                    break;
                }
            }

        }}>
            <Menu.Item key="closeCurrent">关闭当前标签</Menu.Item>
            <Menu.Item key="closeOther">关闭其他标签</Menu.Item>
            <Menu.Item key="closeAll">关闭全部标签</Menu.Item>
            <Menu.Item key="closeLeft" disabled={active === 0}>关闭当前左边标签</Menu.Item>
            <Menu.Item key="closeRight" disabled={active === tabList.length - 1}>关闭当前右边标签</Menu.Item>
        </Menu>
    );



    useEffect(() => {

        window.onresize = () => {
            const width = document.getElementById("contentContainer") ? document.getElementById("contentContainer")!.getBoundingClientRect()!.width : 0;
            dispatch({ type: "CHANGESTATE", payload: { tabsWidth: width, tarnslateX: 0 } })
        }

        const timer = setTimeout(() => {
            const width = document.getElementById("contentContainer") ? document.getElementById("contentContainer")!.getBoundingClientRect()!.width : 0;
            dispatch({ type: "CHANGESTATE", payload: { tabsWidth: width } })
        }, 100);
        return () => {
            clearTimeout(timer)
        }
    }, [collapsed])


    useEffect(() => {
        const timer = setTimeout(() => {
            // 需要重新计算拿到当前tab的宽度
            const tabWidth = document.getElementsByClassName("link-tab")[0] ? document.getElementsByClassName("link-tab")[0]!.getBoundingClientRect().width : 120;
            //计算一排能展示多少个tab 需要减去操作占用的空间100
            const showTabs = Math.ceil((tabsWidth as number - 100) / tabWidth);
            if (tabsWidth > 0 && tabWidth > 0) {
                dispatch({ type: "CHANGESTATE", payload: { showTabs, tabWidth } })
            }
        }, 100);
        return () => {
            clearTimeout(timer)
        }
    }, [tabsWidth])



    return (
        // <div className={styles.tabs} style={{ width: initialState?.collapsed ? "calc(100vw - 41px)" : "calc(100vw - 249px)" }}>
        <div className={styles.tabs} id="contentContainer">
            {tabList.length > 0 && <SortableList onSortEnd={onSortEnd} axis={'x'} distance={1} />}
            <div className={`${styles.tabLeftMenu}  ${tabList.length >= showTabs && styles.boxShadow}`}>
                {
                    tabList.length > showTabs && (
                        <>
                            <Dropdown overlay={menuMore} className={styles.tabMore}>
                                <a className="ant-dropdown-link" onClick={e => e.preventDefault()}>
                                    <MoreOutlined />
                                </a>
                            </Dropdown>
                            <Divider type='vertical' />
                        </>
                    )
                }
                {
                    tabList.length > 1 && (
                        <Dropdown overlay={menu} className={styles.menuRight}>
                            <a className="ant-dropdown-link" onClick={e => e.preventDefault()}>
                                操作 <DownOutlined />
                            </a>
                        </Dropdown>
                    )
                }

            </div>

        </div>
    );
}
Example #29
Source File: index.tsx    From scorpio-h5-design with MIT License 4 votes vote down vote up
export default function() {
  const { pageId, pageSchema, selectPage, setStateByObjectKeys } = useModel('bridge');
  const addPageReq = useRequest(service.addPage, {
    manual: true,
  });
  const editPageReq = useRequest(service.editPage, {
    manual: true,
  });
  const [visible, { toggle }] = useBoolean(false);
  const [qrcodeUrl, setQrcodeUrl] = useState('');

  const save = async function() {
    const dataURL = await window.postmate_mobile.get(childrenModel.CAPTURE);
    if (dataURL) {
      const file = dataURLtoFile(dataURL, new Date().getTime().toString());
      const fileName = `${uuidv4()}.png`;
      await ossClient.put(`design/${fileName}`, file);
      selectPage.cover = `https://scorpio-design.lxzyl.cn/design/${fileName}`;
    }
    let res;
    if (pageId) {
      res = await editPageReq.run({
        _id: pageId,
        pageSchema,
      });
    } else {
      res = await addPageReq.run({
        pageSchema,
      });
    }
    return res;
  };

  const onSave = async function() {
    if (pageSchema.length === 0) {
      return message.error('请新建页面后再保存!');
    }
    if (selectPage.components.length === 0) {
      return message.error('至少添加一个组件后再保存!');
    }
    const res = await save();
    const state = {
      pageId: res._id,
    };
    setStateByObjectKeys(state);
    message.success('保存成功!');
  };

  const onVisibleChange = async function() {
    if (pageSchema.length === 0) {
      return message.error('请新建页面后再操作!');
    }
    toggle();
    await save();
    const dataUrl = await QRCode.toDataURL(`${config.h5Base}?id=${pageId}`, {
      margin: 0,
    });
    console.log('dataUrl: ', dataUrl);
    setQrcodeUrl(dataUrl);
  };

  const overviewContent = (
    <div className="overview-qrcode">
      <img className="overview-qrcode-img" src={qrcodeUrl} />
    </div>
  );

  const exportJson = function() {
    const blob = new Blob([JSON.stringify(pageSchema)], { type: 'application/json' });
    console.log('pageSchema: ', pageSchema);
    FileSaver.saveAs(blob, `${pageSchema[0].props.title}.json`);
  };

  return (
    <div className="design-header">
      <div className="design-header-operations">
        <div className="item" onClick={() => { history.push('/manage/page'); }}>
          <i className="iconfont icon-shouye" />
          <div className="text" >首页</div>
        </div>
        <div className="item" onClick={onSave}>
          <i className="iconfont icon-baocun" />
          <div className="text" >保存</div>
          <Spin spinning={addPageReq.loading || editPageReq.loading}>
          </Spin>
        </div>
        {/* <Popover
          title="真机预览"
          trigger="click"
          visible={visible}
          onVisibleChange={onVisibleChange}
          content={overviewContent}
          overlayClassName="overview-qrcode-popover"
        >

          <div className="item">
            <i className="iconfont icon-shouji" />
            <div className="text">预览</div>
          </div>
        </Popover> */}
        <div className="item" onClick={exportJson}>
          <i className="iconfont icon-json" />
          <div className="text">导出</div>
        </div>
        {/* <div className="item">
          <i className="iconfont icon-html" />
          <div className="text">下载</div>
          <i className="iconfont icon-new" style={{position: 'absolute', color: 'red', right: 0, top: 0}}/>
        </div> */}
        <div className="item" onClick={() => { window.open('https://github.com/lx544690189/scorpio-h5-design'); }}>
          <i className="iconfont icon-github-fill" />
          <div className="text">GITHUB</div>
        </div>
      </div>
    </div>
  );
}