feat(compose): 正文内嵌隐藏块并升级 Markdown 编辑器
去掉整帖可见性表单,改为 :::hide 按块脱敏;工具栏补齐代码块、链接/图片对话框与粘贴拖拽上传。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -17,13 +17,11 @@ import {
|
||||
} from "@/lib/api";
|
||||
import {
|
||||
POST_TYPES,
|
||||
CONTENT_ACCESS,
|
||||
BOUNTY_EXPIRE_DAYS,
|
||||
LOTTERY_EXPIRE_DAYS,
|
||||
POLL_EXPIRE_DAYS,
|
||||
normalizePostType,
|
||||
type PostTypeValue,
|
||||
type ContentAccessValue,
|
||||
} from "@/lib/postMeta";
|
||||
import { toast } from "@/lib/toast";
|
||||
import MarkdownEditor from "@/components/MarkdownEditor";
|
||||
@@ -44,8 +42,6 @@ type ComposeDraft = {
|
||||
tags: string;
|
||||
boardId: number;
|
||||
postType?: string;
|
||||
contentAccess?: string;
|
||||
accessPoints?: number;
|
||||
typeMeta?: string;
|
||||
updatedAt: number;
|
||||
};
|
||||
@@ -128,8 +124,6 @@ type EditProps = {
|
||||
initialContent: string;
|
||||
initialTags?: string;
|
||||
initialPostType?: string;
|
||||
initialContentAccess?: string;
|
||||
initialAccessPoints?: number;
|
||||
initialTypeMeta?: string;
|
||||
initialAttachments?: PostAttachment[];
|
||||
/** 投票帖:有票后禁止改选项 */
|
||||
@@ -162,14 +156,6 @@ export default function PostComposer(props: PostComposerProps) {
|
||||
const [postType, setPostType] = useState<PostTypeValue>(
|
||||
normalizePostType(isCreate ? "discussion" : props.initialPostType)
|
||||
);
|
||||
const [contentAccess, setContentAccess] = useState<ContentAccessValue>(
|
||||
(isCreate
|
||||
? "public"
|
||||
: (props.initialContentAccess as ContentAccessValue) || "public") as ContentAccessValue
|
||||
);
|
||||
const [accessPoints, setAccessPoints] = useState(
|
||||
isCreate ? 10 : props.initialAccessPoints || 10
|
||||
);
|
||||
const [typeMeta, setTypeMeta] = useState(
|
||||
isCreate ? "" : props.initialTypeMeta || ""
|
||||
);
|
||||
@@ -364,8 +350,6 @@ export default function PostComposer(props: PostComposerProps) {
|
||||
tags: serializeTags(tagList),
|
||||
boardId,
|
||||
postType,
|
||||
contentAccess,
|
||||
accessPoints,
|
||||
typeMeta,
|
||||
updatedAt: Date.now(),
|
||||
});
|
||||
@@ -380,8 +364,6 @@ export default function PostComposer(props: PostComposerProps) {
|
||||
tagList,
|
||||
boardId,
|
||||
postType,
|
||||
contentAccess,
|
||||
accessPoints,
|
||||
typeMeta,
|
||||
]);
|
||||
|
||||
@@ -392,10 +374,6 @@ export default function PostComposer(props: PostComposerProps) {
|
||||
setTagList(parseTags(draftBanner.tags || ""));
|
||||
if (draftBanner.boardId) setBoardId(draftBanner.boardId);
|
||||
if (draftBanner.postType) setPostType(normalizePostType(draftBanner.postType));
|
||||
if (draftBanner.contentAccess) {
|
||||
setContentAccess(draftBanner.contentAccess as ContentAccessValue);
|
||||
}
|
||||
if (draftBanner.accessPoints) setAccessPoints(draftBanner.accessPoints);
|
||||
if (draftBanner.typeMeta) setTypeMeta(draftBanner.typeMeta);
|
||||
setDraftBanner(null);
|
||||
skipDraftSave.current = false;
|
||||
@@ -533,7 +511,6 @@ export default function PostComposer(props: PostComposerProps) {
|
||||
title.trim().length > 0 &&
|
||||
content.trim().length > 0 &&
|
||||
(isCreate ? boardsReady && boardId > 0 : true) &&
|
||||
(contentAccess !== "points" || accessPoints > 0) &&
|
||||
(postType !== "poll" ||
|
||||
pollOptions.map((o) => o.trim()).filter(Boolean).length >= 2) &&
|
||||
(postType !== "bounty" ||
|
||||
@@ -609,8 +586,6 @@ export default function PostComposer(props: PostComposerProps) {
|
||||
content: content.trim(),
|
||||
tags,
|
||||
post_type: postType,
|
||||
content_access: contentAccess,
|
||||
access_points: contentAccess === "points" ? accessPoints : 0,
|
||||
type_meta: meta,
|
||||
attachment_ids: attIds,
|
||||
});
|
||||
@@ -634,8 +609,6 @@ export default function PostComposer(props: PostComposerProps) {
|
||||
title: title.trim(),
|
||||
content: content.trim(),
|
||||
tags,
|
||||
content_access: contentAccess,
|
||||
access_points: contentAccess === "points" ? accessPoints : 0,
|
||||
type_meta: meta,
|
||||
attachment_ids: attIds,
|
||||
});
|
||||
@@ -818,42 +791,6 @@ export default function PostComposer(props: PostComposerProps) {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="j13-compose-meta-access">
|
||||
<label className="field-label" htmlFor="compose-access">
|
||||
正文可见性
|
||||
</label>
|
||||
<select
|
||||
id="compose-access"
|
||||
className="j13-compose-field"
|
||||
value={contentAccess}
|
||||
disabled={loading}
|
||||
onChange={(e) => setContentAccess(e.target.value as ContentAccessValue)}
|
||||
>
|
||||
{CONTENT_ACCESS.map((a) => (
|
||||
<option key={a.value} value={a.value}>
|
||||
{a.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{contentAccess === "points" && (
|
||||
<div className="mt-2 flex items-center gap-2">
|
||||
<label className="meta text-[12.5px] shrink-0" htmlFor="compose-access-pts">
|
||||
所需积分
|
||||
</label>
|
||||
<input
|
||||
id="compose-access-pts"
|
||||
type="number"
|
||||
min={1}
|
||||
max={100000}
|
||||
value={accessPoints}
|
||||
disabled={loading}
|
||||
onChange={(e) => setAccessPoints(Number(e.target.value) || 0)}
|
||||
className="j13-compose-field !py-1.5 w-28"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
@@ -1241,7 +1178,7 @@ export default function PostComposer(props: PostComposerProps) {
|
||||
disabled={loading}
|
||||
rows={18}
|
||||
placeholder={
|
||||
"从这里开始写正文…\n\n支持 Markdown;可用工具栏插入格式与图片。可点全屏沉浸写作。"
|
||||
"从这里开始写正文…\n\n工具栏可插入格式、代码块、链接、图片与隐藏内容(登录/回复/积分可见)。支持粘贴与拖拽上传图片。"
|
||||
}
|
||||
onSubmitShortcut={() => {
|
||||
if (canSubmit) void handleSubmit();
|
||||
|
||||
Reference in New Issue
Block a user