mirror of https://gitee.com/answerdev/answer.git
add ui
This commit is contained in:
parent
8e6c49a531
commit
c3e33be219
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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',
|
||||
});
|
||||
};
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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 = '';
|
||||
|
|
|
@ -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')}
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
/>
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -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 = () => {
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -31,6 +31,7 @@ export interface TagInfo {
|
|||
created_at?;
|
||||
updated_at?;
|
||||
main_tag_slug_name?: string;
|
||||
excerpt?;
|
||||
}
|
||||
export interface QuestionParams {
|
||||
title: string;
|
||||
|
|
|
@ -140,7 +140,7 @@ class Request {
|
|||
}
|
||||
|
||||
toastStore.getState().show({
|
||||
msg: `statusCode: ${status}, ${msg}`,
|
||||
msg: `statusCode: ${status}; ${msg || ''}`,
|
||||
variant: 'danger',
|
||||
});
|
||||
return Promise.reject(false);
|
||||
|
|
Loading…
Reference in New Issue