mirror of
https://github.com/SECTL/SecScore.git
synced 2026-07-19 21:14:21 +08:00
精简看板顶部操作并移除看板配置区
This commit is contained in:
@@ -83,6 +83,11 @@ interface DragState {
|
||||
containerSize: number
|
||||
}
|
||||
|
||||
const getFirstLeafId = (node: LayoutNode): string => {
|
||||
if (node.type === "leaf") return node.id
|
||||
return getFirstLeafId(node.first)
|
||||
}
|
||||
|
||||
const makeId = () =>
|
||||
typeof crypto !== "undefined" && "randomUUID" in crypto
|
||||
? crypto.randomUUID()
|
||||
@@ -345,6 +350,9 @@ export const BoardManager: React.FC<BoardManagerProps> = ({ canManage }) => {
|
||||
const [errorMap, setErrorMap] = useState<Record<string, string>>({})
|
||||
const [dragState, setDragState] = useState<DragState | null>(null)
|
||||
const [editingListId, setEditingListId] = useState<string | null>(null)
|
||||
const [selectedLeafNodeId, setSelectedLeafNodeId] = useState<string | null>(null)
|
||||
const [renameVisible, setRenameVisible] = useState(false)
|
||||
const [renameValue, setRenameValue] = useState("")
|
||||
|
||||
const panelRefs = useRef<Record<string, HTMLDivElement | null>>({})
|
||||
|
||||
@@ -511,6 +519,15 @@ ORDER BY reward_points DESC, score DESC`,
|
||||
if (!activeBoardId && boards.length > 0) setActiveBoardId(boards[0].id)
|
||||
}, [activeBoardId, boards])
|
||||
|
||||
useEffect(() => {
|
||||
if (!activeBoard) {
|
||||
setSelectedLeafNodeId(null)
|
||||
return
|
||||
}
|
||||
const firstLeafId = getFirstLeafId(activeBoard.layout)
|
||||
setSelectedLeafNodeId((prev) => prev || firstLeafId)
|
||||
}, [activeBoard?.id, activeBoard?.layout])
|
||||
|
||||
useEffect(() => {
|
||||
if (!activeBoard) return
|
||||
runAllInBoard(activeBoard).catch(() => void 0)
|
||||
@@ -567,6 +584,18 @@ ORDER BY reward_points DESC, score DESC`,
|
||||
)
|
||||
}
|
||||
|
||||
const openRenameModal = () => {
|
||||
if (!activeBoard) return
|
||||
setRenameValue(activeBoard.name)
|
||||
setRenameVisible(true)
|
||||
}
|
||||
|
||||
const submitRenameBoard = () => {
|
||||
if (!activeBoard) return
|
||||
updateBoardName(activeBoard.id, renameValue.trim() || t("board.untitledBoard"))
|
||||
setRenameVisible(false)
|
||||
}
|
||||
|
||||
const addBoard = () => {
|
||||
if (!canManage) return
|
||||
const newBoard = createDefaultBoard()
|
||||
@@ -628,6 +657,11 @@ ORDER BY reward_points DESC, score DESC`,
|
||||
)
|
||||
}
|
||||
|
||||
const splitSelectedLeaf = (direction: SplitDirection) => {
|
||||
if (!activeBoard || !selectedLeafNodeId) return
|
||||
addListBySplit(activeBoard.id, selectedLeafNodeId, direction)
|
||||
}
|
||||
|
||||
const removeList = (boardId: string, listId: string) => {
|
||||
if (!canManage) return
|
||||
|
||||
@@ -874,10 +908,18 @@ ORDER BY reward_points DESC, score DESC`,
|
||||
const renderLeafPanel = (board: BoardConfig, leaf: LayoutLeafNode): React.JSX.Element => {
|
||||
const list = board.lists.find((item) => item.id === leaf.listId)
|
||||
if (!list) return <Empty description={t("common.noData")} />
|
||||
const isSelected = selectedLeafNodeId === leaf.id
|
||||
|
||||
return (
|
||||
<Card
|
||||
style={{ height: "100%", backgroundColor: "var(--ss-card-bg)", border: "1px solid var(--ss-border-color)" }}
|
||||
onClick={() => setSelectedLeafNodeId(leaf.id)}
|
||||
style={{
|
||||
height: "100%",
|
||||
backgroundColor: "var(--ss-card-bg)",
|
||||
border: isSelected ? "1px solid var(--ant-color-primary, #1677ff)" : "1px solid var(--ss-border-color)",
|
||||
boxShadow: isSelected ? "0 8px 18px rgba(22, 119, 255, 0.14)" : undefined,
|
||||
cursor: "pointer",
|
||||
}}
|
||||
styles={{ body: { height: "100%", display: "flex", flexDirection: "column", padding: 12 } }}
|
||||
title={<span style={{ fontWeight: 600 }}>{list.name}</span>}
|
||||
extra={
|
||||
@@ -888,12 +930,6 @@ ORDER BY reward_points DESC, score DESC`,
|
||||
<Button size="small" onClick={() => setEditingListId(list.id)} icon={<EditOutlined />}>
|
||||
{t("board.editList")}
|
||||
</Button>
|
||||
<Button size="small" disabled={!canManage} onClick={() => addListBySplit(board.id, leaf.id, "horizontal")}>
|
||||
{t("board.splitHorizontal")}
|
||||
</Button>
|
||||
<Button size="small" disabled={!canManage} onClick={() => addListBySplit(board.id, leaf.id, "vertical")}>
|
||||
{t("board.splitVertical")}
|
||||
</Button>
|
||||
<Popconfirm
|
||||
title={t("board.removeListConfirm")}
|
||||
onConfirm={() => removeList(board.id, list.id)}
|
||||
@@ -996,6 +1032,23 @@ ORDER BY reward_points DESC, score DESC`,
|
||||
<Tag color={canManage ? "success" : "default"}>{canManage ? t("board.editable") : t("board.readonly")}</Tag>
|
||||
</Space>
|
||||
<Space>
|
||||
<Button
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => splitSelectedLeaf("horizontal")}
|
||||
disabled={!canManage || !activeBoard || !selectedLeafNodeId}
|
||||
>
|
||||
{t("board.splitHorizontal")}
|
||||
</Button>
|
||||
<Button
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => splitSelectedLeaf("vertical")}
|
||||
disabled={!canManage || !activeBoard || !selectedLeafNodeId}
|
||||
>
|
||||
{t("board.splitVertical")}
|
||||
</Button>
|
||||
<Button icon={<EditOutlined />} onClick={openRenameModal} disabled={!canManage || !activeBoard}>
|
||||
{t("board.renameBoard")}
|
||||
</Button>
|
||||
<Button icon={<ReloadOutlined />} loading={loading} onClick={fetchBoards}>
|
||||
{t("common.refresh")}
|
||||
</Button>
|
||||
@@ -1016,34 +1069,17 @@ ORDER BY reward_points DESC, score DESC`,
|
||||
|
||||
{activeBoard ? (
|
||||
<Space direction="vertical" size={16} style={{ width: "100%" }}>
|
||||
<Card
|
||||
title={t("board.boardConfig")}
|
||||
extra={
|
||||
<Space>
|
||||
<Button onClick={() => runAllInBoard(activeBoard)} icon={<PlayCircleOutlined />}>
|
||||
{t("board.runAll")}
|
||||
</Button>
|
||||
<Popconfirm title={t("board.removeBoardConfirm")} onConfirm={() => removeBoard(activeBoard.id)} disabled={!canManage}>
|
||||
<Button danger icon={<DeleteOutlined />} disabled={!canManage}>
|
||||
{t("board.removeBoard")}
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
}
|
||||
style={{ backgroundColor: "var(--ss-card-bg)" }}
|
||||
>
|
||||
<Input
|
||||
value={activeBoard.name}
|
||||
onChange={(e) => updateBoardName(activeBoard.id, e.target.value.trim())}
|
||||
placeholder={t("board.boardNamePlaceholder")}
|
||||
disabled={!canManage}
|
||||
/>
|
||||
{saving && (
|
||||
<Typography.Text type="secondary" style={{ display: "block", marginTop: 8 }}>
|
||||
{t("board.saving")}
|
||||
</Typography.Text>
|
||||
)}
|
||||
</Card>
|
||||
<Space>
|
||||
<Button onClick={() => runAllInBoard(activeBoard)} icon={<PlayCircleOutlined />}>
|
||||
{t("board.runAll")}
|
||||
</Button>
|
||||
<Popconfirm title={t("board.removeBoardConfirm")} onConfirm={() => removeBoard(activeBoard.id)} disabled={!canManage}>
|
||||
<Button danger icon={<DeleteOutlined />} disabled={!canManage}>
|
||||
{t("board.removeBoard")}
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
{saving && <Typography.Text type="secondary">{t("board.saving")}</Typography.Text>}
|
||||
</Space>
|
||||
|
||||
{renderBoardWorkspace()}
|
||||
</Space>
|
||||
@@ -1054,6 +1090,17 @@ ORDER BY reward_points DESC, score DESC`,
|
||||
)}
|
||||
</Space>
|
||||
|
||||
<Modal
|
||||
title={t("board.renameBoard")}
|
||||
open={renameVisible}
|
||||
onCancel={() => setRenameVisible(false)}
|
||||
onOk={submitRenameBoard}
|
||||
okText={t("common.confirm")}
|
||||
cancelText={t("common.cancel")}
|
||||
>
|
||||
<Input value={renameValue} onChange={(e) => setRenameValue(e.target.value)} placeholder={t("board.boardNamePlaceholder")} />
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
title={t("board.sqlEditorTitle")}
|
||||
open={Boolean(editingList)}
|
||||
|
||||
@@ -568,6 +568,7 @@
|
||||
"removeBoardConfirm": "Delete current board?",
|
||||
"boardConfig": "Board Config",
|
||||
"boardNamePlaceholder": "Enter board name",
|
||||
"renameBoard": "Rename Board",
|
||||
"newBoard": "New Board",
|
||||
"untitledBoard": "Untitled Board",
|
||||
"addList": "Add Student List",
|
||||
|
||||
@@ -568,6 +568,7 @@
|
||||
"removeBoardConfirm": "确认删除当前看板?",
|
||||
"boardConfig": "看板配置",
|
||||
"boardNamePlaceholder": "输入看板名称",
|
||||
"renameBoard": "重命名看板",
|
||||
"newBoard": "新看板",
|
||||
"untitledBoard": "未命名看板",
|
||||
"addList": "新增学生列表",
|
||||
|
||||
Reference in New Issue
Block a user