chenlei 7 tháng trước cách đây
mục cha
commit
17ce138431

+ 38 - 0
src/api/assessment.ts

@@ -4,10 +4,17 @@ import {
   IAssIndexDetail,
   IFileTemplateFormParams,
   IFileTemplateFormResponse,
+  IAssTemplateDetail,
 } from "@/types";
 import { requestByGet, requestByPost } from "@dage/service";
 
 /**
+ * ====================
+ * 考核指标 API
+ * ====================
+ */
+
+/**
  * 获取指标设置列表树
  * @param {ASS_INDEX_TYPE} type (ASS_INDEX_TYPE.FIXED)
  */
@@ -37,3 +44,34 @@ export const saveAssIndexApi = (params: any) => {
 export const deleteAssIndexApi = (ids: string | number) => {
   return requestByGet(`/api/cms/norm/removes/${ids}`);
 };
+
+/**
+ * ====================
+ * 考核模板 API
+ * ====================
+ */
+
+/** 获取考核模板列表 */
+export const getAssTemplateListApi = (
+  type: ASS_INDEX_TYPE,
+  searchKey?: string
+) => {
+  return requestByGet<IAssTemplateDetail[]>(
+    `/api/cms/template/getList/${type}`,
+    {
+      searchKey,
+    }
+  );
+};
+
+export const saveAssTemplateApi = (params: any) => {
+  return requestByPost("/api/cms/template/save", params);
+};
+
+export const deleteAssTemplateApi = (ids: string | number) => {
+  return requestByGet(`/api/cms/template/removes/${ids}`);
+};
+
+export const getAssTemplateDetailApi = (id: string | number) => {
+  return requestByGet<IAssTemplateDetail>(`/api/cms/template/detail/${id}`);
+};

+ 1 - 0
src/api/index.ts

@@ -16,3 +16,4 @@ export const updatePwd = (data: UpdatePwdRequest) => {
 export * from "./log";
 export * from "./user";
 export * from "./assessment";
+export * from "./management";

+ 18 - 0
src/api/management.ts

@@ -0,0 +1,18 @@
+import { IManageIndexDetail } from "@/types";
+import { requestByGet, requestByPost } from "@dage/service";
+
+export const getManageIndexListApi = (params: any) => {
+  return requestByPost("/api/cms/assess/pageList", params);
+};
+
+export const saveManageIndexApi = (params: any) => {
+  return requestByPost("/api/cms/assess/save", params);
+};
+
+export const deleteManageIndexApi = (ids: string | number) => {
+  return requestByGet(`/api/cms/assess/removes/${ids}`);
+};
+
+export const getManageIndexDetailApi = (id: string | number) => {
+  return requestByGet<IManageIndexDetail>(`/api/cms/assess/detail/${id}`);
+};

+ 5 - 1
src/components/FileTemplateModal/index.tsx

@@ -160,7 +160,11 @@ export const FileTemplateModal: FC<FileTemplateModalProps> = ({
                   buttonStyle="solid"
                 />
               </Form.Item>
-              <Form.Item label="资料模板" name="file">
+              <Form.Item
+                label="资料模板"
+                name="file"
+                rules={[{ required: true }]}
+              >
                 <DageUpload
                   action="/api/cms/norm/file/upload"
                   dType={DageUploadType.DOC}

+ 30 - 8
src/constants.ts

@@ -1,11 +1,4 @@
-/**
- * 发布状态
- */
-export enum PUBLISH_ENUM {
-  PENDING = 0,
-  PUBLISHED = 1,
-  ENDED = 2,
-}
+import { ASS_INDEX_TYPE, PUBLISH_ENUM } from "./types";
 
 export const PUBLISH_STATUS_MAP = {
   [PUBLISH_ENUM.PENDING]: {
@@ -22,6 +15,21 @@ export const PUBLISH_STATUS_MAP = {
   },
 };
 
+export const PUBLISH_STATUS_OPTIONS = [
+  {
+    label: "待发布",
+    value: 0,
+  },
+  {
+    label: "已发布",
+    value: 1,
+  },
+  {
+    label: "已结束",
+    value: 2,
+  },
+];
+
 /**
  * 考核单状态
  */
@@ -63,3 +71,17 @@ export const DEFAULT_BONUS_ITEM = {
   name: "",
   num: null,
 };
+
+/**
+ * 考核类别
+ */
+export const ASSESSMENT_TYPE_OPTIONS = [
+  {
+    label: "定级评估",
+    value: ASS_INDEX_TYPE.FIXED,
+  },
+  {
+    label: "运行评估",
+    value: ASS_INDEX_TYPE.OPERATION,
+  },
+];

+ 3 - 2
src/pages/Assessment/Index/CreateOrEdit/index.tsx

@@ -137,7 +137,7 @@ const CreateOrEditIndex: FC = () => {
   }, []);
 
   return (
-    <PageContainer title="新增指标">
+    <PageContainer title={isEdit ? "编辑指标" : "新增指标"}>
       <Form
         labelCol={{ span: 4 }}
         form={form}
@@ -163,6 +163,7 @@ const CreateOrEditIndex: FC = () => {
           rules={[{ required: true, message: "请输入指标名称" }]}
         >
           <Input
+            disabled={isEdit}
             className="mw650"
             placeholder="请输入内容,最多20字"
             showCount
@@ -177,7 +178,7 @@ const CreateOrEditIndex: FC = () => {
             maxLength={20}
           />
         </Form.Item>
-        <Form.Item label="指标说明" name="reamrk">
+        <Form.Item label="指标说明" name="remark">
           <TextArea
             className="mw650"
             showCount

+ 2 - 1
src/pages/Assessment/Index/index.tsx

@@ -5,9 +5,10 @@ import { Sidebar } from "./components/Sidebar";
 import { Container } from "./components/Container";
 import style from "./index.module.scss";
 import { ASS_INDEX_TYPE } from "@/types";
+import { useHashQuery } from "@/hooks";
 
 const IndexPage = () => {
-  const [type, setType] = useState(ASS_INDEX_TYPE.FIXED);
+  const [type, setType] = useHashQuery("tab", ASS_INDEX_TYPE.FIXED);
   const [currentId, setCurrentId] = useState<number | null>(null);
 
   return (

+ 59 - 6
src/pages/Assessment/Template/CreateOrEdit/index.tsx

@@ -1,22 +1,66 @@
-import { FC } from "react";
+import { FC, Key, useEffect, useState } from "react";
 import { Form, Input, Tree } from "antd";
-import { useNavigate } from "react-router-dom";
+import { useNavigate, useParams } from "react-router-dom";
 import { FormPageFooter, PageContainer } from "@/components";
+import {
+  getAssIndexTreeApi,
+  getAssTemplateDetailApi,
+  saveAssTemplateApi,
+} from "@/api";
+import { AssIndexTreeItemType, IAssTemplateDetail } from "@/types";
+import { isString } from "lodash";
+import { DageLoading } from "@dage/pc-components";
 
 const { TextArea } = Input;
 
 const CreateOrEditTemplate: FC = () => {
   const navigate = useNavigate();
+  const params = useParams();
   const [form] = Form.useForm();
+  const [loading, setLoading] = useState(false);
+  const [list, setList] = useState<AssIndexTreeItemType[]>([]);
+  const [checkedKeys, setCheckedKeys] = useState<Key[]>([]);
+  const [detail, setDetail] = useState<null | IAssTemplateDetail>(null);
+  const isEdit = isString(params.id);
 
   const handleSubmit = async () => {
     if (!(await form.validateFields())) return;
 
-    console.log(form.getFieldsValue());
+    await saveAssTemplateApi({
+      ...form.getFieldsValue(),
+      normIds: checkedKeys.join(","),
+      type: params.type,
+      id: detail?.id,
+    });
+    navigate(-1);
   };
 
+  const getAssIndexTree = async () => {
+    const data = await getAssIndexTreeApi();
+    setList(data);
+  };
+
+  const getDetail = async () => {
+    const data = await getAssTemplateDetailApi(params.id!);
+    form.setFieldsValue({
+      name: data.name,
+      remark: data.remark,
+    });
+    setCheckedKeys(data.normIds.split(",").map((i) => Number(i)));
+    setDetail(data);
+  };
+
+  useEffect(() => {
+    setLoading(true);
+    Promise.all(
+      isEdit ? [getDetail(), getAssIndexTree()] : [getAssIndexTree()]
+    ).finally(() => {
+      setLoading(false);
+    });
+  }, []);
+
   return (
-    <PageContainer title="新增模板">
+    <PageContainer title={isEdit ? "编辑模板" : "新增模板"}>
       <Form labelCol={{ span: 4 }} form={form} onFinish={handleSubmit}>
         <Form.Item
           label="模板名称"
@@ -31,7 +75,7 @@ const CreateOrEditTemplate: FC = () => {
             maxLength={20}
           />
         </Form.Item>
-        <Form.Item label="模板说明">
+        <Form.Item label="模板说明" name="remark">
           <TextArea
             className="mw650"
             showCount
@@ -41,11 +85,20 @@ const CreateOrEditTemplate: FC = () => {
           />
         </Form.Item>
         <Form.Item label="采用指标">
-          <Tree checkable />
+          <Tree
+            checkable
+            checkedKeys={checkedKeys}
+            defaultExpandAll
+            treeData={list}
+            fieldNames={{ title: "name", key: "id" }}
+            onCheck={(keys) => setCheckedKeys(keys as Key[])}
+          />
         </Form.Item>
 
         <FormPageFooter onSubmit={handleSubmit} onCancel={() => navigate(-1)} />
       </Form>
+
+      {loading && <DageLoading />}
     </PageContainer>
   );
 };

+ 0 - 10
src/pages/Assessment/Template/constants.ts

@@ -1,10 +0,0 @@
-export enum TEMPLATE_TABS {
-  /**
-   * 定级评估模板
-   */
-  GRADING = 1,
-  /**
-   * 运行评估模板
-   */
-  RUNNING = 2,
-}

+ 96 - 29
src/pages/Assessment/Template/index.tsx

@@ -1,22 +1,65 @@
-import { useMemo, useState } from "react";
+import { useCallback, useEffect, useMemo, useState } from "react";
 import { Button, Input, Table } from "antd";
 import { PlusOutlined } from "@ant-design/icons";
 import { useNavigate } from "react-router-dom";
 import { PageContainer } from "@/components";
 import style from "./index.module.scss";
-import { TEMPLATE_TABS } from "./constants";
+import { deleteAssTemplateApi, getAssTemplateListApi } from "@/api";
+import { ASS_INDEX_TYPE, IAssTemplateDetail } from "@/types";
+import { DageTableActions } from "@dage/pc-components";
+import { useHashQuery } from "@/hooks";
+import { debounce } from "lodash";
 
 const { Search } = Input;
 
 const TemplatePage = () => {
   const navigate = useNavigate();
-  const [tab, setTab] = useState(TEMPLATE_TABS.GRADING);
-  const isGrading = useMemo(() => tab === TEMPLATE_TABS.GRADING, [tab]);
+  const [tab, setTab] = useHashQuery("tab", ASS_INDEX_TYPE.FIXED);
+  const [fixedLoading, setFixedLoading] = useState(false);
+  const [operationLoading, setOperationLoading] = useState(false);
+  const [fixedList, setFixedList] = useState<IAssTemplateDetail[]>([]);
+  const [operationList, setOperationList] = useState<IAssTemplateDetail[]>([]);
+  const [searchKey, setSearchKey] = useState("");
+  const isFixed = useMemo(() => tab === ASS_INDEX_TYPE.FIXED, [tab]);
 
-  const handleTab = (type: TEMPLATE_TABS) => {
+  const getList = async (type: ASS_INDEX_TYPE, keyword = searchKey) => {
+    const _isFixed = type === ASS_INDEX_TYPE.FIXED;
+    try {
+      _isFixed ? setFixedLoading(true) : setOperationLoading(true);
+      const data = await getAssTemplateListApi(type, keyword);
+      _isFixed ? setFixedList(data) : setOperationList(data);
+    } finally {
+      _isFixed ? setFixedLoading(false) : setOperationLoading(false);
+    }
+  };
+
+  const handleTab = (type: ASS_INDEX_TYPE) => {
     setTab(type);
+    getList(type);
+  };
+
+  const handleEdit = (item: IAssTemplateDetail) => {
+    navigate(`/assessment/template/edit/${tab}/${item.id}`);
+  };
+
+  const handleDelete = async (item: IAssTemplateDetail) => {
+    await deleteAssTemplateApi(item.id);
+    getList(tab);
   };
 
+  const handleSearch = useMemo(
+    () =>
+      debounce((keyword: string) => {
+        getList(tab, keyword);
+      }, 500),
+    [tab]
+  );
+
+  useEffect(() => {
+    getList(ASS_INDEX_TYPE.FIXED);
+    getList(ASS_INDEX_TYPE.OPERATION);
+  }, []);
+
   return (
     <PageContainer
       title="考核模板"
@@ -25,64 +68,88 @@ const TemplatePage = () => {
           <div>
             <Button
               type="primary"
-              ghost={!isGrading}
+              ghost={!isFixed}
               size="large"
-              onClick={handleTab.bind(undefined, TEMPLATE_TABS.GRADING)}
+              onClick={handleTab.bind(undefined, ASS_INDEX_TYPE.FIXED)}
             >
-              定级评估模板 11
+              定级评估模板 {fixedLoading ? "-" : fixedList.length}
             </Button>
             <Button
               type="primary"
-              ghost={isGrading}
+              ghost={isFixed}
               size="large"
-              onClick={handleTab.bind(undefined, TEMPLATE_TABS.RUNNING)}
+              onClick={handleTab.bind(undefined, ASS_INDEX_TYPE.OPERATION)}
             >
-              运行评估模板 0
+              运行评估模板 {operationLoading ? "-" : operationList.length}
             </Button>
           </div>
 
           <div className={style.pageToolsRight}>
-            {isGrading ? (
-              <>
-                <label>搜索</label>
-                <Search
-                  size="large"
-                  placeholder="请输入模板名称"
-                  allowClear
-                  style={{ width: 170 }}
-                />
-              </>
-            ) : (
-              ""
-            )}
+            <label>搜索</label>
+            <Search
+              value={searchKey}
+              size="large"
+              placeholder="请输入模板名称"
+              allowClear
+              style={{ width: 170 }}
+              onChange={(e) => {
+                setSearchKey(e.target.value);
+                handleSearch(e.target.value);
+              }}
+              onSearch={() => getList(tab)}
+            />
 
             <Button
               type="primary"
               icon={<PlusOutlined />}
               size="large"
               className={style.secondButton}
-              onClick={() => navigate("/assessment/template/create")}
+              onClick={() => navigate(`/assessment/template/create/${tab}`)}
             >
-              新增定级评估模板
+              新增{isFixed ? "定级" : "运行"}评估模板
             </Button>
           </div>
         </div>
       }
     >
       <Table
+        rowKey="id"
+        loading={isFixed ? fixedLoading : operationLoading}
         className="cus-table large"
+        dataSource={isFixed ? fixedList : operationList}
         columns={[
           {
             title: "名称",
             dataIndex: "name",
-            key: "name",
             align: "center",
           },
           {
             title: "说明",
-            dataIndex: "description",
-            key: "description",
+            dataIndex: "remark",
             align: "center",
+            ellipsis: true,
+          },
+          {
+            title: "编辑时间",
+            dataIndex: "updateTime",
+            align: "center",
+          },
+          {
+            title: "编辑人",
+            dataIndex: "creatorName",
+            align: "center",
+          },
+          {
+            title: "操作",
+            align: "center",
+            render: (item: IAssTemplateDetail) => {
+              return (
+                <DageTableActions
+                  onEdit={handleEdit.bind(undefined, item)}
+                  onDelete={handleDelete.bind(undefined, item)}
+                />
+              );
+            },
           },
         ]}
       />

+ 2 - 1
src/pages/Management/Evaluation/index.tsx

@@ -3,8 +3,9 @@ import { useState } from "react";
 import { Button, Form, Input, Select, Table } from "antd";
 import { useNavigate } from "react-router-dom";
 import { PageContainer } from "@/components";
-import { PUBLISH_STATUS_MAP, PUBLISH_ENUM } from "../../../constants";
+import { PUBLISH_STATUS_MAP } from "../../../constants";
 import style from "../Form/index.module.scss";
+import { PUBLISH_ENUM } from "@/types";
 
 const ManagementEvaluationPage = () => {
   const navigate = useNavigate();

+ 1 - 1
src/pages/Management/Files/index.tsx

@@ -3,7 +3,7 @@ import { useState } from "react";
 import { Button, Form, Input, Select, Table } from "antd";
 import { PageContainer } from "@/components";
 import style from "./index.module.scss";
-import { PUBLISH_ENUM } from "../../../constants";
+import { PUBLISH_ENUM } from "@/types";
 
 const ManagementReportPage = () => {
   const [list] = useState([

+ 2 - 1
src/pages/Management/Form/index.tsx

@@ -4,7 +4,8 @@ import { Button, Form, Input, Select, Table } from "antd";
 import { useNavigate } from "react-router-dom";
 import { PageContainer } from "@/components";
 import style from "./index.module.scss";
-import { PUBLISH_STATUS_MAP, PUBLISH_ENUM } from "../../../constants";
+import { PUBLISH_STATUS_MAP } from "../../../constants";
+import { PUBLISH_ENUM } from "@/types";
 
 const ManagementReportPage = () => {
   const navigate = useNavigate();

+ 10 - 0
src/pages/Management/Index/CreateOrEdit/index.module.scss

@@ -19,3 +19,13 @@
   line-height: 32px;
   color: rgba(36, 36, 36, 0.4);
 }
+
+:global {
+  .ant-pro-table {
+    .ant-form-item-has-error {
+      input::placeholder {
+        color: #ff4d4f !important;
+      }
+    }
+  }
+}

+ 80 - 11
src/pages/Management/Index/CreateOrEdit/index.tsx

@@ -1,26 +1,68 @@
-import { FC, useRef } from "react";
+import { FC, Key, useEffect, useRef, useState } from "react";
 import { DatePicker, Form, Input, InputNumber } from "antd";
 import {
   EditableFormInstance,
   EditableProTable,
 } from "@ant-design/pro-components";
-import { useNavigate } from "react-router-dom";
-import { uniqueId } from "lodash";
+import { useNavigate, useParams } from "react-router-dom";
+import { isString, uniqueId } from "lodash";
 import { FileTemplateTable, FormPageFooter, PageContainer } from "@/components";
 import { DEFAULT_BONUS_ITEM } from "../../../../constants";
 import { TableBonusType } from "../../types";
 import style from "./index.module.scss";
+import { dayjs, formatDate } from "@dage/utils";
+import { getManageIndexDetailApi, saveManageIndexApi } from "@/api";
+import { DageLoading } from "@dage/pc-components";
+import { IManageIndexDetail } from "@/types";
 
 const { TextArea } = Input;
 const { RangePicker } = DatePicker;
 
 const CreateOrEditManagementIndex: FC = () => {
   const navigate = useNavigate();
+  const params = useParams();
+  const isEdit = isString(params.id);
+  const [loading, setLoading] = useState(false);
+  const [detail, setDetail] = useState<IManageIndexDetail | null>(null);
   const [form] = Form.useForm();
   /** 加分项列表 */
   const bonusRef = useRef<EditableFormInstance<TableBonusType>>();
+  const [bounsEditableKeys, setBounsEditableKeys] = useState<Key[]>([]);
   // 减分项列表
   const deductionRef = useRef<EditableFormInstance<TableBonusType>>();
+  const [deductionEditableKeys, setDeductionEditableKeys] = useState<Key[]>([]);
+
+  const getDetail = async () => {
+    try {
+      setLoading(true);
+      const data = await getManageIndexDetailApi(params.id!);
+      form.setFieldsValue({
+        name: data.name,
+        date: [dayjs(data.dateStart), dayjs(data.dateEnd)],
+        remark: data.remark,
+        materialIds: data.materials,
+        bonus: data.jsonAdd ? JSON.parse(data.jsonAdd) : undefined,
+        deduction: data.jsonSub ? JSON.parse(data.jsonSub) : undefined,
+      });
+      if (data.jsonAdd) {
+        setBounsEditableKeys(
+          JSON.parse(data.jsonAdd).map(
+            (i: IManageIndexDetail["materials"][number]) => i.id
+          )
+        );
+      }
+      if (data.jsonSub) {
+        setDeductionEditableKeys(
+          JSON.parse(data.jsonSub).map(
+            (i: IManageIndexDetail["materials"][number]) => i.id
+          )
+        );
+      }
+      setDetail(data);
+    } finally {
+      setLoading(false);
+    }
+  };
 
   const handleSubmit = async () => {
     if (
@@ -30,13 +72,31 @@ const CreateOrEditManagementIndex: FC = () => {
     )
       return;
 
-    console.log(form.getFieldsValue());
+    const { date, materialIds, bonus, deduction, ...rest } =
+      form.getFieldsValue();
+    if (materialIds)
+      rest.materialIds = materialIds.map((i: any) => i.id).join(",");
+    if (bonus) rest.jsonAdd = JSON.stringify(bonus);
+    if (deduction) rest.jsonSub = JSON.stringify(deduction);
+
+    await saveManageIndexApi({
+      ...rest,
+      dateStart: formatDate(date[0], "YYYY-MM-DD"),
+      dateEnd: formatDate(date[1], "YYYY-MM-DD"),
+      type: params.type,
+      id: detail?.id,
+    });
+    navigate(-1);
   };
 
+  useEffect(() => {
+    isEdit && getDetail();
+  }, []);
+
   return (
-    <PageContainer title="新增考核">
+    <PageContainer title={isEdit ? "编辑考核" : "新增考核"}>
       <Form labelCol={{ span: 4 }} form={form} onFinish={handleSubmit}>
-        <Form.Item label="考核名称" required>
+        <Form.Item label="考核名称" name="name" rules={[{ required: true }]}>
           <Input
             className="mw650"
             placeholder="请输入内容,最多20字"
@@ -44,10 +104,10 @@ const CreateOrEditManagementIndex: FC = () => {
             maxLength={20}
           />
         </Form.Item>
-        <Form.Item label="考核周期" required>
-          <RangePicker />
+        <Form.Item label="考核周期" required name="date">
+          <RangePicker format="YYYY-MM-DD" />
         </Form.Item>
-        <Form.Item label="说明">
+        <Form.Item label="说明" name="remark">
           <TextArea
             className="mw650"
             showCount
@@ -57,8 +117,11 @@ const CreateOrEditManagementIndex: FC = () => {
           />
         </Form.Item>
 
-        <Form.Item label="需上传资料" name="file">
-          {/* <FileTemplateTable tips="注:该资料用于此次整体考核,与具体指标无关" /> */}
+        <Form.Item label="需上传资料" name="materialIds">
+          <FileTemplateTable
+            module="assess"
+            tips="注:该资料用于此次整体考核,与具体指标无关"
+          />
         </Form.Item>
 
         <Form.Item label="附加项">
@@ -138,12 +201,14 @@ const CreateOrEditManagementIndex: FC = () => {
               ]}
               editable={{
                 type: "multiple",
+                editableKeys: bounsEditableKeys,
                 actionRender: (row, config, defaultDoms) => {
                   return [defaultDoms.delete];
                 },
                 onValuesChange: (record, recordList) => {
                   form.setFieldValue("bonus", recordList);
                 },
+                onChange: setBounsEditableKeys,
               }}
             />
           </Form.Item>
@@ -215,12 +280,14 @@ const CreateOrEditManagementIndex: FC = () => {
               ]}
               editable={{
                 type: "multiple",
+                editableKeys: deductionEditableKeys,
                 actionRender: (row, config, defaultDoms) => {
                   return [defaultDoms.delete];
                 },
                 onValuesChange: (record, recordList) => {
                   form.setFieldValue("deduction", recordList);
                 },
+                onChange: setDeductionEditableKeys,
               }}
             />
           </Form.Item>
@@ -228,6 +295,8 @@ const CreateOrEditManagementIndex: FC = () => {
 
         <FormPageFooter onSubmit={handleSubmit} onCancel={() => navigate(-1)} />
       </Form>
+
+      {loading && <DageLoading />}
     </PageContainer>
   );
 };

+ 119 - 68
src/pages/Management/Index/index.tsx

@@ -1,29 +1,72 @@
 import classNames from "classnames";
-import { useState } from "react";
+import { useCallback, useEffect, useMemo, useState } from "react";
 import { Button, Form, Input, Select, Table } from "antd";
 import { PlusOutlined } from "@ant-design/icons";
 import { useNavigate } from "react-router-dom";
 import { PageContainer } from "@/components";
 import { DageTableActions } from "@dage/pc-components";
 import style from "./index.module.scss";
-import { PUBLISH_STATUS_MAP, PUBLISH_ENUM } from "../../../constants";
+import {
+  PUBLISH_STATUS_MAP,
+  ASSESSMENT_TYPE_OPTIONS,
+  PUBLISH_STATUS_OPTIONS,
+} from "../../../constants";
+import { deleteManageIndexApi, getManageIndexListApi } from "@/api";
+import { debounce } from "lodash";
+import { ASS_INDEX_TYPE, IManageIndexDetail } from "@/types";
+
+const DEFAULT_PARAMS = {
+  pageNum: 1,
+  pageSize: 20,
+  searchKey: "",
+  status: "",
+  type: "",
+};
 
 const ManagementIndexPage = () => {
   const navigate = useNavigate();
-  const [list] = useState([
-    {
-      id: 1,
-      name: "模板名称",
-      a: "定级评估",
-      description: "模板说明",
-      b: "",
-      c: PUBLISH_ENUM.PENDING,
-      d: "",
-      e: "",
-      f: "2024-09-24 16:50:30",
-      g: "钱韵澄",
+  const [form] = Form.useForm();
+  const [loading, setLoading] = useState(false);
+  const [params, setParams] = useState({
+    ...DEFAULT_PARAMS,
+  });
+  const [total, setTotal] = useState(0);
+  const [list, setList] = useState<IManageIndexDetail[]>([]);
+
+  const debounceSearch = useMemo(
+    () =>
+      debounce((changedVal: unknown, vals: any) => {
+        setParams({ ...params, ...vals });
+      }, 500),
+    [params]
+  );
+
+  const paginationChange = useCallback(
+    () => (pageNum: number, pageSize: number) => {
+      setParams({ ...params, pageNum, pageSize });
     },
-  ]);
+    [params]
+  );
+
+  const getList = useCallback(async () => {
+    setLoading(true);
+    try {
+      const data = await getManageIndexListApi(params);
+      setList(data.records);
+      setTotal(data.total);
+    } finally {
+      setLoading(false);
+    }
+  }, [params]);
+
+  const handleDelete = async (item: IManageIndexDetail) => {
+    await deleteManageIndexApi(item.id);
+    getList();
+  };
+
+  useEffect(() => {
+    getList();
+  }, []);
 
   return (
     <PageContainer
@@ -35,7 +78,9 @@ const ManagementIndexPage = () => {
             icon={<PlusOutlined />}
             size="large"
             className="second-button"
-            onClick={() => navigate("/management/index/create")}
+            onClick={() =>
+              navigate("/management/index/create/" + ASS_INDEX_TYPE.FIXED)
+            }
           >
             新增定级评估考核
           </Button>
@@ -45,7 +90,9 @@ const ManagementIndexPage = () => {
             icon={<PlusOutlined />}
             size="large"
             className="second-button"
-            onClick={() => navigate("/management/index/create")}
+            onClick={() =>
+              navigate("/management/index/create/" + ASS_INDEX_TYPE.OPERATION)
+            }
           >
             新增运行评估考核
           </Button>
@@ -53,38 +100,48 @@ const ManagementIndexPage = () => {
       }
     >
       <div className={style.filter}>
-        <Form layout="inline" className="inline-form">
+        <Form
+          form={form}
+          layout="inline"
+          className="inline-form"
+          onValuesChange={debounceSearch}
+        >
           <Form.Item label="考核类别">
             <div className="w160">
-              <Select />
+              <Form.Item noStyle name="type">
+                <Select
+                  allowClear
+                  placeholder="请选择"
+                  options={ASSESSMENT_TYPE_OPTIONS}
+                />
+              </Form.Item>
             </div>
           </Form.Item>
           <Form.Item label="发布状态">
             <div className="w160">
-              <Select />
-            </div>
-          </Form.Item>
-          <Form.Item label="自评进度">
-            <div className="w160">
-              <Select />
-            </div>
-          </Form.Item>
-          <Form.Item label="评价进度">
-            <div className="w160">
-              <Select />
+              <Form.Item noStyle name="status">
+                <Select
+                  allowClear
+                  placeholder="请选择"
+                  options={PUBLISH_STATUS_OPTIONS}
+                />
+              </Form.Item>
             </div>
           </Form.Item>
-          <Form.Item label="搜索">
-            <Input className="w160" placeholder="请输入考核名称" />
+          <Form.Item label="搜索" name="searchKey">
+            <Input allowClear className="w160" placeholder="请输入考核名称" />
           </Form.Item>
           <Form.Item>
-            <Button type="primary">查询</Button>
+            <Button type="primary" onClick={getList}>
+              查询
+            </Button>
           </Form.Item>
         </Form>
       </div>
 
       <div className={style.table}>
         <Table
+          loading={loading}
           className={classNames("cus-table large")}
           dataSource={list}
           rowKey="id"
@@ -93,84 +150,69 @@ const ManagementIndexPage = () => {
             {
               title: "名称",
               dataIndex: "name",
-              key: "name",
               align: "center",
               minWidth: 100,
             },
             {
               title: "类别",
-              dataIndex: "a",
-              key: "a",
               align: "center",
               minWidth: 100,
+              render: (item: IManageIndexDetail) => {
+                return ASSESSMENT_TYPE_OPTIONS.find(
+                  (i) => i.value === item.type
+                )?.label;
+              },
             },
             {
               title: "说明",
-              dataIndex: "description",
-              key: "description",
+              dataIndex: "remark",
               align: "center",
               minWidth: 100,
+              ellipsis: true,
             },
             {
               title: "考核周期",
-              dataIndex: "b",
-              key: "b",
               align: "center",
               minWidth: 100,
+              render: (item: IManageIndexDetail) => {
+                return `${item.dateStart}-${item.dateEnd}`;
+              },
             },
             {
               title: "发布状态",
-              key: "c",
               align: "center",
               minWidth: 100,
-              render: (item: (typeof list)[0]) => {
+              render: (item: IManageIndexDetail) => {
                 return (
-                  <p style={{ color: PUBLISH_STATUS_MAP[item.c].color }}>
-                    {PUBLISH_STATUS_MAP[item.c].label}
+                  <p style={{ color: PUBLISH_STATUS_MAP[item.status].color }}>
+                    {PUBLISH_STATUS_MAP[item.status].label}
                   </p>
                 );
               },
             },
             {
-              title: "自评状态",
-              key: "d",
-              align: "center",
-              minWidth: 100,
-              render: (item: (typeof list)[0]) => {
-                return item.d || "/";
-              },
-            },
-            {
-              title: "评定状态",
-              key: "e",
-              align: "center",
-              minWidth: 100,
-              render: (item: (typeof list)[0]) => {
-                return item.e || "/";
-              },
-            },
-            {
               title: "编辑时间",
-              dataIndex: "f",
-              key: "f",
+              dataIndex: "updateTime",
               align: "center",
               minWidth: 160,
             },
             {
               title: "编辑人",
-              dataIndex: "g",
-              key: "g",
+              dataIndex: "creatorName",
               align: "center",
               minWidth: 100,
             },
             {
               title: "操作",
-              key: "h",
               align: "center",
               fixed: "right",
-              render: (item: (typeof list)[0]) => {
+              render: (item: IManageIndexDetail) => {
                 return (
                   <DageTableActions
+                    onEdit={() =>
+                      navigate(`/management/index/edit/${item.type}/${item.id}`)
+                    }
+                    onDelete={handleDelete.bind(undefined, item)}
                     renderBefore={
                       <>
                         <Button
@@ -205,6 +247,15 @@ const ManagementIndexPage = () => {
               },
             },
           ]}
+          pagination={{
+            showQuickJumper: true,
+            position: ["bottomCenter"],
+            showSizeChanger: true,
+            current: params.pageNum,
+            pageSize: params.pageSize,
+            total,
+            onChange: paginationChange(),
+          }}
         />
       </div>
     </PageContainer>

+ 18 - 2
src/router/index.tsx

@@ -43,12 +43,20 @@ export const DEFAULT_MENU: DageRouteItem[] = [
         children: [
           {
             hide: true,
-            path: "/assessment/template/create",
+            path: "/assessment/template/create/:type",
             title: "新增模板",
             Component: React.lazy(
               () => import("../pages/Assessment/Template/CreateOrEdit")
             ),
           },
+          {
+            hide: true,
+            path: "/assessment/template/edit/:type/:id",
+            title: "编辑模板",
+            Component: React.lazy(
+              () => import("../pages/Assessment/Template/CreateOrEdit")
+            ),
+          },
         ],
       },
     ],
@@ -66,7 +74,7 @@ export const DEFAULT_MENU: DageRouteItem[] = [
         children: [
           {
             hide: true,
-            path: "/management/index/create",
+            path: "/management/index/create/:type",
             title: "新增考核",
             Component: React.lazy(
               () => import("../pages/Management/Index/CreateOrEdit")
@@ -74,6 +82,14 @@ export const DEFAULT_MENU: DageRouteItem[] = [
           },
           {
             hide: true,
+            path: "/management/index/edit/:type/:id",
+            title: "编辑考核",
+            Component: React.lazy(
+              () => import("../pages/Management/Index/CreateOrEdit")
+            ),
+          },
+          {
+            hide: true,
             path: "/management/index/setting-index",
             title: "设置指标",
             Component: React.lazy(

+ 9 - 0
src/types/assessment.ts

@@ -43,3 +43,12 @@ export interface IAssIndexDetail {
   updateTime: string;
   creatorName: string;
 }
+
+export interface IAssTemplateDetail {
+  id: number;
+  name: string;
+  remark: string;
+  updateTime: string;
+  creatorName: string;
+  normIds: string;
+}

+ 1 - 0
src/types/index.ts

@@ -55,3 +55,4 @@ export enum YES_OR_NO {
 export * from "./log";
 export * from "./user";
 export * from "./assessment";
+export * from "./management";

+ 31 - 0
src/types/management.ts

@@ -0,0 +1,31 @@
+import { ASS_INDEX_TYPE } from "./assessment";
+
+/**
+ * 发布状态
+ */
+export enum PUBLISH_ENUM {
+  PENDING = 0,
+  PUBLISHED = 1,
+  ENDED = 2,
+}
+
+export interface IManageIndexDetail {
+  id: number;
+  name: string;
+  remark: string;
+  dateEnd: string;
+  dateStart: string;
+  status: PUBLISH_ENUM;
+  type: ASS_INDEX_TYPE;
+  updateTime: string;
+  creatorName: string;
+  jsonAdd: string;
+  jsonSub: string;
+  materials: {
+    id: number;
+    name: string;
+    fileName: string;
+    filePath: string;
+    suffix: string;
+  }[];
+}