Commit b2203c5d authored by Ylg's avatar Ylg

resolve file conflict

parents cad06772 a252c5a5
......@@ -2,6 +2,7 @@
* @see https://umijs.org/zh-CN/plugins/plugin-access
* */
export default function access(initialState: { currentUser?: API.CurrentUser } | undefined) {
console.log(initialState)
const { currentUser } = initialState ?? {};
return {
canAdmin: currentUser && currentUser.access === 'admin',
......
import Footer from '@/components/Footer';
import RightContent from '@/components/RightContent';
import type { Settings as LayoutSettings } from '@ant-design/pro-components';
import { PageLoading, SettingDrawer } from '@ant-design/pro-components';
import type { RunTimeLayoutConfig } from 'umi';
import { isEmpty } from 'lodash';
import { history } from 'umi';
import defaultSettings from '../config/defaultSettings';
import { currentUser as queryCurrentUser } from './services/ant-design-pro/api';
const loginPath = '/chat';
/** 获取用户信息比较慢的时候会展示一个 loading */
......@@ -18,52 +13,24 @@ export const initialStateConfig = {
/**
* @see https://umijs.org/zh-CN/plugins/plugin-initial-state
* */
export async function getInitialState(): Promise<{
settings?: Partial<LayoutSettings>;
currentUser?: API.CurrentUser;
loading?: boolean;
fetchUserInfo?: () => Promise<API.CurrentUser | undefined>;
}> {
const fetchUserInfo = async () => {
try {
const msg = await queryCurrentUser();
return msg.data;
} catch (error) {
history.push(loginPath);
}
return undefined;
};
// 如果不是登录页面,执行
if (history.location.pathname !== loginPath) {
const currentUser = await fetchUserInfo();
return {
fetchUserInfo,
currentUser,
settings: defaultSettings,
};
export async function getInitialState() {
const userMessage = JSON.parse(localStorage.getItem('user'));
if (isEmpty(userMessage)) {
history.push(loginPath);
return {};
}
return {
fetchUserInfo,
settings: defaultSettings,
};
return { userMessage };
}
// ProLayout 支持的api https://procomponents.ant.design/components/layout
export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => {
export const layout = ({ initialState, setInitialState }) => {
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);
}
},
menuHeaderRender: undefined,
// 自定义 403 页面
// unAccessible: <div>unAccessible</div>,
......
@import (reference) '~antd/es/style/themes/index';
.headerSearch {
display: inline-flex;
align-items: center;
.input {
width: 0;
min-width: 0;
overflow: hidden;
background: transparent;
border-radius: 0;
transition: width 0.3s, margin-left 0.3s;
:global(.ant-select-selection) {
background: transparent;
}
input {
box-shadow: none !important;
}
&.show {
width: 210px;
margin-left: 8px;
}
}
}
import { SearchOutlined } from '@ant-design/icons';
import type { InputRef } from 'antd';
import { AutoComplete, Input } from 'antd';
import type { AutoCompleteProps } from 'antd/es/auto-complete';
import classNames from 'classnames';
import useMergedState from 'rc-util/es/hooks/useMergedState';
import React, { useRef } from 'react';
import styles from './index.less';
export type HeaderSearchProps = {
onSearch?: (value?: string) => void;
onChange?: (value?: string) => void;
onVisibleChange?: (b: boolean) => void;
className?: string;
placeholder?: string;
options: AutoCompleteProps['options'];
defaultVisible?: boolean;
visible?: boolean;
defaultValue?: string;
value?: string;
};
const HeaderSearch: React.FC<HeaderSearchProps> = (props) => {
const {
className,
defaultValue,
onVisibleChange,
placeholder,
visible,
defaultVisible,
...restProps
} = props;
const inputRef = useRef<InputRef | null>(null);
const [value, setValue] = useMergedState<string | undefined>(defaultValue, {
value: props.value,
onChange: props.onChange,
});
const [searchMode, setSearchMode] = useMergedState(defaultVisible ?? false, {
value: props.visible,
onChange: onVisibleChange,
});
const inputClass = classNames(styles.input, {
[styles.show]: searchMode,
});
return (
<div
className={classNames(className, styles.headerSearch)}
onClick={() => {
setSearchMode(true);
if (searchMode && inputRef.current) {
inputRef.current.focus();
}
}}
onTransitionEnd={({ propertyName }) => {
if (propertyName === 'width' && !searchMode) {
if (onVisibleChange) {
onVisibleChange(searchMode);
}
}
}}
>
<SearchOutlined
key="Icon"
style={{
cursor: 'pointer',
}}
/>
<AutoComplete
key="AutoComplete"
className={inputClass}
value={value}
options={restProps.options}
onChange={(completeValue) => setValue(completeValue)}
>
<Input
size="small"
ref={inputRef}
defaultValue={defaultValue}
aria-label={placeholder}
placeholder={placeholder}
onKeyDown={(e) => {
if (e.key === 'Enter') {
if (restProps.onSearch) {
restProps.onSearch(value);
}
}
}}
onBlur={() => {
setSearchMode(false);
}}
/>
</AutoComplete>
</div>
);
};
export default HeaderSearch;
import { QuestionCircleOutlined } from '@ant-design/icons';
import { Space } from 'antd';
import React from 'react';
import { SelectLang, useModel } from 'umi';
import HeaderSearch from '../HeaderSearch';
import Avatar from './AvatarDropdown';
import styles from './index.less';
......@@ -23,37 +21,6 @@ const GlobalHeaderRight: React.FC = () => {
}
return (
<Space className={className}>
<HeaderSearch
className={`${styles.action} ${styles.search}`}
placeholder="站内搜索"
defaultValue="umi ui"
options={[
{ label: <a href="https://umijs.org/zh/guide/umi-ui.html">umi ui</a>, value: 'umi ui' },
{
label: <a href="next.ant.design">Ant Design</a>,
value: 'Ant Design',
},
{
label: <a href="https://protable.ant.design/">Pro Table</a>,
value: 'Pro Table',
},
{
label: <a href="https://prolayout.ant.design/">Pro Layout</a>,
value: 'Pro Layout',
},
]}
// onSearch={value => {
// console.log('input', value);
// }}
/>
<span
className={styles.action}
onClick={() => {
window.open('https://pro.ant.design/docs/getting-started');
}}
>
<QuestionCircleOutlined />
</span>
<Avatar />
<SelectLang className={styles.action} />
</Space>
......
......@@ -52,57 +52,6 @@ export default () => {
};
```
## HeaderSearch 头部搜索框
一个带补全数据的输入框,支持收起和展开 Input
```tsx
/**
* background: '#f0f2f5'
*/
import HeaderSearch from '@/components/HeaderSearch';
import React from 'react';
export default () => {
return (
<HeaderSearch
placeholder="站内搜索"
defaultValue="umi ui"
options={[
{ label: 'Ant Design Pro', value: 'Ant Design Pro' },
{
label: 'Ant Design',
value: 'Ant Design',
},
{
label: 'Pro Table',
value: 'Pro Table',
},
{
label: 'Pro Layout',
value: 'Pro Layout',
},
]}
onSearch={(value) => {
console.log('input', value);
}}
/>
);
};
```
### API
| 参数 | 说明 | 类型 | 默认值 |
| --------------- | ---------------------------------- | ---------------------------- | ------ |
| value | 输入框的值 | `string` | - |
| onChange | 值修改后触发 | `(value?: string) => void` | - |
| onSearch | 查询后触发 | `(value?: string) => void` | - |
| options | 选项菜单的的列表 | `{label,value}[]` | - |
| defaultVisible | 输入框默认是否显示,只有第一次生效 | `boolean` | - |
| visible | 输入框是否显示 | `boolean` | - |
| onVisibleChange | 输入框显示隐藏的回调函数 | `(visible: boolean) => void` | - |
## NoticeIcon 通知工具
通知工具提供一个展示多种通知信息的界面。
......
/* eslint-disable @typescript-eslint/no-unused-expressions */
import { Form, Button, Col, Row, Input, Typography } from 'antd';
import { Form, Button, Col, Row, Input, Typography, Grid } from 'antd';
import React, { useState, useEffect } from 'react';
import styles from './index.less';
import ChatFirstContent from './components/content';
import {
DeleteOutlined,
FieldTimeOutlined,
MenuOutlined,
PlusOutlined,
......@@ -13,7 +12,7 @@ import {
WechatOutlined,
} from '@ant-design/icons';
import classNames from 'classnames';
import { Grid } from 'antd';
import { history } from 'umi';
import LoginModal from '@/components/loginModal';
import NewSession from '@/components/newSession';
......@@ -31,7 +30,7 @@ const Chat: React.FC = () => {
const [selectSiderTabs, setSelectSiderTabs] = useState('');
const [open, setOpen] = useState(false);
const tabShow = showSider && !isMobile ;
const tabShow = showSider;
const questionValue = form.getFieldValue('chatInput');
......@@ -42,7 +41,7 @@ const Chat: React.FC = () => {
}, [isMobile]);
let token = '';
useEffect(() => {
useEffect(() => {
if (localStorage.getItem('user')) {
token = JSON.parse(localStorage.user)?.token;
}
......@@ -59,25 +58,20 @@ const Chat: React.FC = () => {
};
const setInput = (value: any) => {
setChat(value?.firstInput);
form.setFieldValue('chatInput', value?.firstInput);
};
const onChange = (value: any) => {
console.log(value);
value?.chatInput && setChat(value?.chatInput);
value?.firstInput && setInput(value);
};
const siderTabsList = [
{
icons: <DeleteOutlined />,
text: '清空所有会话',
checked: 'clear',
},
{
icons: <SettingOutlined />,
text: '预留功能',
checked: 'moreFunction',
text: '后台',
checked: 'gotoAdmin',
},
{
icons: <WechatOutlined />,
......@@ -93,6 +87,9 @@ const Chat: React.FC = () => {
const selectSliderTabsHandleClick = (value: string) => {
setSelectSiderTabs(value);
if (value === 'gotoAdmin') {
history.push('/admin/user');
}
};
const renderMobileHeader = () => {
......@@ -192,10 +189,7 @@ const Chat: React.FC = () => {
onFinish={onSend}
>
{firstChat ? (
<NewSession
questionValue={chat}
answerValue=''
/>
<NewSession questionValue={chat} answerValue="" />
) : (
<div className={classNames(isMobile && styles.mobileContent)}>
<Item name="firstInput">
......@@ -218,11 +212,7 @@ const Chat: React.FC = () => {
<Col span={4} push={isMobile ? 0 : 4}>
<div className={styles.outputButtonWrapper}>
<Item name="outputButton">
<Button
htmlType="submit"
type="primary"
size="large"
>
<Button htmlType="submit" type="primary" size="large">
发送
</Button>
</Item>
......
import { EllipsisOutlined, PlusOutlined } from '@ant-design/icons';
import { ActionType, PageContainer, ProColumns } from '@ant-design/pro-components';
import { ProTable, TableDropdown } from '@ant-design/pro-components';
import { Button, Dropdown, Space, Tag } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import type { ActionType } from '@ant-design/pro-components';
import { PageContainer } from '@ant-design/pro-components';
import { ProTable } from '@ant-design/pro-components';
import { Button } from 'antd';
import { useRef } from 'react';
import request from 'umi-request';
export const waitTimePromise = async (time: number = 100) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, time);
});
};
export const waitTime = async (time: number = 100) => {
await waitTimePromise(time);
};
type GithubIssueItem = {
url: string;
id: number;
number: number;
title: string;
labels: {
name: string;
color: string;
}[];
state: string;
comments: number;
created_at: string;
updated_at: string;
closed_at?: string;
};
const columns: ProColumns<GithubIssueItem>[] = [
const columns: any[] = [
{
dataIndex: 'index',
valueType: 'indexBorder',
width: 48,
title: '用户',
dataIndex: 'name',
ellipsis: true,
},
{
title: '标题',
dataIndex: 'title',
copyable: true,
title: '用户账号',
dataIndex: 'username',
ellipsis: true,
tip: '标题过长会自动收缩',
formItemProps: {
rules: [
{
required: true,
message: '此项为必填项',
},
],
},
},
{
disable: true,
title: '状态',
dataIndex: 'state',
filters: true,
onFilter: true,
title: '角色',
dataIndex: 'role',
hideInSearch: true,
ellipsis: true,
valueType: 'select',
valueEnum: {
all: { text: '超长'.repeat(50) },
open: {
text: '未解决',
status: 'Error',
},
closed: {
text: '已解决',
status: 'Success',
disabled: true,
},
processing: {
text: '解决中',
status: 'Processing',
},
},
},
{
disable: true,
title: '标签',
dataIndex: 'labels',
search: false,
renderFormItem: (_, { defaultRender }) => {
return defaultRender(_);
},
render: (_, record) => (
<Space>
{record.labels.map(({ name, color }) => (
<Tag color={color} key={name}>
{name}
</Tag>
))}
</Space>
),
title: '账号状态',
dataIndex: 'iaActive',
hideInSearch: true,
},
{
title: '创建时间',
key: 'showTime',
dataIndex: 'created_at',
valueType: 'date',
sorter: true,
dataIndex: 'creationTime',
hideInSearch: true,
valueType: 'date',
},
{
title: '创建时间',
dataIndex: 'created_at',
valueType: 'dateRange',
hideInTable: true,
search: {
transform: (value) => {
return {
startTime: value[0],
endTime: value[1],
};
},
},
title: '备注',
hideInSearch: true,
dataIndex: 'creationTime',
valueType: 'date',
},
{
title: '操作',
......@@ -132,16 +54,11 @@ const columns: ProColumns<GithubIssueItem>[] = [
编辑
</a>,
<a href={record.url} target="_blank" rel="noopener noreferrer" key="view">
查看
重置
</a>,
<a href={record.url} target="_blank" rel="noopener noreferrer" key="view">
删除
</a>,
<TableDropdown
key="actionGroup"
onSelect={() => action?.reload()}
menus={[
{ key: 'copy', name: '复制' },
{ key: 'delete', name: '删除' },
]}
/>,
],
},
];
......@@ -150,54 +67,36 @@ const UserManage = () => {
const actionRef = useRef<ActionType>();
return (
<PageContainer>
<ProTable<GithubIssueItem>
<ProTable
columns={columns}
actionRef={actionRef}
cardBordered
request={async (params = {}, sort, filter) => {
const defaultParams = {
name: '',
Enabled: false,
PageSize: 9,
PageIndex: 1,
};
return request<{
data: GithubIssueItem[];
}>('https://proapi.azurewebsites.net/github/issues', {
params,
data: any[];
}>('https://glm-mangement-api.baibaomen.com/User/page', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
__tenant: '3a0a90fe-9a0d-70f4-200d-a80a41fb6195',
},
data: defaultParams,
});
}}
editable={{
type: 'multiple',
}}
columnsState={{
persistenceKey: 'pro-table-singe-demos',
persistenceType: 'localStorage',
onChange(value) {
console.log('value: ', value);
},
}}
rowKey="id"
search={{
labelWidth: 'auto',
}}
options={{
setting: {
listsHeight: 400,
},
}}
form={{
// 由于配置了 transform,提交的参与与定义的不同这里需要转化一下
syncToUrl: (values, type) => {
if (type === 'get') {
return {
...values,
created_at: [values.startTime, values.endTime],
};
}
return values;
},
}}
pagination={{
pageSize: 5,
onChange: (page) => console.log(page),
onChange: (page) => {},
}}
options={false}
dateFormatter="string"
headerTitle="高级表格"
headerTitle="账号列表"
toolBarRender={() => [
<Button
key="button"
......@@ -207,31 +106,8 @@ const UserManage = () => {
}}
type="primary"
>
新建
添加账号
</Button>,
<Dropdown
key="menu"
menu={{
items: [
{
label: '1st item',
key: '1',
},
{
label: '2nd item',
key: '1',
},
{
label: '3rd item',
key: '1',
},
],
}}
>
<Button>
<EllipsisOutlined />
</Button>
</Dropdown>,
]}
/>
</PageContainer>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment