<div id="root"></div>
<script>
  import React, { useEffect, useState } from 'react';
  import type { ProSelectProps, Params, RequestDate } from './interface';
  import { Select, Spin } from 'antd';
  import { debounce } from 'lodash';
<p>const ProSelect: React.FC<ProSelectProps> = ({ request, style = { width: 300 }, ...props }) =&gt; {
const [optionsData, setOptionsData] = useState<RequestDate>({
data: [],
total: 0,
});
const [pageOption, setPageOption] = useState<Params>({
pageSize: 20,
current: 1,
keyWord: '',
});
const [loadding, setLoadding] = useState<boolean>(false);</p>
<pre><code>const handlePopupScroll: React.UIEventHandler&lt;HTMLDivElement&gt; = (e) =&gt; {
  const { scrollTop, scrollHeight, clientHeight } = e.target as HTMLElement;
  const isScrollEnd = scrollHeight - scrollTop === clientHeight;
  if (isScrollEnd &amp;&amp; optionsData &amp;&amp; optionsData.data.length &lt; optionsData?.total) {
    setPageOption((prePageOptions) =&gt; {
      return {
        ...prePageOptions,
        current: prePageOptions.current + 1,
      };
    });
  }
};

const handelSearch = debounce((keyWord: string) =&gt; {
  setPageOption({
    pageSize: 20,
    current: 1,
    keyWord,
  });
  setOptionsData({
    data: [],
    total: 0,
  });
}, 800);

useEffect(() =&gt; {
  if (request) {
    setLoadding(true);
    request({ ...pageOption }).then((res) =&gt; {
      setLoadding(false);
      setOptionsData((preOptions) =&gt; {
        return {
          data: [...preOptions.data, ...res.data],
          success: true,
          total: res.total,
        };
      });
    });
  }
}, [pageOption, request]);

return (
  &lt;Select
    {...props}
    options={props.options || optionsData.data}
    onPopupScroll={handlePopupScroll}
    notFoundContent={loadding ? &lt;Spin size=&quot;small&quot; /&gt; : null}
    style={style}
    filterOption={false}
    onSearch={handelSearch}
    showSearch
  /&gt;
);
</code></pre>
<p>};</p>
<p>export default React.memo(ProSelect);
import { PageContainer } from '@ant-design/pro-layout';
import type { ProColumns } from '@ant-design/pro-table';
import ProCard from '@/components/ProCard';
import ProTable from '@ant-design/pro-table';
import { Typography, Radio } from 'antd';
import React, { useEffect, useState } from 'react';
import ContentCard from '@/components/ContentCard';
import {
getProjectMilepostList,
getDropdownPage,
sapUserCentAndDept,
} from '@/services/project/kanban/index';
import { history } from 'umi';
import './index.less';
import { isArray } from 'lodash';
import ProSelect from '@/components/ProSelect';</p>
<p>const { Link } = Typography;
interface NodeItems {
[x: string]: any;
id: number;
projectId: string;
projectName: string;
spmUserName: string;
summary: string;
assignee: string;
dep: string;
issueStatus: string;
dueDate: string;
timeEnding1: string;
delayDays: string;
keyWord: string;
issueLink: string;
}
let day = 0;
let days = 0;</p>
<p>const DeparmentDiList: React.FC = () =&gt; {
const [radioValue, setRadioValue] = useState<boolean>(false);
const [deptData, setDeptData] = useState([]);
const [deadlineList, setDeadlineList] = useState({});
const [projectList, setProjectList] = useState&lt;{ name: string; code: string }[]&gt;([]);
const [searchData, setSearchData] = useState({
pagination: { current: 1, size: 10, totals: 0 },
searchValue: '',
});</p>
<pre><code>const {
  pagination: { current, size, totals },
  searchValue,
} = searchData;

// const getDropdownPages = async () =&gt; {
//   // 页码,及搜索值变化时,发请求
//   const params = {
//     current,
//     size,
//     keyword: searchValue,
//     kanbanDropdownType: 'SPM_ROLE',
//   };
//   const { data } = await getDropdownPage(params);
//   setProjectList((preOptions) =&gt; {
//     return [...preOptions, ...data.records];
//   });
//   setSearchData({
//     ...searchData,
//     pagination: {
//       current: data.current,
//       totals: data.total,
//       size: data.size,
//     },
//   });
// };
</code></pre>
<p>const   getDropdownPages=async()=&gt;{
const { data } = await getDropdownPage({ kanbanDropdownType: 'SPM_ROLE',});
setProjectList((preOptions) =&gt; {
return [...preOptions, ...data.records];
});
}
useEffect(() =&gt; {
getDropdownPages();</p>
<pre><code>}, []);

useEffect(() =&gt; {
  const scrollEnd: React.UIEventHandler&lt;HTMLElement&gt; = (e) =&gt; {
    e.persist();
    const { target } = e;
    // 滚动 触底 看接口是否还有剩余的值没传过来
    if (
      (target as HTMLElement).scrollTop + (target as HTMLElement).offsetHeight ===
      (target as HTMLElement).scrollHeight
    ) {
      if (current * size &lt; totals) {
        setSearchData({
          ...searchData,
          pagination: {
            ...searchData.pagination,
            current: current + 1,
          },
        });
      }
    }
  };
  document.getElementById('table-container')?.addEventListener('scroll', scrollEnd);
  return () =&gt; {
    document.getElementById('table-container')?.removeEventListener('scroll', scrollEnd);
  };
}, [current, size, totals, searchData.searchValue]);

const columns: ProColumns&lt;NodeItems&gt;[] = [
  {
    title: '序号',
    width: 50,
    dataIndex: 'index',
    align: 'center',
    valueType: 'index',
  },

  {
    title: '项目ID',
    dataIndex: 'projectId',
    align: 'center',
    hideInSearch: true,
    width: 60,
  },

  {
    title: '项目名称',
    dataIndex: 'projectName',
    align: 'center',
    width: 300,
    hideInSearch: true,
    render: (_, record) =&gt; (
      &lt;div style={{ textAlign: 'left' }}&gt;
        &lt;Link
          onClick={() =&gt; history.push(`/project/operation/home?projectId=${record.projectId}`)}
        &gt;
          {record.projectName}
        &lt;/Link&gt;
      &lt;/div&gt;
    ),
  },
  {
    title: '业务中心',
    dataIndex: 'cent',
    valueType: 'select',
    hideInTable: true,
    request: async () =&gt; {
      const { data } = await sapUserCentAndDept({});
      if (!isArray(data)) throw new Error('');
      const centerData = data.map((item: any) =&gt; {
        const childrenCenter = (item.deptList || []).map((child: any) =&gt; {
          return {
            label: child,
            value: `${child}`,
          };
        });
        return {
          label: item.cent,
          value: `${item.cent}`,
          childrenCenter,
        };
      });
      return centerData;
    },
    fieldProps: {
      showSearch: true,
      fieldNames: {
        label: 'label',
        value: 'value',
      },
      onChange: (val: any, option: any) =&gt; {
        if (val) {
          const deparSlect = option.childrenCenter.filter((item: any) =&gt; item.label);
          setDeptData(deparSlect);
        } else {
          setDeptData([]);
        }
      },
    },
  },
  {
    title: '所在部门',
    dataIndex: 'dep',
    align: 'center',
    valueType: 'select',
    fieldProps: { options: deptData },
    width: 110,
    render: (_, record) =&gt; {
      return &lt;span&gt;{`${record.cent}/${record.dep}`}&lt;/span&gt;;
    },
  },
  {
    title: 'SPM',
    dataIndex: 'spmUserName',
    align: 'center',
    valueType: 'select',
    width: 60,
    // request: async () =&gt; {
    //   const { data } = await getDropdownPage({ kanbanDropdownType: 'SPM_ROLE' });
    //   return data.records;
    // },
    fieldProps: {
      showSearch: true,
      fieldNames: {
        label: 'name',
        value: 'code',
      },
      // options: projectList,
      // filterOption: true,
      // onPopupScroll: scrollEnd,
    },
    renderFormItem: () =&gt; {
      return &lt;ProSelect options={projectList} /&gt;;
    },
  },

  {
    title: 'Bug概要',
    dataIndex: 'summary',
    align: 'center',
    width: 400,
    hideInSearch: true,
    render: (record, rowRecord) =&gt; {
      return (
        &lt;div style={{ textAlign: 'left' }}&gt;
          &lt;Link href={rowRecord.issueLink} target={'_blank'}&gt;
            {record}
          &lt;/Link&gt;
        &lt;/div&gt;
      );
    },
  },
  {
    title: '关键字',
    dataIndex: 'issueKey',
    align: 'center',
    valueType: 'select',
    width: 100,
    request: async () =&gt; {
      const { data } = await getDropdownPage({ kanbanDropdownType: 'ISSUE_KEY' });
      return data.records;
    },
    fieldProps: {
      showSearch: true,
      fieldNames: {
        label: 'name',
        value: 'code',
      },
    },
  },
  {
    title: '经办人',
    dataIndex: 'assignee',
    align: 'center',
    hideInSearch: true,
    valueType: 'select',
    width: 60,
  },

  {
    title: '状态',
    dataIndex: 'issueStatus',
    align: 'center',
    hideInSearch: true,
    width: 80,
  },
  {
    title: '到期时间',
    dataIndex: 'dueDate',
    align: 'center',
    width: 90,
    hideInSearch: true,
    render: (_, record) =&gt; {
      return &lt;span&gt;{record.dueDate}&lt;/span&gt;;
    },
  },
  {
    title: '倒计时(天)',
    dataIndex: 'timeEnding1',
    align: 'center',
    hideInSearch: true,
    width: 90,
    render: (_, record) =&gt; {
      if (record &amp;&amp; record?.dueDate) {
        const setTime = new Date(record?.dueDate as any);
        const nowTime = new Date();
        const restSec: any = setTime.getTime() - nowTime.getTime();
        day = parseInt((restSec / (60 * 60 * 24 * 1000)) as any);
      }
      return &lt;span&gt;{record?.dueDate ? day : '-'}&lt;/span&gt;;
    },
  },
  {
    title: '延期天数',
    dataIndex: 'delayDays',
    align: 'center',
    hideInSearch: true,
    width: 80,
    render: (_, record) =&gt; {
      if (record &amp;&amp; record?.dueDate) {
        const setTime = new Date(record?.dueDate as any);
        const nowTime = new Date();
        const restSec: any = nowTime.getTime() - setTime.getTime();
        days = parseInt((restSec / (60 * 60 * 24 * 1000)) as any);
      }
      return &lt;span&gt;{record?.dueDate ? days : '-'}&lt;/span&gt;;
    },
  },

  {
    title: '项目',
    dataIndex: 'projectId',
    align: 'center',
    valueType: 'select',
    hideInTable: true,
    request: async () =&gt; {
      const { data } = await getDropdownPage({ kanbanDropdownType: 'PROJECT_INFO' });
      return data.records;
    },
    fieldProps: {
      showSearch: true,
      fieldNames: {
        label: 'name',
        value: 'code',
      },
    },
  },
  // {
  //     title: '区域',
  //     dataIndex: 'regison',
  //     align: 'center',
  //     valueType: 'select',
  //     hideInTable: true,

  // },
];
const radioChange = (e: any) =&gt; {
  setRadioValue(e.target.value);
  setDeadlineList({ solveFlag: e.target.value });
};

return (
  &lt;PageContainer className=&quot;pageNodes&quot;&gt;
    &lt;ProCard&gt;
      &lt;ContentCard title={'期限释放问题'}&gt;
        &lt;div className=&quot;TableStyle&quot; id=&quot;table-container&quot;&gt;
          &lt;ProTable
            rowKey={'id'}
            className=&quot;nodeLists&quot;
            columns={columns}
            options={false}
            bordered
            scroll={{ y: 'calc(100vh - 366px)', x: 'max-content' }}
            search={{
              labelWidth: 100,
            }}
            pagination={{
              pageSize: 10,
              showSizeChanger: false,
            }}
            headerTitle={
              &lt;div className=&quot;deadline-bug&quot;&gt;
                &lt;div className=&quot;table-radio-box&quot;&gt;
                  &lt;Radio.Group
                    defaultValue={radioValue}
                    buttonStyle=&quot;solid&quot;
                    onChange={radioChange}
                  &gt;
                    &lt;Radio.Button value={false}&gt;未解决&lt;/Radio.Button&gt;
                    &lt;Radio.Button value={true}&gt;已解决&lt;/Radio.Button&gt;
                  &lt;/Radio.Group&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            }
            params={deadlineList}
            request={async (params) =&gt; {
              const { keyword } = params;
              try {
                delete params.pageSize;
                const {
                  data: { total, records },
                } = await getProjectMilepostList({
                  ...params,
                  current: params.current || 1,
                  size: params.pageSize || 10,
                  solveFlag: radioValue,
                  keyword,
                });

                return {
                  success: true,
                  data: records,
                  total,
                };
              } catch (error) {
                return { success: false };
              }
            }}
          /&gt;
        &lt;/div&gt;
      &lt;/ContentCard&gt;
    &lt;/ProCard&gt;
  &lt;/PageContainer&gt;
);
</code></pre>
<p>};
export default DeparmentDiList;
</script></p>
期限释放问题列表 - 项目管理系统

原文地址: https://www.cveoy.top/t/topic/orYa 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录