Skip to content

Commit 4f2db72

Browse files
authored
Merge pull request #53 from guanweiwang/main
feat: 优化用户展示, 更多贡献榜
2 parents 380bd73 + 6180704 commit 4f2db72

12 files changed

Lines changed: 280 additions & 113 deletions

File tree

ui/src/components/avatar/index.tsx

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import Logo from '@/assets/images/logo.png';
22
import { Avatar as MuiAvatar, type SxProps } from '@mui/material';
3-
import { Icon } from '@c-x/ui';
43
import { type ReactNode } from 'react';
54

65
interface AvatarProps {
@@ -41,21 +40,15 @@ function stringAvatar(name: string) {
4140

4241
const Avatar = (props: AvatarProps) => {
4342
const src = props.src;
43+
const avatarObj = props.name ? stringAvatar(props.name) : undefined;
4444
return (
4545
<MuiAvatar
46-
// sx={{
47-
// img: { objectFit: 'contain' },
48-
// bgcolor: 'transparent',
49-
// ...props.sx,
50-
// }}
51-
46+
sx={props.name ? { ...avatarObj!.sx, ...props.sx } : props.sx}
5247
{...(props.name
53-
? stringAvatar(props.name)
54-
: {
55-
children: <img src={Logo} alt='logo' />,
56-
})}
48+
? { children: avatarObj!.children }
49+
: { children: <img src={Logo} alt='logo' /> })}
5750
src={src}
58-
></MuiAvatar>
51+
/>
5952
);
6053
};
6154

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// @ts-nocheck
2+
import React from 'react';
3+
4+
const Code = () => {
5+
return (
6+
<div style={{ height: 420 }}>
7+
<MonacoEditor
8+
height='100%'
9+
language={getBaseLanguageId(data?.program_language || 'plaintext')}
10+
value={editorValue}
11+
theme='vs-dark'
12+
options={{
13+
readOnly: true,
14+
minimap: { enabled: false },
15+
fontSize: 14,
16+
scrollBeyondLastLine: false,
17+
wordWrap: 'on',
18+
lineNumbers: 'on',
19+
glyphMargin: false,
20+
folding: false,
21+
overviewRulerLanes: 0,
22+
guides: {
23+
indentation: true,
24+
highlightActiveIndentation: true,
25+
highlightActiveBracketPair: false,
26+
},
27+
renderLineHighlight: 'none',
28+
cursorStyle: 'line',
29+
cursorBlinking: 'solid',
30+
cursorWidth: 0,
31+
contextmenu: false,
32+
selectionHighlight: false,
33+
selectOnLineNumbers: false,
34+
occurrencesHighlight: 'off',
35+
links: false,
36+
hover: { enabled: false },
37+
codeLens: false,
38+
dragAndDrop: false,
39+
mouseWheelZoom: false,
40+
accessibilitySupport: 'off',
41+
bracketPairColorization: { enabled: false },
42+
matchBrackets: 'never',
43+
}}
44+
onMount={(editor) => {
45+
editorRef.current = editor;
46+
setEditorReady(true);
47+
// 隐藏光标
48+
const editorDom = editor.getDomNode();
49+
if (editorDom) {
50+
const style = document.createElement('style');
51+
style.innerHTML = `.monaco-editor .cursor { display: none !important; }`;
52+
editorDom.appendChild(style);
53+
}
54+
}}
55+
/>
56+
</div>
57+
);
58+
};
59+
60+
export default Code;

ui/src/components/user/index.tsx

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Stack, Link, Typography } from '@mui/material';
2+
import { Link as RouterLink } from 'react-router-dom';
3+
import Avatar from '../avatar';
4+
5+
const User = ({
6+
id,
7+
username = '',
8+
email = '',
9+
}: {
10+
id?: string;
11+
username?: string;
12+
email?: string;
13+
}) => {
14+
return (
15+
<Stack>
16+
<Link
17+
component={RouterLink}
18+
to={id ? `/dashboard/member/${id}` : ''}
19+
sx={{
20+
'&:hover': {
21+
color: id ? 'info.main' : 'text.primary',
22+
},
23+
cursor: 'pointer',
24+
}}
25+
>
26+
<Stack direction={'row'} alignItems={'center'} gap={1}>
27+
<Avatar
28+
name={username}
29+
sx={{ width: 22, height: 22, fontSize: 14 }}
30+
/>
31+
<Typography>{username}</Typography>
32+
</Stack>
33+
</Link>
34+
{email && (
35+
<Typography color='text.auxiliary' sx={{ fontSize: 14 }}>
36+
{email}
37+
</Typography>
38+
)}
39+
</Stack>
40+
);
41+
};
42+
43+
export default User;

ui/src/pages/admin/adminTable.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import dayjs from 'dayjs';
1717
import { DomainAdminUser } from '@/api/types';
1818
import { Controller, useForm } from 'react-hook-form';
1919
import { useEffect, useState } from 'react';
20-
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
20+
import User from '@/components/user';
2121

2222
const AddAdminModal = ({
2323
open,
@@ -182,6 +182,9 @@ const AdminTable = () => {
182182
{
183183
title: '账号',
184184
dataIndex: 'username',
185+
render: (text) => {
186+
return <User username={text} />;
187+
},
185188
},
186189
{
187190
title: '最近活跃时间',

ui/src/pages/admin/loginHistory.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import dayjs from 'dayjs';
55
import { useRequest } from 'ahooks';
66
import { getAdminLoginHistory } from '@/api/User';
77
import { ColumnsType } from '@c-x/ui/dist/Table';
8-
import { DomainListAdminLoginHistoryResp, DomainAdminUser } from '@/api/types';
8+
import { DomainListAdminLoginHistoryResp } from '@/api/types';
9+
import User from '@/components/user';
910

1011
type LoginHistory = NonNullable<
1112
DomainListAdminLoginHistoryResp['login_histories']
@@ -18,7 +19,7 @@ const LoginHistory = () => {
1819
title: '账号',
1920
dataIndex: 'user',
2021
render: (user, record) => {
21-
return record?.user?.username;
22+
return <User username={record!.user!.username!} />;
2223
},
2324
},
2425
{

ui/src/pages/chat/index.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,17 @@
11
import React, { useState, useEffect } from 'react';
2-
import { Table, Ellipsis } from '@c-x/ui';
2+
import { Table } from '@c-x/ui';
33
import { getListChatRecord } from '@/api/Billing';
4-
import { aggregatedTime } from '@/utils';
54
import dayjs from 'dayjs';
6-
import { convertTokensToRMB } from '@/utils';
75

86
import Card from '@/components/card';
9-
import { Box, Stack, styled, Chip } from '@mui/material';
7+
import { Box } from '@mui/material';
108
import StyledLabel from '@/components/label';
119

1210
import ChatDetailModal from './chatDetailModal';
1311
import { ColumnsType } from '@c-x/ui/dist/Table';
14-
import { DomainChatRecord } from '@/api/types';
12+
import { DomainChatRecord, DomainUser } from '@/api/types';
1513
import { addCommasToNumber } from '@/utils';
16-
17-
const StyledHighlightText = styled('span')(({ theme }) => ({
18-
color: theme.vars.palette.text.primary,
19-
fontWeight: 700,
20-
}));
14+
import User from '@/components/user';
2115

2216
const Chat = () => {
2317
const [page, setPage] = useState(1);
@@ -47,9 +41,15 @@ const Chat = () => {
4741
{
4842
dataIndex: 'user',
4943
title: '成员',
50-
width: 160,
51-
render(value: DomainChatRecord['user']) {
52-
return value?.username;
44+
width: 260,
45+
render(value: DomainUser) {
46+
return (
47+
<User
48+
id={value.id!}
49+
username={value.username!}
50+
email={value.email!}
51+
/>
52+
);
5353
},
5454
},
5555
{

ui/src/pages/completion/index.tsx

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,18 @@
1-
import React, {
2-
useState,
3-
useEffect,
4-
useMemo,
5-
useCallback,
6-
useRef,
7-
} from 'react';
8-
import { DomainCompletionRecord } from '@/api/types';
1+
import { useState, useEffect, useCallback, useRef } from 'react';
2+
import { DomainCompletionRecord, DomainUser } from '@/api/types';
93
import { getListCompletionRecord } from '@/api/Billing';
104
import { useRequest } from 'ahooks';
115
import { Table } from '@c-x/ui';
126
import Card from '@/components/card';
137
import {
14-
Box,
15-
Button,
168
ButtonBase,
17-
Chip,
189
Stack,
19-
alpha,
2010
MenuItem,
2111
Select,
2212
FormControl,
2313
InputLabel,
2414
Autocomplete,
2515
TextField,
26-
InputAdornment,
2716
} from '@mui/material';
2817
import { getListUser } from '@/api/User';
2918
import dayjs from 'dayjs';
@@ -33,6 +22,7 @@ import CompletionDetailModal from './completionDetailModal';
3322
import StyledLabel from '@/components/label';
3423
import { LANG_OPTIONS } from './constant';
3524
import { ArrowDropDown as ArrowDropDownIcon } from '@mui/icons-material';
25+
import User from '@/components/user';
3626

3727
// 防抖 hook
3828
function useDebounce(fn: (...args: any[]) => void, delay: number) {
@@ -113,8 +103,14 @@ const Completion = () => {
113103
{
114104
dataIndex: 'user',
115105
title: '成员',
116-
render(value: DomainCompletionRecord['user']) {
117-
return value?.username;
106+
render(value: DomainUser) {
107+
return (
108+
<User
109+
id={value.id!}
110+
username={value.username!}
111+
email={value.email!}
112+
/>
113+
);
118114
},
119115
},
120116
{
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { Box, Stack } from '@mui/material';
2+
import { DomainUserCodeRank } from '@/api/types';
3+
import { Modal } from '@c-x/ui';
4+
import { StyledItem, StyledSerialNumber, StyledText } from './statisticCard';
5+
6+
const ContributionModal = ({
7+
open,
8+
onCancel,
9+
data,
10+
}: {
11+
open: boolean;
12+
onCancel: () => void;
13+
data: DomainUserCodeRank[];
14+
}) => {
15+
return (
16+
<Modal
17+
open={open}
18+
onCancel={onCancel}
19+
title='用户贡献榜'
20+
showCancel={false}
21+
okText='关闭'
22+
>
23+
<Box
24+
gap={0.5}
25+
sx={{
26+
display: 'flex',
27+
flexDirection: 'column',
28+
}}
29+
>
30+
{data.map((item, index) => (
31+
<Stack
32+
direction='row'
33+
alignItems='center'
34+
justifyContent='space-between'
35+
key={item.username}
36+
>
37+
<StyledItem>
38+
<StyledSerialNumber num={index + 1}>
39+
{index + 1}
40+
</StyledSerialNumber>
41+
<Stack
42+
direction='row'
43+
alignItems='center'
44+
gap={1.5}
45+
sx={{
46+
flex: 1,
47+
minWidth: 0,
48+
}}
49+
>
50+
{/* <Avatar size={24} src={item.avatar} /> */}
51+
<StyledText className='active-user-name'>
52+
{item.username}
53+
</StyledText>
54+
</Stack>
55+
</StyledItem>
56+
<Box sx={{ fontSize: 14 }}>{item.lines}</Box>
57+
</Stack>
58+
))}
59+
</Box>
60+
</Modal>
61+
);
62+
};
63+
64+
export default ContributionModal;

0 commit comments

Comments
 (0)