123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734 |
- import React, {
- useCallback,
- useEffect,
- useMemo,
- useRef,
- useState,
- } from "react";
- import styles from "./index.module.scss";
- import { Button, Input, Popconfirm, Select, Table, Tooltip, Popover, Radio, Checkbox } from "antd";
- import { DownOutlined } from '@ant-design/icons';
- import { useDispatch, useSelector } from "react-redux";
- import { RootState } from "@/store";
- import { A1TableType } from "@/types";
- import A1Add from "./A1Add";
- import A1Down from "./A1Down";
- import A1Look from "./A1Look";
- import { A1_APIgetList, A1_APIdelProject } from "@/store/action/A1Project";
- import { A2_APIgetList1 } from "@/store/action/A2Dict";
- import { hasAuditStatusArr } from "./data";
- import { MessageFu } from "@/utils/message";
- import AuthCom from "@/components/AuthCom";
- import type { CheckboxProps, GetProp } from 'antd';
- type CheckboxValueType = GetProp<typeof Checkbox.Group, 'value'>[number];
- function A1Project() {
- const dispatch = useDispatch();
- useEffect(() => {
- // 获取 字典 的 职能(项目详情的项目成员用) 和 状态(这个页面用)
- dispatch(A2_APIgetList1());
- }, [dispatch]);
- // 从仓库 获取 项目状态的下拉框 数据
- const statusArr = useSelector(
- (state: RootState) => state.A2Dict.A2Tab1_1Obj.status
- );
- // 顶部的试图切换
- const [topType, setTopType] = useState<"outer" | "inner">("outer");
- // 表单数据
- const [fromData, setFromData] = useState({
- searchKey: "",
- pmName: "",
- bmName: "",
- statusId: "",
- hasAuditStatus: "",
- projectRole: "",
- pageNum: 1,
- pageSize: 10,
- type: "inside",
- dictProjectBusinessIds: '', // 业务类型id
- dictProjectScopeIds: '', // 项目范围id
- dictProjectAppIds: '', // 客户端id
- });
- // 封装发送请求的函数
- const A1getListFu = useCallback(() => {
- dispatch(A1_APIgetList(fromData));
- }, [dispatch, fromData]);
- useEffect(() => {
- A1getListFu();
- }, [A1getListFu]);
- // 项目编号/项目名称/建设单位 的 输入
- const searchKeyTime = useRef(-1);
- const searchKeyChange = useCallback(
- (
- e: React.ChangeEvent<HTMLInputElement>,
- key: "searchKey" | "pmName" | "bmName"
- ) => {
- clearTimeout(searchKeyTime.current);
- searchKeyTime.current = window.setTimeout(() => {
- setFromData({
- ...fromData,
- [key]: e.target.value,
- pageNum: 1,
- });
- }, 500);
- },
- [fromData]
- );
- // 点击重置
- const [inputKey, setInputKey] = useState(1);
- const resetSelectFu = useCallback(() => {
- // 把2个输入框和时间选择器清空
- setInputKey(Date.now());
- setFromData({
- searchKey: "",
- pmName: "",
- bmName: "",
- statusId: "",
- hasAuditStatus: "",
- projectRole: "",
- pageNum: 1,
- pageSize: 10,
- type: "inside",
- dictProjectBusinessIds: '', // 业务类型id
- dictProjectScopeIds: '', // 项目范围id
- dictProjectAppIds: '', // 客户端id
- });
- }, []);
- // 点击顶部的切换视图 按钮
- const topTypeFu = useCallback(
- (val: "outer" | "inner") => {
- if (topType === val) return;
- setTopType(val);
- resetSelectFu();
- },
- [resetSelectFu, topType]
- );
- // 权限-------项目视图 和 内控文件视图
- const authArr = useSelector((state: RootState) => state.A4Role.A4RoleAll);
- useEffect(() => {
- // 没有项目文件视图权限,一定有内控文件视图权限
- if (!authArr.includes("1010")) setTopType("inner");
- }, [authArr]);
- // 从仓库获取表格数据
- const tableInfo = useSelector(
- (state: RootState) => state.A1Project.tableInfo
- );
- /**
- * 业务类型 相关逻辑
- */
- // 从仓库 获取 业务类型 数据
- const projectBusinessArr = useSelector(
- (state: RootState) => state.A2Dict.A2Tab1_1Obj.projectBusiness
- );
- const projectBusinessArrForCheckbox = projectBusinessArr.map((v) => {
- return {
- label: v.name,
- value: v.id,
- }
- });
- // 选中的选项
- const [checkedProjectBusinessArr, setCheckedProjectBusinessArr] = useState<CheckboxValueType[]>([]);
- // 是否已全选
- const isProjectBusinessAllChecked = projectBusinessArr.length === checkedProjectBusinessArr.length;
- // 是否选了一部分
- const isProjectBusinessPartiallyChecked = checkedProjectBusinessArr.length > 0 && checkedProjectBusinessArr.length < projectBusinessArr.length;
- // 全选项 选中状态变化
- const onProjectBusinessCheckAllChange: CheckboxProps['onChange'] = (e) => {
- setCheckedProjectBusinessArr(e.target.checked ? projectBusinessArr.map((i) => {return i.id}) : []);
- };
- // 普通选项 选中状态变化
- const onProjectBusinessNormalCheckboxChange = (list: CheckboxValueType[]) => {
- setCheckedProjectBusinessArr(list);
- };
- useEffect(() => {
- setFromData(currentFromData => ({
- ...currentFromData,
- dictProjectBusinessIds: checkedProjectBusinessArr.join(','),
- pageNum: 1
- }));
- }, [checkedProjectBusinessArr]);
- /**
- * end of 业务类型 相关逻辑
- */
- /**
- * 项目范围 相关逻辑
- */
- // 从仓库 获取 项目范围 数据
- const projectScopeArr = useSelector(
- (state: RootState) => state.A2Dict.A2Tab1_1Obj.projectScope
- );
- const projectScopeArrForCheckbox = projectScopeArr.map((v) => {
- return {
- label: v.name,
- value: v.id,
- }
- });
- // 选中的选项
- const [checkedProjectScopeArr, setCheckedProjectScopeArr] = useState<CheckboxValueType[]>([]);
- // 是否已全选
- const isProjectScopeAllChecked = projectScopeArrForCheckbox.length === checkedProjectScopeArr.length;
- // 是否选了一部分
- const isProjectScopePartiallyChecked = checkedProjectScopeArr.length > 0 && checkedProjectScopeArr.length < projectScopeArr.length;
- // 全选项 选中状态变化
- const onProjectScopeCheckAllChange: CheckboxProps['onChange'] = (e) => {
- setCheckedProjectScopeArr(e.target.checked ? projectScopeArrForCheckbox.map((i) => {return i.value}) : []);
- };
- // 普通选项 选中状态变化
- const onProjectScopeNormalCheckboxChange = (list: CheckboxValueType[]) => {
- setCheckedProjectScopeArr(list);
- };
- useEffect(() => {
- setFromData(currentFromData => ({
- ...currentFromData,
- dictProjectScopeIds: checkedProjectScopeArr.join(','),
- pageNum: 1
- }));
- }, [checkedProjectScopeArr]);
-
- /**
- * end of 项目范围 相关逻辑
- */
- /**
- * 客户端 相关逻辑
- */
- // 从仓库 获取 客户端 数据
- const projectAppArr = useSelector(
- (state: RootState) => state.A2Dict.A2Tab1_1Obj.projectApp
- );
- const projectAppArrForCheckbox = projectAppArr.map((v) => {
- return {
- label: v.name,
- value: v.id,
- }
- });
- // 选中的选项
- const [checkedProjectAppArr, setCheckedProjectAppArr] = useState<CheckboxValueType[]>([]);
- // 是否已全选
- const isProjectAppAllChecked = projectAppArrForCheckbox.length === checkedProjectAppArr.length;
- // 是否选了一部分
- const isProjectAppPartiallyChecked = checkedProjectAppArr.length > 0 && checkedProjectAppArr.length < projectAppArr.length;
- // 全选项 选中状态变化
- const onProjectAppCheckAllChange: CheckboxProps['onChange'] = (e) => {
- setCheckedProjectAppArr(e.target.checked ? projectAppArrForCheckbox.map((i) => {return i.value}) : []);
- };
- // 普通选项 选中状态变化
- const onProjectAppNormalCheckboxChange = (list: CheckboxValueType[]) => {
- setCheckedProjectAppArr(list);
- };
- useEffect(() => {
- setFromData(currentFromData => ({
- ...currentFromData,
- dictProjectAppIds: checkedProjectAppArr.join(','),
- pageNum: 1
- }));
- }, [checkedProjectAppArr]);
- /**
- * end of 客户端 相关逻辑
- */
-
- /**
- * 项目类型筛选按钮显示的文字
- */
- const [projectTypeCurrentText, setProjectTypeCurrentText] = useState('全部类型')
- useEffect(() => {
- setProjectTypeCurrentText(v => {
- if (
- (checkedProjectBusinessArr.length === 0 && checkedProjectScopeArr.length === 0 && checkedProjectAppArr.length === 0) ||
- (checkedProjectBusinessArr.length === projectBusinessArr.length && checkedProjectScopeArr.length === projectScopeArr.length && checkedProjectAppArr.length === projectAppArr.length)
- ) {
- return '全部类型'
- } else {
- // 把checkedProjectBusinessArr各元素对应的name存入一个数组
- const checkedProjectBusinessArrName = checkedProjectBusinessArr.map(v => {
- const item = projectBusinessArr.find(i => i.id === v)
- return item ? item.name : ''
- })
- // 把checkedProjectScopeArr各元素对应的name存入一个数组
- const checkedProjectScopeArrName = checkedProjectScopeArr.map(v => {
- const item = projectScopeArr.find(i => i.id === v)
- return item ? item.name : ''
- })
- // 把checkedProjectAppArr各元素对应的name存入一个数组
- const checkedProjectAppArrName = checkedProjectAppArr.map(v => {
- const item = projectAppArr.find(i => i.id === v)
- return item ? item.name : ''
- })
- // 把3个数组合并成一个数组,再转成字符串
- return checkedProjectBusinessArrName.concat(checkedProjectScopeArrName, checkedProjectAppArrName).join(',')
- }
- })
- }, [
- checkedProjectBusinessArr,
- checkedProjectScopeArr,
- checkedProjectAppArr,
- projectBusinessArr,
- projectScopeArr,
- projectAppArr
- ])
-
-
- // 页码变化
- const paginationChange = useCallback(
- () => (pageNum: number, pageSize: number) => {
- setFromData({ ...fromData, pageNum, pageSize });
- },
- [fromData]
- );
- // 点击删除
- const delById = useCallback(
- async (id: number) => {
- const res = await A1_APIdelProject(id);
- if (res.code === 0) {
- MessageFu.success("删除成功!");
- A1getListFu();
- }
- },
- [A1getListFu]
- );
- // 点击下载
- const [downId, setDownId] = useState({ id: 0, txt: "" });
- // 点击审批
- const lookTabType = useRef(false);
- // 待审批,通过,驳回 的 格式处理
- const pcsTxt = useCallback((s1: string, s2: string, s3: string) => {
- const ss1 = s1 ? s1 : "0";
- const ss2 = s2 ? `/${s2}` : "/0";
- const ss3 = s3 ? `/${s3}` : "/0";
- return ss1 + ss2 + ss3;
- }, []);
- // 如果 项目详情 -5个tab都没有设置权限
- const tabFlag = useMemo(() => {
- let flag = false;
- if (
- !authArr.includes("1080") &&
- !authArr.includes("1115") &&
- !authArr.includes("1090") &&
- !authArr.includes("1100") &&
- !authArr.includes("1110")
- ) {
- flag = true;
- }
- return flag;
- }, [authArr]);
- const columns = useMemo(() => {
- const arr: any = [
- {
- title: "项目编号",
- dataIndex: "num",
- },
- {
- title: "项目名称",
- dataIndex: "name",
- },
- {
- title: "建设单位",
- render: (item: A1TableType) => (item.unit ? item.unit : "(空)"),
- },
- {
- title: "项目地点",
- render: (item: A1TableType) =>
- item.province ? item.province : "(空)",
- },
- {
- title: "项目周期",
- render: (item: A1TableType) =>
- item.dateScope ? item.dateScope : "(空)",
- },
- {
- title: "项目经理",
- render: (item: A1TableType) =>
- item.snapPmUser ? item.snapPmUser : "(空)",
- },
- {
- title: "商务经理",
- render: (item: A1TableType) =>
- item.snapBmUser ? item.snapBmUser : "(空)",
- },
- {
- title: "项目状态",
- render: (item: A1TableType) =>
- item.statusName ? item.statusName : "(空)",
- },
- ];
- if (topType === "inner") {
- arr.push(
- {
- title: "收集文件类型",
- render: (item: A1TableType) =>
- item.pcsCollect ? item.pcsCollect : "(空)",
- },
- {
- width: 164,
- title: (
- <Tooltip title="该项目内控文件的审批状态和数量">
- <div className="iconHoverTit">
- 待审批/通过/驳回
- <div className="iconHoverTitTxt">?</div>
- </div>
- </Tooltip>
- ),
- render: (item: A1TableType) =>
- pcsTxt(item.pcs0, item.pcs1, item.pcs2),
- }
- );
- }
- arr.push({
- width: 130,
- title: "存在待审批文件",
- render: (item: A1TableType) => (item.hasAuditStatus ? "是" : "否"),
- });
- arr.push({
- title: "最近编辑时间",
- dataIndex: "updateTime",
- });
- arr.push({
- title: "操作",
- render: (item: A1TableType) => (
- <>
- <Button
- hidden={tabFlag}
- size="small"
- type="text"
- onClick={() => {
- lookTabType.current = false;
- setPageType({
- txt: "look",
- id: item.id,
- tit: item.num + " - " + item.name,
- });
- }}
- >
- 查看
- </Button>
- {topType === "inner" ? (
- <>
- <AuthCom aId="1104">
- <Button
- hidden={tabFlag}
- size="small"
- type="text"
- onClick={() => {
- lookTabType.current = true;
- setPageType({
- txt: "look",
- id: item.id,
- tit: item.num + " - " + item.name,
- });
- }}
- >
- 审批
- </Button>
- </AuthCom>
- <AuthCom aId="1050">
- <Button
- size="small"
- type="text"
- onClick={() =>
- setDownId({
- id: item.id,
- txt: item.num + " - " + item.name,
- })
- }
- >
- 下载内控文件
- </Button>
- </AuthCom>
- </>
- ) : null}
- <AuthCom aId="1060">
- <Popconfirm
- title="删除后无法恢复,是否删除?"
- okText="删除"
- cancelText="取消"
- onConfirm={() => delById(item.id)}
- okButtonProps={{ loading: false }}
- >
- <Button size="small" type="text" danger>
- 删除
- </Button>
- </Popconfirm>
- </AuthCom>
- </>
- ),
- });
- return arr;
- }, [delById, pcsTxt, tabFlag, topType]);
- // 新增和查看
- const [pageType, setPageType] = useState<{
- txt: string;
- id: number;
- tit?: string;
- }>({ txt: "", id: 0 });
- // 是否只有 项目文件视图 / 内控文件视图的 其中一个
- const isOneTopType = useMemo(() => {
- if (authArr.includes("1010") && authArr.includes("1020")) return false;
- else return true;
- }, [authArr]);
- return (
- <div className={styles.A1Project}>
- <div className="pageTitle">
- 项目管理
- {pageType.txt === "add"
- ? " > 新增项目"
- : pageType.txt === "look"
- ? " > 查看项目"
- : null}
- </div>
- {/* 顶部筛选 */}
- <div className="A1top">
- <div className="A1Search">
- {/* 顶部试图切换 */}
- <div className="A1SearchRow" hidden={isOneTopType}>
- <AuthCom aId="1010">
- <Button
- onClick={() => topTypeFu("outer")}
- type={topType === "outer" ? "primary" : "default"}
- >
- 项目文件视图
- </Button>
- </AuthCom>
- <AuthCom aId="1020">
- <Button
- onClick={() => topTypeFu("inner")}
- type={topType === "inner" ? "primary" : "default"}
- >
- 内控文件视图
- </Button>
- </AuthCom>
- </div>
- <div className="A1SearchRow">
- <span>项目编号/项目名称/建设单位:</span>
- <Input
- key={inputKey}
- maxLength={20}
- style={{ width: 200 }}
- placeholder="请输入内容,最多20字"
- allowClear
- onChange={(e) => searchKeyChange(e, "searchKey")}
- />
- </div>
- <div className="A1SearchRow">
- <span>项目经理:</span>
- <Input
- key={inputKey}
- maxLength={10}
- style={{ width: 200 }}
- placeholder="请输入内容,最多10字"
- allowClear
- onChange={(e) => searchKeyChange(e, "pmName")}
- />
- </div>
- <div className="A1SearchRow">
- <span>商务经理:</span>
- <Input
- key={inputKey}
- maxLength={10}
- style={{ width: 200 }}
- placeholder="请输入内容,最多10字"
- allowClear
- onChange={(e) => searchKeyChange(e, "bmName")}
- />
- </div>
- </div>
- <div className="A1Search A1Search2">
- <div className="A1SearchRow">
- <span>项目状态:</span>
- <Select
- style={{ width: 164 }}
- value={fromData.statusId}
- onChange={(e) =>
- setFromData({ ...fromData, statusId: e, pageNum: 1 })
- }
- options={[
- { value: "", label: "全部" },
- ...statusArr.map((v) => ({ value: v.id, label: v.name })),
- ]}
- />
- </div>
- <div className="A1SearchRow">
- <span>项目类型:</span>
- <Popover
- trigger="click"
- placement="bottomLeft"
- content={
- <div className={styles.projectTypePopOver}>
- <div className={styles.row}>
- <span className={styles.title} title="甲方的业务类型">业务类型:</span>
- <Checkbox
- indeterminate={isProjectBusinessPartiallyChecked}
- onChange={onProjectBusinessCheckAllChange}
- checked={isProjectBusinessAllChecked}
- className={styles.selectAll}
- >
- 全选
- </Checkbox>
- <Checkbox.Group
- options={projectBusinessArrForCheckbox}
- value={checkedProjectBusinessArr}
- onChange={onProjectBusinessNormalCheckboxChange}
- />
- </div>
- <div className={styles.row}>
- <span className={styles.title} title="项目的建设范围">项目范围:</span>
- <Checkbox
- indeterminate={isProjectScopePartiallyChecked}
- onChange={onProjectScopeCheckAllChange}
- checked={isProjectScopeAllChecked}
- className={styles.selectAll}
- >
- 全选
- </Checkbox>
- <Checkbox.Group
- options={projectScopeArrForCheckbox}
- value={checkedProjectScopeArr}
- onChange={onProjectScopeNormalCheckboxChange}
- />
- </div>
- <div className={styles.row}>
- <span className={styles.title} title="项目成果的呈现载体">客户端:</span>
- <Checkbox
- indeterminate={isProjectAppPartiallyChecked}
- onChange={onProjectAppCheckAllChange}
- checked={isProjectAppAllChecked}
- className={styles.selectAll}
- >
- 全选
- </Checkbox>
- <Checkbox.Group
- options={projectAppArrForCheckbox}
- value={checkedProjectAppArr}
- onChange={onProjectAppNormalCheckboxChange}
- />
- </div>
- </div>
- }
- >
- <Button className="projectTypeFilterButton">
- {projectTypeCurrentText}
- <DownOutlined />
- </Button>
- </Popover>
- </div>
- {/* 通过顶部状态 动态渲染 这3个下拉框 */}
- {topType === "outer" ? null : (
- <>
- <div className="A1SearchRow">
- <span>是否存在待审批文件:</span>
- <Select
- style={{ width: 164 }}
- value={fromData.hasAuditStatus}
- onChange={(e) =>
- setFromData({ ...fromData, hasAuditStatus: e, pageNum: 1 })
- }
- options={hasAuditStatusArr}
- />
- </div>
- </>
- )}
- <div className="A1SearchRow A1SearchBtn">
- <AuthCom aId="1030">
- <Button
- type="primary"
- onClick={() => setPageType({ txt: "add", id: 0 })}
- >
- 新增项目
- </Button>
- </AuthCom>
-   
- <Button onClick={resetSelectFu}>重置</Button>
- </div>
- </div>
- </div>
- {/* 表格主体 */}
- <div className="A1tableBox">
- <Table
- scroll={{ y: 575 }}
- dataSource={tableInfo.list}
- columns={columns}
- rowKey="id"
- pagination={{
- showQuickJumper: true,
- position: ["bottomCenter"],
- showSizeChanger: true,
- current: fromData.pageNum,
- pageSize: fromData.pageSize,
- total: tableInfo.total,
- onChange: paginationChange(),
- }}
- />
- </div>
- {/* 新增、查看 */}
- {pageType.txt === "add" ? (
- <A1Add
- pageType={pageType}
- closeFu={() => setPageType({ txt: "", id: 0 })}
- addFu={() => resetSelectFu()}
- editFu={() => A1getListFu()}
- />
- ) : pageType.txt === "look" ? (
- <A1Look
- pageType={pageType}
- closeFu={() => {
- setPageType({ txt: "", id: 0 });
- // 从查看页面返回的时候更新列表数据
- A1getListFu();
- }}
- tabType={lookTabType.current}
- lookTit={pageType.tit!}
- />
- ) : null}
- {/* 下载 */}
- {downId.id ? (
- <A1Down downId={downId} closeFu={() => setDownId({ id: 0, txt: "" })} />
- ) : null}
- </div>
- );
- }
- const MemoA1Project = React.memo(A1Project);
- export default MemoA1Project;
|