Skip to content

Commit 73af9d7

Browse files
审核题解页显示该题题目难度
1 parent 11c1bf6 commit 73af9d7

File tree

6 files changed

+152
-50
lines changed

6 files changed

+152
-50
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"@mr.python/axios-userscript-adapter": "^1.0.0",
2626
"axios": "^1.7.2",
2727
"dayjs": "^1.11.11",
28+
"deepmerge": "^4.3.1",
2829
"hast-util-to-jsx-runtime": "^2.3.0",
2930
"highlight.js": "^11.10.0",
3031
"katex": "^0.16.11",

src/app/features/article/index.tsx

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,19 @@ import {
1616
PopoverSurface
1717
} from '@fluentui/react-components';
1818
import { getArticle, submitArticleCheckResult } from '../../../fetch';
19-
import { ErrorDiv, InputDateTime, UserName } from '../../utils';
19+
import {
20+
ErrorDiv,
21+
InputDateTime,
22+
ProblemNameWithDifficulty,
23+
UserName
24+
} from '../../utils';
2025
import dayjs from 'dayjs';
2126
import emptyQueueImage from 'assets/emptyQueue.webp';
2227
import './style.css';
2328
import { useNotUndefinedContext } from '../../../notUndefinedContext';
2429
import { MyInfoContext } from '../../contexts';
2530
import { isCancel } from 'axios';
31+
import { oldDifficultySystem } from '../../../constants';
2632

2733
export default function Article() {
2834
const [status, setStatus] = useState<{
@@ -46,12 +52,10 @@ export default function Article() {
4652
const cancel = new AbortController();
4753
getArticle(skipBefore / 1000, { signal: cancel.signal })
4854
.then(v => {
49-
console.log(v);
5055
setStatus({ details: v }),
5156
v.article && setSkipBefore(v.article.promoteResult.updateAt * 1000);
5257
})
5358
.catch(e => {
54-
console.log(e);
5559
if (isCancel(e)) return;
5660
console.error('Error in feature Article', e), setFetchError(e);
5761
});
@@ -71,7 +75,9 @@ export default function Article() {
7175
async function submit() {
7276
if (!details?.article) throw new Error('No article');
7377
setStatus({ details: details, submiting: true });
74-
await submitArticleCheckResult([details.article.lid, refuseCommit || true]);
78+
await submitArticleCheckResult([
79+
[details.article.lid, refuseCommit || true]
80+
]);
7581
setStatus(null);
7682
setOtherRefuseCommit('');
7783
updateArticle();
@@ -129,13 +135,13 @@ export default function Article() {
129135
{details.article.solutionFor && (
130136
<Text>
131137
关联于题目{' '}
132-
<Link
133-
href={`https://www.luogu.com.cn/problem/${details.article.solutionFor.pid}`}
134-
target="_blank"
135-
>
136-
{details.article.solutionFor.pid}{' '}
137-
{details.article.solutionFor.title}
138-
</Link>
138+
<ProblemNameWithDifficulty
139+
pid={details.article.solutionFor.pid}
140+
name={details.article.solutionFor.title}
141+
difficulty={oldDifficultySystem.findIndex(
142+
x => x >= details.article.solutionFor!.difficulty
143+
)}
144+
/>
139145
140146
{details.countForProblem && (
141147
<>
@@ -154,7 +160,10 @@ export default function Article() {
154160
)}
155161
<div className="adminCommit">
156162
<Text>管理员备注:</Text>
157-
<textarea defaultValue={details.article.adminComment} />
163+
<textarea
164+
defaultValue={details.article.adminComment}
165+
spellCheck="false"
166+
/>
158167
</div>
159168
</>
160169
) : undefined}
@@ -185,7 +194,7 @@ export default function Article() {
185194
很遗憾,您的《
186195
<Link
187196
href={`https://www.luogu.com.cn/article/${details.article.lid}`}
188-
target='_blank'
197+
target="_blank"
189198
>
190199
{details.article.title}
191200
</Link>

src/app/utils.tsx

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,16 @@
1-
import React from 'react';
1+
import React, { memo, useEffect, useState } from 'react';
22

33
import { UserSummary } from 'luogu-api';
44
import { isError } from 'lodash';
5-
import { isAxiosError } from 'axios';
6-
import { Button, tokens, Input } from '@fluentui/react-components';
5+
import { isAxiosError, isCancel } from 'axios';
6+
import { Button, tokens, Input, Link } from '@fluentui/react-components';
77
import dayjs from 'dayjs';
88
import { DismissCircleRegular } from '@fluentui/react-icons';
9+
import { getProblemData } from '../fetch';
10+
import { UsernameColor, DifficultyColor } from '../constants';
911

1012
export type Override<P, S> = Omit<P, keyof S> & S;
1113

12-
export const UsernameColor = {
13-
Purple: 'rgb(157, 61, 207)',
14-
Red: 'rgb(254, 76, 97)',
15-
Orange: 'rgb(243, 156, 17)',
16-
Green: 'rgb(82, 196, 26)',
17-
Blue: 'rgb(52, 152, 219)',
18-
Gray: 'rgb(191, 191, 191)'
19-
},
20-
DifficultyColor = [
21-
'#BFBFBF',
22-
'#FE4C61',
23-
'#F39C11',
24-
'#FFC116',
25-
'#52C41A',
26-
'#3498DB',
27-
'#9D3DCF',
28-
'#0E1D69'
29-
];
30-
3114
export function UserName({ children }: { children: UserSummary }) {
3215
return (
3316
<a
@@ -151,3 +134,54 @@ export function InputDateTime(
151134
/>
152135
);
153136
}
137+
138+
export const ProblemNameWithDifficulty = memo(
139+
({
140+
pid,
141+
name,
142+
difficulty
143+
}: {
144+
pid: string;
145+
name?: string;
146+
difficulty?: number;
147+
}) => {
148+
const [difficultyState, setDifficultyState] = useState<number | undefined>(
149+
difficulty
150+
);
151+
const [nameState, setNameState] = useState<string | undefined>(name);
152+
useEffect(() => {
153+
if (difficultyState !== undefined && nameState !== undefined) return;
154+
const cancel = new AbortController();
155+
getProblemData(pid, { signal: cancel.signal })
156+
.then(data => {
157+
if (difficultyState === undefined)
158+
setDifficultyState(data.currentData.problem.difficulty);
159+
if (nameState === undefined)
160+
setNameState(data.currentData.problem.title);
161+
})
162+
.catch(e => {
163+
if (isCancel(e)) return;
164+
console.error('Error when fetch problem data', e);
165+
});
166+
return () => cancel.abort();
167+
}, []);
168+
return (
169+
<Link href={'https://www.luogu.com.cn/problem/' + pid} target="_blank">
170+
<span
171+
style={
172+
difficultyState !== undefined
173+
? {
174+
fontWeight: 'bold',
175+
fontSize: '16px',
176+
color: DifficultyColor[difficultyState]
177+
}
178+
: undefined
179+
}
180+
>
181+
{pid}
182+
</span>
183+
{nameState !== undefined && ' ' + nameState}
184+
</Link>
185+
);
186+
}
187+
);

src/constants.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export const DifficultyColor = [
2+
'rgb(191, 191, 191)',
3+
'rgb(254, 76, 97)',
4+
'rgb(243, 156, 17)',
5+
'rgb(255, 193, 22)',
6+
'rgb(82, 196, 26)',
7+
'rgb(52, 152, 219)',
8+
'rgb(157, 61, 207)',
9+
'rgb(14, 29, 105)'
10+
];
11+
12+
export const oldDifficultySystem = [0, 2, 3.5, 5, 6, 8, 10, 2147483647];
13+
14+
export const UsernameColor = {
15+
Purple: 'rgb(157, 61, 207)',
16+
Red: 'rgb(254, 76, 97)',
17+
Orange: 'rgb(243, 156, 17)',
18+
Green: 'rgb(82, 196, 26)',
19+
Blue: 'rgb(52, 152, 219)',
20+
Gray: 'rgb(191, 191, 191)',
21+
Cheater: 'rgb(173, 139, 0)'
22+
};

src/fetch/index.ts

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import Axios, { AxiosRequestConfig, CancelToken } from 'axios';
22
import GMadaptr from '@mr.python/axios-userscript-adapter';
33

44
import { AdminMeta, SolutionAdminInfo } from '../interface';
5+
import deepmerge from 'deepmerge';
6+
import { DataResponse, ProblemData } from 'luogu-api';
57

68
const axios = Axios.create({
79
baseURL: 'https://www.luogu.com.cn/sadmin',
@@ -16,35 +18,61 @@ axios.interceptors.response.use(v => {
1618

1719
GM_xmlhttpRequest; // add it to @grant
1820

19-
export const fetchMyInfo = () =>
21+
export const fetchMyInfo = (config: AxiosRequestConfig = {}) =>
2022
axios
21-
.get<AdminMeta>('https://www.luogu.com.cn/sadmin', {
22-
headers: {
23-
'x-lentille-request': 'content-only'
24-
}
25-
})
23+
.get<AdminMeta>(
24+
'https://www.luogu.com.cn/sadmin',
25+
deepmerge(
26+
{
27+
headers: {
28+
'x-lentille-request': 'content-only'
29+
}
30+
},
31+
config
32+
)
33+
)
2634
.then(x => {
2735
if (!x.data.user) throw new Error('unknown user', { cause: x });
2836
return x.data.user;
2937
});
3038

31-
export const getArticle = (skipBefore: number, config?: AxiosRequestConfig) =>
39+
export const getArticle = (
40+
skipBefore: number,
41+
config: AxiosRequestConfig = {}
42+
) =>
3243
axios
33-
.post<SolutionAdminInfo>('api/article/promotionReview/next', undefined, {
34-
params: {
35-
skipBefore: skipBefore || 0
36-
},
37-
...config
38-
})
44+
.post<SolutionAdminInfo>(
45+
'api/article/promotionReview/next',
46+
undefined,
47+
deepmerge(
48+
{
49+
params: {
50+
skipBefore: skipBefore || 0
51+
}
52+
},
53+
config
54+
)
55+
)
3956
.then(x => x.data);
4057

41-
export const submitArticleCheckResult = (...data: [string, string | true][]) =>
58+
export const submitArticleCheckResult = (
59+
data: [string, string | true][],
60+
config: AxiosRequestConfig = {}
61+
) =>
4262
axios
4363
.post<{
4464
rejected: string[];
4565
accepted: string[];
4666
}>(
4767
'https://www.luogu.com.cn/sadmin/api/article/promotionReview/submit',
48-
Object.fromEntries<string | true>(data)
68+
Object.fromEntries<string | true>(data),
69+
config
4970
)
5071
.then(x => x.data);
72+
73+
export const getProblemData = (pid: string, config: AxiosRequestConfig = {}) =>
74+
axios
75+
.get<
76+
DataResponse<ProblemData>
77+
>(`https://www.luogu.com.cn/problem/${pid}`, deepmerge({ headers: { 'x-luogu-type': 'content-only' } }, config))
78+
.then(x => x.data);

yarn.lock

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4187,6 +4187,13 @@ __metadata:
41874187
languageName: node
41884188
linkType: hard
41894189

4190+
"deepmerge@npm:^4.3.1":
4191+
version: 4.3.1
4192+
resolution: "deepmerge@npm:4.3.1"
4193+
checksum: 10c0/e53481aaf1aa2c4082b5342be6b6d8ad9dfe387bc92ce197a66dea08bd4265904a087e75e464f14d1347cf2ac8afe1e4c16b266e0561cc5df29382d3c5f80044
4194+
languageName: node
4195+
linkType: hard
4196+
41904197
"default-gateway@npm:^6.0.3":
41914198
version: 6.0.3
41924199
resolution: "default-gateway@npm:6.0.3"
@@ -6621,6 +6628,7 @@ __metadata:
66216628
css-loader: "npm:^7.1.2"
66226629
css-minimizer-webpack-plugin: "npm:^7.0.0"
66236630
dayjs: "npm:^1.11.11"
6631+
deepmerge: "npm:^4.3.1"
66246632
eslint: "npm:8.56.0"
66256633
eslint-plugin-react: "npm:^7.34.2"
66266634
hast-util-to-jsx-runtime: "npm:^2.3.0"

0 commit comments

Comments
 (0)