This commit is contained in:
aichy 2022-09-28 10:06:18 +08:00
parent 8e6c49a531
commit c3e33be219
36 changed files with 171 additions and 136 deletions

View File

@ -6,7 +6,7 @@ To learn more about the philosophy and goals of the project, visit [Answer](http
### 📦 Prerequisites
- [Node.js](https://nodejs.org/) `>=14`
- [Node.js](https://nodejs.org/) `>=16.17`
- [pnpm](https://pnpm.io/) `>=7`
pnpm is required by building the Answer project. To installing the pnpm tools with below commands:

View File

@ -26,7 +26,8 @@ module.exports = {
const config = configFunction(proxy, allowedHost);
config.proxy = {
'/answer': {
target: 'http://10.0.10.98:2060',
target: 'http://10.0.20.84:8080',
// target: 'http://10.0.10.98:2060',
changeOrigin: true,
secure: false,
},

View File

@ -12,6 +12,7 @@
"test": "react-app-rewired test",
"eject": "react-scripts eject",
"lint": "eslint . --cache --fix --ext .ts,.tsx",
"prepare": "husky install",
"cz": "cz",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
"prettier": "prettier --write \"src/**/*.{js,jsx,ts,tsx,json,css,scss,md}\""
@ -103,7 +104,7 @@
},
"license": "MIT",
"engines": {
"node": ">=14",
"node": ">=16.17",
"pnpm": ">=7"
}
}

View File

@ -39,7 +39,8 @@ const Editor = ({
placeholder: editorPlaceholder,
});
cm.on('change', (e) => {
eventRef.current?.onChange?.(e.getValue());
const newValue = e.getValue();
eventRef.current?.onChange?.(newValue);
});
cm.on('focus', () => {
@ -89,7 +90,7 @@ const Editor = ({
return;
}
if (editor.getValue() !== value) {
editor.setValue(value);
// editor.setValue(value);
}
}, [editor, value]);

View File

@ -29,7 +29,7 @@ const BlockQuote: FC<IEditorContext> = ({ editor, replaceLines }) => {
editor?.focus();
};
return <ToolItem {...item} click={handleClick} />;
return <ToolItem {...item} onClick={handleClick} />;
};
export default memo(BlockQuote);

View File

@ -18,7 +18,7 @@ const Bold: FC<IEditorContext> = ({ editor, wrapText }) => {
editor?.focus();
};
return <ToolItem {...item} click={handleClick} />;
return <ToolItem {...item} onClick={handleClick} />;
};
export default memo(Bold);

View File

@ -103,6 +103,7 @@ const Chart: FC<IEditorContext> = ({ editor }) => {
tip: `${t('chart.text')}`,
};
const [isShow, setShowState] = useState(false);
const [isLocked, setLockState] = useState(false);
useEffect(() => {
if (!editor) {
@ -122,10 +123,25 @@ const Chart: FC<IEditorContext> = ({ editor }) => {
const onAddHeader = () => {
setShowState(!isShow);
};
const handleMouseEnter = () => {
if (isLocked) {
return;
}
setLockState(true);
};
const handleMouseLeave = () => {
setLockState(false);
};
return (
<ToolItem as="dropdown" {...item} click={onAddHeader}>
<Dropdown.Menu>
<ToolItem
as="dropdown"
{...item}
onClick={onAddHeader}
onBlur={onAddHeader}>
<Dropdown.Menu
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}>
{headerList.map((header) => {
return (
<Dropdown.Item

View File

@ -210,7 +210,7 @@ const Code: FC<IEditorContext> = ({ editor, wrapText }) => {
const onExited = () => editor?.focus();
return (
<ToolItem {...item} click={addCode}>
<ToolItem {...item} onClick={addCode}>
<Modal
show={visible}
onHide={onHide}

View File

@ -22,6 +22,7 @@ const Formula: FC<IEditorContext> = ({ editor, wrapText }) => {
tip: t('formula.text'),
};
const [isShow, setShowState] = useState(false);
const [isLocked, setLockState] = useState(false);
const handleClick = (type, label) => {
if (!editor) {
@ -43,12 +44,29 @@ const Formula: FC<IEditorContext> = ({ editor, wrapText }) => {
setShowState(false);
};
const onAddFormula = () => {
if (isLocked) {
return;
}
setShowState(!isShow);
};
const handleMouseEnter = () => {
setLockState(true);
};
const handleMouseLeave = () => {
setLockState(false);
};
return (
<ToolItem as="dropdown" {...item} isShow={isShow} click={onAddFormula}>
<Dropdown.Menu>
<ToolItem
as="dropdown"
{...item}
isShow={isShow}
onClick={onAddFormula}
onBlur={onAddFormula}>
<Dropdown.Menu
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}>
{formulaList.map((formula) => {
return (
<Dropdown.Item

View File

@ -30,6 +30,7 @@ const Heading: FC<IEditorContext> = (context) => {
tip: `${t('heading.text')} (Ctrl+H)`,
};
const [isShow, setShowState] = useState(false);
const [isLocked, setLockState] = useState(false);
const handleClick = (level = 2, label = '大标题') => {
const { replaceLines } = context;
@ -42,18 +43,36 @@ const Heading: FC<IEditorContext> = (context) => {
setShowState(false);
};
const onAddHeader = () => {
if (isLocked) {
return;
}
setShowState(!isShow);
};
const handleMouseEnter = () => {
setLockState(true);
};
const handleMouseLeave = () => {
setLockState(false);
};
return (
<ToolItem as="dropdown" {...item} isShow={isShow} click={onAddHeader}>
<Dropdown.Menu>
<ToolItem
as="dropdown"
{...item}
isShow={isShow}
onClick={onAddHeader}
onBlur={onAddHeader}>
<Dropdown.Menu
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}>
{headerList.map((header) => {
return (
<Dropdown.Item
key={header.text}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
handleClick(header.level, header.label);
}}
dangerouslySetInnerHTML={{ __html: header.text }}

View File

@ -14,7 +14,7 @@ const Help = () => {
window.open('https://commonmark.org/help/');
};
return <ToolItem {...item} click={handleClick} />;
return <ToolItem {...item} onClick={handleClick} />;
};
export default memo(Help);

View File

@ -16,7 +16,7 @@ const Hr: FC<IEditorContext> = ({ editor, appendBlock }) => {
editor?.focus();
};
return <ToolItem {...item} click={handleClick} />;
return <ToolItem {...item} onClick={handleClick} />;
};
export default memo(Hr);

View File

@ -221,7 +221,7 @@ const Image: FC<IEditorContext> = ({ editor }) => {
setCurrentTab(tab);
};
return (
<ToolItem {...item} click={addLink}>
<ToolItem {...item} onClick={addLink}>
<Modal
show={visible}
onHide={onHide}

View File

@ -18,7 +18,7 @@ const Indent: FC<IEditorContext> = ({ editor, replaceLines }) => {
editor?.focus();
};
return <ToolItem {...item} click={handleClick} />;
return <ToolItem {...item} onClick={handleClick} />;
};
export default memo(Indent);

View File

@ -18,7 +18,7 @@ const Italic: FC<IEditorContext> = ({ editor, wrapText }) => {
editor?.focus();
};
return <ToolItem {...item} click={handleClick} />;
return <ToolItem {...item} onClick={handleClick} />;
};
export default memo(Italic);

View File

@ -65,7 +65,7 @@ const Link: FC<IEditorContext> = ({ editor }) => {
const onExited = () => editor?.focus();
return (
<ToolItem {...item} click={addLink}>
<ToolItem {...item} onClick={addLink}>
<Modal
show={visible}
onHide={onHide}

View File

@ -29,7 +29,7 @@ const OL: FC<IEditorContext> = ({ editor, replaceLines }) => {
editor.focus();
};
return <ToolItem {...item} click={handleClick} />;
return <ToolItem {...item} onClick={handleClick} />;
};
export default memo(OL);

View File

@ -21,7 +21,7 @@ const Outdent: FC<IEditorContext> = ({ editor, replaceLines }) => {
editor?.focus();
};
return <ToolItem {...item} click={handleClick} />;
return <ToolItem {...item} onClick={handleClick} />;
};
export default memo(Outdent);

View File

@ -72,7 +72,7 @@ const Table: FC<IEditorContext> = ({ editor }) => {
editor?.focus();
};
return <ToolItem {...item} click={handleClick} />;
return <ToolItem {...item} onClick={handleClick} />;
};
export default memo(Table);

View File

@ -29,7 +29,7 @@ const UL: FC<IEditorContext> = ({ editor, replaceLines }) => {
editor.focus();
};
return <ToolItem {...item} click={handleClick} />;
return <ToolItem {...item} onClick={handleClick} />;
};
export default memo(UL);

View File

@ -5,7 +5,7 @@ import { EditorContext } from './EditorContext';
interface IProps {
keyMap?: string[];
click?: () => void;
onClick?: () => void;
tip?: string;
className?: string;
as?: any;
@ -13,6 +13,7 @@ interface IProps {
label?: string;
disable?: boolean;
isShow?: boolean;
onBlur?: () => void;
}
const ToolItem: FC<IProps> = (props) => {
const context = useContext(EditorContext);
@ -24,10 +25,11 @@ const ToolItem: FC<IProps> = (props) => {
disable = false,
isShow,
keyMap,
click,
onClick,
className,
as,
children,
onBlur,
} = props;
useEffect(() => {
@ -38,8 +40,8 @@ const ToolItem: FC<IProps> = (props) => {
keyMap.forEach((key) => {
editor.addKeyMap({
[key]: () => {
if (typeof click === 'function') {
click();
if (typeof onClick === 'function') {
onClick();
}
},
});
@ -56,14 +58,14 @@ const ToolItem: FC<IProps> = (props) => {
disabled={disable}
onClick={(e) => {
e.preventDefault();
if (typeof click === 'function') {
click();
if (typeof onClick === 'function') {
onClick();
}
}}
onBlur={(e) => {
e.preventDefault();
if (typeof click === 'function') {
click();
if (typeof onBlur === 'function') {
onBlur();
}
}}
/>
@ -77,7 +79,7 @@ const ToolItem: FC<IProps> = (props) => {
<div className={`toolbar-item-wrap ${className || ''}`}>
{as === 'dropdown' ? (
<Dropdown className="h-100 w-100" show={isShow}>
<Dropdown.Toggle as="div" id="tootlbars-toogle" className="h-100">
<Dropdown.Toggle as="div" className="h-100">
{btnRender()}
</Dropdown.Toggle>
{children}

View File

@ -22,7 +22,7 @@ interface IProps {
const Index: FC<IProps> = ({
type,
qid,
aid,
aid = '',
title,
isAccepted = false,
hasAnswer = false,
@ -39,7 +39,7 @@ const Index: FC<IProps> = ({
const handleReport = () => {
reportModal.onShow({
type,
id: qid,
id: type === 'answer' ? aid : qid,
action: 'flag',
});
};

View File

@ -25,13 +25,17 @@ const Flags: FC = () => {
const curType = urlSearchParams.get('type') || flagTypeKeys[0];
const pageSize = 20;
const curPage = Number(urlSearchParams.get('page')) || 1;
const { data: listData, isLoading } = useFlagSearch({
const {
data: listData,
isLoading,
mutate: refreshList,
} = useFlagSearch({
page_size: pageSize,
page: curPage,
status: curFilter as Type.FlagStatus,
object_type: curType as Type.FlagType,
});
const reportModal = useReportModal();
const reportModal = useReportModal(refreshList);
const count = listData?.count || 0;
const onFilterChange = (filter) => {

View File

@ -20,7 +20,7 @@ const Achievements = ({ data, handleReadNotification }) => {
url = `/questions/${item.object_info.object_id}`;
break;
case 'answer':
url = `/questions/${item.object_info.object_map.question}/${item.object_info.object_id}`;
url = `/questions/${item.object_info?.object_map?.question}/${item.object_info.object_id}`;
break;
default:
url = '';

View File

@ -1,5 +1,5 @@
import { memo, FC, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useSearchParams, Link } from 'react-router-dom';
import { Button } from 'react-bootstrap';
import { useTranslation } from 'react-i18next';
@ -50,17 +50,12 @@ const Index: FC<Props> = ({ data }) => {
</p>
{data?.slug_name && (
<>
<p
dangerouslySetInnerHTML={{
__html: data.parsed_text.replace(
/(<\/p>|<\/p>\n)$/,
`<a href="/tags/${data.slug_name}/info"> [${t(
'more',
)}]</a></p>`,
),
}}
className="last-p"
/>
{data.excerpt && (
<p className="text-break">
{data.excerpt}
<Link to={`/tags/${data.slug_name}/info`}> [{t('more')}]</Link>
</p>
)}
<Button variant="outline-primary" onClick={follow}>
{followed ? t('following') : t('follow')}

View File

@ -37,14 +37,12 @@ const Questions: FC = () => {
if (followResp) {
info.is_follower = followResp.is_followed;
}
const reg = /<p>(.*?)<\/p>/;
const text = info.parsed_text.match(reg);
console.log(text);
if (text?.length && text[1]) {
info.parsed_text =
text[1].length > 256 ? text[1].slice(0, 256) : text[1];
if (info.excerpt) {
info.excerpt =
info.excerpt.length > 256
? [...info.excerpt].slice(0, 256).join('')
: info.excerpt;
}
setTagInfo(info);
@ -62,7 +60,7 @@ const Questions: FC = () => {
<Container className="pt-4 mt-2 mb-5">
<Row className="justify-content-center">
<Col lg={7}>
<div className="tag-box mt-2 mb-5">
<div className="tag-box mb-5">
<h3 className="mb-3">
<Link
to={`/tags/${tagInfo?.slug_name}`}
@ -72,11 +70,8 @@ const Questions: FC = () => {
</Link>
</h3>
<p className="last-p">
<div
dangerouslySetInnerHTML={{ __html: tagInfo.parsed_text }}
className="me-1 text-break float-start"
/>
<p className="text-break">
{tagInfo.excerpt}
<Link to={`/tags/${curTagName}/info`}> [{t('more')}]</Link>
</p>

View File

@ -40,23 +40,7 @@ const TagIntroduction = () => {
const handleSave = () => {
saveSynonymsTags({
tag_id: tagInfo?.tag_id,
synonym_tag_list: synonymsTags?.map((item) => {
if (item.slug_name) {
return {
tag: item.slug_name,
original_text: '',
parsed_text: '',
};
}
if (item.tag) {
return item;
}
return {
tag: item,
original_text: '',
parsed_text: '',
};
}),
synonym_tag_list: synonymsTags,
}).then(() => {
mutate();
setEditState(false);
@ -97,12 +81,7 @@ const TagIntroduction = () => {
handleDeleteTag();
}
};
const tags: any = synonymsTags?.map((tag) => {
if (tag.slug_name) {
return tag.slug_name;
}
return tag;
});
let pageTitle = '';
if (tagInfo) {
pageTitle = `${tagInfo.display_name} ${t('tag_wiki', {
@ -184,7 +163,7 @@ const TagIntroduction = () => {
</Tag>
</div>
<TagSelector
value={tags}
value={synonymsTags}
onChange={handleTagsChange}
hiddenDescription
/>

View File

@ -6,7 +6,7 @@ import request from '@answer/utils/request';
import type * as Type from './types';
export const useAnswerSearch = (params: Type.AdminContentsReq) => {
const apiUrl = `/answer/admin/api/answer/search?${qs.stringify(params)}`;
const apiUrl = `/answer/admin/api/answer/page?${qs.stringify(params)}`;
const { data, error, mutate } = useSWR<Type.ListResult, Error>(
[apiUrl],
request.instance.get,
@ -23,7 +23,7 @@ export const changeAnswerStatus = (
answer_id: string,
status: Type.AdminAnswerStatus,
) => {
return request.post('/answer/admin/api/answer/status', {
return request.put('/answer/admin/api/answer/status', {
answer_id,
status,
});

View File

@ -13,7 +13,7 @@ export const uploadImage = (file) => {
};
export const useQueryQuestionByTitle = (title) => {
return useSWR<Record<string, any>>(
title ? `/answer/api/v1/question/title/like?title=${title}` : '',
title ? `/answer/api/v1/question/similar?title=${title}` : '',
request.instance.get,
);
};
@ -62,7 +62,7 @@ export const addComment = (params) => {
};
export const queryTags = (tag: string) => {
return request.get(`/answer/api/v1/question/tag/search?tag=${tag}`);
return request.get(`/answer/api/v1/question/tags?tag=${tag}`);
};
export const useQueryAnswerInfo = (id: string) => {
@ -75,11 +75,11 @@ export const useQueryAnswerInfo = (id: string) => {
export const modifyQuestion = (
params: Type.QuestionParams & { id: string },
) => {
return request.put(`/answer/api/v1/question/modify`, params);
return request.put(`/answer/api/v1/question`, params);
};
export const modifyAnswer = (params: Type.AnswerParams) => {
return request.post(`/answer/api/v1/answer/modify`, params);
return request.put(`/answer/api/v1/answer`, params);
};
export const login = (params: Type.LoginReqParams) => {
@ -102,11 +102,14 @@ export const emailVerify = (code: string) => {
};
export const emailReSend = (params?: Type.ImgCodeReq) => {
return request.get(
`/answer/api/v1/user/email/verify/send?${qs.stringify(params, {
params = qs.parse(
qs.stringify(params, {
skipNulls: true,
})}`,
}),
);
return request.post('/answer/api/v1/user/email/verification/send', {
...params,
});
};
/**
@ -130,15 +133,15 @@ export const uploadAvatar = (params: Type.AvatarUploadReq) => {
};
export const passRetrieve = (params: Type.PssRetReq) => {
return request.post('/answer/api/v1/user/password/retrieve', params);
return request.post('/answer/api/v1/user/password/reset', params);
};
export const passRetrieveSet = (params: { code: string; pass: string }) => {
return request.post('/answer/api/v1/user/password/retrieve/set', params);
return request.post('/answer/api/v1/user/password/replacement', params);
};
export const accountActivate = (code: string) => {
return request.get(`/answer/api/v1/user/email/verify?code=${code}`);
return request.post(`/answer/api/v1/user/email/verification`, { code });
};
export const checkImgCode = (params: Type.CheckImgReq) => {
@ -152,7 +155,7 @@ export const noticeSet = (params: Type.NoticeSetReq) => {
};
export const saveQuestion = (params: Type.QuestionParams) => {
return request.post('/answer/api/v1/question/add', params);
return request.post('/answer/api/v1/question', params);
};
export const questionDetail = (id: string) => {
@ -168,11 +171,12 @@ export const languages = () => {
};
export const getAnswers = (params: Type.AnswersReq) => {
return request.post<Type.AnswerRes>('/answer/api/v1/answer/list', params);
const apiUrl = `/answer/api/v1/answer/page?${qs.stringify(params)}`;
return request.get<Type.AnswerRes>(apiUrl);
};
export const postAnswer = (params: Type.PostAnswerReq) => {
return request.post('/answer/api/v1/answer/add', params);
return request.post('/answer/api/v1/answer', params);
};
export const bookmark = (params: { group_id: string; object_id: string }) => {
@ -200,7 +204,7 @@ export const adoptAnswer = (params: {
answer_id: string;
question_id: string;
}) => {
return request.post('/answer/api/v1/answer/adopted', params);
return request.post('/answer/api/v1/answer/acceptance', params);
};
export const reportList = ({
@ -225,11 +229,11 @@ export const postReport = (params: {
};
export const questionDelete = (params: { id: string }) => {
return request.delete('/answer/api/v1/question/remove', params);
return request.delete('/answer/api/v1/question', params);
};
export const answerDelete = (params: { id: string }) => {
return request.delete('/answer/api/v1/answer/remove', params);
return request.delete('/answer/api/v1/answer', params);
};
export const closeQuestion = (params: {
@ -237,11 +241,7 @@ export const closeQuestion = (params: {
close_msg?: string;
close_type: number;
}) => {
return request.post('/answer/api/v1/question/close', params);
};
export const closeReasons = () => {
return request.get('/answer/api/v1/question/closemsglist');
return request.put('/answer/api/v1/question/status', params);
};
export const changeEmail = (params: { e_mail: string }) => {
@ -249,7 +249,7 @@ export const changeEmail = (params: { e_mail: string }) => {
};
export const changeEmailVerify = (params: { code: string }) => {
return request.put('/answer/api/v1/user/email/change', params);
return request.put('/answer/api/v1/user/email', params);
};
export const useSiteSettings = () => {

View File

@ -1,4 +1,5 @@
import useSWR from 'swr';
import qs from 'qs';
import request from '@answer/utils/request';
@ -9,8 +10,8 @@ export const putReport = (params) => {
};
export const useFlagSearch = (params: Type.AdminFlagsReq) => {
const apiUrl = `/answer/admin/api/reports/${params.status}/${params.object_type}?page=${params.page}&page_size=${params.page_size}`;
const { data, error } = useSWR<Type.ListResult, Error>(
const apiUrl = `/answer/admin/api/reports/page?${qs.stringify(params)}`;
const { data, error, mutate } = useSWR<Type.ListResult, Error>(
[apiUrl],
request.instance.get,
);
@ -18,5 +19,6 @@ export const useFlagSearch = (params: Type.AdminFlagsReq) => {
data,
isLoading: !data && !error,
error,
mutate,
};
};

View File

@ -7,7 +7,7 @@ import { isLogin } from '@answer/utils';
import type * as Type from './types';
export const useQueryNotifications = (params) => {
const apiUrl = `/answer/api/v1/notification/list?${qs.stringify(params, {
const apiUrl = `/answer/api/v1/notification/page?${qs.stringify(params, {
skipNulls: true,
})}`;
@ -25,13 +25,13 @@ export const useQueryNotifications = (params) => {
};
export const readNotification = (id) => {
return request.instance.post('/answer/api/v1/notification/read', {
return request.instance.put('/answer/api/v1/notification/read/state', {
id,
});
};
export const useQueryNotificationRedDot = () => {
const apiUrl = '/answer/api/v1/notification/reddot';
const apiUrl = '/answer/api/v1/notification/status';
return useSWR<{ inbox: number; achievement: number }>(
isLogin() ? apiUrl : null,
@ -40,13 +40,13 @@ export const useQueryNotificationRedDot = () => {
};
export const clearNotificationRedDot = (type) => {
return request.instance.post('/answer/api/v1/notification/reddot/clear', {
return request.instance.put('/answer/api/v1/notification/status', {
type,
});
};
export const clearUnReadNotification = (type) => {
return request.instance.post('/answer/api/v1/notification/unread/clear', {
return request.instance.put('/answer/api/v1/notification/read/state/all', {
type,
});
};

View File

@ -6,7 +6,7 @@ import request from '@answer/utils/request';
import type * as Type from './types';
export const usePersonalInfoByName = (username: string) => {
const apiUrl = '/answer/api/v1/user/info/username';
const apiUrl = '/answer/api/v1/personal/user/info';
const { data, error, mutate } = useSWR<Type.UserInfoRes, Error>(
username ? `${apiUrl}?username=${username}` : null,
request.instance.get,
@ -32,7 +32,7 @@ interface ListRes {
}
export const usePersonalTop = (username: string, tabName: string) => {
const apiUrl = '/answer/api/v1/question/user/top?username=';
const apiUrl = '/answer/api/v1/personal/qa/top?username=';
const { data, error } = useSWR<{ answer: any[]; question: any[] }, Error>(
tabName === 'overview' ? `${apiUrl}${username}` : null,
request.instance.get,
@ -47,26 +47,26 @@ export const usePersonalTop = (username: string, tabName: string) => {
export const usePersonalListByTabName = (params: ListReq, tabName: string) => {
let apiUrl = '';
if (tabName === 'answers') {
apiUrl = '/answer/api/v1/answer/user';
apiUrl = '/answer/api/v1/personal/answer/page';
}
if (tabName === 'questions') {
apiUrl = '/answer/api/v1/question/user';
apiUrl = '/answer/api/v1/personal/question/page';
}
if (tabName === 'bookmarks') {
delete params.order;
apiUrl = '/answer/api/v1/collection/user';
apiUrl = '/answer/api/v1/personal/collection/page';
}
if (tabName === 'comments') {
delete params.order;
apiUrl = '/answer/api/v1/comment/personal/page';
apiUrl = '/answer/api/v1/personal/comment/page';
}
if (tabName === 'reputation') {
delete params.order;
apiUrl = '/answer/api/v1/rank/personal/page';
apiUrl = '/answer/api/v1/personal/rank/page';
}
if (tabName === 'votes') {
delete params.username;
apiUrl = '/answer/api/v1/votes/personal';
apiUrl = '/answer/api/v1/personal/vote/page';
}
const queryParams = qs.stringify(params, { skipNulls: true });
@ -74,6 +74,7 @@ export const usePersonalListByTabName = (params: ListReq, tabName: string) => {
tabName !== 'overview' ? `${apiUrl}?${queryParams}` : null,
request.instance.get,
);
return {
data: {
[tabName]: data,

View File

@ -24,7 +24,7 @@ export const useQueryUsers = (params) => {
};
export const useQuestionSearch = (params: Type.AdminContentsReq) => {
const apiUrl = `/answer/admin/api/question/search?${qs.stringify(params)}`;
const apiUrl = `/answer/admin/api/question/page?${qs.stringify(params)}`;
const { data, error, mutate } = useSWR<Type.ListResult, Error>(
[apiUrl],
request.instance.get,
@ -41,7 +41,7 @@ export const changeQuestionStatus = (
question_id: string,
status: Type.AdminQuestionStatus,
) => {
return request.post('/answer/admin/api/question/status', {
return request.put('/answer/admin/api/question/status', {
question_id,
status,
});

View File

@ -6,10 +6,10 @@ import request from '@answer/utils/request';
import type * as Type from './types';
export const useQuestionList = (params: Type.QueryQuestionsReq) => {
const apiUrl = '/answer/api/v1/question/index';
const apiUrl = `/answer/api/v1/question/page?${qs.stringify(params)}`;
const { data, error } = useSWR<Type.ListResult, Error>(
[apiUrl, params],
request.instance.post,
[apiUrl],
request.instance.get,
);
return {
data,
@ -25,10 +25,10 @@ export const useHotQuestions = (
order: 'frequent',
},
) => {
const apiUrl = '/answer/api/v1/question/index';
const apiUrl = `/answer/api/v1/question/page?${qs.stringify(params)}`;
const { data, error } = useSWR<Type.ListResult, Error>(
[apiUrl, params],
request.instance.post,
[apiUrl],
request.instance.get,
);
return {
data,
@ -41,7 +41,7 @@ export const useSimilarQuestion = (params: {
question_id: string;
page_size: number;
}) => {
const apiUrl = `/answer/api/v1/question/similar?${qs.stringify(params)}`;
const apiUrl = `/answer/api/v1/question/similar/tag?${qs.stringify(params)}`;
const { data, error } = useSWR<Type.ListResult, Error>(
params.question_id ? apiUrl : null,

View File

@ -31,6 +31,7 @@ export interface TagInfo {
created_at?;
updated_at?;
main_tag_slug_name?: string;
excerpt?;
}
export interface QuestionParams {
title: string;

View File

@ -140,7 +140,7 @@ class Request {
}
toastStore.getState().show({
msg: `statusCode: ${status}, ${msg}`,
msg: `statusCode: ${status}; ${msg || ''}`,
variant: 'danger',
});
return Promise.reject(false);