|
@@ -0,0 +1,323 @@
|
|
|
+import {
|
|
|
+ getTopicDetailAPI,
|
|
|
+ topicGetBindingAPI,
|
|
|
+ topicGoodsSearchAPI,
|
|
|
+ topicSaveAPI,
|
|
|
+} from "@/store/action/B5Topic";
|
|
|
+import {
|
|
|
+ Button,
|
|
|
+ Form,
|
|
|
+ Input,
|
|
|
+ Popconfirm,
|
|
|
+ Radio,
|
|
|
+ Select,
|
|
|
+ SelectProps,
|
|
|
+} from "antd";
|
|
|
+import { CloseCircleOutlined } from "@ant-design/icons";
|
|
|
+import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
|
+import TextArea from "antd/es/input/TextArea";
|
|
|
+import styles from "./index.module.scss";
|
|
|
+import { TopicAddType } from "@/types";
|
|
|
+import { MessageFu } from "@/utils/message";
|
|
|
+import encodeStr from "@/utils/pass";
|
|
|
+import { Base64 } from "js-base64";
|
|
|
+import { topicItoAObj } from "@/utils/changeData";
|
|
|
+
|
|
|
+type Props = {
|
|
|
+ id: number;
|
|
|
+ closeMoalFu: () => void;
|
|
|
+ addTableFu: () => void;
|
|
|
+ editTableFu: () => void;
|
|
|
+};
|
|
|
+
|
|
|
+function TopicAdd({ id, closeMoalFu, addTableFu, editTableFu }: Props) {
|
|
|
+ // 把下拉列表的id存起来,用来对比
|
|
|
+ const [editGoodsId, setEditGoodsId] = useState(0);
|
|
|
+
|
|
|
+ // 通过id获取详情
|
|
|
+ const getTopicDetailFu = useCallback(async (id: number) => {
|
|
|
+ const res = await getTopicDetailAPI(id);
|
|
|
+ const arrTit = JSON.parse(res.data.answer);
|
|
|
+ // 把下拉列表的id存起来,用来对比
|
|
|
+ setEditGoodsId(res.data.goodsId);
|
|
|
+
|
|
|
+ const arrTemp: any = [];
|
|
|
+
|
|
|
+ const obj = {
|
|
|
+ ...res.data,
|
|
|
+ correct: arrTit.correct,
|
|
|
+ };
|
|
|
+
|
|
|
+ arrTit.answer.forEach((v: any, i: number) => {
|
|
|
+ arrTemp.push({ label: topicItoAObj[i], value: v.val });
|
|
|
+ obj[v.val] = v.name;
|
|
|
+ });
|
|
|
+
|
|
|
+ FormBoxRef.current.setFieldsValue(obj);
|
|
|
+
|
|
|
+ setAnswerArr(arrTemp);
|
|
|
+
|
|
|
+ // 回显文物下拉列表
|
|
|
+ const res2 = await topicGoodsSearchAPI(res.data.goodsName);
|
|
|
+ setData(res2.data);
|
|
|
+ }, []);
|
|
|
+
|
|
|
+ // 答案的数组
|
|
|
+ const [answerArr, setAnswerArr] = useState([
|
|
|
+ { label: "A", value: encodeStr(Base64.encode("A")) },
|
|
|
+ { label: "B", value: encodeStr(Base64.encode("B")) },
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 点击新增选项
|
|
|
+ const addAnswerFu = useCallback(
|
|
|
+ (i: number) => {
|
|
|
+ const label = topicItoAObj[i];
|
|
|
+ const newData = [
|
|
|
+ ...answerArr,
|
|
|
+ { label, value: encodeStr(Base64.encode(label)) },
|
|
|
+ ];
|
|
|
+ setAnswerArr(newData);
|
|
|
+ },
|
|
|
+ [answerArr]
|
|
|
+ );
|
|
|
+
|
|
|
+ // 删除选项
|
|
|
+ const delImgListFu = useCallback(
|
|
|
+ (label: string, ind: number) => {
|
|
|
+ const arr = answerArr.map((v, i) => {
|
|
|
+ return {
|
|
|
+ label: i > ind ? answerArr[i - 1].label : v.label,
|
|
|
+ value: v.value,
|
|
|
+ };
|
|
|
+ });
|
|
|
+ const newData = arr.filter((v, i) => i !== ind);
|
|
|
+ setAnswerArr(newData);
|
|
|
+ },
|
|
|
+ [answerArr]
|
|
|
+ );
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (id > 0) getTopicDetailFu(id);
|
|
|
+ }, [getTopicDetailFu, id]);
|
|
|
+
|
|
|
+ // 表单的ref
|
|
|
+ const FormBoxRef = useRef<any>({});
|
|
|
+ // 没有通过校验
|
|
|
+ const onFinishFailed = useCallback(() => {}, []);
|
|
|
+ // 通过校验点击确定
|
|
|
+ const onFinish = useCallback(
|
|
|
+ async (value: any) => {
|
|
|
+ const arrTemp = [];
|
|
|
+
|
|
|
+ // 过滤掉除了答案的其他字段
|
|
|
+ const arrFilter = ["question", "goodsId", "correct", "description"];
|
|
|
+
|
|
|
+ for (const k in value) {
|
|
|
+ if (!arrFilter.includes(k)) {
|
|
|
+ arrTemp.push({ val: k, name: value[k] });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const answer = {
|
|
|
+ answer: arrTemp,
|
|
|
+ correct: value.correct,
|
|
|
+ };
|
|
|
+
|
|
|
+ const obj: TopicAddType = {
|
|
|
+ answer: JSON.stringify(answer),
|
|
|
+ description: value.description ? value.description : "",
|
|
|
+ goodsId: value.goodsId,
|
|
|
+ id: id > 0 ? id : null,
|
|
|
+ question: value.question,
|
|
|
+ };
|
|
|
+
|
|
|
+ const res = await topicSaveAPI(obj);
|
|
|
+ if (res.code === 0) {
|
|
|
+ MessageFu.success(id > 0 ? "编辑成功!" : "新增成功!");
|
|
|
+ if (id < 0) addTableFu();
|
|
|
+ else editTableFu();
|
|
|
+ closeMoalFu();
|
|
|
+ }
|
|
|
+
|
|
|
+ // console.log("通过校验,点击确定", value);
|
|
|
+ },
|
|
|
+ [addTableFu, closeMoalFu, editTableFu, id]
|
|
|
+ );
|
|
|
+
|
|
|
+ // 关于文物名称的下拉搜索
|
|
|
+ const [value, setValue] = useState(0);
|
|
|
+ const [data, setData] = useState<SelectProps["options"]>([]);
|
|
|
+
|
|
|
+ const timeRef = useRef(0);
|
|
|
+
|
|
|
+ const handleSearch = useCallback((newValue: string) => {
|
|
|
+ if (newValue) {
|
|
|
+ clearTimeout(timeRef.current);
|
|
|
+ timeRef.current = window.setTimeout(async () => {
|
|
|
+ const res = await topicGoodsSearchAPI(newValue);
|
|
|
+ setData(res.data);
|
|
|
+ }, 500);
|
|
|
+ } else setData([]);
|
|
|
+ }, []);
|
|
|
+
|
|
|
+ const handleChange = useCallback(async (newValue: number) => {
|
|
|
+ setValue(newValue);
|
|
|
+ }, []);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className={styles.TopicAdd}>
|
|
|
+ <div className="main">
|
|
|
+ {/* 新增答案选项按钮 */}
|
|
|
+ <div className="addAnswer">
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ disabled={answerArr.length >= 5}
|
|
|
+ onClick={() => addAnswerFu(answerArr.length)}
|
|
|
+ >
|
|
|
+ 新增选项
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <Form
|
|
|
+ ref={FormBoxRef}
|
|
|
+ name="basic"
|
|
|
+ labelCol={{ span: 3 }}
|
|
|
+ onFinish={onFinish}
|
|
|
+ onFinishFailed={onFinishFailed}
|
|
|
+ autoComplete="off"
|
|
|
+ >
|
|
|
+ <Form.Item
|
|
|
+ label="题目"
|
|
|
+ name="question"
|
|
|
+ rules={[{ required: true, message: "请输入题目!" }]}
|
|
|
+ getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
|
|
|
+ >
|
|
|
+ <Input maxLength={100} showCount placeholder="请输入内容" />
|
|
|
+ </Form.Item>
|
|
|
+
|
|
|
+ <Form.Item
|
|
|
+ label="文物"
|
|
|
+ name="goodsId"
|
|
|
+ rules={[
|
|
|
+ { required: true, message: "请选择文物名称!" },
|
|
|
+ {
|
|
|
+ validator: async (rule, value) => {
|
|
|
+ if (value) {
|
|
|
+ const res = await topicGetBindingAPI(value);
|
|
|
+ if (res.data >= 3 && editGoodsId !== value)
|
|
|
+ return Promise.reject("每个文物最多关联三个问题!");
|
|
|
+ else return Promise.resolve();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ <Select
|
|
|
+ showSearch
|
|
|
+ value={value}
|
|
|
+ placeholder="请搜索文物名称"
|
|
|
+ style={{ width: 695.63 }}
|
|
|
+ defaultActiveFirstOption={false}
|
|
|
+ showArrow={false}
|
|
|
+ filterOption={false}
|
|
|
+ onSearch={handleSearch}
|
|
|
+ onChange={handleChange}
|
|
|
+ notFoundContent={null}
|
|
|
+ options={(data || []).map((d) => ({
|
|
|
+ value: d.id,
|
|
|
+ label: d.name,
|
|
|
+ }))}
|
|
|
+ />
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item
|
|
|
+ label="正确答案"
|
|
|
+ name="correct"
|
|
|
+ rules={[
|
|
|
+ { required: true, message: "请选择正确答案!" },
|
|
|
+ {
|
|
|
+ validator: async (rule, value) => {
|
|
|
+ if (value && answerArr.every((v) => v.value !== value)) {
|
|
|
+ return Promise.reject("请选择正确答案!");
|
|
|
+ } else return Promise.resolve();
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ <Radio.Group>
|
|
|
+ {answerArr.map((v) => (
|
|
|
+ <Radio key={v.label} value={v.value}>
|
|
|
+ {v.label}
|
|
|
+ </Radio>
|
|
|
+ ))}
|
|
|
+ </Radio.Group>
|
|
|
+ </Form.Item>
|
|
|
+
|
|
|
+ {answerArr.map((v, i) => (
|
|
|
+ <Form.Item
|
|
|
+ key={v.label}
|
|
|
+ label={v.label}
|
|
|
+ name={v.value}
|
|
|
+ rules={[{ required: true, message: "请输入答案!" }]}
|
|
|
+ getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
|
|
|
+ >
|
|
|
+ <Input maxLength={100} showCount placeholder="请输入内容" />
|
|
|
+ </Form.Item>
|
|
|
+ ))}
|
|
|
+
|
|
|
+ {/* 删除按钮X */}
|
|
|
+ <div className="btnXBox">
|
|
|
+ {answerArr.map((v, i) =>
|
|
|
+ i > 1 ? (
|
|
|
+ <div className="btnX" key={v.label}>
|
|
|
+ <Popconfirm
|
|
|
+ title="删除后无法恢复,是否删除?"
|
|
|
+ okText="删除"
|
|
|
+ cancelText="取消"
|
|
|
+ onConfirm={() => delImgListFu(v.label, i)}
|
|
|
+ >
|
|
|
+ <div className="clearCover">
|
|
|
+ <CloseCircleOutlined />
|
|
|
+ </div>
|
|
|
+ </Popconfirm>
|
|
|
+ </div>
|
|
|
+ ) : null
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <Form.Item
|
|
|
+ label="解释"
|
|
|
+ name="description"
|
|
|
+ getValueFromEvent={(e) => e.target.value.trim()}
|
|
|
+ >
|
|
|
+ <TextArea
|
|
|
+ rows={4}
|
|
|
+ placeholder="请输入内容"
|
|
|
+ showCount
|
|
|
+ maxLength={200}
|
|
|
+ />
|
|
|
+ </Form.Item>
|
|
|
+ {/* 确定和取消按钮 */}
|
|
|
+ <br />
|
|
|
+ <Form.Item wrapperCol={{ offset: 10, span: 20 }}>
|
|
|
+ <Button type="primary" htmlType="submit">
|
|
|
+ 提交
|
|
|
+ </Button>
|
|
|
+    
|
|
|
+ <Popconfirm
|
|
|
+ title="放弃编辑后,信息将不会保存!"
|
|
|
+ okText="放弃"
|
|
|
+ cancelText="取消"
|
|
|
+ onConfirm={closeMoalFu}
|
|
|
+ >
|
|
|
+ <Button>取消</Button>
|
|
|
+ </Popconfirm>
|
|
|
+ </Form.Item>
|
|
|
+ </Form>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+const MemoTopicAdd = React.memo(TopicAdd);
|
|
|
+
|
|
|
+export default MemoTopicAdd;
|