add
This commit is contained in:
parent
2769bac7f8
commit
e93fbbcb53
|
@ -1,6 +1,5 @@
|
||||||
import MindEditor from "@web/src/components/common/editor/MindEditor";
|
import MindEditor from "@web/src/components/common/editor/MindEditor";
|
||||||
// import MindElixir, { MindElixirInstance } from "mind-elixir";
|
|
||||||
import { useEffect, useRef } from "react";
|
|
||||||
export default function PathsPage() {
|
export default function PathsPage() {
|
||||||
return <MindEditor></MindEditor>
|
return <MindEditor></MindEditor>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,24 +3,24 @@ import { useRef, useEffect } from "react";
|
||||||
import MindElixir from "mind-elixir";
|
import MindElixir from "mind-elixir";
|
||||||
|
|
||||||
export default function MindEditor() {
|
export default function MindEditor() {
|
||||||
const me = useRef<MindElixirInstance>();
|
const me = useRef<MindElixirInstance>();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const instance = new MindElixir({
|
const instance = new MindElixir({
|
||||||
el: "#map",
|
el: "#map",
|
||||||
direction: MindElixir.SIDE,
|
direction: MindElixir.SIDE,
|
||||||
draggable: true, // default true
|
draggable: true, // default true
|
||||||
contextMenu: true, // default true
|
contextMenu: true, // default true
|
||||||
toolBar: true, // default true
|
toolBar: true, // default true
|
||||||
nodeMenu: true, // default true
|
nodeMenu: true, // default true
|
||||||
keypress: true // default true
|
keypress: true, // default true
|
||||||
|
});
|
||||||
});
|
// instance.install(NodeMenu);
|
||||||
// instance.install(NodeMenu);
|
instance.init(MindElixir.new("新主题"));
|
||||||
instance.init(MindElixir.new("新主题"));
|
me.current = instance;
|
||||||
me.current = instance;
|
}, []);
|
||||||
}, []);
|
return (
|
||||||
return <div >
|
<div>
|
||||||
|
<div id="map" style={{ width: "100%" }} />
|
||||||
<div id="map" style={{ width: "100%" }} />
|
</div>
|
||||||
</div>
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,21 +70,6 @@ export function FormArrayField({
|
||||||
{...inputProps}
|
{...inputProps}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
style={{ width: "100%" }}
|
style={{ width: "100%" }}
|
||||||
// suffix={
|
|
||||||
// inputProps.maxLength && (
|
|
||||||
// <Typography.Text type="secondary">
|
|
||||||
// {inputProps.maxLength -
|
|
||||||
// (
|
|
||||||
// Form.useWatch(
|
|
||||||
// [
|
|
||||||
// name,
|
|
||||||
// field.name,
|
|
||||||
// ]
|
|
||||||
// ) || ""
|
|
||||||
// ).length}
|
|
||||||
// </Typography.Text>
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
// 更新 items 状态
|
// 更新 items 状态
|
||||||
const newItems = [...items];
|
const newItems = [...items];
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { Input, Button } from "antd";
|
||||||
|
import { DeleteOutlined } from "@ant-design/icons";
|
||||||
|
|
||||||
|
interface InputListProps {
|
||||||
|
initialValue?: string[];
|
||||||
|
onChange?: (value: string[]) => void;
|
||||||
|
placeholder?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const InputList: React.FC<InputListProps> = ({
|
||||||
|
initialValue,
|
||||||
|
onChange,
|
||||||
|
placeholder = "请输入内容",
|
||||||
|
}) => {
|
||||||
|
// Internal state management with fallback to initial value or empty array
|
||||||
|
const [inputValues, setInputValues] = useState<string[]>(
|
||||||
|
initialValue && initialValue.length > 0 ? initialValue : [""]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Handle individual input value change
|
||||||
|
const handleInputChange = (index: number, newValue: string) => {
|
||||||
|
const newValues = [...inputValues];
|
||||||
|
newValues[index] = newValue;
|
||||||
|
|
||||||
|
// Update internal state
|
||||||
|
setInputValues(newValues);
|
||||||
|
|
||||||
|
// Call external onChange if provided
|
||||||
|
onChange?.(newValues);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle delete operation
|
||||||
|
const handleDelete = (index: number) => {
|
||||||
|
const newValues = inputValues.filter((_, i) => i !== index);
|
||||||
|
|
||||||
|
// Ensure at least one input remains
|
||||||
|
const finalValues = newValues.length === 0 ? [""] : newValues;
|
||||||
|
|
||||||
|
// Update internal state
|
||||||
|
setInputValues(finalValues);
|
||||||
|
|
||||||
|
// Call external onChange if provided
|
||||||
|
onChange?.(finalValues);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add new input field
|
||||||
|
const handleAdd = () => {
|
||||||
|
const newValues = [...inputValues, ""];
|
||||||
|
|
||||||
|
// Update internal state
|
||||||
|
setInputValues(newValues);
|
||||||
|
|
||||||
|
// Call external onChange if provided
|
||||||
|
onChange?.(newValues);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-2">
|
||||||
|
{inputValues.map((item, index) => (
|
||||||
|
<div key={index} className="flex items-center space-x-2 group">
|
||||||
|
<Input
|
||||||
|
value={item}
|
||||||
|
onChange={(e) =>
|
||||||
|
handleInputChange(index, e.target.value)
|
||||||
|
}
|
||||||
|
placeholder={placeholder}
|
||||||
|
className="flex-grow"
|
||||||
|
/>
|
||||||
|
{inputValues.length > 1 && (
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
danger
|
||||||
|
className="opacity-0 group-hover:opacity-100"
|
||||||
|
onClick={() => handleDelete(index)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<div className="flex items-center space-x-2 group">
|
||||||
|
<Button
|
||||||
|
type="dashed"
|
||||||
|
block
|
||||||
|
onClick={handleAdd}
|
||||||
|
className="w-full">
|
||||||
|
添加输入框
|
||||||
|
</Button>
|
||||||
|
{inputValues.length > 1 && (
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
danger
|
||||||
|
className="opacity-0"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default InputList;
|
|
@ -3,6 +3,7 @@ import { CourseLevel, CourseLevelLabel } from "@nice/common";
|
||||||
import { convertToOptions } from "@nice/client";
|
import { convertToOptions } from "@nice/client";
|
||||||
import TermSelect from "../../../term/term-select";
|
import TermSelect from "../../../term/term-select";
|
||||||
import { useCourseEditor } from "../context/CourseEditorContext";
|
import { useCourseEditor } from "../context/CourseEditorContext";
|
||||||
|
import AvatarUploader from "@web/src/components/common/uploader/AvatarUploader";
|
||||||
|
|
||||||
const { TextArea } = Input;
|
const { TextArea } = Input;
|
||||||
|
|
||||||
|
@ -27,14 +28,12 @@ export function CourseBasicForm() {
|
||||||
]}>
|
]}>
|
||||||
<Input placeholder="请输入课程标题" />
|
<Input placeholder="请输入课程标题" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="subTitle"
|
name="subTitle"
|
||||||
label="课程副标题"
|
label="课程副标题"
|
||||||
rules={[{ max: 10, message: "副标题最多10个字符" }]}>
|
rules={[{ max: 10, message: "副标题最多10个字符" }]}>
|
||||||
<Input placeholder="请输入课程副标题" />
|
<Input placeholder="请输入课程副标题" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item name="content" label="课程描述">
|
<Form.Item name="content" label="课程描述">
|
||||||
<TextArea
|
<TextArea
|
||||||
placeholder="请输入课程描述"
|
placeholder="请输入课程描述"
|
||||||
|
@ -58,9 +57,6 @@ export function CourseBasicForm() {
|
||||||
taxonomyId={tax.id}></TermSelect>
|
taxonomyId={tax.id}></TermSelect>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
))}
|
))}
|
||||||
{/* <Form.Item name="level" label="难度等级">
|
|
||||||
<Select placeholder="请选择难度等级" options={levelOptions} />
|
|
||||||
</Form.Item> */}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,7 @@ import {
|
||||||
message,
|
message,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import React, { useCallback, useEffect, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
import {
|
import { useSortable } from "@dnd-kit/sortable";
|
||||||
useSortable,
|
|
||||||
} from "@dnd-kit/sortable";
|
|
||||||
import { CSS } from "@dnd-kit/utilities";
|
import { CSS } from "@dnd-kit/utilities";
|
||||||
import { Lecture, LectureType, PostType } from "@nice/common";
|
import { Lecture, LectureType, PostType } from "@nice/common";
|
||||||
import { usePost } from "@nice/client";
|
import { usePost } from "@nice/client";
|
||||||
|
@ -101,7 +99,7 @@ export const SortableSection: React.FC<SortableSectionProps> = ({
|
||||||
<div ref={setNodeRef} style={style} className="mb-4">
|
<div ref={setNodeRef} style={style} className="mb-4">
|
||||||
<Collapse>
|
<Collapse>
|
||||||
<Collapse.Panel
|
<Collapse.Panel
|
||||||
disabled={!field.id} // 添加此行以禁用未创建章节的展开
|
collapsible={!field.id ? "disabled" : undefined} // 添加此行以禁用未创建章节的展开
|
||||||
header={
|
header={
|
||||||
editing ? (
|
editing ? (
|
||||||
<Form
|
<Form
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
import { FormArrayField } from "@web/src/components/common/form/FormArrayField";
|
import { FormArrayField } from "@web/src/components/common/form/FormArrayField";
|
||||||
import { useFormContext } from "react-hook-form";
|
import { useFormContext } from "react-hook-form";
|
||||||
import { CourseFormData } from "../context/CourseEditorContext";
|
import { CourseFormData } from "../context/CourseEditorContext";
|
||||||
|
import InputList from "@web/src/components/common/input/InputList";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Form } from "antd";
|
||||||
|
|
||||||
export function CourseGoalForm() {
|
export function CourseGoalForm() {
|
||||||
// const { register, formState: { errors }, watch, handleSubmit } = useFormContext<CourseFormData>();
|
// const { register, formState: { errors }, watch, handleSubmit } = useFormContext<CourseFormData>();
|
||||||
|
const [inputValues, setInputValues] = useState<string[]>([""]);
|
||||||
return (
|
return (
|
||||||
<form className="max-w-2xl mx-auto space-y-6 p-6">
|
<div className="max-w-2xl mx-auto space-y-6 p-6">
|
||||||
<FormArrayField
|
<Form.Item name="requirements" label="前置要求">
|
||||||
name="requirements"
|
<InputList placeholder="请输入前置要求"></InputList>
|
||||||
label="前置要求"
|
</Form.Item>
|
||||||
placeholder="添加要求"></FormArrayField>
|
<Form.Item name="objectives" label="学习目标">
|
||||||
<FormArrayField
|
<InputList placeholder="请输入学习目标"></InputList>
|
||||||
name="objectives"
|
</Form.Item>
|
||||||
label="学习目标"
|
</div>
|
||||||
placeholder="添加目标"></FormArrayField>
|
|
||||||
</form>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue