完善投稿功能

This commit is contained in:
2026-01-23 13:46:20 +08:00
parent 50371f9a2e
commit abae2e266a
4 changed files with 137 additions and 4 deletions

View File

@@ -116,7 +116,7 @@ def get_about():
# about在初始化时不会被设置避免管理面板报错返回默认文本
return jsonify({
"code": 1000,
"data": "# 默认关于页面\n关于页面未设置,请前往管理面板。"
"data": "# 默认关于页面\n关于页面未设置,请前往管理面板操作"
})
@app.route('/api/get_id_token', methods=['GET'])
@@ -197,7 +197,8 @@ def submit_post():
db.session.add(new_post)
db.session.commit()
return jsonify({"code": 1000, "data": "投稿成功"})
code = 1002 if new_post.status == 'Pending' else 1001
return jsonify({"code": code, "data": {"id": new_post.id}})
except Exception as e:
return jsonify({"code": 2003, "data": f"投稿失败: {str(e)}"})

View File

@@ -29,12 +29,14 @@
| Code | 含义 |
| ---- | ---------------------------------------------------- |
| 1000 | 正常。适用于大多数成功的GET请求的返回。 |
| | |
| 1001 | 正常。适用于大多数成功的POST请求的返回。 |
| 1002 | 正常。提交内容需要等待审核。 |
| 2000 | 失败。请求方式错误,例如缺少指定参数。 |
| 2001 | 失败。未初始化。不应该在成功初始化后继续使用该code。 |
| 2002 | 失败。数据不存在。 |
| 2003 | 失败。服务器内部错误。 |
| 2004 | 失败。试图请求不存在的资源或使用不存在的Identity。 |
| 2005 | 失败。提交内容包含违禁词。 |
| 404 | api端点不存在。 |
| | |
| | |

View File

@@ -89,3 +89,76 @@ export const saveDraft = (content: string): void => {
export const getDraft = (): string | null => {
return localStorage.getItem('draft');
};
export const fetch_id_token = async (): Promise<string> => {
try {
const response = await fetch('/api/get_id_token');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const json = await response.json();
if (json.code === 1000) {
return json.data;
} else {
throw new Error(json.data || 'Failed to fetch identity token');
}
} catch (error) {
console.error('Failed to fetch identity token:', error);
throw error;
}
};
export const get_id_token = async (): Promise<string> => {
let token = localStorage.getItem('identity_token');
if (!token) {
token = await fetch_id_token();
localStorage.setItem('identity_token', token);
}
return token;
};
export interface CreatePostResponse {
code: number;
data: any;
}
export const createPost = async (content: string): Promise<CreatePostResponse> => {
try {
const identity = await get_id_token();
// 解析标签:#开头,后跟非空白字符
const hashtopic: string[] = [];
const regex = /#\S+/g;
const matches = content.match(regex);
if (matches) {
matches.forEach(tag => {
const cleanTag = tag.substring(1);
// 去重添加
if (!hashtopic.includes(cleanTag)) {
hashtopic.push(cleanTag);
}
});
}
const response = await fetch('/api/post', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
content,
hashtopic,
identity
}),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Failed to create post:', error);
throw error;
}
};

View File

@@ -23,8 +23,9 @@ import {
Send24Regular,
Save24Regular
} from '@fluentui/react-icons';
import { useNavigate } from 'react-router-dom';
import { useLayout } from '../context/LayoutContext';
import { saveDraft, getDraft } from '../api';
import { saveDraft, getDraft, createPost } from '../api';
const useStyles = makeStyles({
container: {
@@ -118,6 +119,7 @@ const remarkTagPlugin = () => {
const CreatePost: React.FC = () => {
const styles = useStyles();
const navigate = useNavigate();
const { isDarkMode, toasterId } = useLayout();
const { dispatchToast } = useToastController(toasterId);
const [value, setValue] = useState<string | undefined>("");
@@ -135,6 +137,60 @@ const CreatePost: React.FC = () => {
const activeElapsedRef = useRef<number>(0);
const hasStartedAutoSaveRef = useRef(false);
const handlePostSubmit = async () => {
if (!value || !value.trim()) {
dispatchToast(
<Toast>
<ToastTitle></ToastTitle>
</Toast>,
{ intent: 'error' }
);
return;
}
try {
const response = await createPost(value);
if (response.code === 1001 || response.code === 1002) {
// 清除草稿
saveDraft('');
setValue('');
// 停止自动保存计时器
if (autoSaveIntervalRef.current !== null) {
window.clearInterval(autoSaveIntervalRef.current);
autoSaveIntervalRef.current = null;
}
activeElapsedRef.current = 0;
hasStartedAutoSaveRef.current = false;
dispatchToast(
<Toast>
<ToastTitle>{response.code === 1002 ? "投稿成功,等待审核" : "投稿成功!"}</ToastTitle>
</Toast>,
{ intent: 'success' }
);
navigate('/');
} else if (response.code === 2005) {
dispatchToast(
<Toast>
<ToastTitle>稿</ToastTitle>
</Toast>,
{ intent: 'error' }
);
} else {
throw new Error(response.data || 'Unknown error');
}
} catch (error) {
dispatchToast(
<Toast>
<ToastTitle>稿</ToastTitle>
</Toast>,
{ intent: 'error' }
);
}
};
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
@@ -270,6 +326,7 @@ const CreatePost: React.FC = () => {
<Button
appearance="primary"
icon={<Send24Regular />}
onClick={handlePostSubmit}
>
</Button>