@ant-design/icons#PlusSquareFilled TypeScript Examples

The following examples show how to use @ant-design/icons#PlusSquareFilled. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx    From dashboard with Apache License 2.0 4 votes vote down vote up
ContactWayList: React.FC = () => {
  const [currentGroup, setCurrentGroup] = useState<ContactWayGroupItem>({});
  const [itemDetailVisible, setItemDetailVisible] = useState(false);
  const [currentItem, setCurrentItem] = useState<ContactWayItem>({});
  const [selectedItems, setSelectedItems] = useState<ContactWayItem[]>([]);
  const [filterGroupID, setFilterGroupID] = useState('0');
  const [groupItems, setGroupItems] = useState<ContactWayGroupItem[]>([]);
  const [groupItemsTimestamp, setGroupItemsTimestamp] = useState(Date.now);
  const [createGroupVisible, setCreateGroupVisible] = useState(false);
  const [batchUpdateVisible, setBatchUpdateVisible] = useState(false);
  const [editGroupVisible, setEditGroupVisible] = useState(false);
  const [allStaffs, setAllStaffs] = useState<StaffOption[]>([]);
  const actionRef = useRef<ActionType>();

  function showDeleteGroupConfirm(item: ContactWayGroupItem) {
    Modal.confirm({
      title: `删除分组`,
      content: `是否确认删除「${item.name}」分组?`,
      // icon: <ExclamationCircleOutlined/>,
      okText: '删除',
      okType: 'danger',
      cancelText: '取消',
      onOk() {
        return HandleRequest({ids: [item.id]}, DeleteGroup, () => {
          setGroupItemsTimestamp(Date.now);
        });
      },
    });
  }

  useEffect(() => {
    QuerySimpleStaffs({page_size: 5000}).then((res) => {
      if (res.code === 0) {
        setAllStaffs(
          res?.data?.items?.map((item: SimpleStaffInterface) => {
            return {
              label: item.name,
              value: item.ext_id,
              ...item,
            };
          }) || [],
        );
      } else {
        message.error(res.message);
      }
    });
  }, []);

  useEffect(() => {
    QueryGroup({page_size: 1000, sort_field: 'sort_weight', sort_type: 'asc'})
      .then((resp) => {
        if (resp && resp.data && resp.data.items) {
          setGroupItems(resp.data.items);
        }
      })
      .catch((err) => {
        message.error(err);
      });
  }, [groupItemsTimestamp]);

  const columns: ProColumns<ContactWayItem>[] = [
    {
      title: 'ID',
      dataIndex: 'id',
      valueType: 'text',
      hideInTable: true,
      hideInSearch: true,
      fixed:'left',
    },
    {
      title: '渠道码',
      dataIndex: 'qr_code',
      valueType: 'image',
      hideInSearch: true,
      width: 80,
      fixed:'left',
      render: (dom, item) => {
        return (
          <div className={'qrcodeWrapper'}>
            <img
              src={item.qr_code}
              onClick={() => {
                setItemDetailVisible(true);
                setCurrentItem(item);
              }}
              className={'qrcode clickable'}
              alt={item.name}
            />
          </div>
        );
      },
    },
    {
      title: '名称',
      dataIndex: 'name',
      valueType: 'text',
      fixed:'left',
    },
    {
      title: '使用员工',
      dataIndex: 'staffs',
      valueType: 'text',
      hideInSearch: true,
      width: 210,
      render: (_, item) => {
        let staffs: any[] = [];
        item.schedules?.forEach((schedule) => {
          if (schedule.staffs) {
            staffs = [...staffs, ...schedule.staffs];
          }
        });
        if (item.schedule_enable === True) {
          staffs = uniqWith(staffs, (a, b) => a.ext_staff_id === b.ext_staff_id);
          return <CollapsedStaffs limit={2} staffs={staffs}/>;
        }
        return <CollapsedStaffs limit={2} staffs={item.staffs}/>;
      },
    },
    {
      title: '使用员工',
      dataIndex: 'ext_staff_ids',
      valueType: 'text',
      hideInTable: true,
      renderFormItem: () => {
        return <StaffTreeSelect options={allStaffs}/>;
      },
    },
    {
      title: '备份员工',
      dataIndex: 'backup_staffs',
      valueType: 'text',
      hideInSearch: true,
      width: 210,
      render: (_, item) => {
        return <CollapsedStaffs limit={2} staffs={item.backup_staffs}/>;
      },
    },
    {
      title: '标签',
      dataIndex: 'customer_tags',
      valueType: 'text',
      ellipsis: true,
      hideInSearch: true,
      width: 210,
      render: (_, item) => {
        return <CollapsedTags limit={3} tags={item.customer_tags}/>;
      },
    },
    {
      title: '添加人次',
      dataIndex: 'add_customer_count',
      valueType: 'digit',
      hideInSearch: true,
      sorter: true,
      showSorterTooltip: false,
      width: 120,
      tooltip: '统计添加渠道码的人次,若客户重复添加将会记录多条数据',
    },
    {
      title: '创建时间',
      dataIndex: 'created_at',
      valueType: 'dateRange',
      sorter: true,
      filtered: true,
      render: (dom, item) => {
        return (
          <div
            dangerouslySetInnerHTML={{
              __html: moment(item.created_at).format('YYYY-MM-DD HH:mm').split(' ').join('<br />'),
            }}
          />
        );
      },
    },
    {
      title: '操作',
      width: 180,
      valueType: 'option',
      render: (_, item) => [
        <a
          key='detail'
          onClick={() => {
            setItemDetailVisible(true);
            setCurrentItem(item);
          }}
        >
          详情
        </a>,
        <a
          key='download'
          onClick={() => {
            if (item?.qr_code) {
              FileSaver.saveAs(item?.qr_code, `${item.name}.png`);
            }
          }}
        >
          下载
        </a>,
        <Dropdown
          key='more'
          overlay={
            <Menu>
              <Menu.Item
                key='edit'
                onClick={() => {
                  history.push(`/staff-admin/customer-growth/contact-way/edit?id=${item.id}`);
                }}
              >
                修改
              </Menu.Item>
              <Menu.Item
                key='copy'
                onClick={() => {
                  history.push(`/staff-admin/customer-growth/contact-way/copy?id=${item.id}`);
                }}
              >
                复制
              </Menu.Item>
              {item.ext_creator_id === localStorage.getItem(LSExtStaffAdminID) && (
                <Menu.Item
                  key='delete'
                  onClick={() => {
                    Modal.confirm({
                      title: `删除渠道码`,
                      content: `是否确认删除「${item.name}」渠道码?`,
                      okText: '删除',
                      okType: 'danger',
                      cancelText: '取消',
                      onOk() {
                        return HandleRequest({ids: [item.id]}, Delete, () => {
                          actionRef.current?.clearSelected?.();
                          actionRef.current?.reload?.();
                        });
                      },
                    });
                  }}
                >删除</Menu.Item>
              )}
            </Menu>
          }
          trigger={['hover']}
        >
          <a style={{display: 'flex', alignItems: 'center'}}>
            编辑
            <CaretDownOutlined style={{fontSize: '8px', marginLeft: '3px'}}/>
          </a>
        </Dropdown>,
      ],
    },
  ];

  // @ts-ignore
  // @ts-ignore
  return (
    <PageContainer
      fixedHeader
      header={{
        title: '渠道活码列表',
        subTitle: (
          <a
            target={'_blank'}
            className={styles.tipsLink}
            // href={'https://www.openscrm.cn/wiki/contact-way'}
          >
            什么是渠道活码?
          </a>
        ),
      }}
      extra={[
        <Button
          key='create'
          type='primary'
          icon={<PlusOutlined style={{fontSize: 16, verticalAlign: '-3px'}}/>}
          onClick={() => {
            history.push('/staff-admin/customer-growth/contact-way/create');
          }}
        >
          新建活码
        </Button>,
      ]}
    >
      <ProTable<ContactWayItem>
        actionRef={actionRef}
        className={'table'}
        scroll={{x: 'max-content'}}
        columns={columns}
        rowKey='id'
        pagination={{
          pageSizeOptions: ['5', '10', '20', '50', '100'],
          pageSize: 5,
        }}
        toolBarRender={false}
        bordered={false}
        tableAlertRender={false}
        rowSelection={{
          onChange: (_, items) => {
            setSelectedItems(items);
          },
        }}
        tableRender={(_, dom) => (
          <div className={styles.mixedTable}>
            <div className={styles.leftPart}>
              <div className={styles.header}>
                <Button
                  key='1'
                  className={styles.button}
                  type='text'
                  onClick={() => setCreateGroupVisible(true)}
                  icon={<PlusSquareFilled style={{color: 'rgb(154,173,193)', fontSize: 15}}/>}
                >
                  新建分组
                </Button>
              </div>
              <Menu
                onSelect={(e) => {
                  setFilterGroupID(e.key as string);
                }}
                defaultSelectedKeys={['0']}
                mode='inline'
                className={styles.menuList}
              >
                <Menu.Item
                  icon={<FolderFilled style={{fontSize: '16px', color: '#138af8'}}/>}
                  key='0'
                >
                  全部
                </Menu.Item>
                {groupItems.map((item) => (
                  <Menu.Item
                    icon={<FolderFilled style={{fontSize: '16px', color: '#138af8'}}/>}
                    key={item.id}
                  >
                    <div className={styles.menuItem}>
                      {item.name}
                      <span className={styles.count}
                            style={{marginRight: item.is_default === True ? 16 : 0}}>{item.count}</span>
                    </div>
                    {item.is_default === False && (
                      <Dropdown
                        className={'more-actions'}
                        overlay={
                          <Menu
                            onClick={(e) => {
                              e.domEvent.preventDefault();
                              e.domEvent.stopPropagation();
                            }}
                          >
                            <Menu.Item
                              onClick={() => {
                                setCurrentGroup(item);
                                setEditGroupVisible(true);
                              }}
                              key='edit'
                            >
                              修改名称
                            </Menu.Item>
                            <Menu.Item
                              onClick={() => {
                                showDeleteGroupConfirm(item);
                              }}
                              key='delete'
                            >
                              删除分组
                            </Menu.Item>
                          </Menu>
                        }
                        trigger={['hover']}
                      >
                        <MoreOutlined style={{color: '#9b9b9b', fontSize: 18}}/>
                      </Dropdown>
                    )}
                  </Menu.Item>
                ))}
              </Menu>
            </div>
            <div className={styles.rightPart}>
              <div className={styles.tableWrap}>{dom}</div>
            </div>
          </div>
        )}
        params={{
          group_id: filterGroupID !== '0' ? filterGroupID : '',
        }}
        request={async (params, sort, filter) => {
          return ProTableRequestAdapter(params, sort, filter, Query);
        }}
        dateFormatter='string'
      />

      {selectedItems?.length > 0 && (
        // 底部选中条目菜单栏
        <FooterToolbar>
          <span>
            已选择 <a style={{fontWeight: 600}}>{selectedItems.length}</a> 项 &nbsp;&nbsp;
            <span></span>
          </span>
          <Divider type='vertical'/>
          <Button
            type='link'
            onClick={() => {
              actionRef.current?.clearSelected?.();
            }}
          >
            取消选择
          </Button>
          <Button onClick={() => setBatchUpdateVisible(true)}>批量分组</Button>
          <Button
            icon={<CloudDownloadOutlined/>}
            type={'primary'}
            onClick={() => {
              Modal.confirm({
                title: `批量下载渠道码`,
                content: `是否批量下载所选「${selectedItems.length}」个渠道码?`,
                okText: '下载',
                cancelText: '取消',
                onOk: async () => {
                  const zip = new JSZip();
                  // eslint-disable-next-line no-restricted-syntax
                  for (const item of selectedItems) {
                    if (item?.qr_code) {
                      // eslint-disable-next-line no-await-in-loop
                      const img = (await fetch(item?.qr_code)).blob();
                      zip.file(`${item.name}_${item.id}.png`, img);
                    }
                  }
                  const content = await zip.generateAsync({type: 'blob'});
                  FileSaver.saveAs(content, `渠道活码_${moment().format('YYYY_MM_DD')}.zip`);
                  actionRef.current?.clearSelected?.();
                  return true;
                },
              });
            }}
          >
            批量下载
          </Button>
          <Button
            icon={<DeleteOutlined/>}
            onClick={async () => {
              Modal.confirm({
                title: `删除渠道码`,
                content: `是否批量删除所选「${selectedItems.length}」个渠道码?`,
                okText: '删除',
                okType: 'danger',
                cancelText: '取消',
                onOk() {
                  return HandleRequest(
                    {ids: selectedItems.map((item) => item.id)},
                    Delete,
                    () => {
                      actionRef.current?.clearSelected?.();
                      actionRef.current?.reload?.();
                    },
                  );
                },
              });
            }}
            danger={true}
          >
            批量删除
          </Button>
        </FooterToolbar>
      )}

      <ModalForm
        width={468}
        className={'dialog from-item-label-100w'}
        layout={'horizontal'}
        visible={batchUpdateVisible}
        onVisibleChange={setBatchUpdateVisible}
        onFinish={async (values) => {
          return await HandleRequest(
            {ids: selectedItems.map((item) => item.id), ...values},
            BatchUpdate,
            () => {
              actionRef.current?.clearSelected?.();
              actionRef.current?.reload?.();
              setGroupItemsTimestamp(Date.now);
            },
          );
        }}
      >
        <h2 className='dialog-title'> 批量修改渠道码 </h2>
        <ProFormSelect
          // @ts-ignore
          options={groupItems.map((groupItem) => {
            return {key: groupItem.id, label: groupItem.name, value: groupItem.id};
          })}
          labelAlign={'left'}
          name='group_id'
          label='新分组'
          placeholder='请选择分组'
          rules={[
            {
              required: true,
              message: '请选择新分组',
            },
          ]}
        />
      </ModalForm>

      <ModalForm
        width={400}
        className={'dialog from-item-label-100w'}
        layout={'horizontal'}
        visible={createGroupVisible}
        onVisibleChange={setCreateGroupVisible}
        onFinish={async (params) =>
          HandleRequest({...currentGroup, ...params}, CreateGroup, () => {
            setGroupItemsTimestamp(Date.now);
          })
        }
      >
        <h2 className='dialog-title'> 新建分组 </h2>
        <ProFormText
          name='name'
          label='分组名称'
          tooltip='最长为 24 个汉字'
          placeholder='请输入分组名称'
          rules={[
            {
              required: true,
              message: '请填写分组名称',
            },
          ]}
        />
      </ModalForm>

      <ModalForm
        className={'dialog from-item-label-100w'}
        layout={'horizontal'}
        width={'500px'}
        visible={editGroupVisible}
        onVisibleChange={setEditGroupVisible}
        onFinish={async (params) =>
          HandleRequest({...currentGroup, ...params}, UpdateGroup, () => {
            setGroupItemsTimestamp(Date.now);
          })
        }
      >
        <h2 className='dialog-title'> 修改名称 </h2>
        <ProFormText
          colon={true}
          name='name'
          label='分组名称'
          tooltip='最长为 24 个汉字'
          placeholder='请输入分组名称'
          initialValue={currentGroup.name}
          rules={[
            {
              required: true,
              message: '请填写分组名称',
            },
          ]}
        />
      </ModalForm>

      <Modal
        className={styles.detailDialog}
        width={'800px'}
        visible={itemDetailVisible}
        onCancel={() => setItemDetailVisible(false)}
        footer={null}
      >
        <h2 className='dialog-title' style={{textAlign: "center", fontSize: 19}}> 渠道码详情 </h2>
        <Row>
          <Col span={8} className={styles.leftPart}>
            <img src={currentItem.qr_code}/>
            <h3>{currentItem.name}</h3>
            <Button
              type={'primary'}
              onClick={() => {
                if (currentItem?.qr_code) {
                  FileSaver.saveAs(currentItem?.qr_code, `${currentItem.name}.png`);
                }
              }}
            >
              下载渠道码
            </Button>
            <Button
              onClick={() => {
                history.push(
                  `/staff-admin/customer-growth/contact-way/edit?id=${currentItem.id}`,
                );
              }}
            >
              修改
            </Button>
          </Col>
          <Col span={16} className={styles.rightPart}>
            <div className={styles.section}>
              <div className={styles.titleWrapper}>
                <div className={styles.divider}/>
                <span className={styles.title}>基本设置</span>
              </div>
              <div className={styles.formItem}>
                <span className={styles.title}>创建时间:</span>
                <span className='date'>
                  {moment(currentItem.created_at).format('YYYY-MM-DD HH:mm')}
                </span>
              </div>
              <div className={styles.formItem}>
                <span className={styles.title}>绑定员工:</span>
                {currentItem.staffs?.map((staff) => (
                  <Tag
                    key={staff.id}
                    className={styles.staffTag}
                    style={{opacity: staff.online === False ? '0.5' : '1'}}
                  >
                    <img className={styles.icon} src={staff.avatar_url} alt={staff.name}/>
                    <span className={styles.text}>{staff.name}</span>
                  </Tag>
                ))}
              </div>
              <div className={styles.formItem}>
                <span className={styles.title}>备份员工:</span>
                {currentItem.backup_staffs?.map((staff) => (
                  <Tag
                    key={staff.id}
                    className={styles.staffTag}
                    style={{opacity: staff.online === False ? '0.5' : '1'}}
                  >
                    <img className={styles.icon} src={staff.avatar_url} alt={staff.name}/>
                    <span className={styles.text}>{staff.name}</span>
                  </Tag>
                ))}
              </div>
              <p className={styles.formItem}>
                <span className={styles.title}>自动通过好友:</span>
                {currentItem.auto_skip_verify_enable === True && (
                  <span>
                    {currentItem.skip_verify_start_time && '~'}
                    {currentItem.skip_verify_end_time}自动通过
                  </span>
                )}
                {currentItem.auto_skip_verify_enable === False && <span>未开启</span>}
              </p>
              <p className={styles.formItem}>
                <span className={styles.title}>客户标签:</span>
                {currentItem.customer_tags?.map((tag) => (
                  <Tag key={tag.id} className={styles.staffTag}>
                    <span className={styles.text}>{tag.name}</span>
                  </Tag>
                ))}
              </p>
            </div>
          </Col>
        </Row>
      </Modal>
    </PageContainer>
  );
}
Example #2
Source File: index.tsx    From dashboard with Apache License 2.0 4 votes vote down vote up
RoleList: React.FC = () => {
  const [roles, setRoles] = useState<RoleItem[]>([]);
  const [keyword, setKeyword] = useState<string>('');
  const [assignRoleModalVisible, setAssignRoleModalVisible] = useState<boolean>(false);
  const [currentStaff, setCurrentStaff] = useState<StaffInterface>();
  const [currentRole, setCurrentRole] = useState<RoleItem>();
  const [timeStamp, setTimeStamp] = useState<Date>(new Date());
  const actionRef = useRef<ActionType>();
  const [activeTabPaneKey, setActiveTabPaneKey] = useState<string>('staff_list');
  const roleForm = useRef<FormInstance>();

  const extStaffID = (new URLSearchParams(window.location.search)).get('ext_staff_id') || "";

  useEffect(() => {
    Query({page_size: 5000}).then((res) => {
      if (res.code === 0) {
        setRoles(res?.data?.items || []);
      } else {
        message.error(res.message);
      }
    });
  }, [timeStamp]);


  const columns: ProColumns<StaffInterface>[] = [
    {
      title: 'ID',
      dataIndex: 'id',
      valueType: 'text',
      hideInTable: true,
      hideInSearch: true,
    },
    {
      title: '员工',
      dataIndex: 'name',
      valueType: 'text',
      hideInSearch: false,
      render: (dom, item) => {
        return (
          <Space>
            <div className={'tag-like-staff-item'}>
              <img src={item.avatar_url} className={'icon'} alt={item.name}/>
              <span className={'text'}>{item.name}</span>
            </div>
          </Space>
        );
      },
    },
    {
      title: '所在部门',
      dataIndex: 'departments',
      valueType: 'text',
      hideInSearch: true,
      render: (dom) => {
        // @ts-ignore
        const arr = dom?.length > 1 ? dom?.slice(1) : dom;
        return (
          <Space>
            {arr?.map((i: any) => (
              <span key={i.id}>{i.name}</span>
            ))}
          </Space>
        );
      },
    },
    {
      title: '角色',
      dataIndex: 'role_type',
      hideInSearch: false,
      valueType: 'select',
      valueEnum: {
        '': {text: '全部账号', role_type: ''},
        superAdmin: {text: '超级管理员', role_type: 'superAdmin'},
        admin: {text: '管理员', role_type: 'admin'},
        departmentAdmin: {text: '部门管理员', role_type: 'departmentAdmin'},
        staff: {text: '员工', role_type: 'staff'},
      },
    },
    {
      title: '授权状态',
      dataIndex: 'external',
      valueType: 'text',
      hideInSearch: true,
    },
    {
      title: '操作',
      hideInSearch: true,
      width: 100,
      render: (_, item) => {
        return (
          <a
            type={'link'}
            onClick={() => {
              setCurrentStaff(item);
              setAssignRoleModalVisible(true);
            }}>
            更换角色
          </a>
        );
      },
    },
  ];

  // @ts-ignore
  // @ts-ignore
  return (
    <PageContainer
      fixedHeader
      className={styles.roleListContainer}
      extra={[
        <Button
          key='create'
          type='primary'
          icon={<PlusOutlined style={{fontSize: 16, verticalAlign: '-3px'}}/>}
          onClick={() => {
            history.push('/staff-admin/company-management/role/create');
          }}
        >
          添加角色
        </Button>,
      ]}
    >
      <ProCard gutter={8} ghost>
        <ProCard colSpan={{
          md: '240px',
        }} bordered className={styles.leftPart}>
          <div className={styles.header}>
            <Button
              key='1'
              className={styles.button}
              type='text'
              icon={<PlusSquareFilled style={{color: 'rgb(154,173,193)', fontSize: 15}}/>}
              onClick={() => {
                history.push('/staff-admin/company-management/role/create');
              }}
            >
              新建角色
            </Button>
          </div>
          <Menu
            onSelect={() => {
            }}
            defaultSelectedKeys={['0']}
            mode='inline'
            className={styles.menuList}
          >
            <Menu.Item
              key='0'
              onClick={() => {
                setCurrentRole({});
                setActiveTabPaneKey('staff_list');
              }}
            >
              全部
            </Menu.Item>
            {roles.map((item) => (
              <Menu.Item
                key={item.id}
                onClick={() => {
                  setCurrentRole(item);
                }}
              >
                <div className={styles.menuItem}>
                  {item.name}
                  <span className={styles.count}
                        style={{marginRight: item.is_default === True ? 16 : 0}}>{item.count}</span>
                </div>
                {item.is_default === False && (
                  <Dropdown
                    className={'more-actions'}
                    overlay={
                      <Menu
                        onClick={(e) => {
                          e.domEvent.preventDefault();
                          e.domEvent.stopPropagation();
                        }}
                      >
                        <Menu.Item
                          onClick={() => {
                            history.push(`/staff-admin/company-management/role/edit?id=${item.id}`);
                          }}
                          key='edit'
                        >
                          修改
                        </Menu.Item>
                      </Menu>
                    }
                    trigger={['hover']}
                  >
                    <MoreOutlined style={{color: '#9b9b9b', fontSize: 18}}/>
                  </Dropdown>
                )}
              </Menu.Item>
            ))}
          </Menu>
        </ProCard>

        <ProCard bordered className={styles.rightPart}>
          <Tabs
            activeKey={activeTabPaneKey}
            onChange={(key) => {
              setActiveTabPaneKey(key);
            }}
            tabBarExtraContent={{
              right: (
                <>
                  {activeTabPaneKey === 'staff_list' && (
                    <Search
                      placeholder='搜索员工'
                      allowClear={true}
                      onSearch={setKeyword}
                    />
                  )}
                  {activeTabPaneKey === 'permission' && currentRole?.is_default === False && (
                    <Button
                      key='edit'
                      type='dashed'
                      onClick={() => {
                        history.push(`/staff-admin/company-management/role/edit?id=${currentRole?.id}`);
                      }}
                    >
                      修改角色
                    </Button>
                  )}
                </>
              ),
            }}>
            <TabPane className={styles.tabPane} tab='成员列表' key='staff_list'>
              <ProTable
                actionRef={actionRef}
                className={'table'}
                columns={columns}
                rowKey='id'
                pagination={{
                  pageSizeOptions: ['5', '10', '20', '50', '100'],
                  pageSize: 50,
                }}
                toolBarRender={false}
                search={false}
                bordered={true}
                tableAlertRender={false}
                params={{
                  name: keyword,
                  role_id: currentRole?.id,
                  ext_staff_id: extStaffID,
                }}
                request={async (values, sort, filter) => {
                  return ProTableRequestAdapter(values, sort, filter, QueryRoleStaff);
                }}
                dateFormatter='string'
              />
            </TabPane>

            <TabPane className={styles.tabPane} tab='权限范围' key='permission' disabled={!currentRole?.id}>
              <RoleForm
                mode={'simpleEdit'}
                currentItem={currentRole}
                // @ts-ignore
                formRef={roleForm}
                onFinish={async (params) => {
                  const hide = message.loading('修改中');
                  const res: CommonResp = await Update(params);
                  hide();
                  if (res.code === 0) {
                    message.success('修改成功');
                    return true;
                  }

                  if (res.message) {
                    message.error(res.message);
                    return false;
                  }

                  message.error('修改失败');
                  return false;
                }}
              />
            </TabPane>

          </Tabs>
        </ProCard>

      </ProCard>

      <ModalForm
        className={'dialog from-item-label-100w'}
        layout={'horizontal'}
        width={'560px'}
        visible={assignRoleModalVisible}
        onVisibleChange={setAssignRoleModalVisible}
        onFinish={async (params) =>
          HandleRequest({
            ext_staff_ids: [currentStaff?.ext_staff_id],
            role_id: params.role_id,
          }, AssignRoleToStaff, () => {
            actionRef.current?.reload();
            setTimeStamp(new Date());
          })
        }
      >
        <h2 className='dialog-title'> 更换角色 </h2>
        <ProFormSelect
          width={'md'}
          name='role_id'
          label='设置角色'
          // @ts-ignore
          options={roles.map((role) => {
            if (role.type === 'superAdmin') {
              return '';
            }
            return {value: role.id, label: role.name};
          }).filter((role) => role)}
          placeholder='请选择角色'
          rules={[{required: true, message: '请选择角色'}]}
        />
      </ModalForm>

    </PageContainer>
  );
}
Example #3
Source File: EnterpriseScript.tsx    From dashboard with Apache License 2.0 4 votes vote down vote up
EnterpriseScript: (props: any, ref: any) => JSX.Element = (props, ref) => {
  const actionRef = useRef<ActionType>();
  const formRef = useRef({} as any);
  const [keyWord, setKeyWord] = useState('')
  const [groupId, setGroupId] = useState('')
  const [department_id, setDepartmentId] = useState<number[]>([])
  const [allDepartments, setAllDepartments] = useState<DepartmentOption[]>([]);
  const [allDepartmentMap, setAllDepartmentMap] = useState<Dictionary<DepartmentOption>>({});
  const [targetScriptGroup, setTargetScriptGroup] = useState<Partial<ScriptGroup.Item>>({})
  const [groupModalVisible, setGroupModalVisible] = useState(false);
  const groupModalRef = useRef<any>({});
  const scriptModalRef = useRef<any>({});
  const [groupItemsTimestamp, setGroupItemsTimestamp] = useState(Date.now);
  const [scriptModalVisible, setScriptModalVisible] = useState(false);
  const [targetScript, setTargetScript] = useState<Partial<ScriptGroup.Item>>({})
  const [groupItems, setGroupItems] = useState<Partial<ScriptGroup.Item>[]>([]);
  const [allGroupMap, setAllGroupMap] = useState<Dictionary<ScriptGroup.Item>>({});
  const [selectedItems, setSelectedItems] = useState<Script.Item[]>([]);

  useImperativeHandle(ref, () => {
    return {
      createEnterpriseScript: () => {
        setTargetScript({})
        scriptModalRef.current.open({reply_details: [{content_type: 2}]})
      },
    }
  })
  useEffect(() => {
    QueryEnterpriseScriptGroups({page_size: 5000}).then(res => {
      if (res?.code === 0) {
        setGroupItems(res?.data?.items || [])
        setAllGroupMap(_.keyBy<ScriptGroup.Item>(res?.data?.items || [], 'id'));
      }
    }).catch((err) => {
      message.error(err);
    });
  }, [groupItemsTimestamp])

  useEffect(() => {
    QueryDepartmentList({page_size: 5000}).then((res) => {
      if (res?.code === 0) {
        const departments =
          res?.data?.items?.map((item: DepartmentInterface) => {
            return {
              label: item?.name,
              value: item?.ext_id,
              ...item,
            };
          }) || [];
        setAllDepartments(departments);
        setAllDepartmentMap(_.keyBy<DepartmentOption>(departments, 'ext_id'));
      } else {
        message.error(res.message);
      }
    });
  }, []);

  // 后端数据转为前端组件FormItem -- name
  const transferParams = (paramsFromBackEnd: any) => {
    const newReplyDetails = []
    for (let i = 0; i < paramsFromBackEnd.reply_details.length; i += 1) {
      const typeObjectKey = typeEnums[paramsFromBackEnd.reply_details[i].content_type]
      const replyDetailItem: FrontEndReplyDetailParams = {
        content_type: paramsFromBackEnd.reply_details[i].content_type, id: paramsFromBackEnd.reply_details[i].id
      }
      const quickReplyContent = paramsFromBackEnd.reply_details[i].quick_reply_content
      if (typeObjectKey === 'text') {
        replyDetailItem.text_content = quickReplyContent.text.content
      }
      if (typeObjectKey === 'image') {
        replyDetailItem.image_title = quickReplyContent.image.title
        replyDetailItem.image_size = quickReplyContent.image.size
        replyDetailItem.image_picurl = quickReplyContent.image.picurl
      }
      if (typeObjectKey === 'link') {
        replyDetailItem.link_title = quickReplyContent.link.title
        replyDetailItem.link_desc = quickReplyContent.link.desc
        replyDetailItem.link_picurl = quickReplyContent.link.picurl
        replyDetailItem.link_url = quickReplyContent.link.url
      }
      if (typeObjectKey === 'pdf') {
        replyDetailItem.pdf_title = quickReplyContent.pdf.title
        replyDetailItem.pdf_size = quickReplyContent.pdf.size
        replyDetailItem.pdf_fileurl = quickReplyContent.pdf.fileurl
      }
      if (typeObjectKey === 'video') {
        replyDetailItem.video_title = quickReplyContent.video.title
        replyDetailItem.video_size = quickReplyContent.video.size
        replyDetailItem.video_picurl = quickReplyContent.video.picurl
      }
      newReplyDetails.push(replyDetailItem)
    }
    return {...paramsFromBackEnd, reply_details: newReplyDetails}
  }


  const columns: ProColumns<Script.Item>[] = [
    {
      title: '话术内容',
      dataIndex: 'keyword',
      width: '18%',
      hideInSearch: false,
      render: (dom: any, item: any) => {
        return (
          <ScriptContentPreView script={item}/>
        )
      },
    },
    {
      title: '标题',
      dataIndex: 'name',
      key:'name',
      valueType: 'text',
      hideInSearch: true,
    },
    {
      title: '发送次数',
      dataIndex: 'send_count',
      key: 'name',
      valueType: 'digit',
      hideInSearch: true,
      width: 100,
    },
    {
      title: '所属分组',
      width: '14%',
      dataIndex: 'group_id',
      key: 'group_id',
      valueType: 'text',
      hideInSearch: true,
      render: (dom: any) => {
        return (
          <span>{allGroupMap[dom]?.name || '-'}</span>
        )
      },
    },
    {
      title: '创建人',
      dataIndex: 'staff_name',
      key: 'staff_name',
      hideInSearch: true,
      render: (dom, item) => (
        <div className={'tag-like-staff-item'}>
          <img className={'icon'} src={item.avatar}/>
          <span className={'text'}>{dom}</span>
        </div>
      )
    },
    {
      title: '创建时间',
      dataIndex: 'created_at',
      key: 'created_at',
      valueType: 'dateTime',
      hideInSearch: true,
      render: (dom, item) => {
        return (
          <div
            dangerouslySetInnerHTML={{
              __html: moment(item.created_at)
                .format('YYYY-MM-DD HH:mm')
                .split(' ')
                .join('<br />'),
            }}
          />
        );
      },
    },
    {
      title: '类型',
      dataIndex: 'quick_reply_type',
      key: 'quick_reply_type',
      valueType: 'text',
      hideInSearch: true,
      render: (dom: any) => {
        return <span>{typeEnums[dom]}</span>
      }
    },
    {
      title: '可用部门',
      dataIndex: 'department_id',
      key: 'department_id',
      valueType: 'text',
      hideInSearch: false,
      hideInTable: true,
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      renderFormItem: (schema, config, form) => {
        return (
          <DepartmentTreeSelect
            options={allDepartments}
          />
        )
      },
    },
    {
      title: '操作',
      valueType: 'text',
      width: '10%',
      hideInSearch: true,
      render: (dom) => {
        return (
          <Space>
            <Button
              type={'link'}
              onClick={() => {
                // @ts-ignore
                const target = transferParams(dom)
                setTargetScript(target)
                // @ts-ignore
                scriptModalRef.current.open(target)
              }}
            >修改</Button>
            <Button
              type={'link'}
              onClick={() => {
                Modal.confirm({
                  title: `删除话术`,
                  // @ts-ignore
                  content: `是否确认删除「${dom?.name}」话术?`,
                  okText: '删除',
                  okType: 'danger',
                  cancelText: '取消',
                  onOk() {
                    // @ts-ignore
                    return HandleRequest({ids: [dom?.id]}, DeleteEnterpriseScriptList, () => {
                      actionRef?.current?.reload()
                    })
                  },
                });
              }}
            >
              删除
            </Button>
          </Space>
        )
      }
    },
  ]
  const getUseableDepartment = (departments: number[]) => {
    return departments.map((id) => {
      return <span key={id}>
           {id === 0 ? '全部员工可见' : allDepartmentMap[id]?.label} &nbsp;
        </span>
    })
  }

  return (
    <>
      <ProTable
        onSubmit={() => {
          setKeyWord(formRef.current.getFieldValue('keyword'))
          setDepartmentId(formRef.current.getFieldValue('department_id'))
        }}
        onReset={() => {
          setKeyWord(formRef?.current?.getFieldValue('keyword'))
          setDepartmentId(formRef?.current?.getFieldValue('department_id'))
        }}
        actionRef={actionRef}
        formRef={formRef}
        className={'table'}
        scroll={{x: 'max-content'}}
        columns={columns}
        rowKey={(scriptItem) => scriptItem.id}
        pagination={{
          pageSizeOptions: ['5', '10', '20', '50', '100'],
          pageSize: 5,
        }}
        toolBarRender={false}
        bordered={false}
        tableAlertRender={false}
        rowSelection={{
          onChange: (__, items) => {
            setSelectedItems(items);
          },
        }}
        tableRender={(block, dom) => (
          <div className={styles.mixedTable}>
            <div className={styles.leftPart}>
              <div className={styles.header}>
                <Button
                  key="1"
                  className={styles.button}
                  type="text"
                  onClick={() => {
                    setTargetScriptGroup({})
                    groupModalRef.current.open({})
                  }}
                  icon={<PlusSquareFilled style={{color: 'rgb(154,173,193)', fontSize: 15}}/>}
                >
                  新建分组
                </Button>
              </div>
              <Menu
                onSelect={(e) => {
                  setGroupId(e.key as string)
                }}
                defaultSelectedKeys={['']}
                mode="inline"
                className={styles.menuList}
              >
                <Menu.Item
                  icon={<FolderFilled style={{fontSize: '16px', color: '#138af8'}}/>}
                  onClick={() => setTargetScriptGroup({})}
                  key=""
                >
                  全部
                </Menu.Item>
                {groupItems.map((item) => (
                  <Menu.Item
                    icon={<FolderFilled style={{fontSize: '16px', color: '#138af8'}}/>}
                    key={item.id}
                    onClick={() => {
                      setTargetScriptGroup(item)
                    }}
                  >
                    {item.name}
                    <Dropdown
                      className={'more-actions'}
                      overlay={
                        <Menu
                          onClick={(e) => {
                            e.domEvent.preventDefault();
                            e.domEvent.stopPropagation();
                          }}
                        >
                          <Menu.Item
                            onClick={() => {
                              setTargetScriptGroup(item)
                              groupModalRef.current.open(item)
                            }}
                            key="edit"
                          >
                            <a type={'link'}>修改分组</a>

                          </Menu.Item>
                          <Menu.Item
                            key="delete"
                          >
                            <a
                              type={'link'}
                              onClick={() => {
                                Modal.confirm({
                                  title: `删除分组`,
                                  // @ts-ignore
                                  content: `是否确认删除「${item?.name}」分组?`,
                                  okText: '删除',
                                  okType: 'danger',
                                  cancelText: '取消',
                                  onOk() {
                                    // @ts-ignore
                                    return HandleRequest({ids: [item.id]}, DeleteEnterpriseScriptGroups, () => {
                                      setGroupItemsTimestamp(Date.now)
                                    })
                                  },
                                });
                              }}
                            >
                              删除分组
                            </a>
                          </Menu.Item>
                        </Menu>
                      }
                      trigger={['hover']}
                    >
                      <MoreOutlined style={{color: '#9b9b9b', fontSize: 18}}/>
                    </Dropdown>

                  </Menu.Item>
                ))}

              </Menu>
            </div>
            <div className={styles.rightPart}>
              {
                targetScriptGroup?.id
                &&
                <div className={styles.aboveTableWrap}>
                  可见范围&nbsp;<Tooltip title={'范围内的员工可在企业微信【侧边栏】使用话术'}><QuestionCircleOutlined /></Tooltip>:
                  {allGroupMap[targetScriptGroup.id]?.departments ? getUseableDepartment(allGroupMap[targetScriptGroup.id]?.departments) : '全部员工可见'}
                  &nbsp;&nbsp;&nbsp;
                  <a onClick={() => groupModalRef.current.open(allGroupMap[targetScriptGroup!.id!])}>修改</a>
                </div>
              }
              <div className={styles.tableWrap}>{dom}</div>
            </div>
          </div>
        )}
        params={{
          group_id: groupId || '',
          department_ids: department_id || [],
          keyword: keyWord || ''
        }}
        request={async (params, sort, filter) => {
          return ProTableRequestAdapter(params, sort, filter, QueryEnterpriseScriptList);
        }}
        dateFormatter="string"
      />

      {selectedItems?.length > 0 && (
        // 底部选中条目菜单栏
        <FooterToolbar>
          <span>
            已选择 <a style={{fontWeight: 600}}>{selectedItems.length}</a> 项 &nbsp;&nbsp;
          </span>
          <Divider type='vertical'/>
          <Button
            type='link'
            onClick={() => {
              actionRef.current?.clearSelected?.();
            }}
          >
            取消选择
          </Button>
          <Button
            icon={<DeleteOutlined/>}
            onClick={async () => {
              Modal.confirm({
                title: `删除渠道码`,
                content: `是否批量删除所选「${selectedItems.length}」个渠道码?`,
                okText: '删除',
                okType: 'danger',
                cancelText: '取消',
                onOk() {
                  return HandleRequest(
                    {ids: selectedItems.map((item) => item.id)},
                    DeleteEnterpriseScriptList,
                    () => {
                      actionRef.current?.clearSelected?.();
                      actionRef.current?.reload?.();
                    },
                  );
                },
              });
            }}
            danger={true}
          >
            批量删除
          </Button>
        </FooterToolbar>
      )}
      {/* 新增&修改分组 */}
      <GroupModal
        initialValues={targetScriptGroup}
        allDepartments={allDepartments}
        ref={groupModalRef}
        visible={groupModalVisible}
        setVisible={setGroupModalVisible}
        onFinish={async (values, action) => {
          if (action === 'create') {
            await HandleRequest({...values, sub_groups: []}, CreateEnterpriseScriptGroups, () => {
              setGroupItemsTimestamp(Date.now)
              groupModalRef.current.close()
            })
          } else {
            await HandleRequest({...values, sub_groups: []}, UpdateEnterpriseScriptGroups, () => {
              setGroupItemsTimestamp(Date.now)
              groupModalRef.current.close()
            })
          }
        }}
      />
      {/* 新增&修改话术 */}
      <ScriptModal
        allDepartments={allDepartments}
        initialValues={targetScript}
        ref={scriptModalRef}
        visible={scriptModalVisible}
        setVisible={setScriptModalVisible}
        setPropsGroupsTimestamp={setGroupItemsTimestamp}
        onCancel={() => {
          setGroupItemsTimestamp(Date.now)
        }}
        onFinish={async (values, action) => {
          if (action === 'create') {
            await HandleRequest({...values}, CreateEnterpriseScriptList, () => {
              setGroupItemsTimestamp(Date.now)
              actionRef?.current?.reload()
              scriptModalRef.current.close()
            })
          } else {
            const {reply_details, id, group_id, name, deleted_ids} = values
            await HandleRequest({reply_details, id, group_id, name, deleted_ids}, UpdateEnterpriseScriptList, () => {
              setGroupItemsTimestamp(Date.now)
              actionRef?.current?.reload()
              scriptModalRef.current.close()
            })
          }
        }}
      />
    </>
  )
}